diff options
Diffstat (limited to 'kernel/timer.c')
| -rw-r--r-- | kernel/timer.c | 54 | 
1 files changed, 45 insertions, 9 deletions
| diff --git a/kernel/timer.c b/kernel/timer.c index ee305c8d4e1..97bf05baade 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -90,8 +90,13 @@ 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 for - * the new flag to indicate whether the timer is deferrable + * 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) @@ -321,6 +326,7 @@ EXPORT_SYMBOL_GPL(round_jiffies_up_relative);  /**   * set_timer_slack - set the allowed slack for a timer + * @timer: the timer to be modified   * @slack_hz: the amount of time (in jiffies) allowed for rounding   *   * Set the amount of time, in jiffies, that a certain timer has @@ -577,6 +583,19 @@ static void __init_timer(struct timer_list *timer,  	lockdep_init_map(&timer->lockdep_map, name, key, 0);  } +void setup_deferrable_timer_on_stack_key(struct timer_list *timer, +					 const char *name, +					 struct lock_class_key *key, +					 void (*function)(unsigned long), +					 unsigned long data) +{ +	timer->function = function; +	timer->data = data; +	init_timer_on_stack_key(timer, name, key); +	timer_set_deferrable(timer); +} +EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key); +  /**   * init_timer_key - initialize a timer   * @timer: the timer to be initialized @@ -679,12 +698,8 @@ __mod_timer(struct timer_list *timer, unsigned long expires,  	cpu = smp_processor_id();  #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) -	if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) { -		int preferred_cpu = get_nohz_load_balancer(); - -		if (preferred_cpu >= 0) -			cpu = preferred_cpu; -	} +	if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) +		cpu = get_nohz_timer_target();  #endif  	new_base = per_cpu(tvec_bases, cpu); @@ -1289,7 +1304,6 @@ void run_local_timers(void)  {  	hrtimer_run_queues();  	raise_softirq(TIMER_SOFTIRQ); -	softlockup_tick();  }  /* @@ -1750,3 +1764,25 @@ unsigned long msleep_interruptible(unsigned int msecs)  }  EXPORT_SYMBOL(msleep_interruptible); + +static int __sched do_usleep_range(unsigned long min, unsigned long max) +{ +	ktime_t kmin; +	unsigned long delta; + +	kmin = ktime_set(0, min * NSEC_PER_USEC); +	delta = (max - min) * NSEC_PER_USEC; +	return schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL); +} + +/** + * usleep_range - Drop in replacement for udelay where wakeup is flexible + * @min: Minimum time in usecs to sleep + * @max: Maximum time in usecs to sleep + */ +void usleep_range(unsigned long min, unsigned long max) +{ +	__set_current_state(TASK_UNINTERRUPTIBLE); +	do_usleep_range(min, max); +} +EXPORT_SYMBOL(usleep_range); | 
