XenevaOS
Loading...
Searching...
No Matches
completion.h
Go to the documentation of this file.
1#ifndef __LINUX_COMPLETION_H
2#define __LINUX_COMPLETION_H
3
4/*
5 * DCL <linux/completion.h> -- struct completion and its two initialisers.
6 *
7 * virtio-rng.c reaches this header without naming it: mainline's
8 * <linux/virtio.h> includes <linux/completion.h> directly, and the driver
9 * declares `struct completion have_data` as a struct member. Getting the type
10 * from somewhere other than its own include is the point -- if DCL required
11 * the driver to include a header mainline does not, the vendored file would
12 * stop being byte-identical to upstream.
13 *
14 * ### The struct is one field, on purpose
15 *
16 * mainline's is:
17 *
18 * struct completion { unsigned int done; struct swait_queue_head wait; };
19 *
20 * `wait` is the wait-queue the blocked tasks queue on. DCL has no scheduler
21 * waiting to be woken: DCL/linux_kmod_shim.c's wait_for_completion_killable()
22 * polls, spinning on `done` while calling virtio_poll_vqs() so the virtio
23 * rings keep draining (which is also what makes the wait terminate -- the
24 * completion is signalled by random_recv_done(), a virtqueue callback, and
25 * that callback only runs from a poll). A wait-queue nobody blocks on would
26 * be a member every definition has to lay out and every field offset has to
27 * stay ahead of.
28 *
29 * The load-bearing part is that `done` is the FIRST member: the shim does
30 *
31 * *(unsigned int*)x = 1; -- complete()
32 * while (!*(unsigned int*)x) ... -- wait_for_completion_killable()
33 *
34 * -- it treats the pointer as a bare `unsigned int`. That is exactly
35 * `&completion->done`, which is only true while `done` is at offset 0. Move
36 * it and every complete()/wait pair in the tree starts racing on whatever
37 * object happens to follow.
38 *
39 * ### init/reinit are static inlines, as upstream has them
40 *
41 * (mainline: `static inline void init_completion(struct completion *x)`).
42 * They could be `((x)->done = 0)` macros; as functions they keep the
43 * argument typed, so passing anything but a `struct completion*` is an error
44 * instead of a quietly-wrong dereference. Being `static inline` they also do
45 * not drag an unused-function warning along when a file includes this header
46 * and uses neither.
47 */
48
49#include <linux/kernel.h> /* size_t */
50/* mainline's chain is completion.h -> swait.h -> wait.h; DCL has no swait.h
51 * (completion is the one-field struct above), so the wait queue type
52 * drm_file.h:359 embeds comes in directly. */
53#include <linux/wait.h>
54
55struct completion {
56 /* Must stay first -- see the note above. */
57 unsigned int done;
58};
59
64static inline void init_completion(struct completion* x)
65{
66 x->done = 0;
67}
68
77static inline void reinit_completion(struct completion* x)
78{
79 x->done = 0;
80}
81
82/*
83 * Both are defined in DCL/linux_kmod_shim.c. Declared with these types rather
84 * than `void*` so the definition and every caller agree -- an earlier
85 * arrangement had the shim taking `void*`, which links fine (C has no name
86 * mangling) and silently lets a caller pass something that is not a
87 * completion.
88 *
89 * wait_for_completion_killable() returns 0 on success or -ERESTARTSYS. It
90 * cannot block forever: the shim bounds the spin and polls virtio while it
91 * goes, so an object that is never completed gives up rather than hanging
92 * the boot.
93 */
94extern void complete(struct completion* x);
96
97/*
98 * The rest of mainline's surface, which the drm atomic helpers and the event
99 * path use: complete_all(), try_wait_for_completion(), the timeout wait and
100 * the interruptible pair. Bodies in DCL/linux_kthread_shim.c.
101 *
102 * They all share one honest shape. The completion is the counter above and
103 * there is no scheduler to block in, so a wait answers for the two states it
104 * can actually observe: "already done" -- consume one and report success, as
105 * mainline does -- and "not done", where it reports the failure mainline's
106 * own callers are written against instead of pretending to sleep. A
107 * completion that is not done when the wait is entered cannot become done
108 * while control stays here, because whatever completes it (a flip handler,
109 * the commit path below) runs in this same context.
110 *
111 * The failure values therefore matter and are mainline's: 0 from the timeout
112 * variants and -ERESTARTSYS from the interruptible one. drm_crtc_commit_wait()
113 * turns a 0 from wait_for_completion_timeout() into -ETIMEDOUT with a
114 * drm_err(), and drm_atomic_helper_swap_state() unwinds on any nonzero from
115 * wait_for_completion_interruptible(); success-without-completion would walk
116 * those callers into hardware that was never programmed.
117 *
118 * complete_all() sets `done` to UINT_MAX (saturating, mainline's "permanently
119 * done"), and try_wait_for_completion() does not consume that value, so every
120 * later waiter keeps succeeding -- which is what DRM's fake commits and the
121 * flip_done waiters rely on.
122 */
123extern void complete_all(struct completion* x);
124extern bool try_wait_for_completion(struct completion* x);
125extern unsigned long wait_for_completion_timeout(struct completion* x,
126 unsigned long timeout);
129 unsigned long timeout);
130
146#define DECLARE_COMPLETION(name) struct completion name = { 0 }
147#define DECLARE_COMPLETION_ONSTACK(name) struct completion name = { 0 }
148
149#endif /* __LINUX_COMPLETION_H */
long wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout)
int wait_for_completion_interruptible(struct completion *x)
bool try_wait_for_completion(struct completion *x)
void complete_all(struct completion *x)
unsigned long wait_for_completion_timeout(struct completion *x, unsigned long timeout)
void wait_for_completion_killable(void)
void complete(void)
int x
Definition layout.c:118
Definition completion.h:55
unsigned int done
Definition completion.h:57