From patchwork Tue Nov 6 10:38:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 12675 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D7DE21987CF for ; Tue, 6 Nov 2012 10:39:06 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id 8765FA19396 for ; Tue, 6 Nov 2012 10:39:06 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so313696iej.11 for ; Tue, 06 Nov 2012 02:39:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references:in-reply-to :references:x-originalarrivaltime:x-mc-unique:content-type :content-transfer-encoding:x-gm-message-state; bh=UBkLxr33pX4K/f1IG90V2cTxECBoTJX0sCXo2V5Wx20=; b=nFOpbNGgDLHaegjCSwJ//IzWOYggkpbtFNvd4h2al+r0XqsG+JoHudBHSrTMgIvaXP /8N7AUWuizJSpi9FjgZI2PwJWED/Re1J9co9n4aENqBi5EHxAMMkwZeZphtZiN0Y2nmH 32PSU3K/yzM5lDama9KHVF5CDTUfp8KDg20z7C0bJh2LAsv/FdhBMM6JTm/ufc7oPIfm aQtAB9JQxKBjOQcafu77OBNzL+pP315hDwHUvuy6/M5fJwq/0YtZNIn0Tw2knjw/MJAj MMwOfsMThIP2b9L7ZsAdbDzM7D6DvOYHek6IKXX3XuIgx0tPwDxMp9YCmBP/YxthOK7X MYDQ== Received: by 10.42.203.146 with SMTP id fi18mr434587icb.18.1352198346338; Tue, 06 Nov 2012 02:39:06 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp15156igt; Tue, 6 Nov 2012 02:39:05 -0800 (PST) Received: by 10.180.94.169 with SMTP id dd9mr16816384wib.14.1352198344886; Tue, 06 Nov 2012 02:39:04 -0800 (PST) Received: from service87.mimecast.com (service87.mimecast.com. [91.220.42.44]) by mx.google.com with ESMTP id n17si2823401wen.38.2012.11.06.02.39.04; Tue, 06 Nov 2012 02:39:04 -0800 (PST) Received-SPF: pass (google.com: domain of viresh.kumar2@arm.com designates 91.220.42.44 as permitted sender) client-ip=91.220.42.44; Authentication-Results: mx.google.com; spf=pass (google.com: domain of viresh.kumar2@arm.com designates 91.220.42.44 as permitted sender) smtp.mail=viresh.kumar2@arm.com Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Tue, 06 Nov 2012 10:38:56 +0000 Received: from localhost ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Tue, 6 Nov 2012 10:38:52 +0000 From: Viresh Kumar To: pjt@google.com, paul.mckenney@linaro.org, tglx@linutronix.de, tj@kernel.org, suresh.b.siddha@intel.com, venki@google.com, mingo@redhat.com, peterz@infradead.org, rostedt@goodmis.org Cc: Arvind.Chauhan@arm.com, linaro-dev@lists.linaro.org, patches@linaro.org, pdsw-power-team@arm.com, linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org, Viresh Kumar Subject: [PATCH V2 Resend 1/4] sched: Create sched_select_cpu() to give preferred CPU for power saving Date: Tue, 6 Nov 2012 16:08:43 +0530 Message-Id: <351f8e3a6e9d78f584dc10d9e0ecc1505f73f7d9.1352196505.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: References: In-Reply-To: References: X-OriginalArrivalTime: 06 Nov 2012 10:38:53.0124 (UTC) FILETIME=[EA5C8840:01CDBC0A] X-MC-Unique: 112110610385602601 X-Gm-Message-State: ALoCoQlM4tEuHKtUH5CpqlAHBLLPHwGfhfAHueU61SS3Tx6ga9m54tFZXsXQwPxFFNgbPBNsYO6Q In order to save power, it would be useful to schedule work onto non-IDLE cpus instead of waking up an IDLE one. To achieve this, we need scheduler to guide kernel frameworks (like: timers & workqueues) on which is the most preferred CPU that must be used for these tasks. This routine returns the preferred cpu which is non-idle. It accepts a bitwise OR of SD_* flags present in linux/sched.h. If the local CPU isn't idle, it is returned back. If it is idle, then we must look for another CPU which have all the flags passed as argument as set. Also, as this activity is part of load balancing only, SD_LOAD_BALANCE must also be set for selected domain. This patch reuses the code from get_nohz_timer_target() routine, which had similar implementation. get_nohz_timer_target() is also modified to use sched_select_cpu() now. Signed-off-by: Viresh Kumar --- include/linux/sched.h | 16 ++++++++++-- kernel/sched/core.c | 69 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 0dd42a0..24f546d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -232,14 +232,26 @@ extern void init_idle_bootup_task(struct task_struct *idle); extern int runqueue_is_locked(int cpu); -#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) +#ifdef CONFIG_SMP +extern int sched_select_cpu(unsigned int sd_flags); + +#ifdef CONFIG_NO_HZ extern void nohz_balance_enter_idle(int cpu); extern void set_cpu_sd_state_idle(void); -extern int get_nohz_timer_target(void); +/* + * In the semi idle case, use the nearest busy cpu for migrating timers + * from an idle cpu. This is good for power-savings. + * + * We don't do similar optimization for completely idle system, as + * selecting an idle cpu will add more delays to the timers than intended + * (as that cpu's timer base may not be uptodate wrt jiffies etc). + */ +#define get_nohz_timer_target() sched_select_cpu(0) #else static inline void nohz_balance_enter_idle(int cpu) { } static inline void set_cpu_sd_state_idle(void) { } #endif +#endif /* CONFIG_SMP */ /* * Only dump TASK_* tasks. (0 for all tasks) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2d8927f..cf1a420 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -542,33 +542,6 @@ void resched_cpu(int cpu) #ifdef CONFIG_NO_HZ /* - * In the semi idle case, use the nearest busy cpu for migrating timers - * from an idle cpu. This is good for power-savings. - * - * We don't do similar optimization for completely idle system, as - * selecting an idle cpu will add more delays to the timers than intended - * (as that cpu's timer base may not be uptodate wrt jiffies etc). - */ -int get_nohz_timer_target(void) -{ - int cpu = smp_processor_id(); - int i; - struct sched_domain *sd; - - rcu_read_lock(); - for_each_domain(cpu, sd) { - for_each_cpu(i, sched_domain_span(sd)) { - if (!idle_cpu(i)) { - cpu = i; - goto unlock; - } - } - } -unlock: - rcu_read_unlock(); - return cpu; -} -/* * When add_timer_on() enqueues a timer into the timer wheel of an * idle CPU then this timer might expire before the next timer event * which is scheduled to wake up that CPU. In case of a completely @@ -639,6 +612,48 @@ void sched_avg_update(struct rq *rq) } } +/* + * This routine returns the preferred cpu which is non-idle. It accepts a + * bitwise OR of SD_* flags present in linux/sched.h. If the local CPU isn't + * idle, it is returned back. If it is idle, then we must look for another CPU + * which have all the flags passed as argument as set. Also, as this activity is + * part of load balancing only, SD_LOAD_BALANCE must also be set for selected + * domain. + */ +int sched_select_cpu(unsigned int sd_flags) +{ + struct sched_domain *sd; + int cpu = smp_processor_id(); + int i; + + /* If Current cpu isn't idle, don't migrate anything */ + if (!idle_cpu(cpu)) + return cpu; + + /* Add SD_LOAD_BALANCE to flags */ + sd_flags |= SD_LOAD_BALANCE; + + rcu_read_lock(); + for_each_domain(cpu, sd) { + /* + * If sd doesnt' have both sd_flags and SD_LOAD_BALANCE set, + * skip sd. + */ + if ((sd->flags & sd_flags) != sd_flags) + continue; + + for_each_cpu(i, sched_domain_span(sd)) { + if (!idle_cpu(i)) { + cpu = i; + goto unlock; + } + } + } +unlock: + rcu_read_unlock(); + return cpu; +} + #else /* !CONFIG_SMP */ void resched_task(struct task_struct *p) {