diff options
Diffstat (limited to 'kernel/timer.c')
| -rw-r--r-- | kernel/timer.c | 50 | 
1 files changed, 14 insertions, 36 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 353b9227c2e..43ca9936f2d 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -88,18 +88,6 @@ struct tvec_base boot_tvec_bases;  EXPORT_SYMBOL(boot_tvec_bases);  static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases; -/* - * Note that all tvec_bases are 2 byte aligned and lower bit of - * base in timer_list is guaranteed to be zero. Use the LSB to - * indicate whether the timer is deferrable. - * - * A deferrable timer will work normally when the system is busy, but - * will not cause a CPU to come out of idle just to service it; instead, - * the timer will be serviced when the CPU eventually wakes up with a - * subsequent non-deferrable timer. - */ -#define TBASE_DEFERRABLE_FLAG		(0x1) -  /* Functions below help us manage 'deferrable' flag */  static inline unsigned int tbase_get_deferrable(struct tvec_base *base)  { @@ -113,8 +101,7 @@ static inline struct tvec_base *tbase_get_base(struct tvec_base *base)  static inline void timer_set_deferrable(struct timer_list *timer)  { -	timer->base = ((struct tvec_base *)((unsigned long)(timer->base) | -				       TBASE_DEFERRABLE_FLAG)); +	timer->base = TBASE_MAKE_DEFERRED(timer->base);  }  static inline void @@ -343,15 +330,6 @@ void set_timer_slack(struct timer_list *timer, int slack_hz)  }  EXPORT_SYMBOL_GPL(set_timer_slack); - -static inline void set_running_timer(struct tvec_base *base, -					struct timer_list *timer) -{ -#ifdef CONFIG_SMP -	base->running_timer = timer; -#endif -} -  static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)  {  	unsigned long expires = timer->expires; @@ -936,15 +914,12 @@ int del_timer(struct timer_list *timer)  }  EXPORT_SYMBOL(del_timer); -#ifdef CONFIG_SMP  /**   * try_to_del_timer_sync - Try to deactivate a timer   * @timer: timer do del   *   * This function tries to deactivate a timer. Upon successful (ret >= 0)   * exit the timer is not queued and the handler is not running on any CPU. - * - * It must not be called from interrupt contexts.   */  int try_to_del_timer_sync(struct timer_list *timer)  { @@ -973,6 +948,7 @@ out:  }  EXPORT_SYMBOL(try_to_del_timer_sync); +#ifdef CONFIG_SMP  /**   * del_timer_sync - deactivate a timer and wait for the handler to finish.   * @timer: the timer to be deactivated @@ -983,7 +959,7 @@ EXPORT_SYMBOL(try_to_del_timer_sync);   *   * Synchronization rules: Callers must prevent restarting of the timer,   * otherwise this function is meaningless. It must not be called from - * interrupt contexts. The caller must not hold locks which would prevent + * hardirq contexts. The caller must not hold locks which would prevent   * completion of the timer's handler. The timer's handler must not call   * add_timer_on(). Upon exit the timer is not queued and the handler is   * not running on any CPU. @@ -993,14 +969,16 @@ EXPORT_SYMBOL(try_to_del_timer_sync);  int del_timer_sync(struct timer_list *timer)  {  #ifdef CONFIG_LOCKDEP -	unsigned long flags; - -	local_irq_save(flags); +	local_bh_disable();  	lock_map_acquire(&timer->lockdep_map);  	lock_map_release(&timer->lockdep_map); -	local_irq_restore(flags); +	local_bh_enable();  #endif - +	/* +	 * don't use it in hardirq context, because it +	 * could lead to deadlock. +	 */ +	WARN_ON(in_irq());  	for (;;) {  		int ret = try_to_del_timer_sync(timer);  		if (ret >= 0) @@ -1111,7 +1089,7 @@ static inline void __run_timers(struct tvec_base *base)  			timer_stats_account_timer(timer); -			set_running_timer(base, timer); +			base->running_timer = timer;  			detach_timer(timer, 1);  			spin_unlock_irq(&base->lock); @@ -1119,7 +1097,7 @@ static inline void __run_timers(struct tvec_base *base)  			spin_lock_irq(&base->lock);  		}  	} -	set_running_timer(base, NULL); +	base->running_timer = NULL;  	spin_unlock_irq(&base->lock);  } @@ -1249,7 +1227,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,   */  unsigned long get_next_timer_interrupt(unsigned long now)  { -	struct tvec_base *base = __get_cpu_var(tvec_bases); +	struct tvec_base *base = __this_cpu_read(tvec_bases);  	unsigned long expires;  	/* @@ -1298,7 +1276,7 @@ void update_process_times(int user_tick)   */  static void run_timer_softirq(struct softirq_action *h)  { -	struct tvec_base *base = __get_cpu_var(tvec_bases); +	struct tvec_base *base = __this_cpu_read(tvec_bases);  	hrtimer_run_pending();  |