Merge branch 'signal-for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / kernel / kthread.c
index 4ed9e7b..a2c156e 100644 (file)
@@ -52,6 +52,7 @@ struct kthread_create_info
 struct kthread {
        unsigned long flags;
        unsigned int cpu;
+       int result;
        int (*threadfn)(void *);
        void *data;
        mm_segment_t oldfs;
@@ -71,7 +72,7 @@ enum KTHREAD_BITS {
 static inline struct kthread *to_kthread(struct task_struct *k)
 {
        WARN_ON(!(k->flags & PF_KTHREAD));
-       return (__force void *)k->set_child_tid;
+       return k->worker_private;
 }
 
 /*
@@ -79,7 +80,7 @@ static inline struct kthread *to_kthread(struct task_struct *k)
  *
  * Per construction; when:
  *
- *   (p->flags & PF_KTHREAD) && p->set_child_tid
+ *   (p->flags & PF_KTHREAD) && p->worker_private
  *
  * the task is both a kthread and struct kthread is persistent. However
  * PF_KTHREAD on it's own is not, kernel_thread() can exec() (See umh.c and
@@ -87,26 +88,29 @@ static inline struct kthread *to_kthread(struct task_struct *k)
  */
 static inline struct kthread *__to_kthread(struct task_struct *p)
 {
-       void *kthread = (__force void *)p->set_child_tid;
+       void *kthread = p->worker_private;
        if (kthread && !(p->flags & PF_KTHREAD))
                kthread = NULL;
        return kthread;
 }
 
-void set_kthread_struct(struct task_struct *p)
+bool set_kthread_struct(struct task_struct *p)
 {
        struct kthread *kthread;
 
-       if (__to_kthread(p))
-               return;
+       if (WARN_ON_ONCE(to_kthread(p)))
+               return false;
 
        kthread = kzalloc(sizeof(*kthread), GFP_KERNEL);
-       /*
-        * We abuse ->set_child_tid to avoid the new member and because it
-        * can't be wrongly copied by copy_process(). We also rely on fact
-        * that the caller can't exec, so PF_KTHREAD can't be cleared.
-        */
-       p->set_child_tid = (__force void __user *)kthread;
+       if (!kthread)
+               return false;
+
+       init_completion(&kthread->exited);
+       init_completion(&kthread->parked);
+       p->vfork_done = &kthread->exited;
+
+       p->worker_private = kthread;
+       return true;
 }
 
 void free_kthread_struct(struct task_struct *k)
@@ -114,13 +118,13 @@ void free_kthread_struct(struct task_struct *k)
        struct kthread *kthread;
 
        /*
-        * Can be NULL if this kthread was created by kernel_thread()
-        * or if kmalloc() in kthread() failed.
+        * Can be NULL if kmalloc() in set_kthread_struct() failed.
         */
        kthread = to_kthread(k);
 #ifdef CONFIG_BLK_CGROUP
        WARN_ON_ONCE(kthread && kthread->blkcg_css);
 #endif
+       k->worker_private = NULL;
        kfree(kthread);
 }
 
@@ -268,6 +272,44 @@ void kthread_parkme(void)
 }
 EXPORT_SYMBOL_GPL(kthread_parkme);
 
+/**
+ * kthread_exit - Cause the current kthread return @result to kthread_stop().
+ * @result: The integer value to return to kthread_stop().
+ *
+ * While kthread_exit can be called directly, it exists so that
+ * functions which do some additional work in non-modular code such as
+ * module_put_and_kthread_exit can be implemented.
+ *
+ * Does not return.
+ */
+void __noreturn kthread_exit(long result)
+{
+       struct kthread *kthread = to_kthread(current);
+       kthread->result = result;
+       do_exit(0);
+}
+
+/**
+ * kthread_complete_and_exit - Exit the current kthread.
+ * @comp: Completion to complete
+ * @code: The integer value to return to kthread_stop().
+ *
+ * If present complete @comp and the reuturn code to kthread_stop().
+ *
+ * A kernel thread whose module may be removed after the completion of
+ * @comp can use this function exit safely.
+ *
+ * Does not return.
+ */
+void __noreturn kthread_complete_and_exit(struct completion *comp, long code)
+{
+       if (comp)
+               complete(comp);
+
+       kthread_exit(code);
+}
+EXPORT_SYMBOL(kthread_complete_and_exit);
+
 static int kthread(void *_create)
 {
        static const struct sched_param param = { .sched_priority = 0 };
@@ -279,27 +321,17 @@ static int kthread(void *_create)
        struct kthread *self;
        int ret;
 
-       set_kthread_struct(current);
        self = to_kthread(current);
 
        /* If user was SIGKILLed, I release the structure. */
        done = xchg(&create->done, NULL);
        if (!done) {
                kfree(create);
-               do_exit(-EINTR);
-       }
-
-       if (!self) {
-               create->result = ERR_PTR(-ENOMEM);
-               complete(done);
-               do_exit(-ENOMEM);
+               kthread_exit(-EINTR);
        }
 
        self->threadfn = threadfn;
        self->data = data;
-       init_completion(&self->exited);
-       init_completion(&self->parked);
-       current->vfork_done = &self->exited;
 
        /*
         * The new thread inherited kthreadd's priority and CPU mask. Reset
@@ -326,7 +358,7 @@ static int kthread(void *_create)
                __kthread_parkme(self);
                ret = threadfn(data);
        }
-       do_exit(ret);
+       kthread_exit(ret);
 }
 
 /* called from kernel_clone() to get node information for about to be created task */
@@ -628,7 +660,7 @@ EXPORT_SYMBOL_GPL(kthread_park);
  * instead of calling wake_up_process(): the thread will exit without
  * calling threadfn().
  *
- * If threadfn() may call do_exit() itself, the caller must ensure
+ * If threadfn() may call kthread_exit() itself, the caller must ensure
  * task_struct can't go away.
  *
  * Returns the result of threadfn(), or %-EINTR if wake_up_process()
@@ -647,7 +679,7 @@ int kthread_stop(struct task_struct *k)
        kthread_unpark(k);
        wake_up_process(k);
        wait_for_completion(&kthread->exited);
-       ret = k->exit_code;
+       ret = kthread->result;
        put_task_struct(k);
 
        trace_sched_kthread_stop_ret(ret);