Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner: "The time/timekeeping/timer folks deliver with this update: - Fix a reintroduced signed/unsigned issue and cleanup the whole signed/unsigned mess in the timekeeping core so this wont happen accidentaly again. - Add a new trace clock based on boot time - Prevent injection of random sleep times when PM tracing abuses the RTC for storage - Make posix timers configurable for real tiny systems - Add tracepoints for the alarm timer subsystem so timer based suspend wakeups can be instrumented - The usual pile of fixes and updates to core and drivers" * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits) timekeeping: Use mul_u64_u32_shr() instead of open coding it timekeeping: Get rid of pointless typecasts timekeeping: Make the conversion call chain consistently unsigned timekeeping_Force_unsigned_clocksource_to_nanoseconds_conversion alarmtimer: Add tracepoints for alarm timers trace: Update documentation for mono, mono_raw and boot clock trace: Add an option for boot clock as trace clock timekeeping: Add a fast and NMI safe boot clock timekeeping/clocksource_cyc2ns: Document intended range limitation timekeeping: Ignore the bogus sleep time if pm_trace is enabled selftests/timers: Fix spelling mistake "Asyncrhonous" -> "Asynchronous" clocksource/drivers/bcm2835_timer: Unmap region obtained by of_iomap clocksource/drivers/arm_arch_timer: Map frame with of_io_request_and_map() arm64: dts: rockchip: Arch counter doesn't tick in system suspend clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend posix-timers: Make them configurable posix_cpu_timers: Move the add_device_randomness() call to a proper place timer: Move sys_alarm from timer.c to itimer.c ptp_clock: Allow for it to be optional Kconfig: Regenerate *.c_shipped files after previous changes ...
此提交包含在:
@@ -1,6 +1,12 @@
|
||||
obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
|
||||
obj-y += time.o timer.o hrtimer.o
|
||||
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
|
||||
obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
|
||||
obj-y += timeconv.o timecounter.o alarmtimer.o
|
||||
|
||||
ifeq ($(CONFIG_POSIX_TIMERS),y)
|
||||
obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o itimer.o
|
||||
else
|
||||
obj-y += posix-stubs.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o
|
||||
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
|
||||
|
@@ -26,6 +26,9 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/alarmtimer.h>
|
||||
|
||||
/**
|
||||
* struct alarm_base - Alarm timer bases
|
||||
* @lock: Lock for syncrhonized access to the base
|
||||
@@ -40,7 +43,9 @@ static struct alarm_base {
|
||||
clockid_t base_clockid;
|
||||
} alarm_bases[ALARM_NUMTYPE];
|
||||
|
||||
/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
|
||||
/* freezer information to handle clock_nanosleep triggered wakeups */
|
||||
static enum alarmtimer_type freezer_alarmtype;
|
||||
static ktime_t freezer_expires;
|
||||
static ktime_t freezer_delta;
|
||||
static DEFINE_SPINLOCK(freezer_delta_lock);
|
||||
|
||||
@@ -194,6 +199,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
|
||||
}
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
|
||||
trace_alarmtimer_fired(alarm, base->gettime());
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -218,15 +224,16 @@ EXPORT_SYMBOL_GPL(alarm_expires_remaining);
|
||||
*/
|
||||
static int alarmtimer_suspend(struct device *dev)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
ktime_t min, now;
|
||||
unsigned long flags;
|
||||
ktime_t min, now, expires;
|
||||
int i, ret, type;
|
||||
struct rtc_device *rtc;
|
||||
int i;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
struct rtc_time tm;
|
||||
|
||||
spin_lock_irqsave(&freezer_delta_lock, flags);
|
||||
min = freezer_delta;
|
||||
expires = freezer_expires;
|
||||
type = freezer_alarmtype;
|
||||
freezer_delta = ktime_set(0, 0);
|
||||
spin_unlock_irqrestore(&freezer_delta_lock, flags);
|
||||
|
||||
@@ -247,8 +254,11 @@ static int alarmtimer_suspend(struct device *dev)
|
||||
if (!next)
|
||||
continue;
|
||||
delta = ktime_sub(next->expires, base->gettime());
|
||||
if (!min.tv64 || (delta.tv64 < min.tv64))
|
||||
if (!min.tv64 || (delta.tv64 < min.tv64)) {
|
||||
expires = next->expires;
|
||||
min = delta;
|
||||
type = i;
|
||||
}
|
||||
}
|
||||
if (min.tv64 == 0)
|
||||
return 0;
|
||||
@@ -258,6 +268,8 @@ static int alarmtimer_suspend(struct device *dev)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
trace_alarmtimer_suspend(expires, type);
|
||||
|
||||
/* Setup an rtc timer to fire that far in the future */
|
||||
rtc_timer_cancel(rtc, &rtctimer);
|
||||
rtc_read_time(rtc, &tm);
|
||||
@@ -295,15 +307,32 @@ static int alarmtimer_resume(struct device *dev)
|
||||
|
||||
static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
|
||||
{
|
||||
ktime_t delta;
|
||||
struct alarm_base *base;
|
||||
unsigned long flags;
|
||||
struct alarm_base *base = &alarm_bases[type];
|
||||
ktime_t delta;
|
||||
|
||||
switch(type) {
|
||||
case ALARM_REALTIME:
|
||||
base = &alarm_bases[ALARM_REALTIME];
|
||||
type = ALARM_REALTIME_FREEZER;
|
||||
break;
|
||||
case ALARM_BOOTTIME:
|
||||
base = &alarm_bases[ALARM_BOOTTIME];
|
||||
type = ALARM_BOOTTIME_FREEZER;
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Invalid alarm type: %d\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
delta = ktime_sub(absexp, base->gettime());
|
||||
|
||||
spin_lock_irqsave(&freezer_delta_lock, flags);
|
||||
if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
|
||||
if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64)) {
|
||||
freezer_delta = delta;
|
||||
freezer_expires = absexp;
|
||||
freezer_alarmtype = type;
|
||||
}
|
||||
spin_unlock_irqrestore(&freezer_delta_lock, flags);
|
||||
}
|
||||
|
||||
@@ -342,6 +371,8 @@ void alarm_start(struct alarm *alarm, ktime_t start)
|
||||
alarmtimer_enqueue(base, alarm);
|
||||
hrtimer_start(&alarm->timer, alarm->node.expires, HRTIMER_MODE_ABS);
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
|
||||
trace_alarmtimer_start(alarm, base->gettime());
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alarm_start);
|
||||
|
||||
@@ -390,6 +421,8 @@ int alarm_try_to_cancel(struct alarm *alarm)
|
||||
if (ret >= 0)
|
||||
alarmtimer_dequeue(base, alarm);
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
|
||||
trace_alarmtimer_cancel(alarm, base->gettime());
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alarm_try_to_cancel);
|
||||
@@ -846,8 +879,10 @@ static int __init alarmtimer_init(void)
|
||||
|
||||
alarmtimer_rtc_timer_init();
|
||||
|
||||
posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
|
||||
posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
|
||||
if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
|
||||
posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
|
||||
posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
|
||||
}
|
||||
|
||||
/* Initialize alarm bases */
|
||||
alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
|
||||
|
@@ -1742,15 +1742,19 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
|
||||
* You can set the task state as follows -
|
||||
*
|
||||
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
|
||||
* pass before the routine returns.
|
||||
* pass before the routine returns unless the current task is explicitly
|
||||
* woken up, (e.g. by wake_up_process()).
|
||||
*
|
||||
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
|
||||
* delivered to the current task.
|
||||
* delivered to the current task or the current task is explicitly woken
|
||||
* up.
|
||||
*
|
||||
* The current task state is guaranteed to be TASK_RUNNING when this
|
||||
* routine returns.
|
||||
*
|
||||
* Returns 0 when the timer has expired otherwise -EINTR
|
||||
* Returns 0 when the timer has expired. If the task was woken before the
|
||||
* timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
|
||||
* by an explicit wakeup, it returns -EINTR.
|
||||
*/
|
||||
int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
|
||||
const enum hrtimer_mode mode)
|
||||
@@ -1772,15 +1776,19 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
|
||||
* You can set the task state as follows -
|
||||
*
|
||||
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
|
||||
* pass before the routine returns.
|
||||
* pass before the routine returns unless the current task is explicitly
|
||||
* woken up, (e.g. by wake_up_process()).
|
||||
*
|
||||
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
|
||||
* delivered to the current task.
|
||||
* delivered to the current task or the current task is explicitly woken
|
||||
* up.
|
||||
*
|
||||
* The current task state is guaranteed to be TASK_RUNNING when this
|
||||
* routine returns.
|
||||
*
|
||||
* Returns 0 when the timer has expired otherwise -EINTR
|
||||
* Returns 0 when the timer has expired. If the task was woken before the
|
||||
* timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
|
||||
* by an explicit wakeup, it returns -EINTR.
|
||||
*/
|
||||
int __sched schedule_hrtimeout(ktime_t *expires,
|
||||
const enum hrtimer_mode mode)
|
||||
|
@@ -238,6 +238,8 @@ again:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_ALARM
|
||||
|
||||
/**
|
||||
* alarm_setitimer - set alarm in seconds
|
||||
*
|
||||
@@ -250,7 +252,7 @@ again:
|
||||
* On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
|
||||
* negative timeval settings which would cause immediate expiry.
|
||||
*/
|
||||
unsigned int alarm_setitimer(unsigned int seconds)
|
||||
static unsigned int alarm_setitimer(unsigned int seconds)
|
||||
{
|
||||
struct itimerval it_new, it_old;
|
||||
|
||||
@@ -275,6 +277,17 @@ unsigned int alarm_setitimer(unsigned int seconds)
|
||||
return it_old.it_value.tv_sec;
|
||||
}
|
||||
|
||||
/*
|
||||
* For backwards compatibility? This can be done in libc so Alpha
|
||||
* and all newer ports shouldn't need it.
|
||||
*/
|
||||
SYSCALL_DEFINE1(alarm, unsigned int, seconds)
|
||||
{
|
||||
return alarm_setitimer(seconds);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
|
||||
struct itimerval __user *, ovalue)
|
||||
{
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <trace/events/timer.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/tick.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
@@ -447,10 +446,7 @@ static void cleanup_timers(struct list_head *head)
|
||||
*/
|
||||
void posix_cpu_timers_exit(struct task_struct *tsk)
|
||||
{
|
||||
add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
|
||||
sizeof(unsigned long long));
|
||||
cleanup_timers(tsk->cpu_timers);
|
||||
|
||||
}
|
||||
void posix_cpu_timers_exit_group(struct task_struct *tsk)
|
||||
{
|
||||
|
123
kernel/time/posix-stubs.c
一般檔案
123
kernel/time/posix-stubs.c
一般檔案
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Dummy stubs used when CONFIG_POSIX_TIMERS=n
|
||||
*
|
||||
* Created by: Nicolas Pitre, July 2016
|
||||
* Copyright: (C) 2016 Linaro Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/posix-timers.h>
|
||||
|
||||
asmlinkage long sys_ni_posix_timers(void)
|
||||
{
|
||||
pr_err_once("process %d (%s) attempted a POSIX timer syscall "
|
||||
"while CONFIG_POSIX_TIMERS is not set\n",
|
||||
current->pid, current->comm);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
|
||||
|
||||
SYS_NI(timer_create);
|
||||
SYS_NI(timer_gettime);
|
||||
SYS_NI(timer_getoverrun);
|
||||
SYS_NI(timer_settime);
|
||||
SYS_NI(timer_delete);
|
||||
SYS_NI(clock_adjtime);
|
||||
SYS_NI(getitimer);
|
||||
SYS_NI(setitimer);
|
||||
#ifdef __ARCH_WANT_SYS_ALARM
|
||||
SYS_NI(alarm);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
|
||||
* as it is easy to remain compatible with little code. CLOCK_BOOTTIME
|
||||
* is also included for convenience as at least systemd uses it.
|
||||
*/
|
||||
|
||||
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
|
||||
const struct timespec __user *, tp)
|
||||
{
|
||||
struct timespec new_tp;
|
||||
|
||||
if (which_clock != CLOCK_REALTIME)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&new_tp, tp, sizeof (*tp)))
|
||||
return -EFAULT;
|
||||
return do_sys_settimeofday(&new_tp, NULL);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
|
||||
struct timespec __user *,tp)
|
||||
{
|
||||
struct timespec kernel_tp;
|
||||
|
||||
switch (which_clock) {
|
||||
case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break;
|
||||
case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break;
|
||||
case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
|
||||
{
|
||||
struct timespec rtn_tp = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = hrtimer_resolution,
|
||||
};
|
||||
|
||||
switch (which_clock) {
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_BOOTTIME:
|
||||
if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
|
||||
const struct timespec __user *, rqtp,
|
||||
struct timespec __user *, rmtp)
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
switch (which_clock) {
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_BOOTTIME:
|
||||
if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
|
||||
return -EFAULT;
|
||||
if (!timespec_valid(&t))
|
||||
return -EINVAL;
|
||||
return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ?
|
||||
HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
|
||||
which_clock);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
long clock_nanosleep_restart(struct restart_block *restart_block)
|
||||
{
|
||||
return hrtimer_nanosleep_restart(restart_block);
|
||||
}
|
||||
#endif
|
@@ -258,10 +258,9 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
|
||||
tk->cycle_interval = interval;
|
||||
|
||||
/* Go back from cycles -> shifted ns */
|
||||
tk->xtime_interval = (u64) interval * clock->mult;
|
||||
tk->xtime_interval = interval * clock->mult;
|
||||
tk->xtime_remainder = ntpinterval - tk->xtime_interval;
|
||||
tk->raw_interval =
|
||||
((u64) interval * clock->mult) >> clock->shift;
|
||||
tk->raw_interval = (interval * clock->mult) >> clock->shift;
|
||||
|
||||
/* if changing clocks, convert xtime_nsec shift units */
|
||||
if (old_clock) {
|
||||
@@ -299,10 +298,10 @@ u32 (*arch_gettimeoffset)(void) = default_arch_gettimeoffset;
|
||||
static inline u32 arch_gettimeoffset(void) { return 0; }
|
||||
#endif
|
||||
|
||||
static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
|
||||
static inline u64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
|
||||
cycle_t delta)
|
||||
{
|
||||
s64 nsec;
|
||||
u64 nsec;
|
||||
|
||||
nsec = delta * tkr->mult + tkr->xtime_nsec;
|
||||
nsec >>= tkr->shift;
|
||||
@@ -311,7 +310,7 @@ static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
|
||||
return nsec + arch_gettimeoffset();
|
||||
}
|
||||
|
||||
static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
|
||||
static inline u64 timekeeping_get_ns(struct tk_read_base *tkr)
|
||||
{
|
||||
cycle_t delta;
|
||||
|
||||
@@ -319,8 +318,8 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
|
||||
return timekeeping_delta_to_ns(tkr, delta);
|
||||
}
|
||||
|
||||
static inline s64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
|
||||
cycle_t cycles)
|
||||
static inline u64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
|
||||
cycle_t cycles)
|
||||
{
|
||||
cycle_t delta;
|
||||
|
||||
@@ -425,6 +424,35 @@ u64 ktime_get_raw_fast_ns(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ktime_get_raw_fast_ns);
|
||||
|
||||
/**
|
||||
* ktime_get_boot_fast_ns - NMI safe and fast access to boot clock.
|
||||
*
|
||||
* To keep it NMI safe since we're accessing from tracing, we're not using a
|
||||
* separate timekeeper with updates to monotonic clock and boot offset
|
||||
* protected with seqlocks. This has the following minor side effects:
|
||||
*
|
||||
* (1) Its possible that a timestamp be taken after the boot offset is updated
|
||||
* but before the timekeeper is updated. If this happens, the new boot offset
|
||||
* is added to the old timekeeping making the clock appear to update slightly
|
||||
* earlier:
|
||||
* CPU 0 CPU 1
|
||||
* timekeeping_inject_sleeptime64()
|
||||
* __timekeeping_inject_sleeptime(tk, delta);
|
||||
* timestamp();
|
||||
* timekeeping_update(tk, TK_CLEAR_NTP...);
|
||||
*
|
||||
* (2) On 32-bit systems, the 64-bit boot offset (tk->offs_boot) may be
|
||||
* partially updated. Since the tk->offs_boot update is a rare event, this
|
||||
* should be a rare occurrence which postprocessing should be able to handle.
|
||||
*/
|
||||
u64 notrace ktime_get_boot_fast_ns(void)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
|
||||
return (ktime_get_mono_fast_ns() + ktime_to_ns(tk->offs_boot));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns);
|
||||
|
||||
/* Suspend-time cycles value for halted fast timekeeper. */
|
||||
static cycle_t cycles_at_suspend;
|
||||
|
||||
@@ -623,7 +651,7 @@ static void timekeeping_forward_now(struct timekeeper *tk)
|
||||
{
|
||||
struct clocksource *clock = tk->tkr_mono.clock;
|
||||
cycle_t cycle_now, delta;
|
||||
s64 nsec;
|
||||
u64 nsec;
|
||||
|
||||
cycle_now = tk->tkr_mono.read(clock);
|
||||
delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
|
||||
@@ -652,7 +680,7 @@ int __getnstimeofday64(struct timespec64 *ts)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned long seq;
|
||||
s64 nsecs = 0;
|
||||
u64 nsecs;
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&tk_core.seq);
|
||||
@@ -692,7 +720,7 @@ ktime_t ktime_get(void)
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned int seq;
|
||||
ktime_t base;
|
||||
s64 nsecs;
|
||||
u64 nsecs;
|
||||
|
||||
WARN_ON(timekeeping_suspended);
|
||||
|
||||
@@ -735,7 +763,7 @@ ktime_t ktime_get_with_offset(enum tk_offsets offs)
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned int seq;
|
||||
ktime_t base, *offset = offsets[offs];
|
||||
s64 nsecs;
|
||||
u64 nsecs;
|
||||
|
||||
WARN_ON(timekeeping_suspended);
|
||||
|
||||
@@ -779,7 +807,7 @@ ktime_t ktime_get_raw(void)
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned int seq;
|
||||
ktime_t base;
|
||||
s64 nsecs;
|
||||
u64 nsecs;
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&tk_core.seq);
|
||||
@@ -804,8 +832,8 @@ void ktime_get_ts64(struct timespec64 *ts)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
struct timespec64 tomono;
|
||||
s64 nsec;
|
||||
unsigned int seq;
|
||||
u64 nsec;
|
||||
|
||||
WARN_ON(timekeeping_suspended);
|
||||
|
||||
@@ -893,8 +921,8 @@ void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
|
||||
unsigned long seq;
|
||||
ktime_t base_raw;
|
||||
ktime_t base_real;
|
||||
s64 nsec_raw;
|
||||
s64 nsec_real;
|
||||
u64 nsec_raw;
|
||||
u64 nsec_real;
|
||||
cycle_t now;
|
||||
|
||||
WARN_ON_ONCE(timekeeping_suspended);
|
||||
@@ -1052,7 +1080,7 @@ int get_device_system_crosststamp(int (*get_time_fn)
|
||||
cycle_t cycles, now, interval_start;
|
||||
unsigned int clock_was_set_seq = 0;
|
||||
ktime_t base_real, base_raw;
|
||||
s64 nsec_real, nsec_raw;
|
||||
u64 nsec_real, nsec_raw;
|
||||
u8 cs_was_changed_seq;
|
||||
unsigned long seq;
|
||||
bool do_interp;
|
||||
@@ -1365,7 +1393,7 @@ void getrawmonotonic64(struct timespec64 *ts)
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
struct timespec64 ts64;
|
||||
unsigned long seq;
|
||||
s64 nsecs;
|
||||
u64 nsecs;
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&tk_core.seq);
|
||||
@@ -1616,7 +1644,7 @@ void timekeeping_resume(void)
|
||||
struct clocksource *clock = tk->tkr_mono.clock;
|
||||
unsigned long flags;
|
||||
struct timespec64 ts_new, ts_delta;
|
||||
cycle_t cycle_now, cycle_delta;
|
||||
cycle_t cycle_now;
|
||||
|
||||
sleeptime_injected = false;
|
||||
read_persistent_clock64(&ts_new);
|
||||
@@ -1642,27 +1670,11 @@ void timekeeping_resume(void)
|
||||
cycle_now = tk->tkr_mono.read(clock);
|
||||
if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
|
||||
cycle_now > tk->tkr_mono.cycle_last) {
|
||||
u64 num, max = ULLONG_MAX;
|
||||
u32 mult = clock->mult;
|
||||
u32 shift = clock->shift;
|
||||
s64 nsec = 0;
|
||||
|
||||
cycle_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
|
||||
tk->tkr_mono.mask);
|
||||
|
||||
/*
|
||||
* "cycle_delta * mutl" may cause 64 bits overflow, if the
|
||||
* suspended time is too long. In that case we need do the
|
||||
* 64 bits math carefully
|
||||
*/
|
||||
do_div(max, mult);
|
||||
if (cycle_delta > max) {
|
||||
num = div64_u64(cycle_delta, max);
|
||||
nsec = (((u64) max * mult) >> shift) * num;
|
||||
cycle_delta -= num * max;
|
||||
}
|
||||
nsec += ((u64) cycle_delta * mult) >> shift;
|
||||
u64 nsec, cyc_delta;
|
||||
|
||||
cyc_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
|
||||
tk->tkr_mono.mask);
|
||||
nsec = mul_u64_u32_shr(cyc_delta, clock->mult, clock->shift);
|
||||
ts_delta = ns_to_timespec64(nsec);
|
||||
sleeptime_injected = true;
|
||||
} else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {
|
||||
|
@@ -1615,7 +1615,8 @@ void update_process_times(int user_tick)
|
||||
irq_work_tick();
|
||||
#endif
|
||||
scheduler_tick();
|
||||
run_posix_cpu_timers(p);
|
||||
if (IS_ENABLED(CONFIG_POSIX_TIMERS))
|
||||
run_posix_cpu_timers(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1676,19 +1677,6 @@ void run_local_timers(void)
|
||||
raise_softirq(TIMER_SOFTIRQ);
|
||||
}
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_ALARM
|
||||
|
||||
/*
|
||||
* For backwards compatibility? This can be done in libc so Alpha
|
||||
* and all newer ports shouldn't need it.
|
||||
*/
|
||||
SYSCALL_DEFINE1(alarm, unsigned int, seconds)
|
||||
{
|
||||
return alarm_setitimer(seconds);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void process_timeout(unsigned long __data)
|
||||
{
|
||||
wake_up_process((struct task_struct *)__data);
|
||||
@@ -1705,11 +1693,12 @@ static void process_timeout(unsigned long __data)
|
||||
* You can set the task state as follows -
|
||||
*
|
||||
* %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
|
||||
* pass before the routine returns. The routine will return 0
|
||||
* pass before the routine returns unless the current task is explicitly
|
||||
* woken up, (e.g. by wake_up_process())".
|
||||
*
|
||||
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
|
||||
* delivered to the current task. In this case the remaining time
|
||||
* in jiffies will be returned, or 0 if the timer expired in time
|
||||
* delivered to the current task or the current task is explicitly woken
|
||||
* up.
|
||||
*
|
||||
* The current task state is guaranteed to be TASK_RUNNING when this
|
||||
* routine returns.
|
||||
@@ -1718,7 +1707,9 @@ static void process_timeout(unsigned long __data)
|
||||
* the CPU away without a bound on the timeout. In this case the return
|
||||
* value will be %MAX_SCHEDULE_TIMEOUT.
|
||||
*
|
||||
* In all cases the return value is guaranteed to be non-negative.
|
||||
* Returns 0 when the timer has expired otherwise the remaining time in
|
||||
* jiffies will be returned. In all cases the return value is guaranteed
|
||||
* to be non-negative.
|
||||
*/
|
||||
signed long __sched schedule_timeout(signed long timeout)
|
||||
{
|
||||
@@ -1910,16 +1901,6 @@ unsigned long msleep_interruptible(unsigned int msecs)
|
||||
|
||||
EXPORT_SYMBOL(msleep_interruptible);
|
||||
|
||||
static void __sched do_usleep_range(unsigned long min, unsigned long max)
|
||||
{
|
||||
ktime_t kmin;
|
||||
u64 delta;
|
||||
|
||||
kmin = ktime_set(0, min * NSEC_PER_USEC);
|
||||
delta = (u64)(max - min) * NSEC_PER_USEC;
|
||||
schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
/**
|
||||
* usleep_range - Sleep for an approximate time
|
||||
* @min: Minimum time in usecs to sleep
|
||||
@@ -1933,7 +1914,14 @@ static void __sched do_usleep_range(unsigned long min, unsigned long max)
|
||||
*/
|
||||
void __sched usleep_range(unsigned long min, unsigned long max)
|
||||
{
|
||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
do_usleep_range(min, max);
|
||||
ktime_t exp = ktime_add_us(ktime_get(), min);
|
||||
u64 delta = (u64)(max - min) * NSEC_PER_USEC;
|
||||
|
||||
for (;;) {
|
||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
/* Do not return before the requested sleep time has elapsed */
|
||||
if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(usleep_range);
|
||||
|
新增問題並參考
封鎖使用者