xref: /netbsd-src/sys/external/bsd/drm2/include/drm/drm_wait_netbsd.h (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: drm_wait_netbsd.h,v 1.2 2014/03/18 18:20:43 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 2013 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Taylor R. Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _DRM_DRM_WAIT_NETBSD_H_
33 #define _DRM_DRM_WAIT_NETBSD_H_
34 
35 #include <sys/param.h>
36 #include <sys/condvar.h>
37 #include <sys/kernel.h>
38 #include <sys/mutex.h>
39 #include <sys/systm.h>
40 
41 #include <linux/mutex.h>
42 #include <linux/spinlock.h>
43 
44 typedef kcondvar_t drm_waitqueue_t;
45 
46 #define	DRM_HZ	hz		/* XXX Hurk...  */
47 
48 static inline void
49 DRM_INIT_WAITQUEUE(drm_waitqueue_t *q, const char *name)
50 {
51 	cv_init(q, name);
52 }
53 
54 static inline void
55 DRM_DESTROY_WAITQUEUE(drm_waitqueue_t *q)
56 {
57 	cv_destroy(q);
58 }
59 
60 static inline bool
61 DRM_WAITERS_P(drm_waitqueue_t *q, struct mutex *interlock)
62 {
63 	KASSERT(mutex_is_locked(interlock));
64 	return cv_has_waiters(q);
65 }
66 
67 static inline void
68 DRM_WAKEUP_ONE(drm_waitqueue_t *q, struct mutex *interlock)
69 {
70 	KASSERT(mutex_is_locked(interlock));
71 	cv_signal(q);
72 }
73 
74 static inline void
75 DRM_WAKEUP_ALL(drm_waitqueue_t *q, struct mutex *interlock)
76 {
77 	KASSERT(mutex_is_locked(interlock));
78 	cv_broadcast(q);
79 }
80 
81 static inline bool
82 DRM_SPIN_WAITERS_P(drm_waitqueue_t *q, spinlock_t *interlock)
83 {
84 	KASSERT(spin_is_locked(interlock));
85 	return cv_has_waiters(q);
86 }
87 
88 static inline void
89 DRM_SPIN_WAKEUP_ONE(drm_waitqueue_t *q, spinlock_t *interlock)
90 {
91 	KASSERT(spin_is_locked(interlock));
92 	cv_signal(q);
93 }
94 
95 static inline void
96 DRM_SPIN_WAKEUP_ALL(drm_waitqueue_t *q, spinlock_t *interlock)
97 {
98 	KASSERT(spin_is_locked(interlock));
99 	cv_broadcast(q);
100 }
101 
102 #define	_DRM_WAIT_UNTIL(RET, WAIT, Q, INTERLOCK, CONDITION) do		\
103 {									\
104 	KASSERT(mutex_is_locked((INTERLOCK)));				\
105 	for (;;) {							\
106 		if (CONDITION) {					\
107 			(RET) = 0;					\
108 			break;						\
109 		}							\
110 		/* XXX errno NetBSD->Linux */				\
111 		(RET) = -WAIT((Q), &(INTERLOCK)->mtx_lock);		\
112 		if (RET)						\
113 			break;						\
114 	}								\
115 } while (0)
116 
117 #define	cv_wait_nointr(Q, I)	(cv_wait((Q), (I)), 0)
118 
119 #define	DRM_WAIT_NOINTR_UNTIL(RET, Q, I, C)				\
120 	_DRM_WAIT_UNTIL(RET, cv_wait_nointr, Q, I, C)
121 
122 #define	DRM_WAIT_UNTIL(RET, Q, I, C)				\
123 	_DRM_WAIT_UNTIL(RET, cv_wait_sig, Q, I, C)
124 
125 #define	_DRM_TIMED_WAIT_UNTIL(RET, WAIT, Q, INTERLOCK, TICKS, CONDITION) do \
126 {									\
127 	extern int hardclock_ticks;					\
128 	const int _dtwu_start = hardclock_ticks;			\
129 	int _dtwu_ticks = (TICKS);					\
130 	KASSERT(mutex_is_locked((INTERLOCK)));				\
131 	for (;;) {							\
132 		if (CONDITION) {					\
133 			(RET) = _dtwu_ticks;				\
134 			break;						\
135 		}							\
136 		/* XXX errno NetBSD->Linux */				\
137 		(RET) = -WAIT((Q), &(INTERLOCK)->mtx_lock,		\
138 		    _dtwu_ticks);					\
139 		if (RET)						\
140 			break;						\
141 		const int _dtwu_now = hardclock_ticks;			\
142 		KASSERT(_dtwu_start <= _dtwu_now);			\
143 		if ((_dtwu_now - _dtwu_start) < _dtwu_ticks) {		\
144 			_dtwu_ticks -= (_dtwu_now - _dtwu_start);	\
145 		} else {						\
146 			(RET) = 0;					\
147 			break;						\
148 		}							\
149 	}								\
150 } while (0)
151 
152 #define	DRM_TIMED_WAIT_NOINTR_UNTIL(RET, Q, I, T, C)			\
153 	_DRM_TIMED_WAIT_UNTIL(RET, cv_timedwait, Q, I, T, C)
154 
155 #define	DRM_TIMED_WAIT_UNTIL(RET, Q, I, T, C)			\
156 	_DRM_TIMED_WAIT_UNTIL(RET, cv_timedwait_sig, Q, I, T, C)
157 
158 #define	_DRM_SPIN_WAIT_UNTIL(RET, WAIT, Q, INTERLOCK, CONDITION) do	\
159 {									\
160 	KASSERT(spin_is_locked((INTERLOCK)));				\
161 	while (!(CONDITION)) {						\
162 		/* XXX errno NetBSD->Linux */				\
163 		(RET) = -WAIT((Q), &(INTERLOCK)->sl_lock);		\
164 		if (RET)						\
165 			break;						\
166 	}								\
167 } while (0)
168 
169 #define	DRM_SPIN_WAIT_NOINTR_UNTIL(RET, Q, I, C)			\
170 	_DRM_SPIN_WAIT_UNTIL(RET, cv_wait_nointr, Q, I, C)
171 
172 #define	DRM_SPIN_WAIT_UNTIL(RET, Q, I, C)				\
173 	_DRM_SPIN_WAIT_UNTIL(RET, cv_wait_sig, Q, I, C)
174 
175 #define	_DRM_SPIN_TIMED_WAIT_UNTIL(RET, WAIT, Q, INTERLOCK, TICKS, CONDITION) \
176 	do								\
177 {									\
178 	extern int hardclock_ticks;					\
179 	const int _dstwu_start = hardclock_ticks;			\
180 	int _dstwu_ticks = (TICKS);					\
181 	KASSERT(spin_is_locked((INTERLOCK)));				\
182 	for (;;) {							\
183 		if (CONDITION) {					\
184 			(RET) = _dstwu_ticks;				\
185 			break;						\
186 		}							\
187 		/* XXX errno NetBSD->Linux */				\
188 		(RET) = -WAIT((Q), &(INTERLOCK)->sl_lock,		\
189 		    _dstwu_ticks);					\
190 		if (RET)						\
191 			break;						\
192 		const int _dstwu_now = hardclock_ticks;			\
193 		KASSERT(_dstwu_start <= _dstwu_now);			\
194 		if ((_dstwu_now - _dstwu_start) < _dstwu_ticks) {	\
195 			_dstwu_ticks -= (_dstwu_now - _dstwu_start);	\
196 		} else {						\
197 			(RET) = 0;					\
198 			break;						\
199 		}							\
200 	}								\
201 } while (0)
202 
203 #define	DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(RET, Q, I, T, C)		\
204 	_DRM_SPIN_TIMED_WAIT_UNTIL(RET, cv_timedwait, Q, I, T, C)
205 
206 #define	DRM_SPIN_TIMED_WAIT_UNTIL(RET, Q, I, T, C)			\
207 	_DRM_SPIN_TIMED_WAIT_UNTIL(RET, cv_timedwait_sig, Q, I, T, C)
208 
209 #endif  /* _DRM_DRM_WAIT_NETBSD_H_ */
210