aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kthread.c')
-rw-r--r--kernel/kthread.c87
1 files changed, 35 insertions, 52 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 4ebaf8519abf..9b1a7de26979 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -9,11 +9,12 @@
9#include <linux/kthread.h> 9#include <linux/kthread.h>
10#include <linux/completion.h> 10#include <linux/completion.h>
11#include <linux/err.h> 11#include <linux/err.h>
12#include <linux/cpuset.h>
12#include <linux/unistd.h> 13#include <linux/unistd.h>
13#include <linux/file.h> 14#include <linux/file.h>
14#include <linux/module.h> 15#include <linux/module.h>
15#include <linux/mutex.h> 16#include <linux/mutex.h>
16#include <trace/sched.h> 17#include <trace/events/sched.h>
17 18
18#define KTHREAD_NICE_LEVEL (-5) 19#define KTHREAD_NICE_LEVEL (-5)
19 20
@@ -21,15 +22,11 @@ static DEFINE_SPINLOCK(kthread_create_lock);
21static LIST_HEAD(kthread_create_list); 22static LIST_HEAD(kthread_create_list);
22struct task_struct *kthreadd_task; 23struct task_struct *kthreadd_task;
23 24
24DEFINE_TRACE(sched_kthread_stop);
25DEFINE_TRACE(sched_kthread_stop_ret);
26
27struct kthread_create_info 25struct kthread_create_info
28{ 26{
29 /* Information passed to kthread() from kthreadd. */ 27 /* Information passed to kthread() from kthreadd. */
30 int (*threadfn)(void *data); 28 int (*threadfn)(void *data);
31 void *data; 29 void *data;
32 struct completion started;
33 30
34 /* Result passed back to kthread_create() from kthreadd. */ 31 /* Result passed back to kthread_create() from kthreadd. */
35 struct task_struct *result; 32 struct task_struct *result;
@@ -38,17 +35,13 @@ struct kthread_create_info
38 struct list_head list; 35 struct list_head list;
39}; 36};
40 37
41struct kthread_stop_info 38struct kthread {
42{ 39 int should_stop;
43 struct task_struct *k; 40 struct completion exited;
44 int err;
45 struct completion done;
46}; 41};
47 42
48/* Thread stopping is done by setthing this var: lock serializes 43#define to_kthread(tsk) \
49 * multiple kthread_stop calls. */ 44 container_of((tsk)->vfork_done, struct kthread, exited)
50static DEFINE_MUTEX(kthread_stop_lock);
51static struct kthread_stop_info kthread_stop_info;
52 45
53/** 46/**
54 * kthread_should_stop - should this kthread return now? 47 * kthread_should_stop - should this kthread return now?
@@ -59,36 +52,35 @@ static struct kthread_stop_info kthread_stop_info;
59 */ 52 */
60int kthread_should_stop(void) 53int kthread_should_stop(void)
61{ 54{
62 return (kthread_stop_info.k == current); 55 return to_kthread(current)->should_stop;
63} 56}
64EXPORT_SYMBOL(kthread_should_stop); 57EXPORT_SYMBOL(kthread_should_stop);
65 58
66static int kthread(void *_create) 59static int kthread(void *_create)
67{ 60{
61 /* Copy data: it's on kthread's stack */
68 struct kthread_create_info *create = _create; 62 struct kthread_create_info *create = _create;
69 int (*threadfn)(void *data); 63 int (*threadfn)(void *data) = create->threadfn;
70 void *data; 64 void *data = create->data;
71 int ret = -EINTR; 65 struct kthread self;
66 int ret;
72 67
73 /* Copy data: it's on kthread's stack */ 68 self.should_stop = 0;
74 threadfn = create->threadfn; 69 init_completion(&self.exited);
75 data = create->data; 70 current->vfork_done = &self.exited;
76 71
77 /* OK, tell user we're spawned, wait for stop or wakeup */ 72 /* OK, tell user we're spawned, wait for stop or wakeup */
78 __set_current_state(TASK_UNINTERRUPTIBLE); 73 __set_current_state(TASK_UNINTERRUPTIBLE);
79 create->result = current; 74 create->result = current;
80 complete(&create->started); 75 complete(&create->done);
81 schedule(); 76 schedule();
82 77
83 if (!kthread_should_stop()) 78 ret = -EINTR;
79 if (!self.should_stop)
84 ret = threadfn(data); 80 ret = threadfn(data);
85 81
86 /* It might have exited on its own, w/o kthread_stop. Check. */ 82 /* we can't just return, we must preserve "self" on stack */
87 if (kthread_should_stop()) { 83 do_exit(ret);
88 kthread_stop_info.err = ret;
89 complete(&kthread_stop_info.done);
90 }
91 return 0;
92} 84}
93 85
94static void create_kthread(struct kthread_create_info *create) 86static void create_kthread(struct kthread_create_info *create)
@@ -97,11 +89,10 @@ static void create_kthread(struct kthread_create_info *create)
97 89
98 /* We want our own signal handler (we take no signals by default). */ 90 /* We want our own signal handler (we take no signals by default). */
99 pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD); 91 pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
100 if (pid < 0) 92 if (pid < 0) {
101 create->result = ERR_PTR(pid); 93 create->result = ERR_PTR(pid);
102 else 94 complete(&create->done);
103 wait_for_completion(&create->started); 95 }
104 complete(&create->done);
105} 96}
106 97
107/** 98/**
@@ -132,7 +123,6 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
132 123
133 create.threadfn = threadfn; 124 create.threadfn = threadfn;
134 create.data = data; 125 create.data = data;
135 init_completion(&create.started);
136 init_completion(&create.done); 126 init_completion(&create.done);
137 127
138 spin_lock(&kthread_create_lock); 128 spin_lock(&kthread_create_lock);
@@ -200,30 +190,22 @@ EXPORT_SYMBOL(kthread_bind);
200 */ 190 */
201int kthread_stop(struct task_struct *k) 191int kthread_stop(struct task_struct *k)
202{ 192{
193 struct kthread *kthread;
203 int ret; 194 int ret;
204 195
205 mutex_lock(&kthread_stop_lock);
206
207 /* It could exit after stop_info.k set, but before wake_up_process. */
208 get_task_struct(k);
209
210 trace_sched_kthread_stop(k); 196 trace_sched_kthread_stop(k);
197 get_task_struct(k);
211 198
212 /* Must init completion *before* thread sees kthread_stop_info.k */ 199 kthread = to_kthread(k);
213 init_completion(&kthread_stop_info.done); 200 barrier(); /* it might have exited */
214 smp_wmb(); 201 if (k->vfork_done != NULL) {
202 kthread->should_stop = 1;
203 wake_up_process(k);
204 wait_for_completion(&kthread->exited);
205 }
206 ret = k->exit_code;
215 207
216 /* Now set kthread_should_stop() to true, and wake it up. */
217 kthread_stop_info.k = k;
218 wake_up_process(k);
219 put_task_struct(k); 208 put_task_struct(k);
220
221 /* Once it dies, reset stop ptr, gather result and we're done. */
222 wait_for_completion(&kthread_stop_info.done);
223 kthread_stop_info.k = NULL;
224 ret = kthread_stop_info.err;
225 mutex_unlock(&kthread_stop_lock);
226
227 trace_sched_kthread_stop_ret(ret); 209 trace_sched_kthread_stop_ret(ret);
228 210
229 return ret; 211 return ret;
@@ -239,6 +221,7 @@ int kthreadd(void *unused)
239 ignore_signals(tsk); 221 ignore_signals(tsk);
240 set_user_nice(tsk, KTHREAD_NICE_LEVEL); 222 set_user_nice(tsk, KTHREAD_NICE_LEVEL);
241 set_cpus_allowed_ptr(tsk, cpu_all_mask); 223 set_cpus_allowed_ptr(tsk, cpu_all_mask);
224 set_mems_allowed(node_possible_map);
242 225
243 current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; 226 current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
244 227