Merge branch 'timers-for-linus-migration' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-for-linus-migration' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: timers: Logic to move non pinned timers timers: /proc/sys sysctl hook to enable timer migration timers: Identifying the existing pinned timers timers: Framework for identifying pinned timers timers: allow deferrable timers for intervals tv2-tv5 to be deferred Fix up conflicts in kernel/sched.c and kernel/timer.c manually
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include <linux/tick.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/perf_counter.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
@@ -605,13 +606,12 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
|
||||
}
|
||||
|
||||
static inline int
|
||||
__mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
|
||||
__mod_timer(struct timer_list *timer, unsigned long expires,
|
||||
bool pending_only, int pinned)
|
||||
{
|
||||
struct tvec_base *base, *new_base;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
int ret = 0 , cpu;
|
||||
|
||||
timer_stats_timer_set_start_info(timer);
|
||||
BUG_ON(!timer->function);
|
||||
@@ -630,6 +630,18 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
|
||||
|
||||
new_base = __get_cpu_var(tvec_bases);
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
new_base = per_cpu(tvec_bases, cpu);
|
||||
|
||||
if (base != new_base) {
|
||||
/*
|
||||
* We are trying to schedule the timer on the local CPU.
|
||||
@@ -669,7 +681,7 @@ out_unlock:
|
||||
*/
|
||||
int mod_timer_pending(struct timer_list *timer, unsigned long expires)
|
||||
{
|
||||
return __mod_timer(timer, expires, true);
|
||||
return __mod_timer(timer, expires, true, TIMER_NOT_PINNED);
|
||||
}
|
||||
EXPORT_SYMBOL(mod_timer_pending);
|
||||
|
||||
@@ -703,10 +715,32 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
|
||||
if (timer->expires == expires && timer_pending(timer))
|
||||
return 1;
|
||||
|
||||
return __mod_timer(timer, expires, false);
|
||||
return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
|
||||
}
|
||||
EXPORT_SYMBOL(mod_timer);
|
||||
|
||||
/**
|
||||
* mod_timer_pinned - modify a timer's timeout
|
||||
* @timer: the timer to be modified
|
||||
* @expires: new timeout in jiffies
|
||||
*
|
||||
* mod_timer_pinned() is a way to update the expire field of an
|
||||
* active timer (if the timer is inactive it will be activated)
|
||||
* and not allow the timer to be migrated to a different CPU.
|
||||
*
|
||||
* mod_timer_pinned(timer, expires) is equivalent to:
|
||||
*
|
||||
* del_timer(timer); timer->expires = expires; add_timer(timer);
|
||||
*/
|
||||
int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
|
||||
{
|
||||
if (timer->expires == expires && timer_pending(timer))
|
||||
return 1;
|
||||
|
||||
return __mod_timer(timer, expires, false, TIMER_PINNED);
|
||||
}
|
||||
EXPORT_SYMBOL(mod_timer_pinned);
|
||||
|
||||
/**
|
||||
* add_timer - start a timer
|
||||
* @timer: the timer to be added
|
||||
@@ -1017,6 +1051,9 @@ cascade:
|
||||
index = slot = timer_jiffies & TVN_MASK;
|
||||
do {
|
||||
list_for_each_entry(nte, varp->vec + slot, entry) {
|
||||
if (tbase_get_deferrable(nte->base))
|
||||
continue;
|
||||
|
||||
found = 1;
|
||||
if (time_before(nte->expires, expires))
|
||||
expires = nte->expires;
|
||||
@@ -1307,7 +1344,7 @@ signed long __sched schedule_timeout(signed long timeout)
|
||||
expire = timeout + jiffies;
|
||||
|
||||
setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
|
||||
__mod_timer(&timer, expire, false);
|
||||
__mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
|
||||
schedule();
|
||||
del_singleshot_timer_sync(&timer);
|
||||
|
||||
|
Reference in New Issue
Block a user