diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2008-09-29 08:06:45 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-09-29 11:09:13 -0400 |
| commit | 7659e349672bb0d378ef8d7d62bae4c53d2bdd18 (patch) | |
| tree | d1cf1862c214dc9eb93b46cbc3d123a465ce7b4f /kernel/hrtimer.c | |
| parent | 6ef190cc92e33565accff6a320f0e7d90480bfe7 (diff) | |
hrtimer: migrate pending list on cpu offline
Impact: hrtimers which are on the pending list are not migrated at cpu
offline and can be stale forever
Add the pending list migration when CONFIG_HIGH_RES_TIMERS is enabled
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index b8e4dce80a74..580bc66ae136 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -1610,10 +1610,36 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, | |||
| 1610 | } | 1610 | } |
| 1611 | } | 1611 | } |
| 1612 | 1612 | ||
| 1613 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
| 1614 | static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, | ||
| 1615 | struct hrtimer_cpu_base *new_base) | ||
| 1616 | { | ||
| 1617 | struct hrtimer *timer; | ||
| 1618 | int raise = 0; | ||
| 1619 | |||
| 1620 | while (!list_empty(&old_base->cb_pending)) { | ||
| 1621 | timer = list_entry(old_base->cb_pending.next, | ||
| 1622 | struct hrtimer, cb_entry); | ||
| 1623 | |||
| 1624 | __remove_hrtimer(timer, timer->base, HRTIMER_STATE_PENDING, 0); | ||
| 1625 | timer->base = &new_base->clock_base[timer->base->index]; | ||
| 1626 | list_add_tail(&timer->cb_entry, &new_base->cb_pending); | ||
| 1627 | raise = 1; | ||
| 1628 | } | ||
| 1629 | return raise; | ||
| 1630 | } | ||
| 1631 | #else | ||
| 1632 | static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, | ||
| 1633 | struct hrtimer_cpu_base *new_base) | ||
| 1634 | { | ||
| 1635 | return 0; | ||
| 1636 | } | ||
| 1637 | #endif | ||
| 1638 | |||
| 1613 | static void migrate_hrtimers(int cpu) | 1639 | static void migrate_hrtimers(int cpu) |
| 1614 | { | 1640 | { |
| 1615 | struct hrtimer_cpu_base *old_base, *new_base; | 1641 | struct hrtimer_cpu_base *old_base, *new_base; |
| 1616 | int i; | 1642 | int i, raise = 0; |
| 1617 | 1643 | ||
| 1618 | BUG_ON(cpu_online(cpu)); | 1644 | BUG_ON(cpu_online(cpu)); |
| 1619 | old_base = &per_cpu(hrtimer_bases, cpu); | 1645 | old_base = &per_cpu(hrtimer_bases, cpu); |
| @@ -1630,10 +1656,16 @@ static void migrate_hrtimers(int cpu) | |||
| 1630 | &new_base->clock_base[i]); | 1656 | &new_base->clock_base[i]); |
| 1631 | } | 1657 | } |
| 1632 | 1658 | ||
| 1659 | if (migrate_hrtimer_pending(old_base, new_base)) | ||
| 1660 | raise = 1; | ||
| 1661 | |||
| 1633 | spin_unlock(&old_base->lock); | 1662 | spin_unlock(&old_base->lock); |
| 1634 | spin_unlock(&new_base->lock); | 1663 | spin_unlock(&new_base->lock); |
| 1635 | local_irq_enable(); | 1664 | local_irq_enable(); |
| 1636 | put_cpu_var(hrtimer_bases); | 1665 | put_cpu_var(hrtimer_bases); |
| 1666 | |||
| 1667 | if (raise) | ||
| 1668 | hrtimer_raise_softirq(); | ||
| 1637 | } | 1669 | } |
| 1638 | #endif /* CONFIG_HOTPLUG_CPU */ | 1670 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 1639 | 1671 | ||
