[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix Xen timer interface to allow migration of timers
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 974ed9f7364198b2f3be194847e3b0538f88d5d8 # Parent b246f429f683cce73bf7486c37bf6842983fa49f Fix Xen timer interface to allow migration of timers among CPUs (using new migrate_timer() call). Fix the locking protocol in light of this addition. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r b246f429f683 -r 974ed9f73641 xen/common/timer.c --- a/xen/common/timer.c Wed Feb 8 16:26:20 2006 +++ b/xen/common/timer.c Wed Feb 8 16:27:32 2006 @@ -161,46 +161,122 @@ cpu_raise_softirq(cpu, TIMER_SOFTIRQ); } +static inline void timer_lock(struct timer *timer) +{ + unsigned int cpu; + + for ( ; ; ) + { + cpu = timer->cpu; + spin_lock(&timers[cpu].lock); + if ( likely(timer->cpu == cpu) ) + break; + spin_unlock(&timers[cpu].lock); + } +} + +#define timer_lock_irq(t) \ + do { local_irq_disable(); timer_lock(t); } while ( 0 ) +#define timer_lock_irqsave(t, flags) \ + do { local_irq_save(flags); timer_lock(t); } while ( 0 ) + +static inline void timer_unlock(struct timer *timer) +{ + spin_unlock(&timers[timer->cpu].lock); +} + +#define timer_unlock_irq(t) \ + do { timer_unlock(t); local_irq_enable(); } while ( 0 ) +#define timer_unlock_irqrestore(t, flags) \ + do { timer_unlock(t); local_irq_restore(flags); } while ( 0 ) + void set_timer(struct timer *timer, s_time_t expires) { - int cpu = timer->cpu; unsigned long flags; - spin_lock_irqsave(&timers[cpu].lock, flags); + timer_lock_irqsave(timer, flags); + if ( active_timer(timer) ) __stop_timer(timer); + timer->expires = expires; + if ( likely(!timer->killed) ) __add_timer(timer); - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); } void stop_timer(struct timer *timer) { - int cpu = timer->cpu; unsigned long flags; - spin_lock_irqsave(&timers[cpu].lock, flags); + timer_lock_irqsave(timer, flags); + if ( active_timer(timer) ) __stop_timer(timer); - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); +} + + +void migrate_timer(struct timer *timer, unsigned int new_cpu) +{ + int old_cpu; + unsigned long flags; + + for ( ; ; ) + { + if ( (old_cpu = timer->cpu) == new_cpu ) + return; + + if ( old_cpu < new_cpu ) + { + spin_lock_irqsave(&timers[old_cpu].lock, flags); + spin_lock(&timers[new_cpu].lock); + } + else + { + spin_lock_irqsave(&timers[new_cpu].lock, flags); + spin_lock(&timers[old_cpu].lock); + } + + if ( likely(timer->cpu == old_cpu) ) + break; + + spin_unlock(&timers[old_cpu].lock); + spin_unlock_irqrestore(&timers[new_cpu].lock, flags); + } + + if ( active_timer(timer) ) + __stop_timer(timer); + + timer->cpu = new_cpu; + + if ( likely(!timer->killed) ) + __add_timer(timer); + + spin_unlock(&timers[old_cpu].lock); + spin_unlock_irqrestore(&timers[new_cpu].lock, flags); } void kill_timer(struct timer *timer) { - int cpu = timer->cpu; + int cpu; unsigned long flags; - BUG_ON(timers[cpu].running == timer); - - spin_lock_irqsave(&timers[cpu].lock, flags); + BUG_ON(timers[smp_processor_id()].running == timer); + + timer_lock_irqsave(timer, flags); + if ( active_timer(timer) ) __stop_timer(timer); timer->killed = 1; - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); for_each_online_cpu ( cpu ) while ( timers[cpu].running == timer ) diff -r b246f429f683 -r 974ed9f73641 xen/include/xen/timer.h --- a/xen/include/xen/timer.h Wed Feb 8 16:26:20 2006 +++ b/xen/include/xen/timer.h Wed Feb 8 16:27:32 2006 @@ -66,6 +66,12 @@ extern void stop_timer(struct timer *timer); /* + * Migrate a timer to a different CPU. The timer must have been previously + * initialised by init_timer(). The timer may be active. + */ +extern void migrate_timer(struct timer *timer, unsigned int new_cpu); + +/* * Deactivate a timer and prevent it from being re-set (future calls to * set_timer will silently fail). When this function returns it is guaranteed * that the timer callback handler is not running on any CPU. _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |