]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/kthread.c
check for errors from pthread_create()
[bcachefs-tools-debian] / linux / kthread.c
1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <linux/bitops.h>
6 #include <linux/kthread.h>
7 #include <linux/rcupdate.h>
8 #include <linux/sched.h>
9
10 enum KTHREAD_BITS {
11         KTHREAD_IS_PER_CPU = 0,
12         KTHREAD_SHOULD_STOP,
13         KTHREAD_SHOULD_PARK,
14         KTHREAD_IS_PARKED,
15 };
16
17 static void *kthread_start_fn(void *data)
18 {
19         rcu_register_thread();
20
21         current = data;
22         schedule();
23         current->thread_fn(current->thread_data);
24
25         complete(&current->exited);
26         put_task_struct(current);
27         rcu_unregister_thread();
28         return NULL;
29 }
30
31 /**
32  * kthread_create_on_node - create a kthread.
33  * @threadfn: the function to run until signal_pending(current).
34  * @data: data ptr for @threadfn.
35  * @node: task and thread structures for the thread are allocated on this node
36  * @namefmt: printf-style name for the thread.
37  *
38  * Description: This helper function creates and names a kernel
39  * thread.  The thread will be stopped: use wake_up_process() to start
40  * it.  See also kthread_run().  The new thread has SCHED_NORMAL policy and
41  * is affine to all CPUs.
42  *
43  * If thread is going to be bound on a particular cpu, give its node
44  * in @node, to get NUMA affinity for kthread stack, or else give NUMA_NO_NODE.
45  * When woken, the thread will run @threadfn() with @data as its
46  * argument. @threadfn() can either call do_exit() directly if it is a
47  * standalone thread for which no one will call kthread_stop(), or
48  * return when 'kthread_should_stop()' is true (which means
49  * kthread_stop() has been called).  The return value should be zero
50  * or a negative error number; it will be passed to kthread_stop().
51  *
52  * Returns a task_struct or ERR_PTR(-ENOMEM) or ERR_PTR(-EINTR).
53  */
54 struct task_struct *kthread_create(int (*thread_fn)(void *data),
55                                    void *thread_data,
56                                    const char namefmt[], ...)
57 {
58         va_list args;
59         struct task_struct *p = malloc(sizeof(*p));
60         int ret;
61
62         memset(p, 0, sizeof(*p));
63
64         va_start(args, namefmt);
65         vsnprintf(p->comm, sizeof(p->comm), namefmt, args);
66         va_end(args);
67
68         p->flags        |= PF_KTHREAD;
69         p->thread_fn    = thread_fn;
70         p->thread_data  = thread_data;
71         p->state        = TASK_UNINTERRUPTIBLE;
72         atomic_set(&p->usage, 1);
73         init_completion(&p->exited);
74
75         ret = pthread_create(&p->thread, NULL, kthread_start_fn, p);
76         if (ret)
77                 die("pthread_create error %s", strerror(ret));
78         pthread_setname_np(p->thread, p->comm);
79         return p;
80 }
81
82 /**
83  * kthread_should_stop - should this kthread return now?
84  *
85  * When someone calls kthread_stop() on your kthread, it will be woken
86  * and this will return true.  You should then return, and your return
87  * value will be passed through to kthread_stop().
88  */
89 bool kthread_should_stop(void)
90 {
91         return test_bit(KTHREAD_SHOULD_STOP, &current->kthread_flags);
92 }
93
94 /**
95  * kthread_stop - stop a thread created by kthread_create().
96  * @k: thread created by kthread_create().
97  *
98  * Sets kthread_should_stop() for @k to return true, wakes it, and
99  * waits for it to exit. This can also be called after kthread_create()
100  * instead of calling wake_up_process(): the thread will exit without
101  * calling threadfn().
102  *
103  * If threadfn() may call do_exit() itself, the caller must ensure
104  * task_struct can't go away.
105  *
106  * Returns the result of threadfn(), or %-EINTR if wake_up_process()
107  * was never called.
108  */
109 int kthread_stop(struct task_struct *p)
110 {
111         get_task_struct(p);
112
113         set_bit(KTHREAD_SHOULD_STOP, &p->kthread_flags);
114         wake_up_process(p);
115         wait_for_completion(&p->exited);
116
117         put_task_struct(p);
118
119         return 0;
120 }