From patchwork Thu Mar 20 13:48:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 26706 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f198.google.com (mail-ob0-f198.google.com [209.85.214.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id CABDF202E0 for ; Thu, 20 Mar 2014 13:49:38 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wn1sf3376852obc.9 for ; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:in-reply-to:references :sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=1HTbD4dyvqtD5E/IKsUEFsCpzHcQOguIZosoUxHzkAw=; b=VIBWYZ63vBbil5261n4U13+DVg5DNunsJkO3Y8nlvOJq1y1Z/BIspj2/N/eOaJsCrw oto577oeYXmRgctu41Eur0v6Mmh+MecwDW59lhbr5GVCAbpsBW1w7hMthpa1wE2B0XIB PG/YpaHWe3zZ11SwQhMXvLOPxgDK491FbclgQ8o17pjytKM/6yLtLWbAl1J0AZvV+12c ORXyirb/OKTxgnUtWnXcMfkuN+yWf2UV8vChpxw0l4JhepbTF8GdMjvXyqT+YHAp+O4s VYTetpq7+4t5F/w5lfcIndD+Qc48HIna13ASERpC78o7754NaQYnTYuttODF2gfpL2vW IOQA== X-Gm-Message-State: ALoCoQmZu83LWGhmbo6d86YuMNXrBY10ikD00LD5bqxErJhpjic2dtcvJnFo3Mj7asvT3IUXLwfU X-Received: by 10.182.87.2 with SMTP id t2mr15887411obz.2.1395323378258; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.16.165 with SMTP id 34ls240192qgb.30.gmail; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) X-Received: by 10.58.34.101 with SMTP id y5mr34004167vei.8.1395323378172; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) Received: from mail-ve0-f171.google.com (mail-ve0-f171.google.com [209.85.128.171]) by mx.google.com with ESMTPS id bf4si439047vec.100.2014.03.20.06.49.38 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 20 Mar 2014 06:49:38 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.171; Received: by mail-ve0-f171.google.com with SMTP id cz12so948971veb.2 for ; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) X-Received: by 10.58.220.161 with SMTP id px1mr34528433vec.13.1395323378077; Thu, 20 Mar 2014 06:49:38 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.78.9 with SMTP id i9csp389575vck; Thu, 20 Mar 2014 06:49:37 -0700 (PDT) X-Received: by 10.67.22.100 with SMTP id hr4mr47355020pad.112.1395323377043; Thu, 20 Mar 2014 06:49:37 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e2si1539930pba.44.2014.03.20.06.49.36; Thu, 20 Mar 2014 06:49:36 -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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758920AbaCTNt1 (ORCPT + 26 others); Thu, 20 Mar 2014 09:49:27 -0400 Received: from mail-pd0-f179.google.com ([209.85.192.179]:49058 "EHLO mail-pd0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757116AbaCTNtW (ORCPT ); Thu, 20 Mar 2014 09:49:22 -0400 Received: by mail-pd0-f179.google.com with SMTP id w10so948312pde.38 for ; Thu, 20 Mar 2014 06:49:21 -0700 (PDT) X-Received: by 10.66.66.135 with SMTP id f7mr47289586pat.22.1395323361550; Thu, 20 Mar 2014 06:49:21 -0700 (PDT) Received: from localhost ([122.172.246.56]) by mx.google.com with ESMTPSA id ac5sm4050988pbc.37.2014.03.20.06.49.17 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 20 Mar 2014 06:49:20 -0700 (PDT) From: Viresh Kumar To: tglx@linutronix.de, fweisbec@gmail.com, peterz@infradead.org, mingo@kernel.org, tj@kernel.org, lizefan@huawei.com Cc: linaro-kernel@lists.linaro.org, linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, Viresh Kumar Subject: [RFC 1/4] timer: track pinned timers with TIMER_PINNED flag Date: Thu, 20 Mar 2014 19:18:58 +0530 Message-Id: X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: viresh.kumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , In order to quiesce a CPU on which Isolation might be required, we need to move away all the timers queued on that CPU. There are two types of timers queued on any CPU: ones that are pinned to that CPU and others can run on any CPU but are queued on CPU in question. And we need to migrate only the second type of timers away from the CPU entering quiesce state. For this we need some basic infrastructure in timer core to identify which timers are pinned and which are not. Hence, this patch adds another flag bit TIMER_PINNED which will be set only for the timers which are pinned to a CPU. It also removes 'pinned' parameter of __mod_timer() as it is no more required. NOTE: One functional change worth mentioning Existing Behavior: add_timer_on() followed by multiple mod_timer() wouldn't pin the timer on CPU mentioned in add_timer_on().. New Behavior: add_timer_on() followed by multiple mod_timer() would pin the timer on CPU running mod_timer(). I didn't gave much attention to this as we should call mod_timer_on() for the timers queued with add_timer_on(). Though if required we can simply clear the TIMER_PINNED flag in mod_timer(). Signed-off-by: Viresh Kumar --- include/linux/timer.h | 10 ++++++---- kernel/timer.c | 27 ++++++++++++++++++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/linux/timer.h b/include/linux/timer.h index 8c5a197..2962403 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -49,7 +49,7 @@ extern struct tvec_base boot_tvec_bases; #endif /* - * Note that all tvec_bases are at least 4 byte aligned and lower two bits + * Note that all tvec_bases are at least 8 byte aligned and lower three bits * of base in timer_list is guaranteed to be zero. Use them for flags. * * A deferrable timer will work normally when the system is busy, but @@ -61,14 +61,18 @@ extern struct tvec_base boot_tvec_bases; * the completion of the running instance from IRQ handlers, for example, * by calling del_timer_sync(). * + * A pinned timer is allowed to run only on the cpu mentioned and shouldn't be + * migrated to any other CPU. + * * Note: The irq disabled callback execution is a special case for * workqueue locking issues. It's not meant for executing random crap * with interrupts disabled. Abuse is monitored! */ #define TIMER_DEFERRABLE 0x1LU #define TIMER_IRQSAFE 0x2LU +#define TIMER_PINNED 0x4LU -#define TIMER_FLAG_MASK 0x3LU +#define TIMER_FLAG_MASK 0x7LU #define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \ .entry = { .prev = TIMER_ENTRY_STATIC }, \ @@ -179,8 +183,6 @@ extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires); extern void set_timer_slack(struct timer_list *time, int slack_hz); -#define TIMER_NOT_PINNED 0 -#define TIMER_PINNED 1 /* * The jiffies value which is added to now, when there is no timer * in the timer wheel: diff --git a/kernel/timer.c b/kernel/timer.c index 87bd529..fec4ab4 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -104,6 +104,11 @@ static inline unsigned int tbase_get_irqsafe(struct tvec_base *base) return ((unsigned int)(unsigned long)base & TIMER_IRQSAFE); } +static inline unsigned int tbase_get_pinned(struct tvec_base *base) +{ + return ((unsigned int)(unsigned long)base & TIMER_PINNED); +} + static inline struct tvec_base *tbase_get_base(struct tvec_base *base) { return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK)); @@ -117,6 +122,13 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base) timer->base = (struct tvec_base *)((unsigned long)(new_base) | flags); } +static inline void +timer_set_flags(struct timer_list *timer, unsigned int flags) +{ + timer->base = (struct tvec_base *)((unsigned long)(timer->base) | + flags); +} + static unsigned long round_jiffies_common(unsigned long j, int cpu, bool force_up) { @@ -742,8 +754,7 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer, } static inline int -__mod_timer(struct timer_list *timer, unsigned long expires, - bool pending_only, int pinned) +__mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) { struct tvec_base *base, *new_base; unsigned long flags; @@ -760,7 +771,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, debug_activate(timer, expires); - cpu = get_nohz_timer_target(pinned); + cpu = get_nohz_timer_target(!!tbase_get_pinned(timer->base)); new_base = per_cpu(tvec_bases, cpu); if (base != new_base) { @@ -802,7 +813,7 @@ out_unlock: */ int mod_timer_pending(struct timer_list *timer, unsigned long expires) { - return __mod_timer(timer, expires, true, TIMER_NOT_PINNED); + return __mod_timer(timer, expires, true); } EXPORT_SYMBOL(mod_timer_pending); @@ -877,7 +888,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires) if (timer_pending(timer) && timer->expires == expires) return 1; - return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); + return __mod_timer(timer, expires, false); } EXPORT_SYMBOL(mod_timer); @@ -905,7 +916,8 @@ int mod_timer_pinned(struct timer_list *timer, unsigned long expires) if (timer->expires == expires && timer_pending(timer)) return 1; - return __mod_timer(timer, expires, false, TIMER_PINNED); + timer_set_flags(timer, TIMER_PINNED); + return __mod_timer(timer, expires, false); } EXPORT_SYMBOL(mod_timer_pinned); @@ -944,6 +956,7 @@ void add_timer_on(struct timer_list *timer, int cpu) timer_stats_timer_set_start_info(timer); BUG_ON(timer_pending(timer) || !timer->function); + timer_set_flags(timer, TIMER_PINNED); spin_lock_irqsave(&base->lock, flags); timer_set_base(timer, base); debug_activate(timer, timer->expires); @@ -1493,7 +1506,7 @@ signed long __sched schedule_timeout(signed long timeout) expire = timeout + jiffies; setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); - __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); + __mod_timer(&timer, expire, false); schedule(); del_singleshot_timer_sync(&timer);