diff options
-rw-r--r-- | include/linux/cpu.h | 25 | ||||
-rw-r--r-- | include/linux/cpuset.h | 6 | ||||
-rw-r--r-- | include/linux/perf_event.h | 2 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | kernel/cpu.c | 6 | ||||
-rw-r--r-- | kernel/cpuset.c | 21 | ||||
-rw-r--r-- | kernel/fork.c | 2 | ||||
-rw-r--r-- | kernel/sched.c | 205 | ||||
-rw-r--r-- | kernel/workqueue_sched.h | 16 |
9 files changed, 203 insertions, 81 deletions
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index e287863ac053..de6b1722cdca 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -48,6 +48,31 @@ extern ssize_t arch_cpu_release(const char *, size_t); | |||
48 | #endif | 48 | #endif |
49 | struct notifier_block; | 49 | struct notifier_block; |
50 | 50 | ||
51 | /* | ||
52 | * CPU notifier priorities. | ||
53 | */ | ||
54 | enum { | ||
55 | /* | ||
56 | * SCHED_ACTIVE marks a cpu which is coming up active during | ||
57 | * CPU_ONLINE and CPU_DOWN_FAILED and must be the first | ||
58 | * notifier. CPUSET_ACTIVE adjusts cpuset according to | ||
59 | * cpu_active mask right after SCHED_ACTIVE. During | ||
60 | * CPU_DOWN_PREPARE, SCHED_INACTIVE and CPUSET_INACTIVE are | ||
61 | * ordered in the similar way. | ||
62 | * | ||
63 | * This ordering guarantees consistent cpu_active mask and | ||
64 | * migration behavior to all cpu notifiers. | ||
65 | */ | ||
66 | CPU_PRI_SCHED_ACTIVE = INT_MAX, | ||
67 | CPU_PRI_CPUSET_ACTIVE = INT_MAX - 1, | ||
68 | CPU_PRI_SCHED_INACTIVE = INT_MIN + 1, | ||
69 | CPU_PRI_CPUSET_INACTIVE = INT_MIN, | ||
70 | |||
71 | /* migration should happen before other stuff but after perf */ | ||
72 | CPU_PRI_PERF = 20, | ||
73 | CPU_PRI_MIGRATION = 10, | ||
74 | }; | ||
75 | |||
51 | #ifdef CONFIG_SMP | 76 | #ifdef CONFIG_SMP |
52 | /* Need to know about CPUs going up/down? */ | 77 | /* Need to know about CPUs going up/down? */ |
53 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) | 78 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) |
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 457ed765a116..f20eb8f16025 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h | |||
@@ -20,6 +20,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */ | |||
20 | 20 | ||
21 | extern int cpuset_init(void); | 21 | extern int cpuset_init(void); |
22 | extern void cpuset_init_smp(void); | 22 | extern void cpuset_init_smp(void); |
23 | extern void cpuset_update_active_cpus(void); | ||
23 | extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); | 24 | extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); |
24 | extern int cpuset_cpus_allowed_fallback(struct task_struct *p); | 25 | extern int cpuset_cpus_allowed_fallback(struct task_struct *p); |
25 | extern nodemask_t cpuset_mems_allowed(struct task_struct *p); | 26 | extern nodemask_t cpuset_mems_allowed(struct task_struct *p); |
@@ -132,6 +133,11 @@ static inline void set_mems_allowed(nodemask_t nodemask) | |||
132 | static inline int cpuset_init(void) { return 0; } | 133 | static inline int cpuset_init(void) { return 0; } |
133 | static inline void cpuset_init_smp(void) {} | 134 | static inline void cpuset_init_smp(void) {} |
134 | 135 | ||
136 | static inline void cpuset_update_active_cpus(void) | ||
137 | { | ||
138 | partition_sched_domains(1, NULL, NULL); | ||
139 | } | ||
140 | |||
135 | static inline void cpuset_cpus_allowed(struct task_struct *p, | 141 | static inline void cpuset_cpus_allowed(struct task_struct *p, |
136 | struct cpumask *mask) | 142 | struct cpumask *mask) |
137 | { | 143 | { |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5d0266d94985..469e03e96fe7 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -1068,7 +1068,7 @@ static inline void perf_event_disable(struct perf_event *event) { } | |||
1068 | #define perf_cpu_notifier(fn) \ | 1068 | #define perf_cpu_notifier(fn) \ |
1069 | do { \ | 1069 | do { \ |
1070 | static struct notifier_block fn##_nb __cpuinitdata = \ | 1070 | static struct notifier_block fn##_nb __cpuinitdata = \ |
1071 | { .notifier_call = fn, .priority = 20 }; \ | 1071 | { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ |
1072 | fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ | 1072 | fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ |
1073 | (void *)(unsigned long)smp_processor_id()); \ | 1073 | (void *)(unsigned long)smp_processor_id()); \ |
1074 | fn(&fn##_nb, (unsigned long)CPU_STARTING, \ | 1074 | fn(&fn##_nb, (unsigned long)CPU_STARTING, \ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index f118809c953f..edc3dd168d87 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1696,6 +1696,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * | |||
1696 | #define PF_EXITING 0x00000004 /* getting shut down */ | 1696 | #define PF_EXITING 0x00000004 /* getting shut down */ |
1697 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ | 1697 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ |
1698 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ | 1698 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ |
1699 | #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ | ||
1699 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ | 1700 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ |
1700 | #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ | 1701 | #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ |
1701 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ | 1702 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ |
diff --git a/kernel/cpu.c b/kernel/cpu.c index 97d1b426a4ac..f6e726f18491 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -235,11 +235,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) | |||
235 | return -EINVAL; | 235 | return -EINVAL; |
236 | 236 | ||
237 | cpu_hotplug_begin(); | 237 | cpu_hotplug_begin(); |
238 | set_cpu_active(cpu, false); | ||
239 | err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); | 238 | err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); |
240 | if (err) { | 239 | if (err) { |
241 | set_cpu_active(cpu, true); | ||
242 | |||
243 | nr_calls--; | 240 | nr_calls--; |
244 | __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); | 241 | __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); |
245 | printk("%s: attempt to take down CPU %u failed\n", | 242 | printk("%s: attempt to take down CPU %u failed\n", |
@@ -249,7 +246,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) | |||
249 | 246 | ||
250 | err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); | 247 | err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); |
251 | if (err) { | 248 | if (err) { |
252 | set_cpu_active(cpu, true); | ||
253 | /* CPU didn't die: tell everyone. Can't complain. */ | 249 | /* CPU didn't die: tell everyone. Can't complain. */ |
254 | cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); | 250 | cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); |
255 | 251 | ||
@@ -321,8 +317,6 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) | |||
321 | goto out_notify; | 317 | goto out_notify; |
322 | BUG_ON(!cpu_online(cpu)); | 318 | BUG_ON(!cpu_online(cpu)); |
323 | 319 | ||
324 | set_cpu_active(cpu, true); | ||
325 | |||
326 | /* Now call notifier in preparation. */ | 320 | /* Now call notifier in preparation. */ |
327 | cpu_notify(CPU_ONLINE | mod, hcpu); | 321 | cpu_notify(CPU_ONLINE | mod, hcpu); |
328 | 322 | ||
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 02b9611eadde..05727dcaa80d 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -2113,31 +2113,17 @@ static void scan_for_empty_cpusets(struct cpuset *root) | |||
2113 | * but making no active use of cpusets. | 2113 | * but making no active use of cpusets. |
2114 | * | 2114 | * |
2115 | * This routine ensures that top_cpuset.cpus_allowed tracks | 2115 | * This routine ensures that top_cpuset.cpus_allowed tracks |
2116 | * cpu_online_map on each CPU hotplug (cpuhp) event. | 2116 | * cpu_active_mask on each CPU hotplug (cpuhp) event. |
2117 | * | 2117 | * |
2118 | * Called within get_online_cpus(). Needs to call cgroup_lock() | 2118 | * Called within get_online_cpus(). Needs to call cgroup_lock() |
2119 | * before calling generate_sched_domains(). | 2119 | * before calling generate_sched_domains(). |
2120 | */ | 2120 | */ |
2121 | static int cpuset_track_online_cpus(struct notifier_block *unused_nb, | 2121 | void __cpuexit cpuset_update_active_cpus(void) |
2122 | unsigned long phase, void *unused_cpu) | ||
2123 | { | 2122 | { |
2124 | struct sched_domain_attr *attr; | 2123 | struct sched_domain_attr *attr; |
2125 | cpumask_var_t *doms; | 2124 | cpumask_var_t *doms; |
2126 | int ndoms; | 2125 | int ndoms; |
2127 | 2126 | ||
2128 | switch (phase) { | ||
2129 | case CPU_ONLINE: | ||
2130 | case CPU_ONLINE_FROZEN: | ||
2131 | case CPU_DOWN_PREPARE: | ||
2132 | case CPU_DOWN_PREPARE_FROZEN: | ||
2133 | case CPU_DOWN_FAILED: | ||
2134 | case CPU_DOWN_FAILED_FROZEN: | ||
2135 | break; | ||
2136 | |||
2137 | default: | ||
2138 | return NOTIFY_DONE; | ||
2139 | } | ||
2140 | |||
2141 | cgroup_lock(); | 2127 | cgroup_lock(); |
2142 | mutex_lock(&callback_mutex); | 2128 | mutex_lock(&callback_mutex); |
2143 | cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); | 2129 | cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); |
@@ -2148,8 +2134,6 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, | |||
2148 | 2134 | ||
2149 | /* Have scheduler rebuild the domains */ | 2135 | /* Have scheduler rebuild the domains */ |
2150 | partition_sched_domains(ndoms, doms, attr); | 2136 | partition_sched_domains(ndoms, doms, attr); |
2151 | |||
2152 | return NOTIFY_OK; | ||
2153 | } | 2137 | } |
2154 | 2138 | ||
2155 | #ifdef CONFIG_MEMORY_HOTPLUG | 2139 | #ifdef CONFIG_MEMORY_HOTPLUG |
@@ -2203,7 +2187,6 @@ void __init cpuset_init_smp(void) | |||
2203 | cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); | 2187 | cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); |
2204 | top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; | 2188 | top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; |
2205 | 2189 | ||
2206 | hotcpu_notifier(cpuset_track_online_cpus, 0); | ||
2207 | hotplug_memory_notifier(cpuset_track_online_nodes, 10); | 2190 | hotplug_memory_notifier(cpuset_track_online_nodes, 10); |
2208 | 2191 | ||
2209 | cpuset_wq = create_singlethread_workqueue("cpuset"); | 2192 | cpuset_wq = create_singlethread_workqueue("cpuset"); |
diff --git a/kernel/fork.c b/kernel/fork.c index b6cce14ba047..a82a65cef741 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -907,7 +907,7 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
907 | { | 907 | { |
908 | unsigned long new_flags = p->flags; | 908 | unsigned long new_flags = p->flags; |
909 | 909 | ||
910 | new_flags &= ~PF_SUPERPRIV; | 910 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); |
911 | new_flags |= PF_FORKNOEXEC; | 911 | new_flags |= PF_FORKNOEXEC; |
912 | new_flags |= PF_STARTING; | 912 | new_flags |= PF_STARTING; |
913 | p->flags = new_flags; | 913 | p->flags = new_flags; |
diff --git a/kernel/sched.c b/kernel/sched.c index 2aaceebd484c..8f351c56567f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <asm/irq_regs.h> | 77 | #include <asm/irq_regs.h> |
78 | 78 | ||
79 | #include "sched_cpupri.h" | 79 | #include "sched_cpupri.h" |
80 | #include "workqueue_sched.h" | ||
80 | 81 | ||
81 | #define CREATE_TRACE_POINTS | 82 | #define CREATE_TRACE_POINTS |
82 | #include <trace/events/sched.h> | 83 | #include <trace/events/sched.h> |
@@ -2264,11 +2265,55 @@ static void update_avg(u64 *avg, u64 sample) | |||
2264 | } | 2265 | } |
2265 | #endif | 2266 | #endif |
2266 | 2267 | ||
2267 | /*** | 2268 | static inline void ttwu_activate(struct task_struct *p, struct rq *rq, |
2269 | bool is_sync, bool is_migrate, bool is_local, | ||
2270 | unsigned long en_flags) | ||
2271 | { | ||
2272 | schedstat_inc(p, se.statistics.nr_wakeups); | ||
2273 | if (is_sync) | ||
2274 | schedstat_inc(p, se.statistics.nr_wakeups_sync); | ||
2275 | if (is_migrate) | ||
2276 | schedstat_inc(p, se.statistics.nr_wakeups_migrate); | ||
2277 | if (is_local) | ||
2278 | schedstat_inc(p, se.statistics.nr_wakeups_local); | ||
2279 | else | ||
2280 | schedstat_inc(p, se.statistics.nr_wakeups_remote); | ||
2281 | |||
2282 | activate_task(rq, p, en_flags); | ||
2283 | } | ||
2284 | |||
2285 | static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq, | ||
2286 | int wake_flags, bool success) | ||
2287 | { | ||
2288 | trace_sched_wakeup(p, success); | ||
2289 | check_preempt_curr(rq, p, wake_flags); | ||
2290 | |||
2291 | p->state = TASK_RUNNING; | ||
2292 | #ifdef CONFIG_SMP | ||
2293 | if (p->sched_class->task_woken) | ||
2294 | p->sched_class->task_woken(rq, p); | ||
2295 | |||
2296 | if (unlikely(rq->idle_stamp)) { | ||
2297 | u64 delta = rq->clock - rq->idle_stamp; | ||
2298 | u64 max = 2*sysctl_sched_migration_cost; | ||
2299 | |||
2300 | if (delta > max) | ||
2301 | rq->avg_idle = max; | ||
2302 | else | ||
2303 | update_avg(&rq->avg_idle, delta); | ||
2304 | rq->idle_stamp = 0; | ||
2305 | } | ||
2306 | #endif | ||
2307 | /* if a worker is waking up, notify workqueue */ | ||
2308 | if ((p->flags & PF_WQ_WORKER) && success) | ||
2309 | wq_worker_waking_up(p, cpu_of(rq)); | ||
2310 | } | ||
2311 | |||
2312 | /** | ||
2268 | * try_to_wake_up - wake up a thread | 2313 | * try_to_wake_up - wake up a thread |
2269 | * @p: the to-be-woken-up thread | 2314 | * @p: the thread to be awakened |
2270 | * @state: the mask of task states that can be woken | 2315 | * @state: the mask of task states that can be woken |
2271 | * @sync: do a synchronous wakeup? | 2316 | * @wake_flags: wake modifier flags (WF_*) |
2272 | * | 2317 | * |
2273 | * Put it on the run-queue if it's not already there. The "current" | 2318 | * Put it on the run-queue if it's not already there. The "current" |
2274 | * thread is always on the run-queue (except when the actual | 2319 | * thread is always on the run-queue (except when the actual |
@@ -2276,7 +2321,8 @@ static void update_avg(u64 *avg, u64 sample) | |||
2276 | * the simpler "current->state = TASK_RUNNING" to mark yourself | 2321 | * the simpler "current->state = TASK_RUNNING" to mark yourself |
2277 | * runnable without the overhead of this. | 2322 | * runnable without the overhead of this. |
2278 | * | 2323 | * |
2279 | * returns failure only if the task is already active. | 2324 | * Returns %true if @p was woken up, %false if it was already running |
2325 | * or @state didn't match @p's state. | ||
2280 | */ | 2326 | */ |
2281 | static int try_to_wake_up(struct task_struct *p, unsigned int state, | 2327 | static int try_to_wake_up(struct task_struct *p, unsigned int state, |
2282 | int wake_flags) | 2328 | int wake_flags) |
@@ -2356,38 +2402,11 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, | |||
2356 | 2402 | ||
2357 | out_activate: | 2403 | out_activate: |
2358 | #endif /* CONFIG_SMP */ | 2404 | #endif /* CONFIG_SMP */ |
2359 | schedstat_inc(p, se.statistics.nr_wakeups); | 2405 | ttwu_activate(p, rq, wake_flags & WF_SYNC, orig_cpu != cpu, |
2360 | if (wake_flags & WF_SYNC) | 2406 | cpu == this_cpu, en_flags); |
2361 | schedstat_inc(p, se.statistics.nr_wakeups_sync); | ||
2362 | if (orig_cpu != cpu) | ||
2363 | schedstat_inc(p, se.statistics.nr_wakeups_migrate); | ||
2364 | if (cpu == this_cpu) | ||
2365 | schedstat_inc(p, se.statistics.nr_wakeups_local); | ||
2366 | else | ||
2367 | schedstat_inc(p, se.statistics.nr_wakeups_remote); | ||
2368 | activate_task(rq, p, en_flags); | ||
2369 | success = 1; | 2407 | success = 1; |
2370 | |||
2371 | out_running: | 2408 | out_running: |
2372 | trace_sched_wakeup(p, success); | 2409 | ttwu_post_activation(p, rq, wake_flags, success); |
2373 | check_preempt_curr(rq, p, wake_flags); | ||
2374 | |||
2375 | p->state = TASK_RUNNING; | ||
2376 | #ifdef CONFIG_SMP | ||
2377 | if (p->sched_class->task_woken) | ||
2378 | p->sched_class->task_woken(rq, p); | ||
2379 | |||
2380 | if (unlikely(rq->idle_stamp)) { | ||
2381 | u64 delta = rq->clock - rq->idle_stamp; | ||
2382 | u64 max = 2*sysctl_sched_migration_cost; | ||
2383 | |||
2384 | if (delta > max) | ||
2385 | rq->avg_idle = max; | ||
2386 | else | ||
2387 | update_avg(&rq->avg_idle, delta); | ||
2388 | rq->idle_stamp = 0; | ||
2389 | } | ||
2390 | #endif | ||
2391 | out: | 2410 | out: |
2392 | task_rq_unlock(rq, &flags); | 2411 | task_rq_unlock(rq, &flags); |
2393 | put_cpu(); | 2412 | put_cpu(); |
@@ -2396,6 +2415,37 @@ out: | |||
2396 | } | 2415 | } |
2397 | 2416 | ||
2398 | /** | 2417 | /** |
2418 | * try_to_wake_up_local - try to wake up a local task with rq lock held | ||
2419 | * @p: the thread to be awakened | ||
2420 | * | ||
2421 | * Put @p on the run-queue if it's not alredy there. The caller must | ||
2422 | * ensure that this_rq() is locked, @p is bound to this_rq() and not | ||
2423 | * the current task. this_rq() stays locked over invocation. | ||
2424 | */ | ||
2425 | static void try_to_wake_up_local(struct task_struct *p) | ||
2426 | { | ||
2427 | struct rq *rq = task_rq(p); | ||
2428 | bool success = false; | ||
2429 | |||
2430 | BUG_ON(rq != this_rq()); | ||
2431 | BUG_ON(p == current); | ||
2432 | lockdep_assert_held(&rq->lock); | ||
2433 | |||
2434 | if (!(p->state & TASK_NORMAL)) | ||
2435 | return; | ||
2436 | |||
2437 | if (!p->se.on_rq) { | ||
2438 | if (likely(!task_running(rq, p))) { | ||
2439 | schedstat_inc(rq, ttwu_count); | ||
2440 | schedstat_inc(rq, ttwu_local); | ||
2441 | } | ||
2442 | ttwu_activate(p, rq, false, false, true, ENQUEUE_WAKEUP); | ||
2443 | success = true; | ||
2444 | } | ||
2445 | ttwu_post_activation(p, rq, 0, success); | ||
2446 | } | ||
2447 | |||
2448 | /** | ||
2399 | * wake_up_process - Wake up a specific process | 2449 | * wake_up_process - Wake up a specific process |
2400 | * @p: The process to be woken up. | 2450 | * @p: The process to be woken up. |
2401 | * | 2451 | * |
@@ -3600,10 +3650,24 @@ need_resched_nonpreemptible: | |||
3600 | clear_tsk_need_resched(prev); | 3650 | clear_tsk_need_resched(prev); |
3601 | 3651 | ||
3602 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { | 3652 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { |
3603 | if (unlikely(signal_pending_state(prev->state, prev))) | 3653 | if (unlikely(signal_pending_state(prev->state, prev))) { |
3604 | prev->state = TASK_RUNNING; | 3654 | prev->state = TASK_RUNNING; |
3605 | else | 3655 | } else { |
3656 | /* | ||
3657 | * If a worker is going to sleep, notify and | ||
3658 | * ask workqueue whether it wants to wake up a | ||
3659 | * task to maintain concurrency. If so, wake | ||
3660 | * up the task. | ||
3661 | */ | ||
3662 | if (prev->flags & PF_WQ_WORKER) { | ||
3663 | struct task_struct *to_wakeup; | ||
3664 | |||
3665 | to_wakeup = wq_worker_sleeping(prev, cpu); | ||
3666 | if (to_wakeup) | ||
3667 | try_to_wake_up_local(to_wakeup); | ||
3668 | } | ||
3606 | deactivate_task(rq, prev, DEQUEUE_SLEEP); | 3669 | deactivate_task(rq, prev, DEQUEUE_SLEEP); |
3670 | } | ||
3607 | switch_count = &prev->nvcsw; | 3671 | switch_count = &prev->nvcsw; |
3608 | } | 3672 | } |
3609 | 3673 | ||
@@ -5804,20 +5868,49 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
5804 | */ | 5868 | */ |
5805 | static struct notifier_block __cpuinitdata migration_notifier = { | 5869 | static struct notifier_block __cpuinitdata migration_notifier = { |
5806 | .notifier_call = migration_call, | 5870 | .notifier_call = migration_call, |
5807 | .priority = 10 | 5871 | .priority = CPU_PRI_MIGRATION, |
5808 | }; | 5872 | }; |
5809 | 5873 | ||
5874 | static int __cpuinit sched_cpu_active(struct notifier_block *nfb, | ||
5875 | unsigned long action, void *hcpu) | ||
5876 | { | ||
5877 | switch (action & ~CPU_TASKS_FROZEN) { | ||
5878 | case CPU_ONLINE: | ||
5879 | case CPU_DOWN_FAILED: | ||
5880 | set_cpu_active((long)hcpu, true); | ||
5881 | return NOTIFY_OK; | ||
5882 | default: | ||
5883 | return NOTIFY_DONE; | ||
5884 | } | ||
5885 | } | ||
5886 | |||
5887 | static int __cpuinit sched_cpu_inactive(struct notifier_block *nfb, | ||
5888 | unsigned long action, void *hcpu) | ||
5889 | { | ||
5890 | switch (action & ~CPU_TASKS_FROZEN) { | ||
5891 | case CPU_DOWN_PREPARE: | ||
5892 | set_cpu_active((long)hcpu, false); | ||
5893 | return NOTIFY_OK; | ||
5894 | default: | ||
5895 | return NOTIFY_DONE; | ||
5896 | } | ||
5897 | } | ||
5898 | |||
5810 | static int __init migration_init(void) | 5899 | static int __init migration_init(void) |
5811 | { | 5900 | { |
5812 | void *cpu = (void *)(long)smp_processor_id(); | 5901 | void *cpu = (void *)(long)smp_processor_id(); |
5813 | int err; | 5902 | int err; |
5814 | 5903 | ||
5815 | /* Start one for the boot CPU: */ | 5904 | /* Initialize migration for the boot CPU */ |
5816 | err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu); | 5905 | err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu); |
5817 | BUG_ON(err == NOTIFY_BAD); | 5906 | BUG_ON(err == NOTIFY_BAD); |
5818 | migration_call(&migration_notifier, CPU_ONLINE, cpu); | 5907 | migration_call(&migration_notifier, CPU_ONLINE, cpu); |
5819 | register_cpu_notifier(&migration_notifier); | 5908 | register_cpu_notifier(&migration_notifier); |
5820 | 5909 | ||
5910 | /* Register cpu active notifiers */ | ||
5911 | cpu_notifier(sched_cpu_active, CPU_PRI_SCHED_ACTIVE); | ||
5912 | cpu_notifier(sched_cpu_inactive, CPU_PRI_SCHED_INACTIVE); | ||
5913 | |||
5821 | return 0; | 5914 | return 0; |
5822 | } | 5915 | } |
5823 | early_initcall(migration_init); | 5916 | early_initcall(migration_init); |
@@ -7276,29 +7369,35 @@ int __init sched_create_sysfs_power_savings_entries(struct sysdev_class *cls) | |||
7276 | } | 7369 | } |
7277 | #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ | 7370 | #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ |
7278 | 7371 | ||
7279 | #ifndef CONFIG_CPUSETS | ||
7280 | /* | 7372 | /* |
7281 | * Add online and remove offline CPUs from the scheduler domains. | 7373 | * Update cpusets according to cpu_active mask. If cpusets are |
7282 | * When cpusets are enabled they take over this function. | 7374 | * disabled, cpuset_update_active_cpus() becomes a simple wrapper |
7375 | * around partition_sched_domains(). | ||
7283 | */ | 7376 | */ |
7284 | static int update_sched_domains(struct notifier_block *nfb, | 7377 | static int __cpuexit cpuset_cpu_active(struct notifier_block *nfb, |
7285 | unsigned long action, void *hcpu) | 7378 | unsigned long action, void *hcpu) |
7286 | { | 7379 | { |
7287 | switch (action) { | 7380 | switch (action & ~CPU_TASKS_FROZEN) { |
7288 | case CPU_ONLINE: | 7381 | case CPU_ONLINE: |
7289 | case CPU_ONLINE_FROZEN: | ||
7290 | case CPU_DOWN_PREPARE: | ||
7291 | case CPU_DOWN_PREPARE_FROZEN: | ||
7292 | case CPU_DOWN_FAILED: | 7382 | case CPU_DOWN_FAILED: |
7293 | case CPU_DOWN_FAILED_FROZEN: | 7383 | cpuset_update_active_cpus(); |
7294 | partition_sched_domains(1, NULL, NULL); | ||
7295 | return NOTIFY_OK; | 7384 | return NOTIFY_OK; |
7385 | default: | ||
7386 | return NOTIFY_DONE; | ||
7387 | } | ||
7388 | } | ||
7296 | 7389 | ||
7390 | static int __cpuexit cpuset_cpu_inactive(struct notifier_block *nfb, | ||
7391 | unsigned long action, void *hcpu) | ||
7392 | { | ||
7393 | switch (action & ~CPU_TASKS_FROZEN) { | ||
7394 | case CPU_DOWN_PREPARE: | ||
7395 | cpuset_update_active_cpus(); | ||
7396 | return NOTIFY_OK; | ||
7297 | default: | 7397 | default: |
7298 | return NOTIFY_DONE; | 7398 | return NOTIFY_DONE; |
7299 | } | 7399 | } |
7300 | } | 7400 | } |
7301 | #endif | ||
7302 | 7401 | ||
7303 | static int update_runtime(struct notifier_block *nfb, | 7402 | static int update_runtime(struct notifier_block *nfb, |
7304 | unsigned long action, void *hcpu) | 7403 | unsigned long action, void *hcpu) |
@@ -7344,10 +7443,8 @@ void __init sched_init_smp(void) | |||
7344 | mutex_unlock(&sched_domains_mutex); | 7443 | mutex_unlock(&sched_domains_mutex); |
7345 | put_online_cpus(); | 7444 | put_online_cpus(); |
7346 | 7445 | ||
7347 | #ifndef CONFIG_CPUSETS | 7446 | hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE); |
7348 | /* XXX: Theoretical race here - CPU may be hotplugged now */ | 7447 | hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE); |
7349 | hotcpu_notifier(update_sched_domains, 0); | ||
7350 | #endif | ||
7351 | 7448 | ||
7352 | /* RT runtime code needs to handle some hotplug events */ | 7449 | /* RT runtime code needs to handle some hotplug events */ |
7353 | hotcpu_notifier(update_runtime, 0); | 7450 | hotcpu_notifier(update_runtime, 0); |
diff --git a/kernel/workqueue_sched.h b/kernel/workqueue_sched.h new file mode 100644 index 000000000000..af040babb742 --- /dev/null +++ b/kernel/workqueue_sched.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * kernel/workqueue_sched.h | ||
3 | * | ||
4 | * Scheduler hooks for concurrency managed workqueue. Only to be | ||
5 | * included from sched.c and workqueue.c. | ||
6 | */ | ||
7 | static inline void wq_worker_waking_up(struct task_struct *task, | ||
8 | unsigned int cpu) | ||
9 | { | ||
10 | } | ||
11 | |||
12 | static inline struct task_struct *wq_worker_sleeping(struct task_struct *task, | ||
13 | unsigned int cpu) | ||
14 | { | ||
15 | return NULL; | ||
16 | } | ||