summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/time.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2005-11-07 00:59:02 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 07:53:32 -0800
commit1b44e98d7d0754bbcf0222baf179f5e2e3dbea7b (patch)
treec4e69506205a175fa9675e5dcec1ad4944c4b87a /arch/s390/kernel/time.c
parente1c3ad96f662bf1071a71feffadfe0f7604f14e2 (diff)
downloadlwn-1b44e98d7d0754bbcf0222baf179f5e2e3dbea7b.tar.gz
lwn-1b44e98d7d0754bbcf0222baf179f5e2e3dbea7b.zip
[PATCH] s390: stop_hz_timer vs. xtime updates
The calculation of the value return by next_timer_interrupt from jiffies to jiffies_64 is racy against xtime updates. We need to protect the calculation with read_seqbegin/read_seqretry. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/s390/kernel/time.c')
-rw-r--r--arch/s390/kernel/time.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9a1d95894f3d..c36353e8c140 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -237,6 +237,8 @@ int sysctl_hz_timer = 1;
*/
static inline void stop_hz_timer(void)
{
+ unsigned long flags;
+ unsigned long seq, next;
__u64 timer, todval;
if (sysctl_hz_timer != 0)
@@ -257,7 +259,11 @@ static inline void stop_hz_timer(void)
* This cpu is going really idle. Set up the clock comparator
* for the next event.
*/
- timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
+ next = next_timer_interrupt();
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ timer = (__u64)(next - jiffies) + jiffies_64;
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
todval = -1ULL;
/* Be careful about overflows. */
if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {