Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751586AbdG0PTF (ORCPT ); Thu, 27 Jul 2017 11:19:05 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:55074 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750981AbdG0PTE (ORCPT ); Thu, 27 Jul 2017 11:19:04 -0400 Date: Thu, 27 Jul 2017 17:19:01 +0200 (CEST) From: Thomas Gleixner To: Will Deacon cc: qiaozhou , John Stultz , sboyd@codeaurora.org, LKML , Wang Wilbur , Marc Zyngier , Peter Zijlstra Subject: Re: [Question]: try to fix contention between expire_timers and try_to_del_timer_sync In-Reply-To: <20170727151400.GE20746@arm.com> Message-ID: References: <3d2459c7-defd-a47e-6cea-007c10cecaac@asrmicro.com> <20170727151400.GE20746@arm.com> User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 Content-Type: multipart/mixed; BOUNDARY="8323329-1842306044-1501168741=:1813" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2078 Lines: 57 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --8323329-1842306044-1501168741=:1813 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8BIT On Thu, 27 Jul 2017, Will Deacon wrote: > On Thu, Jul 27, 2017 at 09:29:20AM +0800, qiaozhou wrote: > > On 2017年07月26日 22:16, Thomas Gleixner wrote: > > >--- a/kernel/time/timer.c > > >+++ b/kernel/time/timer.c > > >@@ -1301,10 +1301,12 @@ static void expire_timers(struct timer_b > > > if (timer->flags & TIMER_IRQSAFE) { > > > raw_spin_unlock(&base->lock); > > > call_timer_fn(timer, fn, data); > > >+ base->running_timer = NULL; > > > raw_spin_lock(&base->lock); > > > } else { > > > raw_spin_unlock_irq(&base->lock); > > > call_timer_fn(timer, fn, data); > > >+ base->running_timer = NULL; > > > raw_spin_lock_irq(&base->lock); > > > } > > > } > > It should work for this particular issue and I'll test it. Previously I > > thought it was unsafe to touch base->running_timer without holding lock. > > I think it works out in practice because base->lock and base->running_timer > share a cacheline, so end up being ordered correctly. We should probably be > using READ_ONCE/WRITE_ONCE for accessing the running_time field though. > > One thing I don't get though, is why try_to_del_timer_sync needs to check > base->running_timer at all. Given that it holds the base->lock, can't it > be the person that sets it to NULL? No. The timer callback code does: base->running_timer = timer; spin_unlock(base->lock); fn(timer); spin_lock(base->lock); base->running_timer = NULL; So for del_timer_sync() the only way to figure out whether the timer callback is running is to check base->running_timer. We cannot store state in the timer itself because we cannot clear that state when the callback return as the timer might have been freed in the callback. Yes, that's nasty, but reality. Thanks, tglx --8323329-1842306044-1501168741=:1813--