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