diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2008-02-07 07:01:26 +0100 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-02-14 06:22:08 +0100 |
commit | 960c65e88452e761e257c6a20062c91c3e7fa5ac (patch) | |
tree | 75c2be5c6b87c685ae85c70dbeebc2b30a07256f /arch/sh/kernel/time_32.c | |
parent | sh: Add mach-type entries for MigoR and SDK7780. (diff) | |
download | linux-960c65e88452e761e257c6a20062c91c3e7fa5ac.tar.xz linux-960c65e88452e761e257c6a20062c91c3e7fa5ac.zip |
sh: fix xtime_lock deadlocking.
move update_process_times() out from under xtime_lock.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/time_32.c')
-rw-r--r-- | arch/sh/kernel/time_32.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 2bc04bfee738..7281342c044d 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -120,10 +120,6 @@ static long last_rtc_update; */ void handle_timer_tick(void) { - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif if (current->pid) profile_tick(CPU_PROFILING); @@ -133,6 +129,16 @@ void handle_timer_tick(void) #endif /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + do_timer(1); + + /* * If we have an externally synchronized Linux clock, then update * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. @@ -147,6 +153,11 @@ void handle_timer_tick(void) /* do it again in 60s */ last_rtc_update = xtime.tv_sec - 600; } + write_sequnlock(&xtime_lock); + +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif } #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ |