aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-29 15:44:46 +0200
committerThomas Gleixner <tglx@linutronix.de>2008-09-29 17:09:14 +0200
commitb00c1a99e7758f794923c61e5cd55268d61c9469 (patch)
treeaace17598caf3dfaa01f8f2f4c6e587bb1f9a2f8 /kernel
parenthrtimer: fix migration of CB_IRQSAFE_NO_SOFTIRQ hrtimers (diff)
downloadlinux-dev-b00c1a99e7758f794923c61e5cd55268d61c9469.tar.xz
linux-dev-b00c1a99e7758f794923c61e5cd55268d61c9469.zip
hrtimer: mark migration state
Impact: during migration active hrtimers can be seen as inactive The migration code removes the hrtimers from the queues of the dead CPU and sets the state temporary to INACTIVE. The enqueue code sets it to ACTIVE/PENDING again. Prevent that the wrong state can be seen by using a separate migration state bit. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/hrtimer.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index ac2f6d6d4868..ace723dd1e52 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1602,7 +1602,13 @@ static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
timer = rb_entry(node, struct hrtimer, node);
BUG_ON(hrtimer_callback_running(timer));
debug_hrtimer_deactivate(timer);
- __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
+
+ /*
+ * Mark it as STATE_MIGRATE not INACTIVE otherwise the
+ * timer could be seen as !active and just vanish away
+ * under us on another CPU
+ */
+ __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0);
timer->base = new_base;
/*
* Enqueue the timer. Allow reprogramming of the event device
@@ -1620,13 +1626,15 @@ static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
* state, we need to do that otherwise we end up with
* a stale timer.
*/
- if (timer->state == HRTIMER_STATE_INACTIVE) {
+ if (timer->state == HRTIMER_STATE_MIGRATE) {
timer->state = HRTIMER_STATE_PENDING;
list_add_tail(&timer->cb_entry,
&new_base->cpu_base->cb_pending);
raise = 1;
}
#endif
+ /* Clear the migration state bit */
+ timer->state &= ~HRTIMER_STATE_MIGRATE;
}
return raise;
}