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