Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1845924imm; Thu, 2 Aug 2018 01:54:27 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfXjefbDmsZkL3nWPxfkQu1uil7s0uWasMPpWvkA1AtNK3Xn0Koma7E5+D1kgsIU6cW7xSI X-Received: by 2002:a62:8d16:: with SMTP id z22-v6mr1989075pfd.181.1533200067594; Thu, 02 Aug 2018 01:54:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533200067; cv=none; d=google.com; s=arc-20160816; b=guHIkziVfFZp3+Fu+skFwuq2oJkIcbFQBdHyzpQcu5rNbASE+qL12JK2JuqWAuHSBg 3I64zfEMZbtgMB7tM4xJ3tt4sbt0A70rULB7PumKlVXUFMfywjbwcc8wWiGeMAXk3SuS 10jyFc8UWOb6NUfAeHuvvzcPWR4cxjT8A3qq335GbtHxz8SzO74P8YUdX0XG9dfCknzr D3ZD+C//IjOJiT481/rvzohHYDWllxwG0AaybOWjK6e9AbQIAADHrqCXYj2Oh5BHZ4/Z sWOfniwm9AbHVjkpIfYb36p5WQT5GKl2V+L0jspPysACKs48sIRUBA23GzzOFBFAyxAR s4nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=gXxhL4Ym+i3GSjZ//joHjTTaQTWRyelc4W5uwK6AUjI=; b=UcNjsGICW3d3HGerONkGjRAjDSMKUM7QiOqF34Lg+1ovZ1HmcUlXmYzQAPq6XQ2dZS xn1ygfhLA02mbcb6q0xQBzByadQwVfjgOibeOcAdyxP+8nbMXRnhwsD3WhmEv6cHEN3K jgMFMaGPHgx2Z7RMJ710Tl6xygs6C9vnGBSudx8pZ3m+461ANWIZ41Y/fENcmL5hRraq CZIJEq2afzGMjdZXm9RJKwLRKoeDfFuFfwc/ihl8Hux8aDpIBIbpDhDAJvwSAVqDvkfh fU6uU3/2agZKWHvhzEJJKI0RCd0teGw5AwQPxawTlerslOokjuPpVlKnyuE7jsG2C7cI 5Nqg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u9-v6si1549143pfg.62.2018.08.02.01.54.13; Thu, 02 Aug 2018 01:54:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727517AbeHBKm6 (ORCPT + 99 others); Thu, 2 Aug 2018 06:42:58 -0400 Received: from alexa-out-blr-02.qualcomm.com ([103.229.18.198]:53049 "EHLO alexa-out-blr.qualcomm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726702AbeHBKm6 (ORCPT ); Thu, 2 Aug 2018 06:42:58 -0400 X-IronPort-AV: E=Sophos;i="5.51,434,1526322600"; d="scan'208";a="120563" Received: from ironmsg01-blr.qualcomm.com ([10.86.208.130]) by alexa-out-blr.qualcomm.com with ESMTP/TLS/AES256-SHA; 02 Aug 2018 14:21:12 +0530 X-IronPort-AV: E=McAfee;i="5900,7806,8972"; a="834704" Received: from gkohli-linux.qualcomm.com ([10.204.78.26]) by ironmsg01-blr.qualcomm.com with ESMTP; 02 Aug 2018 14:21:12 +0530 Received: by gkohli-linux.qualcomm.com (Postfix, from userid 427023) id CA7CC303D; Thu, 2 Aug 2018 14:21:10 +0530 (IST) From: Gaurav Kohli To: tglx@linutronix.de, john.stultz@linaro.org, sboyd@kernel.org Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Gaurav Kohli Subject: [PATCH v3] timers: Clear must_forward_clk inside base lock Date: Thu, 2 Aug 2018 14:21:03 +0530 Message-Id: <1533199863-22748-1-git-send-email-gkohli@codeaurora.org> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Timer wheel base->must_forward_clock is indicating that the base clock might be stale due to a long idle sleep. The forwarding of the base clock takes place in the timer softirq or when a timer is enqueued to a base which is idle. If the enqueue of timer to an idle base happens from a remote CPU, then the following race can happen: CPU0 CPU1 run_timer_softirq mod_timer base = lock_timer_base(timer); base->must_forward_clk = false if (base->must_forward_clk) forward(base); >>skip enqueue_timer(base, timer, idx); >> idx is calculated high due to >> stale base unlock_timer_base(timer); base = lock_timer_base(timer); forward(base); The root cause is that base->must_forward_clk is cleared outside the base->lock held region, so the remote queuing CPU observes it as cleared, but the base clock is still stale. This can cause large granularity values for timers, i.e. the accuracy of the expiry time suffers. Prevent this by clearing the flag with base->lock held, so that the forwarding takes place before the cleared flag is observable by a remote CPU. Signed-off-by: Gaurav Kohli --- Changes since v2: - Updated commit suggested by Thomas. diff --git a/kernel/time/timer.c b/kernel/time/timer.c index cc2d23e..8f61d45 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1657,6 +1657,22 @@ static inline void __run_timers(struct timer_base *base) raw_spin_lock_irq(&base->lock); + /* + * Timer wheel base must_forward_clk must be cleared before running + * timers so that any timer functions that call mod_timer will not + * try to forward the base. idle tracking / clock forwarding logic + * is only used with BASE_STD timers. + * + * The must_forward_clk flag is cleared unconditionally also for + * the deferrable base. The deferrable base is not affected by idle + * tracking and never forwarded, so clearing the flag is a NOOP. + * + * The fact that the deferrable base is never forwarded can cause + * large variations in granularity for deferrable timers, but they + * can be deferred for long periods due to idle anyway. + */ + base->must_forward_clk = false; + while (time_after_eq(jiffies, base->clk)) { levels = collect_expired_timers(base, heads); @@ -1676,19 +1692,6 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h) { struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); - /* - * must_forward_clk must be cleared before running timers so that any - * timer functions that call mod_timer will not try to forward the - * base. idle trcking / clock forwarding logic is only used with - * BASE_STD timers. - * - * The deferrable base does not do idle tracking at all, so we do - * not forward it. This can result in very large variations in - * granularity for deferrable timers, but they can be deferred for - * long periods due to idle. - */ - base->must_forward_clk = false; - __run_timers(base); if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) __run_timers(this_cpu_ptr(&timer_bases[BASE_DEF])); -- 1.9.1