xref: /openbsd/sys/dev/pci/drm/include/linux/completion.h (revision 667382c7)
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 
26 struct 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 
34 static inline void
init_completion(struct completion * x)35 init_completion(struct completion *x)
36 {
37 	x->done = 0;
38 	mtx_init(&x->lock, IPL_TTY);
39 }
40 
41 static inline void
reinit_completion(struct completion * x)42 reinit_completion(struct completion *x)
43 {
44 	x->done = 0;
45 }
46 
47 static inline u_long
wait_for_completion_timeout(struct completion * x,u_long timo)48 wait_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 
70 static inline void
wait_for_completion(struct completion * x)71 wait_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 
84 static inline u_long
wait_for_completion_interruptible(struct completion * x)85 wait_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 
108 static inline u_long
wait_for_completion_interruptible_timeout(struct completion * x,u_long timo)109 wait_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 
132 static inline void
complete(struct completion * x)133 complete(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 
142 static inline void
complete_all(struct completion * x)143 complete_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 
151 static inline bool
try_wait_for_completion(struct completion * x)152 try_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
166