aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kthread.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 01:45:43 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 01:45:43 -0500
commit5cbb3d216e2041700231bcfc383ee5f8b7fc8b74 (patch)
treea738fa82dbcefa9bd283c08bc67f38827be63937 /kernel/kthread.c
parent9bc9ccd7db1c9f043f75380b5a5b94912046a60e (diff)
parent4e9b45a19241354daec281d7a785739829b52359 (diff)
Merge branch 'akpm' (patches from Andrew Morton)
Merge first patch-bomb from Andrew Morton: "Quite a lot of other stuff is banked up awaiting further next->mainline merging, but this batch contains: - Lots of random misc patches - OCFS2 - Most of MM - backlight updates - lib/ updates - printk updates - checkpatch updates - epoll tweaking - rtc updates - hfs - hfsplus - documentation - procfs - update gcov to gcc-4.7 format - IPC" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (269 commits) ipc, msg: fix message length check for negative values ipc/util.c: remove unnecessary work pending test devpts: plug the memory leak in kill_sb ./Makefile: export initial ramdisk compression config option init/Kconfig: add option to disable kernel compression drivers: w1: make w1_slave::flags long to avoid memory corruption drivers/w1/masters/ds1wm.cuse dev_get_platdata() drivers/memstick/core/ms_block.c: fix unreachable state in h_msb_read_page() drivers/memstick/core/mspro_block.c: fix attributes array allocation drivers/pps/clients/pps-gpio.c: remove redundant of_match_ptr kernel/panic.c: reduce 1 byte usage for print tainted buffer gcov: reuse kbasename helper kernel/gcov/fs.c: use pr_warn() kernel/module.c: use pr_foo() gcov: compile specific gcov implementation based on gcc version gcov: add support for gcc 4.7 gcov format gcov: move gcov structs definitions to a gcc version specific file kernel/taskstats.c: return -ENOMEM when alloc memory fails in add_del_listener() kernel/taskstats.c: add nla_nest_cancel() for failure processing between nla_nest_start() and nla_nest_end() kernel/sysctl_binary.c: use scnprintf() instead of snprintf() ...
Diffstat (limited to 'kernel/kthread.c')
-rw-r--r--kernel/kthread.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 760e86df8c20..b5ae3ee860a9 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -33,7 +33,7 @@ struct kthread_create_info
33 33
34 /* Result passed back to kthread_create() from kthreadd. */ 34 /* Result passed back to kthread_create() from kthreadd. */
35 struct task_struct *result; 35 struct task_struct *result;
36 struct completion done; 36 struct completion *done;
37 37
38 struct list_head list; 38 struct list_head list;
39}; 39};
@@ -178,6 +178,7 @@ static int kthread(void *_create)
178 struct kthread_create_info *create = _create; 178 struct kthread_create_info *create = _create;
179 int (*threadfn)(void *data) = create->threadfn; 179 int (*threadfn)(void *data) = create->threadfn;
180 void *data = create->data; 180 void *data = create->data;
181 struct completion *done;
181 struct kthread self; 182 struct kthread self;
182 int ret; 183 int ret;
183 184
@@ -187,10 +188,16 @@ static int kthread(void *_create)
187 init_completion(&self.parked); 188 init_completion(&self.parked);
188 current->vfork_done = &self.exited; 189 current->vfork_done = &self.exited;
189 190
191 /* If user was SIGKILLed, I release the structure. */
192 done = xchg(&create->done, NULL);
193 if (!done) {
194 kfree(create);
195 do_exit(-EINTR);
196 }
190 /* OK, tell user we're spawned, wait for stop or wakeup */ 197 /* OK, tell user we're spawned, wait for stop or wakeup */
191 __set_current_state(TASK_UNINTERRUPTIBLE); 198 __set_current_state(TASK_UNINTERRUPTIBLE);
192 create->result = current; 199 create->result = current;
193 complete(&create->done); 200 complete(done);
194 schedule(); 201 schedule();
195 202
196 ret = -EINTR; 203 ret = -EINTR;
@@ -223,8 +230,15 @@ static void create_kthread(struct kthread_create_info *create)
223 /* We want our own signal handler (we take no signals by default). */ 230 /* We want our own signal handler (we take no signals by default). */
224 pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD); 231 pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
225 if (pid < 0) { 232 if (pid < 0) {
233 /* If user was SIGKILLed, I release the structure. */
234 struct completion *done = xchg(&create->done, NULL);
235
236 if (!done) {
237 kfree(create);
238 return;
239 }
226 create->result = ERR_PTR(pid); 240 create->result = ERR_PTR(pid);
227 complete(&create->done); 241 complete(done);
228 } 242 }
229} 243}
230 244
@@ -255,36 +269,59 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
255 const char namefmt[], 269 const char namefmt[],
256 ...) 270 ...)
257{ 271{
258 struct kthread_create_info create; 272 DECLARE_COMPLETION_ONSTACK(done);
259 273 struct task_struct *task;
260 create.threadfn = threadfn; 274 struct kthread_create_info *create = kmalloc(sizeof(*create),
261 create.data = data; 275 GFP_KERNEL);
262 create.node = node; 276
263 init_completion(&create.done); 277 if (!create)
278 return ERR_PTR(-ENOMEM);
279 create->threadfn = threadfn;
280 create->data = data;
281 create->node = node;
282 create->done = &done;
264 283
265 spin_lock(&kthread_create_lock); 284 spin_lock(&kthread_create_lock);
266 list_add_tail(&create.list, &kthread_create_list); 285 list_add_tail(&create->list, &kthread_create_list);
267 spin_unlock(&kthread_create_lock); 286 spin_unlock(&kthread_create_lock);
268 287
269 wake_up_process(kthreadd_task); 288 wake_up_process(kthreadd_task);
270 wait_for_completion(&create.done); 289 /*
271 290 * Wait for completion in killable state, for I might be chosen by
272 if (!IS_ERR(create.result)) { 291 * the OOM killer while kthreadd is trying to allocate memory for
292 * new kernel thread.
293 */
294 if (unlikely(wait_for_completion_killable(&done))) {
295 /*
296 * If I was SIGKILLed before kthreadd (or new kernel thread)
297 * calls complete(), leave the cleanup of this structure to
298 * that thread.
299 */
300 if (xchg(&create->done, NULL))
301 return ERR_PTR(-ENOMEM);
302 /*
303 * kthreadd (or new kernel thread) will call complete()
304 * shortly.
305 */
306 wait_for_completion(&done);
307 }
308 task = create->result;
309 if (!IS_ERR(task)) {
273 static const struct sched_param param = { .sched_priority = 0 }; 310 static const struct sched_param param = { .sched_priority = 0 };
274 va_list args; 311 va_list args;
275 312
276 va_start(args, namefmt); 313 va_start(args, namefmt);
277 vsnprintf(create.result->comm, sizeof(create.result->comm), 314 vsnprintf(task->comm, sizeof(task->comm), namefmt, args);
278 namefmt, args);
279 va_end(args); 315 va_end(args);
280 /* 316 /*
281 * root may have changed our (kthreadd's) priority or CPU mask. 317 * root may have changed our (kthreadd's) priority or CPU mask.
282 * The kernel thread should not inherit these properties. 318 * The kernel thread should not inherit these properties.
283 */ 319 */
284 sched_setscheduler_nocheck(create.result, SCHED_NORMAL, &param); 320 sched_setscheduler_nocheck(task, SCHED_NORMAL, &param);
285 set_cpus_allowed_ptr(create.result, cpu_all_mask); 321 set_cpus_allowed_ptr(task, cpu_all_mask);
286 } 322 }
287 return create.result; 323 kfree(create);
324 return task;
288} 325}
289EXPORT_SYMBOL(kthread_create_on_node); 326EXPORT_SYMBOL(kthread_create_on_node);
290 327