Blame view
kernel/kthread.c
6.59 KB
1da177e4c
|
1 2 3 |
/* Kernel thread helper functions. * Copyright (C) 2004 IBM Corporation, Rusty Russell. * |
73c279927
|
4 |
* Creation is done via kthreadd, so that we get a clean environment |
1da177e4c
|
5 6 7 8 9 10 11 |
* even if we're invoked from userspace (think modprobe, hotplug cpu, * etc.). */ #include <linux/sched.h> #include <linux/kthread.h> #include <linux/completion.h> #include <linux/err.h> |
58568d2a8
|
12 |
#include <linux/cpuset.h> |
1da177e4c
|
13 14 15 |
#include <linux/unistd.h> #include <linux/file.h> #include <linux/module.h> |
97d1f15b7
|
16 |
#include <linux/mutex.h> |
ad8d75fff
|
17 |
#include <trace/events/sched.h> |
1da177e4c
|
18 |
|
73c279927
|
19 20 21 |
static DEFINE_SPINLOCK(kthread_create_lock); static LIST_HEAD(kthread_create_list); struct task_struct *kthreadd_task; |
1da177e4c
|
22 23 24 |
struct kthread_create_info { |
73c279927
|
25 |
/* Information passed to kthread() from kthreadd. */ |
1da177e4c
|
26 27 |
int (*threadfn)(void *data); void *data; |
1da177e4c
|
28 |
|
73c279927
|
29 |
/* Result passed back to kthread_create() from kthreadd. */ |
1da177e4c
|
30 31 |
struct task_struct *result; struct completion done; |
65f27f384
|
32 |
|
73c279927
|
33 |
struct list_head list; |
1da177e4c
|
34 |
}; |
63706172f
|
35 36 37 |
struct kthread { int should_stop; struct completion exited; |
1da177e4c
|
38 |
}; |
63706172f
|
39 40 |
#define to_kthread(tsk) \ container_of((tsk)->vfork_done, struct kthread, exited) |
1da177e4c
|
41 |
|
9e37bd301
|
42 43 44 |
/** * kthread_should_stop - should this kthread return now? * |
72fd4a35a
|
45 |
* When someone calls kthread_stop() on your kthread, it will be woken |
9e37bd301
|
46 47 48 |
* and this will return true. You should then return, and your return * value will be passed through to kthread_stop(). */ |
1da177e4c
|
49 50 |
int kthread_should_stop(void) { |
63706172f
|
51 |
return to_kthread(current)->should_stop; |
1da177e4c
|
52 53 |
} EXPORT_SYMBOL(kthread_should_stop); |
1da177e4c
|
54 55 |
static int kthread(void *_create) { |
63706172f
|
56 |
/* Copy data: it's on kthread's stack */ |
1da177e4c
|
57 |
struct kthread_create_info *create = _create; |
63706172f
|
58 59 60 61 |
int (*threadfn)(void *data) = create->threadfn; void *data = create->data; struct kthread self; int ret; |
1da177e4c
|
62 |
|
63706172f
|
63 64 65 |
self.should_stop = 0; init_completion(&self.exited); current->vfork_done = &self.exited; |
1da177e4c
|
66 |
|
1da177e4c
|
67 |
/* OK, tell user we're spawned, wait for stop or wakeup */ |
a076e4bca
|
68 |
__set_current_state(TASK_UNINTERRUPTIBLE); |
3217ab97f
|
69 |
create->result = current; |
cdd140bdd
|
70 |
complete(&create->done); |
1da177e4c
|
71 |
schedule(); |
63706172f
|
72 73 |
ret = -EINTR; if (!self.should_stop) |
1da177e4c
|
74 |
ret = threadfn(data); |
63706172f
|
75 76 |
/* we can't just return, we must preserve "self" on stack */ do_exit(ret); |
1da177e4c
|
77 |
} |
73c279927
|
78 |
static void create_kthread(struct kthread_create_info *create) |
1da177e4c
|
79 |
{ |
1da177e4c
|
80 81 82 83 |
int pid; /* We want our own signal handler (we take no signals by default). */ pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD); |
cdd140bdd
|
84 |
if (pid < 0) { |
1da177e4c
|
85 |
create->result = ERR_PTR(pid); |
cdd140bdd
|
86 87 |
complete(&create->done); } |
1da177e4c
|
88 |
} |
9e37bd301
|
89 90 91 92 93 94 95 96 |
/** * kthread_create - create a kthread. * @threadfn: the function to run until signal_pending(current). * @data: data ptr for @threadfn. * @namefmt: printf-style name for the thread. * * Description: This helper function creates and names a kernel * thread. The thread will be stopped: use wake_up_process() to start |
301ba0457
|
97 |
* it. See also kthread_run(). |
9e37bd301
|
98 99 |
* * When woken, the thread will run @threadfn() with @data as its |
72fd4a35a
|
100 |
* argument. @threadfn() can either call do_exit() directly if it is a |
9e37bd301
|
101 102 103 104 105 106 107 |
* standalone thread for which noone will call kthread_stop(), or * return when 'kthread_should_stop()' is true (which means * kthread_stop() has been called). The return value should be zero * or a negative error number; it will be passed to kthread_stop(). * * Returns a task_struct or ERR_PTR(-ENOMEM). */ |
1da177e4c
|
108 109 110 111 112 113 |
struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...) { struct kthread_create_info create; |
1da177e4c
|
114 115 116 |
create.threadfn = threadfn; create.data = data; |
1da177e4c
|
117 |
init_completion(&create.done); |
73c279927
|
118 119 120 |
spin_lock(&kthread_create_lock); list_add_tail(&create.list, &kthread_create_list); |
73c279927
|
121 |
spin_unlock(&kthread_create_lock); |
cbd9b67bd
|
122 |
wake_up_process(kthreadd_task); |
73c279927
|
123 |
wait_for_completion(&create.done); |
1da177e4c
|
124 |
if (!IS_ERR(create.result)) { |
1c99315bb
|
125 |
struct sched_param param = { .sched_priority = 0 }; |
1da177e4c
|
126 |
va_list args; |
1c99315bb
|
127 |
|
1da177e4c
|
128 129 130 131 |
va_start(args, namefmt); vsnprintf(create.result->comm, sizeof(create.result->comm), namefmt, args); va_end(args); |
1c99315bb
|
132 133 134 135 136 |
/* * root may have changed our (kthreadd's) priority or CPU mask. * The kernel thread should not inherit these properties. */ sched_setscheduler_nocheck(create.result, SCHED_NORMAL, ¶m); |
1c99315bb
|
137 |
set_cpus_allowed_ptr(create.result, cpu_all_mask); |
1da177e4c
|
138 |
} |
1da177e4c
|
139 140 141 |
return create.result; } EXPORT_SYMBOL(kthread_create); |
9e37bd301
|
142 |
/** |
881232b70
|
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
* kthread_bind - bind a just-created kthread to a cpu. * @p: thread created by kthread_create(). * @cpu: cpu (might not be online, must be possible) for @k to run on. * * Description: This function is equivalent to set_cpus_allowed(), * except that @cpu doesn't need to be online, and the thread must be * stopped (i.e., just returned from kthread_create()). */ void kthread_bind(struct task_struct *p, unsigned int cpu) { /* Must have done schedule() in kthread() before we set_task_cpu */ if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) { WARN_ON(1); return; } p->cpus_allowed = cpumask_of_cpu(cpu); p->rt.nr_cpus_allowed = 1; p->flags |= PF_THREAD_BOUND; } EXPORT_SYMBOL(kthread_bind); /** |
9e37bd301
|
166 167 168 169 |
* kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_stop() for @k to return true, wakes it, and |
9ae260270
|
170 171 172 173 174 175 |
* waits for it to exit. This can also be called after kthread_create() * instead of calling wake_up_process(): the thread will exit without * calling threadfn(). * * If threadfn() may call do_exit() itself, the caller must ensure * task_struct can't go away. |
9e37bd301
|
176 177 178 179 |
* * Returns the result of threadfn(), or %-EINTR if wake_up_process() * was never called. */ |
1da177e4c
|
180 181 |
int kthread_stop(struct task_struct *k) { |
63706172f
|
182 |
struct kthread *kthread; |
1da177e4c
|
183 |
int ret; |
0a16b6075
|
184 |
trace_sched_kthread_stop(k); |
63706172f
|
185 |
get_task_struct(k); |
0a16b6075
|
186 |
|
63706172f
|
187 188 189 190 191 192 193 194 |
kthread = to_kthread(k); barrier(); /* it might have exited */ if (k->vfork_done != NULL) { kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); } ret = k->exit_code; |
1da177e4c
|
195 |
|
1da177e4c
|
196 |
put_task_struct(k); |
0a16b6075
|
197 |
trace_sched_kthread_stop_ret(ret); |
1da177e4c
|
198 199 |
return ret; } |
52e92e578
|
200 |
EXPORT_SYMBOL(kthread_stop); |
1da177e4c
|
201 |
|
e804a4a4d
|
202 |
int kthreadd(void *unused) |
1da177e4c
|
203 |
{ |
73c279927
|
204 |
struct task_struct *tsk = current; |
1da177e4c
|
205 |
|
e804a4a4d
|
206 |
/* Setup a clean context for our children to inherit. */ |
73c279927
|
207 |
set_task_comm(tsk, "kthreadd"); |
10ab825bd
|
208 |
ignore_signals(tsk); |
1a2142afa
|
209 |
set_cpus_allowed_ptr(tsk, cpu_all_mask); |
5ab116c93
|
210 |
set_mems_allowed(node_states[N_HIGH_MEMORY]); |
73c279927
|
211 |
|
ebb12db51
|
212 |
current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; |
73c279927
|
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (list_empty(&kthread_create_list)) schedule(); __set_current_state(TASK_RUNNING); spin_lock(&kthread_create_lock); while (!list_empty(&kthread_create_list)) { struct kthread_create_info *create; create = list_entry(kthread_create_list.next, struct kthread_create_info, list); list_del_init(&create->list); spin_unlock(&kthread_create_lock); create_kthread(create); spin_lock(&kthread_create_lock); } spin_unlock(&kthread_create_lock); } return 0; } |