diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-09-24 04:18:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-10-28 05:56:24 -0400 |
commit | 7d4d26966e0b6443c78123a8a8b602e8eaf67694 (patch) | |
tree | 56793392505afde8a8ceff3d6866bea33c31cdfb | |
parent | 97d9e28d1a27b84a6a0b155f2390289afa279341 (diff) |
sched, smp: Correctly deal with nested sleeps
smp_hotplug_thread::{setup,unpark} functions can sleep too, so be
consistent and do the same for all callbacks.
__might_sleep+0x74/0x80
kmem_cache_alloc_trace+0x4e/0x1c0
perf_event_alloc+0x55/0x450
perf_event_create_kernel_counter+0x2f/0x100
watchdog_nmi_enable+0x8d/0x160
watchdog_enable+0x45/0x90
smpboot_thread_fn+0xec/0x2b0
kthread+0xe4/0x100
ret_from_fork+0x7c/0xb0
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: tglx@linutronix.de
Cc: ilya.dryomov@inktank.com
Cc: umgwanakikbuti@gmail.com
Cc: oleg@redhat.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/20140924082242.392279328@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | kernel/smpboot.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/kernel/smpboot.c b/kernel/smpboot.c index eb89e1807408..f032fb5284e3 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c | |||
@@ -110,7 +110,7 @@ static int smpboot_thread_fn(void *data) | |||
110 | set_current_state(TASK_INTERRUPTIBLE); | 110 | set_current_state(TASK_INTERRUPTIBLE); |
111 | preempt_disable(); | 111 | preempt_disable(); |
112 | if (kthread_should_stop()) { | 112 | if (kthread_should_stop()) { |
113 | set_current_state(TASK_RUNNING); | 113 | __set_current_state(TASK_RUNNING); |
114 | preempt_enable(); | 114 | preempt_enable(); |
115 | if (ht->cleanup) | 115 | if (ht->cleanup) |
116 | ht->cleanup(td->cpu, cpu_online(td->cpu)); | 116 | ht->cleanup(td->cpu, cpu_online(td->cpu)); |
@@ -136,26 +136,27 @@ static int smpboot_thread_fn(void *data) | |||
136 | /* Check for state change setup */ | 136 | /* Check for state change setup */ |
137 | switch (td->status) { | 137 | switch (td->status) { |
138 | case HP_THREAD_NONE: | 138 | case HP_THREAD_NONE: |
139 | __set_current_state(TASK_RUNNING); | ||
139 | preempt_enable(); | 140 | preempt_enable(); |
140 | if (ht->setup) | 141 | if (ht->setup) |
141 | ht->setup(td->cpu); | 142 | ht->setup(td->cpu); |
142 | td->status = HP_THREAD_ACTIVE; | 143 | td->status = HP_THREAD_ACTIVE; |
143 | preempt_disable(); | 144 | continue; |
144 | break; | 145 | |
145 | case HP_THREAD_PARKED: | 146 | case HP_THREAD_PARKED: |
147 | __set_current_state(TASK_RUNNING); | ||
146 | preempt_enable(); | 148 | preempt_enable(); |
147 | if (ht->unpark) | 149 | if (ht->unpark) |
148 | ht->unpark(td->cpu); | 150 | ht->unpark(td->cpu); |
149 | td->status = HP_THREAD_ACTIVE; | 151 | td->status = HP_THREAD_ACTIVE; |
150 | preempt_disable(); | 152 | continue; |
151 | break; | ||
152 | } | 153 | } |
153 | 154 | ||
154 | if (!ht->thread_should_run(td->cpu)) { | 155 | if (!ht->thread_should_run(td->cpu)) { |
155 | preempt_enable(); | 156 | preempt_enable_no_resched(); |
156 | schedule(); | 157 | schedule(); |
157 | } else { | 158 | } else { |
158 | set_current_state(TASK_RUNNING); | 159 | __set_current_state(TASK_RUNNING); |
159 | preempt_enable(); | 160 | preempt_enable(); |
160 | ht->thread_fn(td->cpu); | 161 | ht->thread_fn(td->cpu); |
161 | } | 162 | } |