Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S937355AbdLSDYP (ORCPT ); Mon, 18 Dec 2017 22:24:15 -0500 Received: from mail.kernel.org ([198.145.29.99]:50556 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934808AbdLSDYK (ORCPT ); Mon, 18 Dec 2017 22:24:10 -0500 DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D34C9218B1 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=frederic@kernel.org From: Frederic Weisbecker To: LKML Cc: Frederic Weisbecker , Peter Zijlstra , Chris Metcalf , Thomas Gleixner , Luiz Capitulino , Christoph Lameter , "Paul E . McKenney" , Ingo Molnar , Wanpeng Li , Mike Galbraith , Rik van Riel Subject: [PATCH 1/5] sched: Move tick code to a separate file Date: Tue, 19 Dec 2017 04:23:54 +0100 Message-Id: <1513653838-31314-2-git-send-email-frederic@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513653838-31314-1-git-send-email-frederic@kernel.org> References: <1513653838-31314-1-git-send-email-frederic@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10827 Lines: 446 Let's debloat some more core.c Also we are going to expand the tick code even further to introduce scheduler tick offloading. Signed-off-by: Frederic Weisbecker Cc: Chris Metcalf Cc: Christoph Lameter Cc: Luiz Capitulino Cc: Mike Galbraith Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Cc: Wanpeng Li Cc: Ingo Molnar --- kernel/sched/Makefile | 2 +- kernel/sched/core.c | 182 -------------------------------------------------- kernel/sched/sched.h | 7 +- kernel/sched/tick.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 184 deletions(-) create mode 100644 kernel/sched/tick.c diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index e2f9d4f..dd0b01e 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -16,7 +16,7 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer endif -obj-y += core.o loadavg.o clock.o cputime.o +obj-y += core.o loadavg.o clock.o cputime.o tick.o obj-y += idle_task.o fair.o rt.o deadline.o obj-y += wait.o wait_bit.o swait.o completion.o idle.o obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o topology.o stop_task.o diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 644fa2e..06af4fa 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -233,129 +233,6 @@ void update_rq_clock(struct rq *rq) update_rq_clock_task(rq, delta); } - -#ifdef CONFIG_SCHED_HRTICK -/* - * Use HR-timers to deliver accurate preemption points. - */ - -static void hrtick_clear(struct rq *rq) -{ - if (hrtimer_active(&rq->hrtick_timer)) - hrtimer_cancel(&rq->hrtick_timer); -} - -/* - * High-resolution timer tick. - * Runs from hardirq context with interrupts disabled. - */ -static enum hrtimer_restart hrtick(struct hrtimer *timer) -{ - struct rq *rq = container_of(timer, struct rq, hrtick_timer); - struct rq_flags rf; - - WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); - - rq_lock(rq, &rf); - update_rq_clock(rq); - rq->curr->sched_class->task_tick(rq, rq->curr, 1); - rq_unlock(rq, &rf); - - return HRTIMER_NORESTART; -} - -#ifdef CONFIG_SMP - -static void __hrtick_restart(struct rq *rq) -{ - struct hrtimer *timer = &rq->hrtick_timer; - - hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); -} - -/* - * called from hardirq (IPI) context - */ -static void __hrtick_start(void *arg) -{ - struct rq *rq = arg; - struct rq_flags rf; - - rq_lock(rq, &rf); - __hrtick_restart(rq); - rq->hrtick_csd_pending = 0; - rq_unlock(rq, &rf); -} - -/* - * Called to set the hrtick timer state. - * - * called with rq->lock held and irqs disabled - */ -void hrtick_start(struct rq *rq, u64 delay) -{ - struct hrtimer *timer = &rq->hrtick_timer; - ktime_t time; - s64 delta; - - /* - * Don't schedule slices shorter than 10000ns, that just - * doesn't make sense and can cause timer DoS. - */ - delta = max_t(s64, delay, 10000LL); - time = ktime_add_ns(timer->base->get_time(), delta); - - hrtimer_set_expires(timer, time); - - if (rq == this_rq()) { - __hrtick_restart(rq); - } else if (!rq->hrtick_csd_pending) { - smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd); - rq->hrtick_csd_pending = 1; - } -} - -#else -/* - * Called to set the hrtick timer state. - * - * called with rq->lock held and irqs disabled - */ -void hrtick_start(struct rq *rq, u64 delay) -{ - /* - * Don't schedule slices shorter than 10000ns, that just - * doesn't make sense. Rely on vruntime for fairness. - */ - delay = max_t(u64, delay, 10000LL); - hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), - HRTIMER_MODE_REL_PINNED); -} -#endif /* CONFIG_SMP */ - -static void init_rq_hrtick(struct rq *rq) -{ -#ifdef CONFIG_SMP - rq->hrtick_csd_pending = 0; - - rq->hrtick_csd.flags = 0; - rq->hrtick_csd.func = __hrtick_start; - rq->hrtick_csd.info = rq; -#endif - - hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - rq->hrtick_timer.function = hrtick; -} -#else /* CONFIG_SCHED_HRTICK */ -static inline void hrtick_clear(struct rq *rq) -{ -} - -static inline void init_rq_hrtick(struct rq *rq) -{ -} -#endif /* CONFIG_SCHED_HRTICK */ - /* * cmpxchg based fetch_or, macro so it works for different integer types */ @@ -3005,65 +2882,6 @@ unsigned long long task_sched_runtime(struct task_struct *p) return ns; } -/* - * This function gets called by the timer code, with HZ frequency. - * We call it with interrupts disabled. - */ -void scheduler_tick(void) -{ - int cpu = smp_processor_id(); - struct rq *rq = cpu_rq(cpu); - struct task_struct *curr = rq->curr; - struct rq_flags rf; - - sched_clock_tick(); - - rq_lock(rq, &rf); - - update_rq_clock(rq); - curr->sched_class->task_tick(rq, curr, 0); - cpu_load_update_active(rq); - calc_global_load_tick(rq); - - rq_unlock(rq, &rf); - - perf_event_task_tick(); - -#ifdef CONFIG_SMP - rq->idle_balance = idle_cpu(cpu); - trigger_load_balance(rq); -#endif - rq_last_tick_reset(rq); -} - -#ifdef CONFIG_NO_HZ_FULL -/** - * scheduler_tick_max_deferment - * - * Keep at least one tick per second when a single - * active task is running because the scheduler doesn't - * yet completely support full dynticks environment. - * - * This makes sure that uptime, CFS vruntime, load - * balancing, etc... continue to move forward, even - * with a very low granularity. - * - * Return: Maximum deferment in nanoseconds. - */ -u64 scheduler_tick_max_deferment(void) -{ - struct rq *rq = this_rq(); - unsigned long next, now = READ_ONCE(jiffies); - - next = rq->last_sched_tick + HZ; - - if (time_before_eq(next, now)) - return 0; - - return jiffies_to_nsecs(next - now); -} -#endif - #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ defined(CONFIG_PREEMPT_TRACER)) /* diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index b19552a2..43f065e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1676,7 +1676,9 @@ static inline int hrtick_enabled(struct rq *rq) return hrtimer_is_hres_active(&rq->hrtick_timer); } -void hrtick_start(struct rq *rq, u64 delay); +extern void hrtick_start(struct rq *rq, u64 delay); +extern void hrtick_clear(struct rq *rq); +extern void init_rq_hrtick(struct rq *rq); #else @@ -1685,6 +1687,9 @@ static inline int hrtick_enabled(struct rq *rq) return 0; } +static inline void hrtick_clear(struct rq *rq) { } +static inline void init_rq_hrtick(struct rq *rq) { } + #endif /* CONFIG_SCHED_HRTICK */ #ifdef CONFIG_SMP diff --git a/kernel/sched/tick.c b/kernel/sched/tick.c new file mode 100644 index 0000000..bcc6d7d --- /dev/null +++ b/kernel/sched/tick.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include "sched.h" + +/* + * This function gets called by the timer code, with HZ frequency. + * We call it with interrupts disabled. + */ +void scheduler_tick(void) +{ + int cpu = smp_processor_id(); + struct rq *rq = cpu_rq(cpu); + struct task_struct *curr = rq->curr; + struct rq_flags rf; + + sched_clock_tick(); + + rq_lock(rq, &rf); + + update_rq_clock(rq); + curr->sched_class->task_tick(rq, curr, 0); + cpu_load_update_active(rq); + calc_global_load_tick(rq); + + rq_unlock(rq, &rf); + + perf_event_task_tick(); + +#ifdef CONFIG_SMP + rq->idle_balance = idle_cpu(cpu); + trigger_load_balance(rq); +#endif + rq_last_tick_reset(rq); +} + +#ifdef CONFIG_NO_HZ_FULL +/** + * scheduler_tick_max_deferment + * + * Keep at least one tick per second when a single + * active task is running because the scheduler doesn't + * yet completely support full dynticks environment. + * + * This makes sure that uptime, CFS vruntime, load + * balancing, etc... continue to move forward, even + * with a very low granularity. + * + * Return: Maximum deferment in nanoseconds. + */ +u64 scheduler_tick_max_deferment(void) +{ + struct rq *rq = this_rq(); + unsigned long next, now = READ_ONCE(jiffies); + + next = rq->last_sched_tick + HZ; + + if (time_before_eq(next, now)) + return 0; + + return jiffies_to_nsecs(next - now); +} +#endif + +#ifdef CONFIG_SCHED_HRTICK +/* + * Use HR-timers to deliver accurate preemption points. + */ + +void hrtick_clear(struct rq *rq) +{ + if (hrtimer_active(&rq->hrtick_timer)) + hrtimer_cancel(&rq->hrtick_timer); +} + +/* + * High-resolution timer tick. + * Runs from hardirq context with interrupts disabled. + */ +static enum hrtimer_restart hrtick(struct hrtimer *timer) +{ + struct rq *rq = container_of(timer, struct rq, hrtick_timer); + struct rq_flags rf; + + WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); + + rq_lock(rq, &rf); + update_rq_clock(rq); + rq->curr->sched_class->task_tick(rq, rq->curr, 1); + rq_unlock(rq, &rf); + + return HRTIMER_NORESTART; +} + +#ifdef CONFIG_SMP + +static void __hrtick_restart(struct rq *rq) +{ + struct hrtimer *timer = &rq->hrtick_timer; + + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); +} + +/* + * called from hardirq (IPI) context + */ +static void __hrtick_start(void *arg) +{ + struct rq *rq = arg; + struct rq_flags rf; + + rq_lock(rq, &rf); + __hrtick_restart(rq); + rq->hrtick_csd_pending = 0; + rq_unlock(rq, &rf); +} + +/* + * Called to set the hrtick timer state. + * + * called with rq->lock held and irqs disabled + */ +void hrtick_start(struct rq *rq, u64 delay) +{ + struct hrtimer *timer = &rq->hrtick_timer; + ktime_t time; + s64 delta; + + /* + * Don't schedule slices shorter than 10000ns, that just + * doesn't make sense and can cause timer DoS. + */ + delta = max_t(s64, delay, 10000LL); + time = ktime_add_ns(timer->base->get_time(), delta); + + hrtimer_set_expires(timer, time); + + if (rq == this_rq()) { + __hrtick_restart(rq); + } else if (!rq->hrtick_csd_pending) { + smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd); + rq->hrtick_csd_pending = 1; + } +} + +#else +/* + * Called to set the hrtick timer state. + * + * called with rq->lock held and irqs disabled + */ +void hrtick_start(struct rq *rq, u64 delay) +{ + /* + * Don't schedule slices shorter than 10000ns, that just + * doesn't make sense. Rely on vruntime for fairness. + */ + delay = max_t(u64, delay, 10000LL); + hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), + HRTIMER_MODE_REL_PINNED); +} +#endif /* CONFIG_SMP */ + +void init_rq_hrtick(struct rq *rq) +{ +#ifdef CONFIG_SMP + rq->hrtick_csd_pending = 0; + + rq->hrtick_csd.flags = 0; + rq->hrtick_csd.func = __hrtick_start; + rq->hrtick_csd.info = rq; +#endif + + hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rq->hrtick_timer.function = hrtick; +} +#endif /* CONFIG_SCHED_HRTICK */ -- 2.7.4