xref: /openbsd/sys/dev/pci/drm/include/linux/completion.h (revision e5dd7070)
1 /*	$OpenBSD: completion.h,v 1.9 2020/06/22 14:19:35 jsg 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 static inline void
32 init_completion(struct completion *x)
33 {
34 	x->done = 0;
35 	mtx_init(&x->lock, IPL_TTY);
36 }
37 
38 static inline void
39 reinit_completion(struct completion *x)
40 {
41 	x->done = 0;
42 }
43 
44 static inline u_long
45 wait_for_completion_timeout(struct completion *x, u_long timo)
46 {
47 	int ret;
48 
49 	KASSERT(!cold);
50 
51 	mtx_enter(&x->lock);
52 	while (x->done == 0) {
53 		ret = msleep(x, &x->lock, 0, "wfct", timo);
54 		if (ret) {
55 			mtx_leave(&x->lock);
56 			/* timeout */
57 			return 0;
58 		}
59 	}
60 	if (x->done != UINT_MAX)
61 		x->done--;
62 	mtx_leave(&x->lock);
63 
64 	return 1;
65 }
66 
67 static inline void
68 wait_for_completion(struct completion *x)
69 {
70 	KASSERT(!cold);
71 
72 	mtx_enter(&x->lock);
73 	while (x->done == 0) {
74 		msleep_nsec(x, &x->lock, 0, "wfcom", INFSLP);
75 	}
76 	if (x->done != UINT_MAX)
77 		x->done--;
78 	mtx_leave(&x->lock);
79 }
80 
81 static inline u_long
82 wait_for_completion_interruptible(struct completion *x)
83 {
84 	int ret;
85 
86 	KASSERT(!cold);
87 
88 	mtx_enter(&x->lock);
89 	while (x->done == 0) {
90 		ret = msleep_nsec(x, &x->lock, PCATCH, "wfci", INFSLP);
91 		if (ret) {
92 			mtx_leave(&x->lock);
93 			if (ret == EWOULDBLOCK)
94 				return 0;
95 			return -ERESTARTSYS;
96 		}
97 	}
98 	if (x->done != UINT_MAX)
99 		x->done--;
100 	mtx_leave(&x->lock);
101 
102 	return 0;
103 }
104 
105 static inline u_long
106 wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
107 {
108 	int ret;
109 
110 	KASSERT(!cold);
111 
112 	mtx_enter(&x->lock);
113 	while (x->done == 0) {
114 		ret = msleep(x, &x->lock, PCATCH, "wfcit", timo);
115 		if (ret) {
116 			mtx_leave(&x->lock);
117 			if (ret == EWOULDBLOCK)
118 				return 0;
119 			return -ERESTARTSYS;
120 		}
121 	}
122 	if (x->done != UINT_MAX)
123 		x->done--;
124 	mtx_leave(&x->lock);
125 
126 	return 1;
127 }
128 
129 static inline void
130 complete(struct completion *x)
131 {
132 	mtx_enter(&x->lock);
133 	if (x->done != UINT_MAX)
134 		x->done++;
135 	mtx_leave(&x->lock);
136 	wakeup_one(x);
137 }
138 
139 static inline void
140 complete_all(struct completion *x)
141 {
142 	mtx_enter(&x->lock);
143 	x->done = UINT_MAX;
144 	mtx_leave(&x->lock);
145 	wakeup(x);
146 }
147 
148 static inline bool
149 try_wait_for_completion(struct completion *x)
150 {
151 	mtx_enter(&x->lock);
152 	if (x->done == 0) {
153 		mtx_leave(&x->lock);
154 		return false;
155 	}
156 	if (x->done != UINT_MAX)
157 		x->done--;
158 	mtx_leave(&x->lock);
159 	return true;
160 }
161 
162 #endif
163