Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 960c65e8 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Paul Mundt
Browse files

sh: fix xtime_lock deadlocking.



move update_process_times() out from under xtime_lock.

Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 9216f194
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -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);

@@ -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
@@ -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 */

+17 −14
Original line number Diff line number Diff line
@@ -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)
@@ -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
}

/*
@@ -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;
}