From aa02cd2d9bd1e24a230bd66a0a741b984d03915a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 13 Feb 2008 21:33:16 +0100 Subject: xtime_lock vs update_process_times Commit d3d74453c34f8fd87674a8cf5b8a327c68f22e99 ("hrtimer: fixup the HRTIMER_CB_IRQSAFE_NO_SOFTIRQ fallback") broke several archs, and since only Russell bothered to merge the fix, and Greg to ACK his arch, I'm sending this for merger. I have confirmation that the Alpha bit results in a booting kernel. That leaves: blackfin, frv, sh and sparc untested. The deadlock in question was found by Russell: IRQ handle -> timer_tick() - xtime seqlock held for write -> update_process_times() -> run_local_timers() -> hrtimer_run_queues() -> hrtimer_get_softirq_time() - tries to get a read lock Now, Thomas assures me the fix is trivial, only do_timer() needs to be done under the xtime_lock, and update_process_times() can savely be removed from under it. Signed-off-by: Peter Zijlstra Acked-by: Greg Ungerer CC: Richard Henderson CC: Bryan Wu CC: David Howells CC: Paul Mundt CC: William Irwin Acked-by: Ingo Molnar Acked-by: Ivan Kokshaysky Signed-off-by: Linus Torvalds --- arch/sparc/kernel/pcic.c | 2 +- arch/sparc/kernel/time.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 4cd5d7818dc..a6a6f982337 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -713,10 +713,10 @@ static irqreturn_t pcic_timer_handler (int irq, void *h) write_seqlock(&xtime_lock); /* Dummy, to show that we remember */ pcic_clear_clock_irq(); do_timer(1); + write_sequnlock(&xtime_lock); #ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs())); #endif - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 00b393c3a4a..cfaf22c05bc 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -128,10 +128,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) clear_clock_irq(); do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - /* Determine when to update the Mostek clock. */ if (ntp_synced() && @@ -145,6 +141,9 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) } write_sequnlock(&xtime_lock); +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif return IRQ_HANDLED; } -- cgit v1.2.3