From bb48b716f4965d8a3ac8d8f5ff95205bd1188e4f Mon Sep 17 00:00:00 2001 From: Yihao Wu Date: Thu, 14 May 2020 23:20:42 +0800 Subject: [PATCH 1460/2944] alinux: sched: Add switch for update_blocked_averages to #28739709 Unless the workloads are IO-bounded, update_blocked_averages doesn't help load balance. This patch adds a switch to bypass update_blocked_averages if prior knowledge about workloads indicates IO is negligible. Performance Tests: 1) 1100+ tasks in their individual cgroups, on a 96-HT Skylake machine sched overhead(each HT): 3.78% -> 0.74% 2) cgroup-overhead benchmark in our sched-test suite on a 96-HT Skylake overhead: 21.06 -> 18.08 3) unixbench context1 with 96 threads running for 1min Score: 15409.40 -> 16821.77 Besides these, UnixBench has some performance ups and downs. But generally, the performance of UnixBench hasn't changed. Signed-off-by: Yihao Wu Acked-by: Michael Wang --- include/linux/sched/sysctl.h | 5 +++++ kernel/sched/fair.c | 35 +++++++++++++++++++++++++++++++++++ kernel/sysctl.c | 9 +++++++++ 3 files changed, 49 insertions(+) diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index a9c32da..efa5111 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -83,4 +83,9 @@ extern int sysctl_schedstats(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +extern int sysctl_blocked_averages(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos); + +extern struct static_key_true sched_blocked_averages; #endif /* _LINUX_SCHED_SYSCTL_H */ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ddd5de3..853a979 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7449,6 +7449,35 @@ static inline bool others_have_blocked(struct rq *rq) } #ifdef CONFIG_FAIR_GROUP_SCHED +DEFINE_STATIC_KEY_TRUE(sched_blocked_averages); + +static void set_blocked_averages(bool enabled) +{ + if (enabled) + static_branch_enable(&sched_blocked_averages); + else + static_branch_disable(&sched_blocked_averages); +} + +int sysctl_blocked_averages(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table t; + int err; + int state = static_branch_likely(&sched_blocked_averages); + + if (write && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + t = *table; + t.data = &state; + err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); + if (err < 0) + return err; + if (write) + set_blocked_averages(state); + return err; +} static void update_blocked_averages(int cpu) { @@ -7458,6 +7487,9 @@ static void update_blocked_averages(int cpu) struct rq_flags rf; bool done = true; + if (!static_branch_unlikely(&sched_blocked_averages)) + return; + rq_lock_irqsave(rq, &rf); update_rq_clock(rq); @@ -7592,6 +7624,9 @@ static unsigned long task_h_load_static(struct task_struct *p) #else static inline void update_blocked_averages(int cpu) { + if (!static_key_true(&sched_blocked_averages)) + return; + struct rq *rq = cpu_rq(cpu); struct cfs_rq *cfs_rq = &rq->cfs; const struct sched_class *curr_class; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 1b41232..2a2a493 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -355,6 +355,15 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write, }, #ifdef CONFIG_SMP { + .procname = "sched_blocked_averages", + .data = NULL, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = sysctl_blocked_averages, + .extra1 = &zero, + .extra2 = &one, + }, + { .procname = "sched_tunable_scaling", .data = &sysctl_sched_tunable_scaling, .maxlen = sizeof(enum sched_tunable_scaling), -- 1.8.3.1