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
  17#define KTHREAD_NICE_LEVEL (-5)
  18
  19static DEFINE_SPINLOCK(kthread_create_lock);
  20static LIST_HEAD(kthread_create_list);
  21struct task_struct *kthreadd_task;
  22
  23struct kthread_create_info
  24{
  25        /* Information passed to kthread() from kthreadd. */
  26        int (*threadfn)(void *data);
  27        void *data;
  28        struct completion started;
  29
  30        /* Result passed back to kthread_create() from kthreadd. */
  31        struct task_struct *result;
  32        struct completion done;
  33
  34        struct list_head list;
  35};
  36
  37struct kthread_stop_info
  38{
  39        struct task_struct *k;
  40        int err;
  41        struct completion done;
  42};
  43
  44/* Thread stopping is done by setthing this var: lock serializes
  45 * multiple kthread_stop calls. */
  46static DEFINE_MUTEX(kthread_stop_lock);
  47static struct kthread_stop_info kthread_stop_info;
  48
  49/**
  50 * kthread_should_stop - should this kthread return now?
  51 *
  52 * When someone calls kthread_stop() on your kthread, it will be woken
  53 * and this will return true.  You should then return, and your return
  54 * value will be passed through to kthread_stop().
  55 */
  56int kthread_should_stop(void)
  57{
  58        return (kthread_stop_info.k == current);
  59}
  60EXPORT_SYMBOL(kthread_should_stop);
  61
  62static int kthread(void *_create)
  63{
  64        struct kthread_create_info *create = _create;
  65        int (*threadfn)(void *data);
  66        void *data;
  67        int ret = -EINTR;
  68
  69        /* Copy data: it's on kthread's stack */
  70        threadfn = create->threadfn;
  71        data = create->data;
  72
  73        /* OK, tell user we're spawned, wait for stop or wakeup */
  74        __set_current_state(TASK_UNINTERRUPTIBLE);
  75        complete(&create->started);
  76        schedule();
  77
  78        if (!kthread_should_stop())
  79                ret = threadfn(data);
  80
  81        /* It might have exited on its own, w/o kthread_stop.  Check. */
  82        if (kthread_should_stop()) {
  83                kthread_stop_info.err = ret;
  84                complete(&kthread_stop_info.done);
  85        }
  86        return 0;
  87}
  88
  89static void create_kthread(struct kthread_create_info *create)
  90{
  91        int pid;
  92
  93        /* We want our own signal handler (we take no signals by default). */
  94        pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
  95        if (pid < 0) {
  96                create->result = ERR_PTR(pid);
  97        } else {
  98                struct sched_param param = { .sched_priority = 0 };
  99                wait_for_completion(&create->started);
 100                read_lock(&tasklist_lock);
 101                create->result = find_task_by_pid_ns(pid, &init_pid_ns);
 102                read_unlock(&tasklist_lock);
 103                /*
 104                 * root may have changed our (kthreadd's) priority or CPU mask.
 105                 * The kernel thread should not inherit these properties.
 106                 */
 107                sched_setscheduler(create->result, SCHED_NORMAL, &param);
 108                set_user_nice(create->result, KTHREAD_NICE_LEVEL);
 109                set_cpus_allowed(create->result, CPU_MASK_ALL);
 110        }
 111        complete(&create->done);
 112}
 113
 114/**
 115 * kthread_create - create a kthread.
 116 * @threadfn: the function to run until signal_pending(current).
 117 * @data: data ptr for @threadfn.
 118 * @namefmt: printf-style name for the thread.
 119 *
 120 * Description: This helper function creates and names a kernel
 121 * thread.  The thread will be stopped: use wake_up_process() to start
 122 * it.  See also kthread_run(), kthread_create_on_cpu().
 123 *
 124 * When woken, the thread will run @threadfn() with @data as its
 125 * argument. @threadfn() can either call do_exit() directly if it is a
 126 * standalone thread for which noone will call kthread_stop(), or
 127 * return when 'kthread_should_stop()' is true (which means
 128 * kthread_stop() has been called).  The return value should be zero
 129 * or a negative error number; it will be passed to kthread_stop().
 130 *
 131 * Returns a task_struct or ERR_PTR(-ENOMEM).
 132 */
 133struct task_struct *kthread_create(int (*threadfn)(void *data),
 134                                   void *data,
 135                                   const char namefmt[],
 136                                   ...)
 137{
 138        struct kthread_create_info create;
 139
 140        create.threadfn = threadfn;
 141        create.data = data;
 142        init_completion(&create.started);
 143        init_completion(&create.done);
 144
 145        spin_lock(&kthread_create_lock);
 146        list_add_tail(&create.list, &kthread_create_list);
 147        spin_unlock(&kthread_create_lock);
 148
 149        wake_up_process(kthreadd_task);
 150        wait_for_completion(&create.done);
 151
 152        if (!IS_ERR(create.result)) {
 153                va_list args;
 154                va_start(args, namefmt);
 155                vsnprintf(create.result->comm, sizeof(create.result->comm),
 156                          namefmt, args);
 157                va_end(args);
 158        }
 159        return create.result;
 160}
 161EXPORT_SYMBOL(kthread_create);
 162
 163/**
 164 * kthread_bind - bind a just-created kthread to a cpu.
 165 * @k: thread created by kthread_create().
 166 * @cpu: cpu (might not be online, must be possible) for @k to run on.
 167 *
 168 * Description: This function is equivalent to set_cpus_allowed(),
 169 * except that @cpu doesn't need to be online, and the thread must be
 170 * stopped (i.e., just returned from kthread_create()).
 171 */
 172void kthread_bind(struct task_struct *k, unsigned int cpu)
 173{
 174        if (k->state != TASK_UNINTERRUPTIBLE) {
 175                WARN_ON(1);
 176                return;
 177        }
 178        /* Must have done schedule() in kthread() before we set_task_cpu */
 179        wait_task_inactive(k);
 180        set_task_cpu(k, cpu);
 181        k->cpus_allowed = cpumask_of_cpu(cpu);
 182        k->rt.nr_cpus_allowed = 1;
 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.