Commit b00c1a99e7758f794923c61e5cd55268d61c9469

Authored by Thomas Gleixner
1 parent 41e1022eae

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
... ... @@ -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 }