Commit b00c1a99e7758f794923c61e5cd55268d61c9469
1 parent
41e1022eae
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 13 additions and 3 deletions Side-by-side Diff
include/linux/hrtimer.h
... | ... | @@ -67,9 +67,10 @@ |
67 | 67 | * 0x02 callback function running |
68 | 68 | * 0x04 callback pending (high resolution mode) |
69 | 69 | * |
70 | - * Special case: | |
70 | + * Special cases: | |
71 | 71 | * 0x03 callback function running and enqueued |
72 | 72 | * (was requeued on another CPU) |
73 | + * 0x09 timer was migrated on CPU hotunplug | |
73 | 74 | * The "callback function running and enqueued" status is only possible on |
74 | 75 | * SMP. It happens for example when a posix timer expired and the callback |
75 | 76 | * queued a signal. Between dropping the lock which protects the posix timer |
... | ... | @@ -87,6 +88,7 @@ |
87 | 88 | #define HRTIMER_STATE_ENQUEUED 0x01 |
88 | 89 | #define HRTIMER_STATE_CALLBACK 0x02 |
89 | 90 | #define HRTIMER_STATE_PENDING 0x04 |
91 | +#define HRTIMER_STATE_MIGRATE 0x08 | |
90 | 92 | |
91 | 93 | /** |
92 | 94 | * struct hrtimer - the basic hrtimer structure |
kernel/hrtimer.c
... | ... | @@ -1602,7 +1602,13 @@ |
1602 | 1602 | timer = rb_entry(node, struct hrtimer, node); |
1603 | 1603 | BUG_ON(hrtimer_callback_running(timer)); |
1604 | 1604 | debug_hrtimer_deactivate(timer); |
1605 | - __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0); | |
1605 | + | |
1606 | + /* | |
1607 | + * Mark it as STATE_MIGRATE not INACTIVE otherwise the | |
1608 | + * timer could be seen as !active and just vanish away | |
1609 | + * under us on another CPU | |
1610 | + */ | |
1611 | + __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0); | |
1606 | 1612 | timer->base = new_base; |
1607 | 1613 | /* |
1608 | 1614 | * Enqueue the timer. Allow reprogramming of the event device |
1609 | 1615 | |
... | ... | @@ -1620,13 +1626,15 @@ |
1620 | 1626 | * state, we need to do that otherwise we end up with |
1621 | 1627 | * a stale timer. |
1622 | 1628 | */ |
1623 | - if (timer->state == HRTIMER_STATE_INACTIVE) { | |
1629 | + if (timer->state == HRTIMER_STATE_MIGRATE) { | |
1624 | 1630 | timer->state = HRTIMER_STATE_PENDING; |
1625 | 1631 | list_add_tail(&timer->cb_entry, |
1626 | 1632 | &new_base->cpu_base->cb_pending); |
1627 | 1633 | raise = 1; |
1628 | 1634 | } |
1629 | 1635 | #endif |
1636 | + /* Clear the migration state bit */ | |
1637 | + timer->state &= ~HRTIMER_STATE_MIGRATE; | |
1630 | 1638 | } |
1631 | 1639 | return raise; |
1632 | 1640 | } |