jcs's openbsd hax
openbsd
1/* $OpenBSD: completion.h,v 1.10 2024/01/06 09:33:08 kettenis Exp $ */
2/*
3 * Copyright (c) 2015, 2018 Mark Kettenis
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _LINUX_COMPLETION_H
19#define _LINUX_COMPLETION_H
20
21#include <sys/param.h>
22#include <sys/systm.h>
23#include <sys/mutex.h>
24#include <linux/wait.h>
25
26struct completion {
27 u_int done;
28 struct mutex lock;
29};
30
31#define DECLARE_COMPLETION_ONSTACK(name) \
32 struct completion name = { 0, MUTEX_INITIALIZER(IPL_TTY) }
33
34static inline void
35init_completion(struct completion *x)
36{
37 x->done = 0;
38 mtx_init(&x->lock, IPL_TTY);
39}
40
41static inline void
42reinit_completion(struct completion *x)
43{
44 x->done = 0;
45}
46
47static inline u_long
48wait_for_completion_timeout(struct completion *x, u_long timo)
49{
50 int ret;
51
52 KASSERT(!cold);
53
54 mtx_enter(&x->lock);
55 while (x->done == 0) {
56 ret = msleep(x, &x->lock, 0, "wfct", timo);
57 if (ret) {
58 mtx_leave(&x->lock);
59 /* timeout */
60 return 0;
61 }
62 }
63 if (x->done != UINT_MAX)
64 x->done--;
65 mtx_leave(&x->lock);
66
67 return 1;
68}
69
70static inline void
71wait_for_completion(struct completion *x)
72{
73 KASSERT(!cold);
74
75 mtx_enter(&x->lock);
76 while (x->done == 0) {
77 msleep_nsec(x, &x->lock, 0, "wfcom", INFSLP);
78 }
79 if (x->done != UINT_MAX)
80 x->done--;
81 mtx_leave(&x->lock);
82}
83
84static inline u_long
85wait_for_completion_interruptible(struct completion *x)
86{
87 int ret;
88
89 KASSERT(!cold);
90
91 mtx_enter(&x->lock);
92 while (x->done == 0) {
93 ret = msleep_nsec(x, &x->lock, PCATCH, "wfci", INFSLP);
94 if (ret) {
95 mtx_leave(&x->lock);
96 if (ret == EWOULDBLOCK)
97 return 0;
98 return -ERESTARTSYS;
99 }
100 }
101 if (x->done != UINT_MAX)
102 x->done--;
103 mtx_leave(&x->lock);
104
105 return 0;
106}
107
108static inline u_long
109wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
110{
111 int ret;
112
113 KASSERT(!cold);
114
115 mtx_enter(&x->lock);
116 while (x->done == 0) {
117 ret = msleep(x, &x->lock, PCATCH, "wfcit", timo);
118 if (ret) {
119 mtx_leave(&x->lock);
120 if (ret == EWOULDBLOCK)
121 return 0;
122 return -ERESTARTSYS;
123 }
124 }
125 if (x->done != UINT_MAX)
126 x->done--;
127 mtx_leave(&x->lock);
128
129 return 1;
130}
131
132static inline void
133complete(struct completion *x)
134{
135 mtx_enter(&x->lock);
136 if (x->done != UINT_MAX)
137 x->done++;
138 mtx_leave(&x->lock);
139 wakeup_one(x);
140}
141
142static inline void
143complete_all(struct completion *x)
144{
145 mtx_enter(&x->lock);
146 x->done = UINT_MAX;
147 mtx_leave(&x->lock);
148 wakeup(x);
149}
150
151static inline bool
152try_wait_for_completion(struct completion *x)
153{
154 mtx_enter(&x->lock);
155 if (x->done == 0) {
156 mtx_leave(&x->lock);
157 return false;
158 }
159 if (x->done != UINT_MAX)
160 x->done--;
161 mtx_leave(&x->lock);
162 return true;
163}
164
165#endif