diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 41 | 
1 files changed, 21 insertions, 20 deletions
| diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index fd4b13b131f..383319bae3f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -47,6 +47,7 @@  #include <linux/sched/sysctl.h>  #include <linux/sched/rt.h>  #include <linux/timer.h> +#include <linux/freezer.h>  #include <asm/uaccess.h> @@ -721,17 +722,20 @@ static int hrtimer_switch_to_hres(void)  	return 1;  } +static void clock_was_set_work(struct work_struct *work) +{ +	clock_was_set(); +} + +static DECLARE_WORK(hrtimer_work, clock_was_set_work); +  /* - * Called from timekeeping code to reprogramm the hrtimer interrupt - * device. If called from the timer interrupt context we defer it to - * softirq context. + * Called from timekeeping and resume code to reprogramm the hrtimer + * interrupt device on all cpus.   */  void clock_was_set_delayed(void)  { -	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - -	cpu_base->clock_was_set = 1; -	__raise_softirq_irqoff(HRTIMER_SOFTIRQ); +	schedule_work(&hrtimer_work);  }  #else @@ -773,15 +777,19 @@ void clock_was_set(void)  /*   * During resume we might have to reprogram the high resolution timer - * interrupt (on the local CPU): + * interrupt on all online CPUs.  However, all other CPUs will be + * stopped with IRQs interrupts disabled so the clock_was_set() call + * must be deferred.   */  void hrtimers_resume(void)  {  	WARN_ONCE(!irqs_disabled(),  		  KERN_INFO "hrtimers_resume() called with IRQs enabled!"); +	/* Retrigger on the local CPU */  	retrigger_next_event(NULL); -	timerfd_clock_was_set(); +	/* And schedule a retrigger for all others */ +	clock_was_set_delayed();  }  static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) @@ -1432,13 +1440,6 @@ void hrtimer_peek_ahead_timers(void)  static void run_hrtimer_softirq(struct softirq_action *h)  { -	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - -	if (cpu_base->clock_was_set) { -		cpu_base->clock_was_set = 0; -		clock_was_set(); -	} -  	hrtimer_peek_ahead_timers();  } @@ -1545,7 +1546,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod  			t->task = NULL;  		if (likely(t->task)) -			schedule(); +			freezable_schedule();  		hrtimer_cancel(&t->timer);  		mode = HRTIMER_MODE_ABS; @@ -1658,7 +1659,7 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,  /*   * Functions related to boot-time initialization:   */ -static void __cpuinit init_hrtimers_cpu(int cpu) +static void init_hrtimers_cpu(int cpu)  {  	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);  	int i; @@ -1739,7 +1740,7 @@ static void migrate_hrtimers(int scpu)  #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, +static int hrtimer_cpu_notify(struct notifier_block *self,  					unsigned long action, void *hcpu)  {  	int scpu = (long)hcpu; @@ -1772,7 +1773,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,  	return NOTIFY_OK;  } -static struct notifier_block __cpuinitdata hrtimers_nb = { +static struct notifier_block hrtimers_nb = {  	.notifier_call = hrtimer_cpu_notify,  }; | 
