linux/kernel/kthread.c
<<
>>
Prefs
   1/* Kernel thread helper functions.
   2 *   Copyright (C) 2004 IBM Corporation, Rusty Russell.
   3 *
   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,
   6 * etc.).
   7 */
   8#include <linux/sched.h>
   9#include <linux/kthread.h>
  10#include <linux/completion.h>
  11#include <linux/err.h>
  12#include <linux/unistd.h>
  13#include <linux/file.h>
  14#include <linux/module.h>
  15#include <linux/mutex.h>
  16#include <asm/semaphore.h>
  17
  18#define KTHREAD_NICE_LEVEL (-5)
  19
  20static DEFINE_SPINLOCK(kthread_create_lock);
  21static LIST_HEAD(kthread_create_list);
  22struct task_struct *kthreadd_task;
  23
  24struct kthread_create_info
  25{
  26        /* Information passed to kthread() from kthreadd. */
  27        int (*threadfn)(void *data);
  28        void *data;
  29        struct completion started;
  30
  31        /* Result passed back to kthread_create() from kthreadd. */
  32        struct task_struct *result;
  33        struct completion done;
  34
  35        struct list_head list;
  36};
  37
  38struct kthread_stop_info
  39{
  40        struct task_struct *k;
  41        int err;
  42        struct completion done;
  43};
  44
  45/* Thread stopping is done by setthing this var: lock serializes
  46 * multiple kthread_stop calls. */
  47static DEFINE_MUTEX(kthread_stop_lock);
  48static struct kthread_stop_info kthread_stop_info;
  49
  50/**
  51 * kthread_should_stop - should this kthread return now?
  52 *
  53 * When someone calls kthread_stop() on your kthread, it will be woken
  54 * and this will return true.  You should then return, and your return
  55 * value will be passed through to kthread_stop().
  56 */
  57int kthread_should_stop(void)
  58{
  59        return (kthread_stop_info.k == current);
  60}
  61EXPORT_SYMBOL(kthread_should_stop);
  62
  63static int kthread(void *_create)
  64{
  65        struct kthread_create_info *create = _create;
  66        int (*threadfn)(void *data);
  67        void *data;
  68        int ret = -EINTR;
  69
  70        /* Copy data: it's on kthread's stack */
  71        threadfn = create->threadfn;
  72        data = create->data;
  73
  74        /* OK, tell user we're spawned, wait for stop or wakeup */
  75        __set_current_state(TASK_UNINTERRUPTIBLE);
  76        complete(&create->started);
  77        schedule();
  78
  79        if (!kthread_should_stop())
  80                ret = threadfn(data);
  81
  82        /* It might have exited on its own, w/o kthread_stop.  Check. */
  83        if (kthread_should_stop()) {
  84                kthread_stop_info.err = ret;
  85                complete(&kthread_stop_info.done);
  86        }
  87        return 0;
  88}
  89
  90static void create_kthread(struct kthread_create_info *create)
  91{
  92        int pid;
  93
  94        /* We want our own signal handler (we take no signals by default). */
  95        pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
  96        if (pid < 0) {
  97                create->result = ERR_PTR(pid);
  98        } else {
  99                struct sched_param param = { .sched_priority = 0 };
 100                wait_for_completion(&create->started);
 101                read_lock(&tasklist_lock);
 102                create->result = find_task_by_pid(pid);
 103                read_unlock(&tasklist_lock);
 104                /*
 105                 * root may have changed our (kthreadd's) priority or CPU mask.
 106                 * The kernel thread should not inherit these properties.
 107                 */
 108                sched_setscheduler(create->result, SCHED_NORMAL, &param);
 109                set_user_nice(create->result, KTHREAD_NICE_LEVEL);
 110                set_cpus_allowed(create->result, CPU_MASK_ALL);
 111        }
 112        complete(&create->done);
 113}
 114
 115/**
 116 * kthread_create - create a kthread.
 117 * @threadfn: the function to run until signal_pending(current).
 118 * @data: data ptr for @threadfn.
 119 * @namefmt: printf-style name for the thread.
 120 *
 121 * Description: This helper function creates and names a kernel
 122 * thread.  The thread will be stopped: use wake_up_process() to start
 123 * it.  See also kthread_run(), kthread_create_on_cpu().
 124 *
 125 * When woken, the thread will run @threadfn() with @data as its
 126 * argument. @threadfn() can either call do_exit() directly if it is a
 127 * standalone thread for which noone will call kthread_stop(), or
 128 * return when 'kthread_should_stop()' is true (which means
 129 * kthread_stop() has been called).  The return value should be zero
 130 * or a negative error number; it will be passed to kthread_stop().
 131 *
 132 * Returns a task_struct or ERR_PTR(-ENOMEM).
 133 */
 134struct task_struct *kthread_create(int (*threadfn)(void *data),
 135                                   void *data,
 136                                   const char namefmt[],
 137                                   ...)
 138{
 139        struct kthread_create_info create;
 140
 141        create.threadfn = threadfn;
 142        create.data = data;
 143        init_completion(&create.started);
 144        init_completion(&create.done);
 145
 146        spin_lock(&kthread_create_lock);
 147        list_add_tail(&create.list, &kthread_create_list);
 148        wake_up_process(kthreadd_task);
 149        spin_unlock(&kthread_create_lock);
 150
 151        wait_for_completion(&create.done);
 152
 153        if (!IS_ERR(create.result)) {
 154                va_list args;
 155                va_start(args, namefmt);
 156                vsnprintf(create.result->comm, sizeof(create.result->comm),
 157                          namefmt, args);
 158                va_end(args);
 159        }
 160        return create.result;
 161}
 162EXPORT_SYMBOL(kthread_create);
 163
 164/**
 165 * kthread_bind - bind a just-created kthread to a cpu.
 166 * @k: thread created by kthread_create().
 167 * @cpu: cpu (might not be online, must be possible) for @k to run on.
 168 *
 169 * Description: This function is equivalent to set_cpus_allowed(),
 170 * except that @cpu doesn't need to be online, and the thread must be
 171 * stopped (i.e., just returned from kthread_create()).
 172 */
 173void kthread_bind(struct task_struct *k, unsigned int cpu)
 174{
 175        if (k->state != TASK_UNINTERRUPTIBLE) {
 176                WARN_ON(1);
 177                return;
 178        }
 179        /* Must have done schedule() in kthread() before we set_task_cpu */
 180        wait_task_inactive(k);
 181        set_task_cpu(k, cpu);
 182        k->cpus_allowed = cpumask_of_cpu(cpu);
 183}
 184EXPORT_SYMBOL(kthread_bind);
 185
 186/**
 187 * kthread_stop - stop a thread created by kthread_create().
 188 * @k: thread created by kthread_create().
 189 *
 190 * Sets kthread_should_stop() for @k to return true, wakes it, and
 191 * waits for it to exit.  Your threadfn() must not call do_exit()
 192 * itself if you use this function!  This can also be called after
 193 * kthread_create() instead of calling wake_up_process(): the thread
 194 * will exit without calling threadfn().
 195 *
 196 * Returns the result of threadfn(), or %-EINTR if wake_up_process()
 197 * was never called.
 198 */
 199int kthread_stop(struct task_struct *k)
 200{
 201        int ret;
 202
 203        mutex_lock(&kthread_stop_lock);
 204
 205        /* It could exit after stop_info.k set, but before wake_up_process. */
 206        get_task_struct(k);
 207
 208        /* Must init completion *before* thread sees kthread_stop_info.k */
 209        init_completion(&kthread_stop_info.done);
 210        smp_wmb();
 211
 212        /* Now set kthread_should_stop() to true, and wake it up. */
 213        kthread_stop_info.k = k;
 214        wake_up_process(k);
 215        put_task_struct(k);
 216
 217        /* Once it dies, reset stop ptr, gather result and we're done. */
 218        wait_for_completion(&kthread_stop_info.done);
 219        kthread_stop_info.k = NULL;
 220        ret = kthread_stop_info.err;
 221        mutex_unlock(&kthread_stop_lock);
 222
 223        return ret;
 224}
 225EXPORT_SYMBOL(kthread_stop);
 226
 227int kthreadd(void *unused)
 228{
 229        struct task_struct *tsk = current;
 230
 231        /* Setup a clean context for our children to inherit. */
 232        set_task_comm(tsk, "kthreadd");
 233        ignore_signals(tsk);
 234        set_user_nice(tsk, KTHREAD_NICE_LEVEL);
 235        set_cpus_allowed(tsk, CPU_MASK_ALL);
 236
 237        current->flags |= PF_NOFREEZE;
 238
 239        for (;;) {
 240                set_current_state(TASK_INTERRUPTIBLE);
 241                if (list_empty(&kthread_create_list))
 242                        schedule();
 243                __set_current_state(TASK_RUNNING);
 244
 245                spin_lock(&kthread_create_lock);
 246                while (!list_empty(&kthread_create_list)) {
 247                        struct kthread_create_info *create;
 248
 249                        create = list_entry(kthread_create_list.next,
 250                                            struct kthread_create_info, list);
 251                        list_del_init(&create->list);
 252                        spin_unlock(&kthread_create_lock);
 253
 254                        create_kthread(create);
 255
 256                        spin_lock(&kthread_create_lock);
 257                }
 258                spin_unlock(&kthread_create_lock);
 259        }
 260
 261        return 0;
 262}
 263
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.