summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2003-08-14 11:26:03 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-08-14 11:26:03 -0700
commitd563c54ed534eb37283c397a6a4146996c83b350 (patch)
treea0b3cd57d970a7e43abb6cf207cbea8386f5218d /kernel
parent00ed8a2c5e66ab1e6339f59b290d3e3f370b76cb (diff)
[PATCH] More timer race fixes
Patch from Julie DeWandel. This patch has solved the crashes observed during TPC-C runs on the 16-way box. (I'm confident it will fix the other reported cases as well.) The race is the setting of timer->base to NULL, by del_timer() or __run_timers(). If new_base == old_base in __mod_timer() then we do not re-check timer->base after getting the lock. (the only case where we do not have to re-check the base is in the !old_base case, but the else branch also includes the old_base==new_base case.) The __run_timers() case made the lock_timer() patch not work fully - we cannot use lock_timer() in __run_timers() due to lock ordering.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/timer.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index 81bb979fb7e7..ab083d12eb3a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -179,8 +179,13 @@ repeat:
spin_unlock(&old_base->lock);
goto repeat;
}
- } else
+ } else {
spin_lock(&new_base->lock);
+ if (timer->base != old_base) {
+ spin_unlock(&new_base->lock);
+ goto repeat;
+ }
+ }
/*
* Delete the previous timeout (if there was any), and install