XenevaOS
Loading...
Searching...
No Matches
workqueue.h
Go to the documentation of this file.
1#ifndef __WORKQUEUE_H__
2#define __WORKQUEUE_H__
3
4#include <linux/timer.h>
5
6/*
7 * might_alloc(gfp) -- mainline keeps this annotation in <linux/sched/mm.h>:
8 * it asserts the flags allow blocking, then might_sleep()s if they do. DCL's
9 * might_sleep() is already the no-op at kernel.h:216 for the same reason
10 * (nothing here can sleep), so the whole annotation is nothing.
11 *
12 * It is defined here, of all places, because of who calls it: xarray.h's
13 * static inline bodies do, at :594 and thirteen more sites through :1059.
14 * With no definition in scope the build's -Wno-implicit-function-declaration
15 * made each call an external reference, which is the undefined `might_alloc`
16 * lld-link reported for drm_minor_alloc() (drm_drv.c) and drm_syncobj.c.
17 * mainline's home for it, <linux/sched/mm.h>, is a stand-in with nothing in it
18 * (xarray.h:21 includes it and gets no more than the include), and the callers
19 * are xarray.h bodies, so the definition has to come from a header xarray.h
20 * itself already includes: this one, through bitmap.h (:12) -> kernel.h ->
21 * here (kernel.h:128), which is before any of those bodies is parsed on every
22 * include path.
23 *
24 * A macro and not a typed inline like mainline's: gfp_t is a kernel.h:55
25 * typedef, and this header is parsed from headers that have their own reason
26 * to be included before kernel.h; the annotation is worth neither the
27 * dependency nor a type the body does not read.
28 */
29#define might_alloc(gfp) do { (void)(gfp); } while (0)
30
31/*
32 * Forward declaration *before* the typedef. Without it, `struct work_struct`
33 * inside the parameter list is first declared in that prototype's scope, so it
34 * is a different type from the one defined four lines down -- and every later
35 * use reports "incompatible pointer types passing 'struct work_struct *' to
36 * parameter of type 'struct work_struct *'", two identically-spelled types
37 * that are not the same type. It surfaces only in translation units that
38 * reach this header before anything else has named the tag, which is exactly
39 * what the tty headers do (linux/tty.h -> workqueue.h).
40 */
41struct work_struct;
42typedef void (*work_func_t)(struct work_struct* work);
43
46 void* data; /* your private context */
48};
49
51 const char* name;
52 /* stub � single threaded on bare metal */
53};
54
55/* Init */
56#define INIT_WORK(_work, _func) do { \
57 (_work)->func = (_func); \
58 (_work)->pending = 0; \
59 (_work)->data = NULL; \
60} while (0)
61
62/*
63 * INIT_WORK_ONSTACK() / destroy_work_on_stack() -- mainline's ONSTACK pair.
64 * It differs from INIT_WORK only in lockdep/debug-object bookkeeping:
65 * init_work(work, true) marks the object stack-allocated, and
66 * destroy_work_on_stack() frees the debug object at the end of scope
67 * (include/linux/workqueue.h:312 and :271). DCL's lockdep is inert and there
68 * is no debug-object table, so the pair is INIT_WORK and nothing. The pair
69 * exists because drm_framebuffer.c:464 and :819 bracket
70 * drm_mode_rmfb_work_fn() with it.
71 */
72#define INIT_WORK_ONSTACK(_work, _func) INIT_WORK(_work, _func)
73#define destroy_work_on_stack(work) do { (void)(work); } while (0)
74
75/*
76 * work_pending(work) -- mainline tests WORK_STRUCT_PENDING_BIT in the packed
77 * work word; DCL's struct carries the flag directly. Nothing sets it: a
78 * queue is a synchronous run (below), so a work that was queued is never
79 * still pending when something can ask. vkms_crtc.c:84/:98 WARN if a
80 * vkms_crtc_state is torn down with its composer work pending, and inline
81 * execution is what makes that structurally false rather than lucky.
82 */
83static inline bool work_pending(struct work_struct* work)
84{
85 return work->pending != 0;
86}
87
88/*
89 * dcl_current_work -- the work whose func is on the stack right now, saved
90 * and restored around every inline run below. current_work() returns it so
91 * mainline's "am I running on a work item?" tests answer the way they do on
92 * a real kworker; drm_probe_helper.c:868 compares ->func against
93 * output_poll_execute, and with the poll work executed inline from
94 * mod_delayed_work() that comparison must still see the poll work.
95 *
96 * One pointer rather than per-task state, like the rest of DCL (there is one
97 * task). Defined in DCL/linux_kthread_shim.c:259, next to current_work().
98 */
99extern struct work_struct* dcl_current_work;
100
102
103static inline bool __dcl_run_work(struct work_struct* work)
104{
105 struct work_struct* prev = dcl_current_work;
106
107 dcl_current_work = work;
108 if (work->func)
109 work->func(work);
110 dcl_current_work = prev;
111 return true;
112}
113
114/*
115 * Work runs inline: there is no kworker to run it later.
116 *
117 * These are functions, not statement-expressions, because mainline's callers
118 * use their return values -- tty_buffer.c:66 is literally
119 * `return queue_work(flip_wq ?: system_dfl_wq, &buf->work);`, which does not
120 * parse against a do{}while(0) macro. The bool is "work was queued"; since
121 * it runs to completion before we return, true is always the right answer.
122 *
123 * Inline execution is a real deviation from mainline and it is worth being
124 * precise about why it is safe here: tty_flip_buffer_push() calls this from
125 * interrupt context, so flush_to_ldisc() runs before tty_flip_buffer_push()
126 * returns rather than on a worker later. Its only lock is the buffer mutex,
127 * which in DCL is a no-op (<linux/mutex.h> says so plainly), so there is
128 * nothing to deadlock on. This is also what Linux itself did before 2.6.24,
129 * when tty_flip_buffer_push() called the flush directly. The behaviour that
130 * changes is latency, not correctness: a byte arrives at n_tty before the
131 * interrupt handler returns instead of after.
132 */
133static inline bool schedule_work(struct work_struct* work)
134{
135 __dcl_run_work(work);
136 return true;
137}
138
139static inline bool queue_work(struct workqueue_struct* wq,
140 struct work_struct* work)
141{
142 (void)wq;
143 __dcl_run_work(work);
144 return true;
145}
146
147/*
148 * flush_work() answers true: the work has run (it always has -- it ran
149 * inline). cancel_work_sync() answers false: there was never anything
150 * pending to cancel. tty_buffer_cancel_work() returns that straight through,
151 * and false is the truthful value for "did this cancel something?".
152 */
153static inline bool flush_work(struct work_struct* work)
154{
155 (void)work;
156 return true;
157}
158
159static inline bool cancel_work_sync(struct work_struct* work)
160{
161 (void)work;
162 return false;
163}
164
165static inline void flush_workqueue(struct workqueue_struct* wq) { (void)wq; }
166static inline void destroy_workqueue(struct workqueue_struct* wq) { (void)wq; }
167
168/*
169 * system_dfl_wq -- mainline's "default" workqueue, the one queue_work() falls
170 * back to when a tty port has not been linked to a driver-specific one. DCL
171 * has exactly one workqueue, so this is a named pointer whose identity exists
172 * only so `flip_wq ?: system_dfl_wq` (tty_buffer.c:66) has something to
173 * choose.
174 *
175 * It is a *pointer*, not an object, for a mechanical reason worth recording:
176 * `E1 ?: E2` applies the usual arithmetic conversions to its operands and does
177 * not decay a struct lvalue. Declaring it as `struct workqueue_struct
178 * system_dfl_wq` (the object spelling) makes line 66 an error -- "incompatible
179 * operand types ('struct workqueue_struct *' and 'struct workqueue_struct')" --
180 * because the second operand has no way to become a pointer. mainline declares
181 * every system_*wq the same way, as `extern struct workqueue_struct *`.
182 *
183 * Defined in DCL/tty_shim.c.
184 */
185extern struct workqueue_struct* system_dfl_wq;
186
187/*
188 * system_percpu_wq -- mainline's per-cpu queue, and the @wq argument of the
189 * two drm call sites that name one (drm_probe_helper.c:629's output poll,
190 * drm_self_refresh_helper.c:221's self-refresh entry). Same situation as
191 * system_dfl_wq above, one step further removed: nothing here dereferences it
192 * either, because mod_delayed_work() ignores the pointer just as
193 * queue_delayed_work() does. mainline keeps it in kernel/workqueue.c; there is
194 * no such file to keep it in, since <linux/workqueue.h> has no implementation
195 * behind it.
196 *
197 * Defined in DCL/tty_shim.c, beside system_dfl_wq.
198 */
200
201/*
202 * system_long_wq -- mainline's queue for work that may run long, which is
203 * where drm_writeback.c:570 puts a writeback job's cleanup_work. The
204 * distinction mainline draws (a bounded pool, versus per-cpu, versus
205 * unbound) is about CPU affinity and how long a worker may be held; none of
206 * it survives a runner that executes work inline on the caller, which is
207 * what makes this the third name for the same object and not a fourth queue.
208 * It is declared last because it was the last of the three asked for.
209 *
210 * Defined in DCL/tty_shim.c, beside the other two.
211 */
212extern struct workqueue_struct* system_long_wq;
213
214static inline struct workqueue_struct*
215alloc_ordered_workqueue(const char* name, int flags) {
216 static struct workqueue_struct wq;
217 (void)flags; /* no priority/ordering on a single inline queue */
218 wq.name = name;
219 return &wq;
220}
221
222#define create_singlethread_workqueue(name) \
223 alloc_ordered_workqueue(name, 0)
224
225/* Get owning struct back from work pointer */
226#define container_of_work(ptr, type, member) \
227 container_of(ptr, type, member)
228
234
235#define INIT_DELAYED_WORK(_dwork, _func) do { \
236 INIT_WORK(&(_dwork)->work, _func); \
237 timer_setup(&(_dwork)->timer, NULL, 0); \
238 (_dwork)->wq = NULL; \
239} while (0)
240
241/* On bare metal -- execute immediately for bring-up */
242static inline bool schedule_delayed_work(struct delayed_work* dwork,
243 unsigned long delay) {
244 (void)delay; /* no timer wheel: the delay is not honoured, see below */
245 __dcl_run_work(&dwork->work);
246 return true;
247}
248
249static inline bool queue_delayed_work(struct workqueue_struct* wq,
250 struct delayed_work* dwork,
251 unsigned long delay) {
252 (void)wq;
253 (void)delay;
254 __dcl_run_work(&dwork->work);
255 return true;
256}
257
258/*
259 * mod_delayed_work() -- mainline re-arms work that may already be pending and
260 * reports whether it found it that way. There is nothing to re-arm: no timer
261 * wheel to move (see schedule_delayed_work above), so "run this, possibly
262 * later" and "run this now" are the only two states this tree has, and both
263 * are the second one. It forwards to queue_delayed_work() rather than
264 * duplicating the inline run, so the two spellings cannot drift apart.
265 *
266 * The true return is mainline's "yes, it was already pending". Both callers in
267 * the tree discard it, and it is the answer that matches what has just
268 * happened -- the work has run, which is the state a caller checking for true
269 * would go on to expect. Returning false would mean "nothing was queued", for
270 * a call that did queue something.
271 */
272static inline bool mod_delayed_work(struct workqueue_struct* wq,
273 struct delayed_work* dwork,
274 unsigned long delay) {
275 return queue_delayed_work(wq, dwork, delay);
276}
277
278static inline bool cancel_delayed_work(struct delayed_work* dwork) {
279 del_timer(&dwork->timer);
280 dwork->work.pending = 0;
281 return true;
282}
283
284static inline bool cancel_delayed_work_sync(struct delayed_work* dwork) {
285 return cancel_delayed_work(dwork);
286}
287
288static inline bool flush_delayed_work(struct delayed_work* dwork) {
289 (void)dwork; /* work already ran inline; nothing pending to flush */
290 return true;
291}
292
293/* Get owning struct from delayed_work pointer */
294#define to_delayed_work(ptr) \
295 container_of(ptr, struct delayed_work, work)
296#endif
uint8_t flags
Definition virtio.h:0
struct drm_crtc struct drm_plane struct drm_plane const struct drm_crtc_funcs const char * name
Definition drm_crtc.h:1242
Definition workqueue.h:229
struct timer_list timer
Definition workqueue.h:231
struct work_struct work
Definition workqueue.h:230
struct workqueue_struct * wq
Definition workqueue.h:232
Definition timer.h:6
Definition workqueue.h:44
int pending
Definition workqueue.h:47
void * data
Definition workqueue.h:46
work_func_t func
Definition workqueue.h:45
Definition workqueue.h:50
const char * name
Definition workqueue.h:51
struct work_struct * current_work(void)
struct workqueue_struct * system_dfl_wq
struct work_struct * dcl_current_work
void(* work_func_t)(struct work_struct *work)
Definition workqueue.h:42
struct workqueue_struct * system_percpu_wq
struct workqueue_struct * system_long_wq