diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-08-28 22:25:24 +0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-08-28 22:25:24 +0400 |
commit | 7285dd7fd375763bfb8ab1ac9cf3f1206f503c16 (patch) | |
tree | 42f809ab3616cc3d93d655acccfc2d54e9f6d0e4 /include/linux/clocksource.h | |
parent | 90cba64a5f672a239f43ec5cb9a11b806887331e (diff) | |
download | linux-7285dd7fd375763bfb8ab1ac9cf3f1206f503c16.tar.xz |
clocksource: Resolve cpu hotplug dead lock with TSC unstable
Martin Schwidefsky analyzed it:
To register a clocksource the clocksource_mutex is acquired and if
necessary timekeeping_notify is called to install the clocksource as
the timekeeper clock. timekeeping_notify uses stop_machine which needs
to take cpu_add_remove_lock mutex.
Starting a new cpu is done with the cpu_add_remove_lock mutex held.
native_cpu_up checks the tsc of the new cpu and if the tsc is no good
clocksource_change_rating is called. Which needs the clocksource_mutex
and the deadlock is complete.
The solution is to replace the TSC via the clocksource watchdog
mechanism. Mark the TSC as unstable and schedule the watchdog work so
it gets removed in the watchdog thread context.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: John Stultz <johnstul@us.ibm.com>
Diffstat (limited to 'include/linux/clocksource.h')
-rw-r--r-- | include/linux/clocksource.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 9ea40ff26f0e..83d2fbd81b93 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -277,6 +277,7 @@ extern struct clocksource* clocksource_get_next(void); extern void clocksource_change_rating(struct clocksource *cs, int rating); extern void clocksource_resume(void); extern struct clocksource * __init __weak clocksource_default_clock(void); +extern void clocksource_mark_unstable(struct clocksource *cs); #ifdef CONFIG_GENERIC_TIME_VSYSCALL extern void update_vsyscall(struct timespec *ts, struct clocksource *c); |