Received: by 10.213.65.68 with SMTP id h4csp566088imn; Tue, 20 Mar 2018 09:46:17 -0700 (PDT) X-Google-Smtp-Source: AG47ELviAZO3NobpSgS2UhArQpTd8tptox+JJ+SogQa2y7ZynbT1lyQ5XhfzaYsSy6Pu0t+2W96O X-Received: by 2002:a17:902:788b:: with SMTP id q11-v6mr17086656pll.234.1521564377355; Tue, 20 Mar 2018 09:46:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521564377; cv=none; d=google.com; s=arc-20160816; b=tOe0D8LzAuDDlIIpeEG5bJPAucyOgz7VK2TKL4y3WQ9wayGWwViKetL5dvMt/BzT3y dRIm2IxcXjJO2KsiV5HlwuLRpOL60SdR3ZzH/eBOVVMUQNmxKOmF6aD5tyNESh+Z6bvg 3/DhMZYnGNYIUPcmL+DTOSExa4mZ46l5SSxwq9IMkiZYyBYmyCkBNh4rwmNtwRk1kA7g jIW2KP7d5w94T5NVS1GkQXs4GcmKW+uJxkM1b+YUNPMQcxI2399nhr7nr8gatH9uEze8 zIQoSu6zVr4ut3BIo1R87CDU5HXifoL+mHC+pQJmUNpWgaAsQ8QtNUID4GJMRhgCPtfC bOqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=hSBXB8nq19rCJAooBqk9RDB9nfKcbguH5hv+c3NeXbM=; b=HSU7kpeht6gdd46m2ir2mHILcx/NA6Yy/QUbRMGaboDOmqSJTRHPjOmbD86pHufYrL PK1i9F+sKSxyX64a53XuUnUzwxsHeZiNIb2BjDukrw9uxBN6qNE1HCAIA9P4dX1H1bAX IaS6EKS5vB9NQaJTiMCAx2sFMdtWC4al5/aqQLsewcHEuBmVP44rHlb63y9Si4h0ngYu 1p69vETeTaN2lQ8CaqqKJDftcwOSX2oJMr/9u2Bvutd/0nBIWckynOXwlCHKDLTBxoHz fHbN/7NoMgLr63IaPf9SGQ/KhUrSHCWu6o6y57qVSdLKdc5N/fhFw6nppy5DOqgY62IE hR/Q== 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 t74si1434797pgc.38.2018.03.20.09.46.03; Tue, 20 Mar 2018 09:46:17 -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 S1751456AbeCTQoD (ORCPT + 99 others); Tue, 20 Mar 2018 12:44:03 -0400 Received: from cloudserver094114.home.pl ([79.96.170.134]:54568 "EHLO cloudserver094114.home.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751757AbeCTQnr (ORCPT ); Tue, 20 Mar 2018 12:43:47 -0400 Received: from 79.184.254.228.ipv4.supernova.orange.pl (79.184.254.228) (HELO aspire.rjw.lan) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83) id 8651bd8a4c850f84; Tue, 20 Mar 2018 17:43:45 +0100 From: "Rafael J. Wysocki" To: Peter Zijlstra , Linux PM Cc: Frederic Weisbecker , Thomas Gleixner , Paul McKenney , Thomas Ilsche , Doug Smythies , Rik van Riel , Aubrey Li , Mike Galbraith , LKML Subject: [RFT][PATCH v7 1/8] time: tick-sched: Reorganize idle tick management code Date: Tue, 20 Mar 2018 16:13:36 +0100 Message-ID: <2756593.6znKTA0Udp@aspire.rjw.lan> In-Reply-To: <2390019.oHdSGtR3EE@aspire.rjw.lan> References: <2390019.oHdSGtR3EE@aspire.rjw.lan> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rafael J. Wysocki Prepare the scheduler tick code for reworking the idle loop to avoid stopping the tick in some cases. The idea is to split the nohz idle entry call to decouple the idle time stats accounting and preparatory work from the actual tick stop code, in order to later be able to delay the tick stop once we reach more power-knowledgeable callers. Move away the tick_nohz_start_idle() invocation from __tick_nohz_idle_enter(), rename the latter to __tick_nohz_idle_stop_tick() and define tick_nohz_idle_stop_tick() as a wrapper around it for calling it from the outside. Make tick_nohz_idle_enter() only call tick_nohz_start_idle() instead of calling the entire __tick_nohz_idle_enter(), add another wrapper disabling and enabling interrupts around tick_nohz_idle_stop_tick() and make the current callers of tick_nohz_idle_enter() call it too to retain their current functionality. Signed-off-by: Rafael J. Wysocki --- arch/x86/xen/smp_pv.c | 1 + include/linux/tick.h | 12 ++++++++++++ kernel/sched/idle.c | 1 + kernel/time/tick-sched.c | 46 +++++++++++++++++++++++++--------------------- 4 files changed, 39 insertions(+), 21 deletions(-) Index: linux-pm/include/linux/tick.h =================================================================== --- linux-pm.orig/include/linux/tick.h +++ linux-pm/include/linux/tick.h @@ -114,6 +114,7 @@ enum tick_dep_bits { #ifdef CONFIG_NO_HZ_COMMON extern bool tick_nohz_enabled; extern int tick_nohz_tick_stopped(void); +extern void tick_nohz_idle_stop_tick(void); extern void tick_nohz_idle_enter(void); extern void tick_nohz_idle_exit(void); extern void tick_nohz_irq_exit(void); @@ -122,9 +123,18 @@ extern unsigned long tick_nohz_get_idle_ extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu); extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time); + +static inline void tick_nohz_idle_stop_tick_protected(void) +{ + local_irq_disable(); + tick_nohz_idle_stop_tick(); + local_irq_enable(); +} + #else /* !CONFIG_NO_HZ_COMMON */ #define tick_nohz_enabled (0) static inline int tick_nohz_tick_stopped(void) { return 0; } +static inline void tick_nohz_idle_stop_tick(void) { } static inline void tick_nohz_idle_enter(void) { } static inline void tick_nohz_idle_exit(void) { } @@ -134,6 +144,8 @@ static inline ktime_t tick_nohz_get_slee } static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; } + +static inline void tick_nohz_idle_stop_tick_protected(void) { } #endif /* !CONFIG_NO_HZ_COMMON */ #ifdef CONFIG_NO_HZ_FULL Index: linux-pm/kernel/time/tick-sched.c =================================================================== --- linux-pm.orig/kernel/time/tick-sched.c +++ linux-pm/kernel/time/tick-sched.c @@ -539,14 +539,11 @@ static void tick_nohz_stop_idle(struct t sched_clock_idle_wakeup_event(); } -static ktime_t tick_nohz_start_idle(struct tick_sched *ts) +static void tick_nohz_start_idle(struct tick_sched *ts) { - ktime_t now = ktime_get(); - - ts->idle_entrytime = now; + ts->idle_entrytime = ktime_get(); ts->idle_active = 1; sched_clock_idle_sleep_event(); - return now; } /** @@ -911,19 +908,21 @@ static bool can_stop_idle_tick(int cpu, return true; } -static void __tick_nohz_idle_enter(struct tick_sched *ts) +static void __tick_nohz_idle_stop_tick(struct tick_sched *ts) { - ktime_t now, expires; + ktime_t expires; int cpu = smp_processor_id(); - now = tick_nohz_start_idle(ts); - if (can_stop_idle_tick(cpu, ts)) { int was_stopped = ts->tick_stopped; ts->idle_calls++; - expires = tick_nohz_stop_sched_tick(ts, now, cpu); + /* + * The idle entry time should be a sufficient approximation of + * the current time at this point. + */ + expires = tick_nohz_stop_sched_tick(ts, ts->idle_entrytime, cpu); if (expires > 0LL) { ts->idle_sleeps++; ts->idle_expires = expires; @@ -937,16 +936,19 @@ static void __tick_nohz_idle_enter(struc } /** - * tick_nohz_idle_enter - stop the idle tick from the idle task + * tick_nohz_idle_stop_tick - stop the idle tick from the idle task * * When the next event is more than a tick into the future, stop the idle tick - * Called when we start the idle loop. - * - * The arch is responsible of calling: + */ +void tick_nohz_idle_stop_tick(void) +{ + __tick_nohz_idle_stop_tick(this_cpu_ptr(&tick_cpu_sched)); +} + +/** + * tick_nohz_idle_enter - prepare for entering idle on the current CPU * - * - rcu_idle_enter() after its last use of RCU before the CPU is put - * to sleep. - * - rcu_idle_exit() before the first use of RCU after the CPU is woken up. + * Called when we start the idle loop. */ void tick_nohz_idle_enter(void) { @@ -965,7 +967,7 @@ void tick_nohz_idle_enter(void) ts = this_cpu_ptr(&tick_cpu_sched); ts->inidle = 1; - __tick_nohz_idle_enter(ts); + tick_nohz_start_idle(ts); local_irq_enable(); } @@ -982,10 +984,12 @@ void tick_nohz_irq_exit(void) { struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); - if (ts->inidle) - __tick_nohz_idle_enter(ts); - else + if (ts->inidle) { + tick_nohz_start_idle(ts); + __tick_nohz_idle_stop_tick(ts); + } else { tick_nohz_full_update_tick(ts); + } } /** Index: linux-pm/arch/x86/xen/smp_pv.c =================================================================== --- linux-pm.orig/arch/x86/xen/smp_pv.c +++ linux-pm/arch/x86/xen/smp_pv.c @@ -425,6 +425,7 @@ static void xen_pv_play_dead(void) /* us * data back is to call: */ tick_nohz_idle_enter(); + tick_nohz_idle_stop_tick_protected(); cpuhp_online_idle(CPUHP_AP_ONLINE_IDLE); } Index: linux-pm/kernel/sched/idle.c =================================================================== --- linux-pm.orig/kernel/sched/idle.c +++ linux-pm/kernel/sched/idle.c @@ -221,6 +221,7 @@ static void do_idle(void) __current_set_polling(); tick_nohz_idle_enter(); + tick_nohz_idle_stop_tick_protected(); while (!need_resched()) { check_pgt_cache();