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 | |
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')
-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 b8e4dce80a7..580bc66ae13 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 | ||