Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner: "The timer departement delivers: - a regression fix for the NTP code along with a proper selftest - prevent a spurious timer interrupt in the NOHZ lowres code - a fix for user space interfaces returning the remaining time on architectures with CONFIG_TIME_LOW_RES=y - a few patches to fix COMPILE_TEST fallout" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: tick/nohz: Set the correct expiry when switching to nohz/lowres mode clocksource: Fix dependencies for archs w/o HAS_IOMEM clocksource: Select CLKSRC_MMIO where needed tick/sched: Hide unused oneshot timer code kselftests: timers: Add adjtimex SETOFFSET validity tests ntp: Fix ADJ_SETOFFSET being used w/ ADJ_NANO itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper hrtimer: Handle remaining time proper for TIME_LOW_RES clockevents/tcb_clksrc: Prevent disabling an already disabled clock
This commit is contained in:
@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtimer *timer,
|
||||
*/
|
||||
static void __remove_hrtimer(struct hrtimer *timer,
|
||||
struct hrtimer_clock_base *base,
|
||||
unsigned long newstate, int reprogram)
|
||||
u8 newstate, int reprogram)
|
||||
{
|
||||
struct hrtimer_cpu_base *cpu_base = base->cpu_base;
|
||||
unsigned int state = timer->state;
|
||||
u8 state = timer->state;
|
||||
|
||||
timer->state = newstate;
|
||||
if (!(state & HRTIMER_STATE_ENQUEUED))
|
||||
@@ -930,7 +930,7 @@ static inline int
|
||||
remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart)
|
||||
{
|
||||
if (hrtimer_is_queued(timer)) {
|
||||
unsigned long state = timer->state;
|
||||
u8 state = timer->state;
|
||||
int reprogram;
|
||||
|
||||
/*
|
||||
@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool rest
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
|
||||
const enum hrtimer_mode mode)
|
||||
{
|
||||
#ifdef CONFIG_TIME_LOW_RES
|
||||
/*
|
||||
* CONFIG_TIME_LOW_RES indicates that the system has no way to return
|
||||
* granular time values. For relative timers we add hrtimer_resolution
|
||||
* (i.e. one jiffie) to prevent short timeouts.
|
||||
*/
|
||||
timer->is_rel = mode & HRTIMER_MODE_REL;
|
||||
if (timer->is_rel)
|
||||
tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
|
||||
#endif
|
||||
return tim;
|
||||
}
|
||||
|
||||
/**
|
||||
* hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
|
||||
* @timer: the timer to be added
|
||||
@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
|
||||
/* Remove an active timer from the queue: */
|
||||
remove_hrtimer(timer, base, true);
|
||||
|
||||
if (mode & HRTIMER_MODE_REL) {
|
||||
if (mode & HRTIMER_MODE_REL)
|
||||
tim = ktime_add_safe(tim, base->get_time());
|
||||
/*
|
||||
* CONFIG_TIME_LOW_RES is a temporary way for architectures
|
||||
* to signal that they simply return xtime in
|
||||
* do_gettimeoffset(). In this case we want to round up by
|
||||
* resolution when starting a relative timer, to avoid short
|
||||
* timeouts. This will go away with the GTOD framework.
|
||||
*/
|
||||
#ifdef CONFIG_TIME_LOW_RES
|
||||
tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
|
||||
#endif
|
||||
}
|
||||
|
||||
tim = hrtimer_update_lowres(timer, tim, mode);
|
||||
|
||||
hrtimer_set_expires_range_ns(timer, tim, delta_ns);
|
||||
|
||||
@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
|
||||
/**
|
||||
* hrtimer_get_remaining - get remaining time for the timer
|
||||
* @timer: the timer to read
|
||||
* @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y
|
||||
*/
|
||||
ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
|
||||
ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
|
||||
{
|
||||
unsigned long flags;
|
||||
ktime_t rem;
|
||||
|
||||
lock_hrtimer_base(timer, &flags);
|
||||
rem = hrtimer_expires_remaining(timer);
|
||||
if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust)
|
||||
rem = hrtimer_expires_remaining_adjusted(timer);
|
||||
else
|
||||
rem = hrtimer_expires_remaining(timer);
|
||||
unlock_hrtimer_base(timer, &flags);
|
||||
|
||||
return rem;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
|
||||
EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
|
||||
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
/**
|
||||
@@ -1219,6 +1230,14 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
|
||||
timer_stats_account_hrtimer(timer);
|
||||
fn = timer->function;
|
||||
|
||||
/*
|
||||
* Clear the 'is relative' flag for the TIME_LOW_RES case. If the
|
||||
* timer is restarted with a period then it becomes an absolute
|
||||
* timer. If its not restarted it does not matter.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_TIME_LOW_RES))
|
||||
timer->is_rel = false;
|
||||
|
||||
/*
|
||||
* Because we run timers from hardirq context, there is no chance
|
||||
* they get migrated to another cpu, therefore its safe to unlock
|
||||
|
@@ -26,7 +26,7 @@
|
||||
*/
|
||||
static struct timeval itimer_get_remtime(struct hrtimer *timer)
|
||||
{
|
||||
ktime_t rem = hrtimer_get_remaining(timer);
|
||||
ktime_t rem = __hrtimer_get_remaining(timer, true);
|
||||
|
||||
/*
|
||||
* Racy but safe: if the itimer expires after the above
|
||||
|
@@ -685,8 +685,18 @@ int ntp_validate_timex(struct timex *txc)
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EPERM;
|
||||
|
||||
if (!timeval_inject_offset_valid(&txc->time))
|
||||
return -EINVAL;
|
||||
if (txc->modes & ADJ_NANO) {
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = txc->time.tv_sec;
|
||||
ts.tv_nsec = txc->time.tv_usec;
|
||||
if (!timespec_inject_offset_valid(&ts))
|
||||
return -EINVAL;
|
||||
|
||||
} else {
|
||||
if (!timeval_inject_offset_valid(&txc->time))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
|
||||
(timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
|
||||
timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
|
||||
|
||||
remaining = ktime_sub(hrtimer_get_expires(timer), now);
|
||||
remaining = __hrtimer_expires_remaining_adjusted(timer, now);
|
||||
/* Return 0 only, when the timer is expired and not pending */
|
||||
if (remaining.tv64 <= 0) {
|
||||
/*
|
||||
|
@@ -36,16 +36,17 @@
|
||||
*/
|
||||
static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
|
||||
|
||||
/*
|
||||
* The time, when the last jiffy update happened. Protected by jiffies_lock.
|
||||
*/
|
||||
static ktime_t last_jiffies_update;
|
||||
|
||||
struct tick_sched *tick_get_tick_sched(int cpu)
|
||||
{
|
||||
return &per_cpu(tick_cpu_sched, cpu);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
|
||||
/*
|
||||
* The time, when the last jiffy update happened. Protected by jiffies_lock.
|
||||
*/
|
||||
static ktime_t last_jiffies_update;
|
||||
|
||||
/*
|
||||
* Must be called with interrupts disabled !
|
||||
*/
|
||||
@@ -151,6 +152,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
|
||||
update_process_times(user_mode(regs));
|
||||
profile_tick(CPU_PROFILING);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NO_HZ_FULL
|
||||
cpumask_var_t tick_nohz_full_mask;
|
||||
@@ -993,9 +995,9 @@ static void tick_nohz_switch_to_nohz(void)
|
||||
/* Get the next period */
|
||||
next = tick_init_jiffy_update();
|
||||
|
||||
hrtimer_forward_now(&ts->sched_timer, tick_period);
|
||||
hrtimer_set_expires(&ts->sched_timer, next);
|
||||
tick_program_event(next, 1);
|
||||
hrtimer_forward_now(&ts->sched_timer, tick_period);
|
||||
tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
|
||||
tick_nohz_activate(ts, NOHZ_MODE_LOWRES);
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer,
|
||||
print_name_offset(m, taddr);
|
||||
SEQ_printf(m, ", ");
|
||||
print_name_offset(m, timer->function);
|
||||
SEQ_printf(m, ", S:%02lx", timer->state);
|
||||
SEQ_printf(m, ", S:%02x", timer->state);
|
||||
#ifdef CONFIG_TIMER_STATS
|
||||
SEQ_printf(m, ", ");
|
||||
print_name_offset(m, timer->start_site);
|
||||
|
Reference in New Issue
Block a user