xref: /openbsd-src/sys/dev/pci/drm/include/linux/completion.h (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: completion.h,v 1.3 2019/12/30 09:30:31 mpi 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 	wait_queue_head_t wait;
29 };
30 
31 static inline void
32 init_completion(struct completion *x)
33 {
34 	x->done = 0;
35 	mtx_init(&x->wait.lock, IPL_TTY);
36 }
37 
38 static inline u_long
39 wait_for_completion_timeout(struct completion *x, u_long timo)
40 {
41 	int ret;
42 
43 	KASSERT(!cold);
44 
45 	mtx_enter(&x->wait.lock);
46 	while (x->done == 0) {
47 		ret = msleep(x, &x->wait.lock, 0, "wfct", timo);
48 		if (ret) {
49 			mtx_leave(&x->wait.lock);
50 			return (ret == EWOULDBLOCK) ? 0 : -ret;
51 		}
52 	}
53 	x->done--;
54 	mtx_leave(&x->wait.lock);
55 
56 	return 1;
57 }
58 
59 static inline u_long
60 wait_for_completion_interruptible(struct completion *x)
61 {
62 	int ret;
63 
64 	KASSERT(!cold);
65 
66 	mtx_enter(&x->wait.lock);
67 	while (x->done == 0) {
68 		ret = msleep_nsec(x, &x->wait.lock, PCATCH, "wfci", INFSLP);
69 		if (ret) {
70 			mtx_leave(&x->wait.lock);
71 			return (ret == EWOULDBLOCK) ? 0 : -ret;
72 		}
73 	}
74 	x->done--;
75 	mtx_leave(&x->wait.lock);
76 
77 	return 0;
78 }
79 
80 static inline u_long
81 wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
82 {
83 	int ret;
84 
85 	KASSERT(!cold);
86 
87 	mtx_enter(&x->wait.lock);
88 	while (x->done == 0) {
89 		ret = msleep(x, &x->wait.lock, PCATCH, "wfcit", timo);
90 		if (ret) {
91 			mtx_leave(&x->wait.lock);
92 			return (ret == EWOULDBLOCK) ? 0 : -ret;
93 		}
94 	}
95 	x->done--;
96 	mtx_leave(&x->wait.lock);
97 
98 	return 1;
99 }
100 
101 static inline void
102 complete_all(struct completion *x)
103 {
104 	mtx_enter(&x->wait.lock);
105 	x->done = UINT_MAX;
106 	mtx_leave(&x->wait.lock);
107 	wakeup(x);
108 }
109 
110 static inline bool
111 try_wait_for_completion(struct completion *x)
112 {
113 	mtx_enter(&x->wait.lock);
114 	if (x->done == 0) {
115 		mtx_leave(&x->wait.lock);
116 		return false;
117 	}
118 	x->done--;
119 	mtx_leave(&x->wait.lock);
120 	return true;
121 }
122 
123 #endif
124