diff options
Diffstat (limited to 'kernel/kthread.c')
| -rw-r--r-- | kernel/kthread.c | 113 |
1 files changed, 57 insertions, 56 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c index 87c50ccd1d4e..df8a8e8f6ca4 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* Kernel thread helper functions. | 1 | /* Kernel thread helper functions. |
| 2 | * Copyright (C) 2004 IBM Corporation, Rusty Russell. | 2 | * Copyright (C) 2004 IBM Corporation, Rusty Russell. |
| 3 | * | 3 | * |
| 4 | * Creation is done via keventd, so that we get a clean environment | 4 | * Creation is done via kthreadd, so that we get a clean environment |
| 5 | * even if we're invoked from userspace (think modprobe, hotplug cpu, | 5 | * even if we're invoked from userspace (think modprobe, hotplug cpu, |
| 6 | * etc.). | 6 | * etc.). |
| 7 | */ | 7 | */ |
| @@ -15,24 +15,22 @@ | |||
| 15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
| 16 | #include <asm/semaphore.h> | 16 | #include <asm/semaphore.h> |
| 17 | 17 | ||
| 18 | /* | 18 | static DEFINE_SPINLOCK(kthread_create_lock); |
| 19 | * We dont want to execute off keventd since it might | 19 | static LIST_HEAD(kthread_create_list); |
| 20 | * hold a semaphore our callers hold too: | 20 | struct task_struct *kthreadd_task; |
| 21 | */ | ||
| 22 | static struct workqueue_struct *helper_wq; | ||
| 23 | 21 | ||
| 24 | struct kthread_create_info | 22 | struct kthread_create_info |
| 25 | { | 23 | { |
| 26 | /* Information passed to kthread() from keventd. */ | 24 | /* Information passed to kthread() from kthreadd. */ |
| 27 | int (*threadfn)(void *data); | 25 | int (*threadfn)(void *data); |
| 28 | void *data; | 26 | void *data; |
| 29 | struct completion started; | 27 | struct completion started; |
| 30 | 28 | ||
| 31 | /* Result passed back to kthread_create() from keventd. */ | 29 | /* Result passed back to kthread_create() from kthreadd. */ |
| 32 | struct task_struct *result; | 30 | struct task_struct *result; |
| 33 | struct completion done; | 31 | struct completion done; |
| 34 | 32 | ||
| 35 | struct work_struct work; | 33 | struct list_head list; |
| 36 | }; | 34 | }; |
| 37 | 35 | ||
| 38 | struct kthread_stop_info | 36 | struct kthread_stop_info |
| @@ -60,42 +58,17 @@ int kthread_should_stop(void) | |||
| 60 | } | 58 | } |
| 61 | EXPORT_SYMBOL(kthread_should_stop); | 59 | EXPORT_SYMBOL(kthread_should_stop); |
| 62 | 60 | ||
| 63 | static void kthread_exit_files(void) | ||
| 64 | { | ||
| 65 | struct fs_struct *fs; | ||
| 66 | struct task_struct *tsk = current; | ||
| 67 | |||
| 68 | exit_fs(tsk); /* current->fs->count--; */ | ||
| 69 | fs = init_task.fs; | ||
| 70 | tsk->fs = fs; | ||
| 71 | atomic_inc(&fs->count); | ||
| 72 | exit_files(tsk); | ||
| 73 | current->files = init_task.files; | ||
| 74 | atomic_inc(&tsk->files->count); | ||
| 75 | } | ||
| 76 | |||
| 77 | static int kthread(void *_create) | 61 | static int kthread(void *_create) |
| 78 | { | 62 | { |
| 79 | struct kthread_create_info *create = _create; | 63 | struct kthread_create_info *create = _create; |
| 80 | int (*threadfn)(void *data); | 64 | int (*threadfn)(void *data); |
| 81 | void *data; | 65 | void *data; |
| 82 | sigset_t blocked; | ||
| 83 | int ret = -EINTR; | 66 | int ret = -EINTR; |
| 84 | 67 | ||
| 85 | kthread_exit_files(); | 68 | /* Copy data: it's on kthread's stack */ |
| 86 | |||
| 87 | /* Copy data: it's on keventd's stack */ | ||
| 88 | threadfn = create->threadfn; | 69 | threadfn = create->threadfn; |
| 89 | data = create->data; | 70 | data = create->data; |
| 90 | 71 | ||
| 91 | /* Block and flush all signals (in case we're not from keventd). */ | ||
| 92 | sigfillset(&blocked); | ||
| 93 | sigprocmask(SIG_BLOCK, &blocked, NULL); | ||
| 94 | flush_signals(current); | ||
| 95 | |||
| 96 | /* By default we can run anywhere, unlike keventd. */ | ||
| 97 | set_cpus_allowed(current, CPU_MASK_ALL); | ||
| 98 | |||
| 99 | /* OK, tell user we're spawned, wait for stop or wakeup */ | 72 | /* OK, tell user we're spawned, wait for stop or wakeup */ |
| 100 | __set_current_state(TASK_INTERRUPTIBLE); | 73 | __set_current_state(TASK_INTERRUPTIBLE); |
| 101 | complete(&create->started); | 74 | complete(&create->started); |
| @@ -112,11 +85,8 @@ static int kthread(void *_create) | |||
| 112 | return 0; | 85 | return 0; |
| 113 | } | 86 | } |
| 114 | 87 | ||
| 115 | /* We are keventd: create a thread. */ | 88 | static void create_kthread(struct kthread_create_info *create) |
| 116 | static void keventd_create_kthread(struct work_struct *work) | ||
| 117 | { | 89 | { |
| 118 | struct kthread_create_info *create = | ||
| 119 | container_of(work, struct kthread_create_info, work); | ||
| 120 | int pid; | 90 | int pid; |
| 121 | 91 | ||
| 122 | /* We want our own signal handler (we take no signals by default). */ | 92 | /* We want our own signal handler (we take no signals by default). */ |
| @@ -162,17 +132,14 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), | |||
| 162 | create.data = data; | 132 | create.data = data; |
| 163 | init_completion(&create.started); | 133 | init_completion(&create.started); |
| 164 | init_completion(&create.done); | 134 | init_completion(&create.done); |
| 165 | INIT_WORK(&create.work, keventd_create_kthread); | 135 | |
| 166 | 136 | spin_lock(&kthread_create_lock); | |
| 167 | /* | 137 | list_add_tail(&create.list, &kthread_create_list); |
| 168 | * The workqueue needs to start up first: | 138 | wake_up_process(kthreadd_task); |
| 169 | */ | 139 | spin_unlock(&kthread_create_lock); |
| 170 | if (!helper_wq) | 140 | |
| 171 | create.work.func(&create.work); | 141 | wait_for_completion(&create.done); |
| 172 | else { | 142 | |
| 173 | queue_work(helper_wq, &create.work); | ||
| 174 | wait_for_completion(&create.done); | ||
| 175 | } | ||
| 176 | if (!IS_ERR(create.result)) { | 143 | if (!IS_ERR(create.result)) { |
| 177 | va_list args; | 144 | va_list args; |
| 178 | va_start(args, namefmt); | 145 | va_start(args, namefmt); |
| @@ -180,7 +147,6 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), | |||
| 180 | namefmt, args); | 147 | namefmt, args); |
| 181 | va_end(args); | 148 | va_end(args); |
| 182 | } | 149 | } |
| 183 | |||
| 184 | return create.result; | 150 | return create.result; |
| 185 | } | 151 | } |
| 186 | EXPORT_SYMBOL(kthread_create); | 152 | EXPORT_SYMBOL(kthread_create); |
| @@ -245,12 +211,47 @@ int kthread_stop(struct task_struct *k) | |||
| 245 | } | 211 | } |
| 246 | EXPORT_SYMBOL(kthread_stop); | 212 | EXPORT_SYMBOL(kthread_stop); |
| 247 | 213 | ||
| 248 | static __init int helper_init(void) | 214 | |
| 215 | static __init void kthreadd_setup(void) | ||
| 249 | { | 216 | { |
| 250 | helper_wq = create_singlethread_workqueue("kthread"); | 217 | struct task_struct *tsk = current; |
| 251 | BUG_ON(!helper_wq); | ||
| 252 | 218 | ||
| 253 | return 0; | 219 | set_task_comm(tsk, "kthreadd"); |
| 220 | |||
| 221 | ignore_signals(tsk); | ||
| 222 | |||
| 223 | set_user_nice(tsk, -5); | ||
| 224 | set_cpus_allowed(tsk, CPU_MASK_ALL); | ||
| 254 | } | 225 | } |
| 255 | 226 | ||
| 256 | core_initcall(helper_init); | 227 | int kthreadd(void *unused) |
| 228 | { | ||
| 229 | /* Setup a clean context for our children to inherit. */ | ||
| 230 | kthreadd_setup(); | ||
| 231 | |||
| 232 | current->flags |= PF_NOFREEZE; | ||
| 233 | |||
| 234 | for (;;) { | ||
| 235 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 236 | if (list_empty(&kthread_create_list)) | ||
| 237 | schedule(); | ||
| 238 | __set_current_state(TASK_RUNNING); | ||
| 239 | |||
| 240 | spin_lock(&kthread_create_lock); | ||
| 241 | while (!list_empty(&kthread_create_list)) { | ||
| 242 | struct kthread_create_info *create; | ||
| 243 | |||
| 244 | create = list_entry(kthread_create_list.next, | ||
| 245 | struct kthread_create_info, list); | ||
| 246 | list_del_init(&create->list); | ||
| 247 | spin_unlock(&kthread_create_lock); | ||
| 248 | |||
| 249 | create_kthread(create); | ||
| 250 | |||
| 251 | spin_lock(&kthread_create_lock); | ||
| 252 | } | ||
| 253 | spin_unlock(&kthread_create_lock); | ||
| 254 | } | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
