Skip to content

Commit

Permalink
sh: fix xtime_lock deadlocking.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Peter Zijlstra authored and Paul Mundt committed Feb 14, 2008
1 parent 9216f19 commit 960c65e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 18 deletions.
19 changes: 15 additions & 4 deletions arch/sh/kernel/time_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -132,6 +128,16 @@ void handle_timer_tick(void)
sh_mv.mv_heartbeat();
#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
Expand All @@ -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 */

Expand Down
31 changes: 17 additions & 14 deletions arch/sh/kernel/time_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,22 @@ static long last_rtc_update;
static inline void do_timer_interrupt(void)
{
unsigned long long current_ctc;

if (current->pid)
profile_tick(CPU_PROFILING);

/*
* 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_lock(&xtime_lock);
asm ("getcon cr62, %0" : "=r" (current_ctc));
ctc_last_interrupt = (unsigned long) current_ctc;

do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
#endif
if (current->pid)
profile_tick(CPU_PROFILING);

#ifdef CONFIG_HEARTBEAT
if (sh_mv.mv_heartbeat != NULL)
Expand All @@ -259,6 +266,11 @@ static inline void do_timer_interrupt(void)
/* do it again in 60 s */
last_rtc_update = xtime.tv_sec - 600;
}
write_unlock(&xtime_lock);

#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
#endif
}

/*
Expand All @@ -275,16 +287,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
timer_status &= ~0x100;
ctrl_outw(timer_status, TMU0_TCR);

/*
* 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_lock(&xtime_lock);
do_timer_interrupt();
write_unlock(&xtime_lock);

return IRQ_HANDLED;
}
Expand Down

0 comments on commit 960c65e

Please sign in to comment.