aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/timer.c
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-01-13 01:03:44 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-01-13 01:03:44 +0100
commitcc00657854df4e868598b6447ea5599798604da9 (patch)
tree458e3a04aabf424fed3c7eecdf7980352f030eb1 /xen/common/timer.c
parentc5c75c292628864e2f22c4186f8f16da10fbe6da (diff)
downloadxen-cc00657854df4e868598b6447ea5599798604da9.tar.gz
xen-cc00657854df4e868598b6447ea5599798604da9.tar.bz2
xen-cc00657854df4e868598b6447ea5599798604da9.zip
Add a new timer operation kill_timer(). Effectively the
'opposite' of init_timer(), it marks the end of a timer's lifetime. After this call the timer will not be pending, its callback handler will not be running, and future calls to set_timer() will silently fail. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/common/timer.c')
-rw-r--r--xen/common/timer.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/xen/common/timer.c b/xen/common/timer.c
index 336b0a15d1..55f39bfa98 100644
--- a/xen/common/timer.c
+++ b/xen/common/timer.c
@@ -29,6 +29,7 @@
struct timers {
spinlock_t lock;
struct timer **heap;
+ struct timer *running;
} __cacheline_aligned;
struct timers timers[NR_CPUS];
@@ -167,11 +168,11 @@ void set_timer(struct timer *timer, s_time_t expires)
unsigned long flags;
spin_lock_irqsave(&timers[cpu].lock, flags);
- ASSERT(timer != NULL);
if ( active_timer(timer) )
__stop_timer(timer);
timer->expires = expires;
- __add_timer(timer);
+ if ( likely(!timer->killed) )
+ __add_timer(timer);
spin_unlock_irqrestore(&timers[cpu].lock, flags);
}
@@ -182,13 +183,31 @@ void stop_timer(struct timer *timer)
unsigned long flags;
spin_lock_irqsave(&timers[cpu].lock, flags);
- ASSERT(timer != NULL);
if ( active_timer(timer) )
__stop_timer(timer);
spin_unlock_irqrestore(&timers[cpu].lock, flags);
}
+void kill_timer(struct timer *timer)
+{
+ int cpu = timer->cpu;
+ unsigned long flags;
+
+ BUG_ON(timers[cpu].running == timer);
+
+ spin_lock_irqsave(&timers[cpu].lock, flags);
+ if ( active_timer(timer) )
+ __stop_timer(timer);
+ timer->killed = 1;
+ spin_unlock_irqrestore(&timers[cpu].lock, flags);
+
+ for_each_online_cpu ( cpu )
+ while ( timers[cpu].running == timer )
+ cpu_relax();
+}
+
+
static void timer_softirq_action(void)
{
int cpu = smp_processor_id();
@@ -208,19 +227,20 @@ static void timer_softirq_action(void)
{
remove_entry(heap, t);
+ timers[cpu].running = t;
+
fn = t->function;
data = t->data;
- if ( fn != NULL )
- {
- spin_unlock_irq(&timers[cpu].lock);
- (*fn)(data);
- spin_lock_irq(&timers[cpu].lock);
- }
+ spin_unlock_irq(&timers[cpu].lock);
+ (*fn)(data);
+ spin_lock_irq(&timers[cpu].lock);
/* Heap may have grown while the lock was released. */
heap = timers[cpu].heap;
}
+
+ timers[cpu].running = NULL;
}
while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) );