diff options
Diffstat (limited to 'kernel/sched/core.c')
| -rw-r--r-- | kernel/sched/core.c | 449 |
1 files changed, 100 insertions, 349 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 41f6b2215aa8..05114b15b6d1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -67,12 +67,10 @@ | |||
| 67 | #include <linux/pagemap.h> | 67 | #include <linux/pagemap.h> |
| 68 | #include <linux/hrtimer.h> | 68 | #include <linux/hrtimer.h> |
| 69 | #include <linux/tick.h> | 69 | #include <linux/tick.h> |
| 70 | #include <linux/debugfs.h> | ||
| 71 | #include <linux/ctype.h> | 70 | #include <linux/ctype.h> |
| 72 | #include <linux/ftrace.h> | 71 | #include <linux/ftrace.h> |
| 73 | #include <linux/slab.h> | 72 | #include <linux/slab.h> |
| 74 | #include <linux/init_task.h> | 73 | #include <linux/init_task.h> |
| 75 | #include <linux/binfmts.h> | ||
| 76 | #include <linux/context_tracking.h> | 74 | #include <linux/context_tracking.h> |
| 77 | #include <linux/compiler.h> | 75 | #include <linux/compiler.h> |
| 78 | 76 | ||
| @@ -125,138 +123,6 @@ const_debug unsigned int sysctl_sched_features = | |||
| 125 | 123 | ||
| 126 | #undef SCHED_FEAT | 124 | #undef SCHED_FEAT |
| 127 | 125 | ||
| 128 | #ifdef CONFIG_SCHED_DEBUG | ||
| 129 | #define SCHED_FEAT(name, enabled) \ | ||
| 130 | #name , | ||
| 131 | |||
| 132 | static const char * const sched_feat_names[] = { | ||
| 133 | #include "features.h" | ||
| 134 | }; | ||
| 135 | |||
| 136 | #undef SCHED_FEAT | ||
| 137 | |||
| 138 | static int sched_feat_show(struct seq_file *m, void *v) | ||
| 139 | { | ||
| 140 | int i; | ||
| 141 | |||
| 142 | for (i = 0; i < __SCHED_FEAT_NR; i++) { | ||
| 143 | if (!(sysctl_sched_features & (1UL << i))) | ||
| 144 | seq_puts(m, "NO_"); | ||
| 145 | seq_printf(m, "%s ", sched_feat_names[i]); | ||
| 146 | } | ||
| 147 | seq_puts(m, "\n"); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | #ifdef HAVE_JUMP_LABEL | ||
| 153 | |||
| 154 | #define jump_label_key__true STATIC_KEY_INIT_TRUE | ||
| 155 | #define jump_label_key__false STATIC_KEY_INIT_FALSE | ||
| 156 | |||
| 157 | #define SCHED_FEAT(name, enabled) \ | ||
| 158 | jump_label_key__##enabled , | ||
| 159 | |||
| 160 | struct static_key sched_feat_keys[__SCHED_FEAT_NR] = { | ||
| 161 | #include "features.h" | ||
| 162 | }; | ||
| 163 | |||
| 164 | #undef SCHED_FEAT | ||
| 165 | |||
| 166 | static void sched_feat_disable(int i) | ||
| 167 | { | ||
| 168 | static_key_disable(&sched_feat_keys[i]); | ||
| 169 | } | ||
| 170 | |||
| 171 | static void sched_feat_enable(int i) | ||
| 172 | { | ||
| 173 | static_key_enable(&sched_feat_keys[i]); | ||
| 174 | } | ||
| 175 | #else | ||
| 176 | static void sched_feat_disable(int i) { }; | ||
| 177 | static void sched_feat_enable(int i) { }; | ||
| 178 | #endif /* HAVE_JUMP_LABEL */ | ||
| 179 | |||
| 180 | static int sched_feat_set(char *cmp) | ||
| 181 | { | ||
| 182 | int i; | ||
| 183 | int neg = 0; | ||
| 184 | |||
| 185 | if (strncmp(cmp, "NO_", 3) == 0) { | ||
| 186 | neg = 1; | ||
| 187 | cmp += 3; | ||
| 188 | } | ||
| 189 | |||
| 190 | for (i = 0; i < __SCHED_FEAT_NR; i++) { | ||
| 191 | if (strcmp(cmp, sched_feat_names[i]) == 0) { | ||
| 192 | if (neg) { | ||
| 193 | sysctl_sched_features &= ~(1UL << i); | ||
| 194 | sched_feat_disable(i); | ||
| 195 | } else { | ||
| 196 | sysctl_sched_features |= (1UL << i); | ||
| 197 | sched_feat_enable(i); | ||
| 198 | } | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | return i; | ||
| 204 | } | ||
| 205 | |||
| 206 | static ssize_t | ||
| 207 | sched_feat_write(struct file *filp, const char __user *ubuf, | ||
| 208 | size_t cnt, loff_t *ppos) | ||
| 209 | { | ||
| 210 | char buf[64]; | ||
| 211 | char *cmp; | ||
| 212 | int i; | ||
| 213 | struct inode *inode; | ||
| 214 | |||
| 215 | if (cnt > 63) | ||
| 216 | cnt = 63; | ||
| 217 | |||
| 218 | if (copy_from_user(&buf, ubuf, cnt)) | ||
| 219 | return -EFAULT; | ||
| 220 | |||
| 221 | buf[cnt] = 0; | ||
| 222 | cmp = strstrip(buf); | ||
| 223 | |||
| 224 | /* Ensure the static_key remains in a consistent state */ | ||
| 225 | inode = file_inode(filp); | ||
| 226 | inode_lock(inode); | ||
| 227 | i = sched_feat_set(cmp); | ||
| 228 | inode_unlock(inode); | ||
| 229 | if (i == __SCHED_FEAT_NR) | ||
| 230 | return -EINVAL; | ||
| 231 | |||
| 232 | *ppos += cnt; | ||
| 233 | |||
| 234 | return cnt; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int sched_feat_open(struct inode *inode, struct file *filp) | ||
| 238 | { | ||
| 239 | return single_open(filp, sched_feat_show, NULL); | ||
| 240 | } | ||
| 241 | |||
| 242 | static const struct file_operations sched_feat_fops = { | ||
| 243 | .open = sched_feat_open, | ||
| 244 | .write = sched_feat_write, | ||
| 245 | .read = seq_read, | ||
| 246 | .llseek = seq_lseek, | ||
| 247 | .release = single_release, | ||
| 248 | }; | ||
| 249 | |||
| 250 | static __init int sched_init_debug(void) | ||
| 251 | { | ||
| 252 | debugfs_create_file("sched_features", 0644, NULL, NULL, | ||
| 253 | &sched_feat_fops); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | late_initcall(sched_init_debug); | ||
| 258 | #endif /* CONFIG_SCHED_DEBUG */ | ||
| 259 | |||
| 260 | /* | 126 | /* |
| 261 | * Number of tasks to iterate in a single balance run. | 127 | * Number of tasks to iterate in a single balance run. |
| 262 | * Limited because this is done with IRQs disabled. | 128 | * Limited because this is done with IRQs disabled. |
| @@ -2094,7 +1960,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) | |||
| 2094 | 1960 | ||
| 2095 | ttwu_queue(p, cpu); | 1961 | ttwu_queue(p, cpu); |
| 2096 | stat: | 1962 | stat: |
| 2097 | ttwu_stat(p, cpu, wake_flags); | 1963 | if (schedstat_enabled()) |
| 1964 | ttwu_stat(p, cpu, wake_flags); | ||
| 2098 | out: | 1965 | out: |
| 2099 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); | 1966 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); |
| 2100 | 1967 | ||
| @@ -2142,7 +2009,8 @@ static void try_to_wake_up_local(struct task_struct *p) | |||
| 2142 | ttwu_activate(rq, p, ENQUEUE_WAKEUP); | 2009 | ttwu_activate(rq, p, ENQUEUE_WAKEUP); |
| 2143 | 2010 | ||
| 2144 | ttwu_do_wakeup(rq, p, 0); | 2011 | ttwu_do_wakeup(rq, p, 0); |
| 2145 | ttwu_stat(p, smp_processor_id(), 0); | 2012 | if (schedstat_enabled()) |
| 2013 | ttwu_stat(p, smp_processor_id(), 0); | ||
| 2146 | out: | 2014 | out: |
| 2147 | raw_spin_unlock(&p->pi_lock); | 2015 | raw_spin_unlock(&p->pi_lock); |
| 2148 | } | 2016 | } |
| @@ -2184,7 +2052,6 @@ void __dl_clear_params(struct task_struct *p) | |||
| 2184 | dl_se->dl_bw = 0; | 2052 | dl_se->dl_bw = 0; |
| 2185 | 2053 | ||
| 2186 | dl_se->dl_throttled = 0; | 2054 | dl_se->dl_throttled = 0; |
| 2187 | dl_se->dl_new = 1; | ||
| 2188 | dl_se->dl_yielded = 0; | 2055 | dl_se->dl_yielded = 0; |
| 2189 | } | 2056 | } |
| 2190 | 2057 | ||
| @@ -2211,6 +2078,7 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
| 2211 | #endif | 2078 | #endif |
| 2212 | 2079 | ||
| 2213 | #ifdef CONFIG_SCHEDSTATS | 2080 | #ifdef CONFIG_SCHEDSTATS |
| 2081 | /* Even if schedstat is disabled, there should not be garbage */ | ||
| 2214 | memset(&p->se.statistics, 0, sizeof(p->se.statistics)); | 2082 | memset(&p->se.statistics, 0, sizeof(p->se.statistics)); |
| 2215 | #endif | 2083 | #endif |
| 2216 | 2084 | ||
| @@ -2219,6 +2087,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
| 2219 | __dl_clear_params(p); | 2087 | __dl_clear_params(p); |
| 2220 | 2088 | ||
| 2221 | INIT_LIST_HEAD(&p->rt.run_list); | 2089 | INIT_LIST_HEAD(&p->rt.run_list); |
| 2090 | p->rt.timeout = 0; | ||
| 2091 | p->rt.time_slice = sched_rr_timeslice; | ||
| 2092 | p->rt.on_rq = 0; | ||
| 2093 | p->rt.on_list = 0; | ||
| 2222 | 2094 | ||
| 2223 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 2095 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
| 2224 | INIT_HLIST_HEAD(&p->preempt_notifiers); | 2096 | INIT_HLIST_HEAD(&p->preempt_notifiers); |
| @@ -2282,6 +2154,69 @@ int sysctl_numa_balancing(struct ctl_table *table, int write, | |||
| 2282 | #endif | 2154 | #endif |
| 2283 | #endif | 2155 | #endif |
| 2284 | 2156 | ||
| 2157 | DEFINE_STATIC_KEY_FALSE(sched_schedstats); | ||
| 2158 | |||
| 2159 | #ifdef CONFIG_SCHEDSTATS | ||
| 2160 | static void set_schedstats(bool enabled) | ||
| 2161 | { | ||
| 2162 | if (enabled) | ||
| 2163 | static_branch_enable(&sched_schedstats); | ||
| 2164 | else | ||
| 2165 | static_branch_disable(&sched_schedstats); | ||
| 2166 | } | ||
| 2167 | |||
| 2168 | void force_schedstat_enabled(void) | ||
| 2169 | { | ||
| 2170 | if (!schedstat_enabled()) { | ||
| 2171 | pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n"); | ||
| 2172 | static_branch_enable(&sched_schedstats); | ||
| 2173 | } | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | static int __init setup_schedstats(char *str) | ||
| 2177 | { | ||
| 2178 | int ret = 0; | ||
| 2179 | if (!str) | ||
| 2180 | goto out; | ||
| 2181 | |||
| 2182 | if (!strcmp(str, "enable")) { | ||
| 2183 | set_schedstats(true); | ||
| 2184 | ret = 1; | ||
| 2185 | } else if (!strcmp(str, "disable")) { | ||
| 2186 | set_schedstats(false); | ||
| 2187 | ret = 1; | ||
| 2188 | } | ||
| 2189 | out: | ||
| 2190 | if (!ret) | ||
| 2191 | pr_warn("Unable to parse schedstats=\n"); | ||
| 2192 | |||
| 2193 | return ret; | ||
| 2194 | } | ||
| 2195 | __setup("schedstats=", setup_schedstats); | ||
| 2196 | |||
| 2197 | #ifdef CONFIG_PROC_SYSCTL | ||
| 2198 | int sysctl_schedstats(struct ctl_table *table, int write, | ||
| 2199 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
| 2200 | { | ||
| 2201 | struct ctl_table t; | ||
| 2202 | int err; | ||
| 2203 | int state = static_branch_likely(&sched_schedstats); | ||
| 2204 | |||
| 2205 | if (write && !capable(CAP_SYS_ADMIN)) | ||
| 2206 | return -EPERM; | ||
| 2207 | |||
| 2208 | t = *table; | ||
| 2209 | t.data = &state; | ||
| 2210 | err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); | ||
| 2211 | if (err < 0) | ||
| 2212 | return err; | ||
| 2213 | if (write) | ||
| 2214 | set_schedstats(state); | ||
| 2215 | return err; | ||
| 2216 | } | ||
| 2217 | #endif | ||
| 2218 | #endif | ||
| 2219 | |||
| 2285 | /* | 2220 | /* |
| 2286 | * fork()/clone()-time setup: | 2221 | * fork()/clone()-time setup: |
| 2287 | */ | 2222 | */ |
| @@ -3011,16 +2946,6 @@ u64 scheduler_tick_max_deferment(void) | |||
| 3011 | } | 2946 | } |
| 3012 | #endif | 2947 | #endif |
| 3013 | 2948 | ||
| 3014 | notrace unsigned long get_parent_ip(unsigned long addr) | ||
| 3015 | { | ||
| 3016 | if (in_lock_functions(addr)) { | ||
| 3017 | addr = CALLER_ADDR2; | ||
| 3018 | if (in_lock_functions(addr)) | ||
| 3019 | addr = CALLER_ADDR3; | ||
| 3020 | } | ||
| 3021 | return addr; | ||
| 3022 | } | ||
| 3023 | |||
| 3024 | #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ | 2949 | #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ |
| 3025 | defined(CONFIG_PREEMPT_TRACER)) | 2950 | defined(CONFIG_PREEMPT_TRACER)) |
| 3026 | 2951 | ||
| @@ -3042,7 +2967,7 @@ void preempt_count_add(int val) | |||
| 3042 | PREEMPT_MASK - 10); | 2967 | PREEMPT_MASK - 10); |
| 3043 | #endif | 2968 | #endif |
| 3044 | if (preempt_count() == val) { | 2969 | if (preempt_count() == val) { |
| 3045 | unsigned long ip = get_parent_ip(CALLER_ADDR1); | 2970 | unsigned long ip = get_lock_parent_ip(); |
| 3046 | #ifdef CONFIG_DEBUG_PREEMPT | 2971 | #ifdef CONFIG_DEBUG_PREEMPT |
| 3047 | current->preempt_disable_ip = ip; | 2972 | current->preempt_disable_ip = ip; |
| 3048 | #endif | 2973 | #endif |
| @@ -3069,7 +2994,7 @@ void preempt_count_sub(int val) | |||
| 3069 | #endif | 2994 | #endif |
| 3070 | 2995 | ||
| 3071 | if (preempt_count() == val) | 2996 | if (preempt_count() == val) |
| 3072 | trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | 2997 | trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); |
| 3073 | __preempt_count_sub(val); | 2998 | __preempt_count_sub(val); |
| 3074 | } | 2999 | } |
| 3075 | EXPORT_SYMBOL(preempt_count_sub); | 3000 | EXPORT_SYMBOL(preempt_count_sub); |
| @@ -3281,7 +3206,6 @@ static void __sched notrace __schedule(bool preempt) | |||
| 3281 | 3206 | ||
| 3282 | trace_sched_switch(preempt, prev, next); | 3207 | trace_sched_switch(preempt, prev, next); |
| 3283 | rq = context_switch(rq, prev, next); /* unlocks the rq */ | 3208 | rq = context_switch(rq, prev, next); /* unlocks the rq */ |
| 3284 | cpu = cpu_of(rq); | ||
| 3285 | } else { | 3209 | } else { |
| 3286 | lockdep_unpin_lock(&rq->lock); | 3210 | lockdep_unpin_lock(&rq->lock); |
| 3287 | raw_spin_unlock_irq(&rq->lock); | 3211 | raw_spin_unlock_irq(&rq->lock); |
| @@ -3467,7 +3391,7 @@ EXPORT_SYMBOL(default_wake_function); | |||
| 3467 | */ | 3391 | */ |
| 3468 | void rt_mutex_setprio(struct task_struct *p, int prio) | 3392 | void rt_mutex_setprio(struct task_struct *p, int prio) |
| 3469 | { | 3393 | { |
| 3470 | int oldprio, queued, running, enqueue_flag = ENQUEUE_RESTORE; | 3394 | int oldprio, queued, running, queue_flag = DEQUEUE_SAVE | DEQUEUE_MOVE; |
| 3471 | struct rq *rq; | 3395 | struct rq *rq; |
| 3472 | const struct sched_class *prev_class; | 3396 | const struct sched_class *prev_class; |
| 3473 | 3397 | ||
| @@ -3495,11 +3419,15 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
| 3495 | 3419 | ||
| 3496 | trace_sched_pi_setprio(p, prio); | 3420 | trace_sched_pi_setprio(p, prio); |
| 3497 | oldprio = p->prio; | 3421 | oldprio = p->prio; |
| 3422 | |||
| 3423 | if (oldprio == prio) | ||
| 3424 | queue_flag &= ~DEQUEUE_MOVE; | ||
| 3425 | |||
| 3498 | prev_class = p->sched_class; | 3426 | prev_class = p->sched_class; |
| 3499 | queued = task_on_rq_queued(p); | 3427 | queued = task_on_rq_queued(p); |
| 3500 | running = task_current(rq, p); | 3428 | running = task_current(rq, p); |
| 3501 | if (queued) | 3429 | if (queued) |
| 3502 | dequeue_task(rq, p, DEQUEUE_SAVE); | 3430 | dequeue_task(rq, p, queue_flag); |
| 3503 | if (running) | 3431 | if (running) |
| 3504 | put_prev_task(rq, p); | 3432 | put_prev_task(rq, p); |
| 3505 | 3433 | ||
| @@ -3517,7 +3445,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
| 3517 | if (!dl_prio(p->normal_prio) || | 3445 | if (!dl_prio(p->normal_prio) || |
| 3518 | (pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) { | 3446 | (pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) { |
| 3519 | p->dl.dl_boosted = 1; | 3447 | p->dl.dl_boosted = 1; |
| 3520 | enqueue_flag |= ENQUEUE_REPLENISH; | 3448 | queue_flag |= ENQUEUE_REPLENISH; |
| 3521 | } else | 3449 | } else |
| 3522 | p->dl.dl_boosted = 0; | 3450 | p->dl.dl_boosted = 0; |
| 3523 | p->sched_class = &dl_sched_class; | 3451 | p->sched_class = &dl_sched_class; |
| @@ -3525,7 +3453,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
| 3525 | if (dl_prio(oldprio)) | 3453 | if (dl_prio(oldprio)) |
| 3526 | p->dl.dl_boosted = 0; | 3454 | p->dl.dl_boosted = 0; |
| 3527 | if (oldprio < prio) | 3455 | if (oldprio < prio) |
| 3528 | enqueue_flag |= ENQUEUE_HEAD; | 3456 | queue_flag |= ENQUEUE_HEAD; |
| 3529 | p->sched_class = &rt_sched_class; | 3457 | p->sched_class = &rt_sched_class; |
| 3530 | } else { | 3458 | } else { |
| 3531 | if (dl_prio(oldprio)) | 3459 | if (dl_prio(oldprio)) |
| @@ -3540,7 +3468,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
| 3540 | if (running) | 3468 | if (running) |
| 3541 | p->sched_class->set_curr_task(rq); | 3469 | p->sched_class->set_curr_task(rq); |
| 3542 | if (queued) | 3470 | if (queued) |
| 3543 | enqueue_task(rq, p, enqueue_flag); | 3471 | enqueue_task(rq, p, queue_flag); |
| 3544 | 3472 | ||
| 3545 | check_class_changed(rq, p, prev_class, oldprio); | 3473 | check_class_changed(rq, p, prev_class, oldprio); |
| 3546 | out_unlock: | 3474 | out_unlock: |
| @@ -3896,6 +3824,7 @@ static int __sched_setscheduler(struct task_struct *p, | |||
| 3896 | const struct sched_class *prev_class; | 3824 | const struct sched_class *prev_class; |
| 3897 | struct rq *rq; | 3825 | struct rq *rq; |
| 3898 | int reset_on_fork; | 3826 | int reset_on_fork; |
| 3827 | int queue_flags = DEQUEUE_SAVE | DEQUEUE_MOVE; | ||
| 3899 | 3828 | ||
| 3900 | /* may grab non-irq protected spin_locks */ | 3829 | /* may grab non-irq protected spin_locks */ |
| 3901 | BUG_ON(in_interrupt()); | 3830 | BUG_ON(in_interrupt()); |
| @@ -4078,17 +4007,14 @@ change: | |||
| 4078 | * itself. | 4007 | * itself. |
| 4079 | */ | 4008 | */ |
| 4080 | new_effective_prio = rt_mutex_get_effective_prio(p, newprio); | 4009 | new_effective_prio = rt_mutex_get_effective_prio(p, newprio); |
| 4081 | if (new_effective_prio == oldprio) { | 4010 | if (new_effective_prio == oldprio) |
| 4082 | __setscheduler_params(p, attr); | 4011 | queue_flags &= ~DEQUEUE_MOVE; |
| 4083 | task_rq_unlock(rq, p, &flags); | ||
| 4084 | return 0; | ||
| 4085 | } | ||
| 4086 | } | 4012 | } |
| 4087 | 4013 | ||
| 4088 | queued = task_on_rq_queued(p); | 4014 | queued = task_on_rq_queued(p); |
| 4089 | running = task_current(rq, p); | 4015 | running = task_current(rq, p); |
| 4090 | if (queued) | 4016 | if (queued) |
| 4091 | dequeue_task(rq, p, DEQUEUE_SAVE); | 4017 | dequeue_task(rq, p, queue_flags); |
| 4092 | if (running) | 4018 | if (running) |
| 4093 | put_prev_task(rq, p); | 4019 | put_prev_task(rq, p); |
| 4094 | 4020 | ||
| @@ -4098,15 +4024,14 @@ change: | |||
| 4098 | if (running) | 4024 | if (running) |
| 4099 | p->sched_class->set_curr_task(rq); | 4025 | p->sched_class->set_curr_task(rq); |
| 4100 | if (queued) { | 4026 | if (queued) { |
| 4101 | int enqueue_flags = ENQUEUE_RESTORE; | ||
| 4102 | /* | 4027 | /* |
| 4103 | * We enqueue to tail when the priority of a task is | 4028 | * We enqueue to tail when the priority of a task is |
| 4104 | * increased (user space view). | 4029 | * increased (user space view). |
| 4105 | */ | 4030 | */ |
| 4106 | if (oldprio <= p->prio) | 4031 | if (oldprio < p->prio) |
| 4107 | enqueue_flags |= ENQUEUE_HEAD; | 4032 | queue_flags |= ENQUEUE_HEAD; |
| 4108 | 4033 | ||
| 4109 | enqueue_task(rq, p, enqueue_flags); | 4034 | enqueue_task(rq, p, queue_flags); |
| 4110 | } | 4035 | } |
| 4111 | 4036 | ||
| 4112 | check_class_changed(rq, p, prev_class, oldprio); | 4037 | check_class_changed(rq, p, prev_class, oldprio); |
| @@ -5408,183 +5333,6 @@ static void migrate_tasks(struct rq *dead_rq) | |||
| 5408 | } | 5333 | } |
| 5409 | #endif /* CONFIG_HOTPLUG_CPU */ | 5334 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 5410 | 5335 | ||
| 5411 | #if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) | ||
| 5412 | |||
| 5413 | static struct ctl_table sd_ctl_dir[] = { | ||
| 5414 | { | ||
| 5415 | .procname = "sched_domain", | ||
| 5416 | .mode = 0555, | ||
| 5417 | }, | ||
| 5418 | {} | ||
| 5419 | }; | ||
| 5420 | |||
| 5421 | static struct ctl_table sd_ctl_root[] = { | ||
| 5422 | { | ||
| 5423 | .procname = "kernel", | ||
| 5424 | .mode = 0555, | ||
| 5425 | .child = sd_ctl_dir, | ||
| 5426 | }, | ||
| 5427 | {} | ||
| 5428 | }; | ||
| 5429 | |||
| 5430 | static struct ctl_table *sd_alloc_ctl_entry(int n) | ||
| 5431 | { | ||
| 5432 | struct ctl_table *entry = | ||
| 5433 | kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL); | ||
| 5434 | |||
| 5435 | return entry; | ||
| 5436 | } | ||
| 5437 | |||
| 5438 | static void sd_free_ctl_entry(struct ctl_table **tablep) | ||
| 5439 | { | ||
| 5440 | struct ctl_table *entry; | ||
| 5441 | |||
| 5442 | /* | ||
| 5443 | * In the intermediate directories, both the child directory and | ||
| 5444 | * procname are dynamically allocated and could fail but the mode | ||
| 5445 | * will always be set. In the lowest directory the names are | ||
| 5446 | * static strings and all have proc handlers. | ||
| 5447 | */ | ||
| 5448 | for (entry = *tablep; entry->mode; entry++) { | ||
| 5449 | if (entry->child) | ||
| 5450 | sd_free_ctl_entry(&entry->child); | ||
| 5451 | if (entry->proc_handler == NULL) | ||
| 5452 | kfree(entry->procname); | ||
| 5453 | } | ||
| 5454 | |||
| 5455 | kfree(*tablep); | ||
| 5456 | *tablep = NULL; | ||
| 5457 | } | ||
| 5458 | |||
| 5459 | static int min_load_idx = 0; | ||
| 5460 | static int max_load_idx = CPU_LOAD_IDX_MAX-1; | ||
| 5461 | |||
| 5462 | static void | ||
| 5463 | set_table_entry(struct ctl_table *entry, | ||
| 5464 | const char *procname, void *data, int maxlen, | ||
| 5465 | umode_t mode, proc_handler *proc_handler, | ||
| 5466 | bool load_idx) | ||
| 5467 | { | ||
| 5468 | entry->procname = procname; | ||
| 5469 | entry->data = data; | ||
| 5470 | entry->maxlen = maxlen; | ||
| 5471 | entry->mode = mode; | ||
| 5472 | entry->proc_handler = proc_handler; | ||
| 5473 | |||
| 5474 | if (load_idx) { | ||
| 5475 | entry->extra1 = &min_load_idx; | ||
| 5476 | entry->extra2 = &max_load_idx; | ||
| 5477 | } | ||
| 5478 | } | ||
| 5479 | |||
| 5480 | static struct ctl_table * | ||
| 5481 | sd_alloc_ctl_domain_table(struct sched_domain *sd) | ||
| 5482 | { | ||
| 5483 | struct ctl_table *table = sd_alloc_ctl_entry(14); | ||
| 5484 | |||
| 5485 | if (table == NULL) | ||
| 5486 | return NULL; | ||
| 5487 | |||
| 5488 | set_table_entry(&table[0], "min_interval", &sd->min_interval, | ||
| 5489 | sizeof(long), 0644, proc_doulongvec_minmax, false); | ||
| 5490 | set_table_entry(&table[1], "max_interval", &sd->max_interval, | ||
| 5491 | sizeof(long), 0644, proc_doulongvec_minmax, false); | ||
| 5492 | set_table_entry(&table[2], "busy_idx", &sd->busy_idx, | ||
| 5493 | sizeof(int), 0644, proc_dointvec_minmax, true); | ||
| 5494 | set_table_entry(&table[3], "idle_idx", &sd->idle_idx, | ||
| 5495 | sizeof(int), 0644, proc_dointvec_minmax, true); | ||
| 5496 | set_table_entry(&table[4], "newidle_idx", &sd->newidle_idx, | ||
| 5497 | sizeof(int), 0644, proc_dointvec_minmax, true); | ||
| 5498 | set_table_entry(&table[5], "wake_idx", &sd->wake_idx, | ||
| 5499 | sizeof(int), 0644, proc_dointvec_minmax, true); | ||
| 5500 | set_table_entry(&table[6], "forkexec_idx", &sd->forkexec_idx, | ||
| 5501 | sizeof(int), 0644, proc_dointvec_minmax, true); | ||
| 5502 | set_table_entry(&table[7], "busy_factor", &sd->busy_factor, | ||
| 5503 | sizeof(int), 0644, proc_dointvec_minmax, false); | ||
| 5504 | set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct, | ||
| 5505 | sizeof(int), 0644, proc_dointvec_minmax, false); | ||
| 5506 | set_table_entry(&table[9], "cache_nice_tries", | ||
| 5507 | &sd->cache_nice_tries, | ||
| 5508 | sizeof(int), 0644, proc_dointvec_minmax, false); | ||
| 5509 | set_table_entry(&table[10], "flags", &sd->flags, | ||
| 5510 | sizeof(int), 0644, proc_dointvec_minmax, false); | ||
| 5511 | set_table_entry(&table[11], "max_newidle_lb_cost", | ||
| 5512 | &sd->max_newidle_lb_cost, | ||
| 5513 | sizeof(long), 0644, proc_doulongvec_minmax, false); | ||
| 5514 | set_table_entry(&table[12], "name", sd->name, | ||
| 5515 | CORENAME_MAX_SIZE, 0444, proc_dostring, false); | ||
| 5516 | /* &table[13] is terminator */ | ||
| 5517 | |||
| 5518 | return table; | ||
| 5519 | } | ||
| 5520 | |||
| 5521 | static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu) | ||
| 5522 | { | ||
| 5523 | struct ctl_table *entry, *table; | ||
| 5524 | struct sched_domain *sd; | ||
| 5525 | int domain_num = 0, i; | ||
| 5526 | char buf[32]; | ||
| 5527 | |||
| 5528 | for_each_domain(cpu, sd) | ||
| 5529 | domain_num++; | ||
| 5530 | entry = table = sd_alloc_ctl_entry(domain_num + 1); | ||
| 5531 | if (table == NULL) | ||
| 5532 | return NULL; | ||
| 5533 | |||
| 5534 | i = 0; | ||
| 5535 | for_each_domain(cpu, sd) { | ||
| 5536 | snprintf(buf, 32, "domain%d", i); | ||
| 5537 | entry->procname = kstrdup(buf, GFP_KERNEL); | ||
| 5538 | entry->mode = 0555; | ||
| 5539 | entry->child = sd_alloc_ctl_domain_table(sd); | ||
| 5540 | entry++; | ||
| 5541 | i++; | ||
| 5542 | } | ||
| 5543 | return table; | ||
| 5544 | } | ||
| 5545 | |||
| 5546 | static struct ctl_table_header *sd_sysctl_header; | ||
| 5547 | static void register_sched_domain_sysctl(void) | ||
| 5548 | { | ||
| 5549 | int i, cpu_num = num_possible_cpus(); | ||
| 5550 | struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); | ||
| 5551 | char buf[32]; | ||
| 5552 | |||
| 5553 | WARN_ON(sd_ctl_dir[0].child); | ||
| 5554 | sd_ctl_dir[0].child = entry; | ||
| 5555 | |||
| 5556 | if (entry == NULL) | ||
| 5557 | return; | ||
| 5558 | |||
| 5559 | for_each_possible_cpu(i) { | ||
| 5560 | snprintf(buf, 32, "cpu%d", i); | ||
| 5561 | entry->procname = kstrdup(buf, GFP_KERNEL); | ||
| 5562 | entry->mode = 0555; | ||
| 5563 | entry->child = sd_alloc_ctl_cpu_table(i); | ||
| 5564 | entry++; | ||
| 5565 | } | ||
| 5566 | |||
| 5567 | WARN_ON(sd_sysctl_header); | ||
| 5568 | sd_sysctl_header = register_sysctl_table(sd_ctl_root); | ||
| 5569 | } | ||
| 5570 | |||
| 5571 | /* may be called multiple times per register */ | ||
| 5572 | static void unregister_sched_domain_sysctl(void) | ||
| 5573 | { | ||
| 5574 | unregister_sysctl_table(sd_sysctl_header); | ||
| 5575 | sd_sysctl_header = NULL; | ||
| 5576 | if (sd_ctl_dir[0].child) | ||
| 5577 | sd_free_ctl_entry(&sd_ctl_dir[0].child); | ||
| 5578 | } | ||
| 5579 | #else | ||
| 5580 | static void register_sched_domain_sysctl(void) | ||
| 5581 | { | ||
| 5582 | } | ||
| 5583 | static void unregister_sched_domain_sysctl(void) | ||
| 5584 | { | ||
| 5585 | } | ||
| 5586 | #endif /* CONFIG_SCHED_DEBUG && CONFIG_SYSCTL */ | ||
| 5587 | |||
| 5588 | static void set_rq_online(struct rq *rq) | 5336 | static void set_rq_online(struct rq *rq) |
| 5589 | { | 5337 | { |
| 5590 | if (!rq->online) { | 5338 | if (!rq->online) { |
| @@ -6176,11 +5924,16 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu) | |||
| 6176 | /* Setup the mask of cpus configured for isolated domains */ | 5924 | /* Setup the mask of cpus configured for isolated domains */ |
| 6177 | static int __init isolated_cpu_setup(char *str) | 5925 | static int __init isolated_cpu_setup(char *str) |
| 6178 | { | 5926 | { |
| 5927 | int ret; | ||
| 5928 | |||
| 6179 | alloc_bootmem_cpumask_var(&cpu_isolated_map); | 5929 | alloc_bootmem_cpumask_var(&cpu_isolated_map); |
| 6180 | cpulist_parse(str, cpu_isolated_map); | 5930 | ret = cpulist_parse(str, cpu_isolated_map); |
| 5931 | if (ret) { | ||
| 5932 | pr_err("sched: Error, all isolcpus= values must be between 0 and %d\n", nr_cpu_ids); | ||
| 5933 | return 0; | ||
| 5934 | } | ||
| 6181 | return 1; | 5935 | return 1; |
| 6182 | } | 5936 | } |
| 6183 | |||
| 6184 | __setup("isolcpus=", isolated_cpu_setup); | 5937 | __setup("isolcpus=", isolated_cpu_setup); |
| 6185 | 5938 | ||
| 6186 | struct s_data { | 5939 | struct s_data { |
| @@ -7863,11 +7616,9 @@ void sched_destroy_group(struct task_group *tg) | |||
| 7863 | void sched_offline_group(struct task_group *tg) | 7616 | void sched_offline_group(struct task_group *tg) |
| 7864 | { | 7617 | { |
| 7865 | unsigned long flags; | 7618 | unsigned long flags; |
| 7866 | int i; | ||
| 7867 | 7619 | ||
| 7868 | /* end participation in shares distribution */ | 7620 | /* end participation in shares distribution */ |
| 7869 | for_each_possible_cpu(i) | 7621 | unregister_fair_sched_group(tg); |
| 7870 | unregister_fair_sched_group(tg, i); | ||
| 7871 | 7622 | ||
| 7872 | spin_lock_irqsave(&task_group_lock, flags); | 7623 | spin_lock_irqsave(&task_group_lock, flags); |
| 7873 | list_del_rcu(&tg->list); | 7624 | list_del_rcu(&tg->list); |
| @@ -7893,7 +7644,7 @@ void sched_move_task(struct task_struct *tsk) | |||
| 7893 | queued = task_on_rq_queued(tsk); | 7644 | queued = task_on_rq_queued(tsk); |
| 7894 | 7645 | ||
| 7895 | if (queued) | 7646 | if (queued) |
| 7896 | dequeue_task(rq, tsk, DEQUEUE_SAVE); | 7647 | dequeue_task(rq, tsk, DEQUEUE_SAVE | DEQUEUE_MOVE); |
| 7897 | if (unlikely(running)) | 7648 | if (unlikely(running)) |
| 7898 | put_prev_task(rq, tsk); | 7649 | put_prev_task(rq, tsk); |
| 7899 | 7650 | ||
| @@ -7917,7 +7668,7 @@ void sched_move_task(struct task_struct *tsk) | |||
| 7917 | if (unlikely(running)) | 7668 | if (unlikely(running)) |
| 7918 | tsk->sched_class->set_curr_task(rq); | 7669 | tsk->sched_class->set_curr_task(rq); |
| 7919 | if (queued) | 7670 | if (queued) |
| 7920 | enqueue_task(rq, tsk, ENQUEUE_RESTORE); | 7671 | enqueue_task(rq, tsk, ENQUEUE_RESTORE | ENQUEUE_MOVE); |
| 7921 | 7672 | ||
| 7922 | task_rq_unlock(rq, tsk, &flags); | 7673 | task_rq_unlock(rq, tsk, &flags); |
| 7923 | } | 7674 | } |
