locks.c revision 1.15.2.3 1 /* $NetBSD: locks.c,v 1.15.2.3 2008/10/10 22:36:16 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
31 *
32 * Development of this software was supported by the
33 * Finnish Cultural Foundation.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
45 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #include <sys/param.h>
58 #include <sys/mutex.h>
59 #include <sys/rwlock.h>
60 #include <sys/atomic.h>
61
62 #include <rump/rumpuser.h>
63
64 #include "rump_private.h"
65
66 void
67 mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl)
68 {
69
70 rumpuser_mutex_init(&mtx->kmtx_mtx);
71 }
72
73 void
74 mutex_destroy(kmutex_t *mtx)
75 {
76
77 rumpuser_mutex_destroy(mtx->kmtx_mtx);
78 }
79
80 void
81 mutex_enter(kmutex_t *mtx)
82 {
83
84 rumpuser_mutex_enter(mtx->kmtx_mtx);
85 }
86
87 void
88 mutex_spin_enter(kmutex_t *mtx)
89 {
90
91 if (__predict_true(mtx != RUMP_LMUTEX_MAGIC))
92 mutex_enter(mtx);
93 }
94
95 int
96 mutex_tryenter(kmutex_t *mtx)
97 {
98
99 return rumpuser_mutex_tryenter(mtx->kmtx_mtx);
100 }
101
102 void
103 mutex_exit(kmutex_t *mtx)
104 {
105
106 rumpuser_mutex_exit(mtx->kmtx_mtx);
107 }
108
109 void
110 mutex_spin_exit(kmutex_t *mtx)
111 {
112
113 if (__predict_true(mtx != RUMP_LMUTEX_MAGIC))
114 mutex_exit(mtx);
115 }
116
117 int
118 mutex_owned(kmutex_t *mtx)
119 {
120
121 return rumpuser_mutex_held(mtx->kmtx_mtx);
122 }
123
124 /* reader/writer locks */
125
126 void
127 rw_init(krwlock_t *rw)
128 {
129
130 rumpuser_rw_init(&rw->krw_pthlock);
131 }
132
133 void
134 rw_destroy(krwlock_t *rw)
135 {
136
137 rumpuser_rw_destroy(rw->krw_pthlock);
138 }
139
140 void
141 rw_enter(krwlock_t *rw, const krw_t op)
142 {
143
144 rumpuser_rw_enter(rw->krw_pthlock, op == RW_WRITER);
145 }
146
147 int
148 rw_tryenter(krwlock_t *rw, const krw_t op)
149 {
150
151 return rumpuser_rw_tryenter(rw->krw_pthlock, op == RW_WRITER);
152 }
153
154 void
155 rw_exit(krwlock_t *rw)
156 {
157
158 rumpuser_rw_exit(rw->krw_pthlock);
159 }
160
161 /* always fails */
162 int
163 rw_tryupgrade(krwlock_t *rw)
164 {
165
166 return 0;
167 }
168
169 int
170 rw_write_held(krwlock_t *rw)
171 {
172
173 return rumpuser_rw_wrheld(rw->krw_pthlock);
174 }
175
176 int
177 rw_read_held(krwlock_t *rw)
178 {
179
180 return rumpuser_rw_rdheld(rw->krw_pthlock);
181 }
182
183 int
184 rw_lock_held(krwlock_t *rw)
185 {
186
187 return rumpuser_rw_held(rw->krw_pthlock);
188 }
189
190 /* curriculum vitaes */
191
192 /* forgive me for I have sinned */
193 #define RUMPCV(a) ((struct rumpuser_cv *)(__UNCONST((a)->cv_wmesg)))
194
195 void
196 cv_init(kcondvar_t *cv, const char *msg)
197 {
198
199 rumpuser_cv_init((struct rumpuser_cv **)__UNCONST(&cv->cv_wmesg));
200 }
201
202 void
203 cv_destroy(kcondvar_t *cv)
204 {
205
206 rumpuser_cv_destroy(RUMPCV(cv));
207 }
208
209 void
210 cv_wait(kcondvar_t *cv, kmutex_t *mtx)
211 {
212
213 rumpuser_cv_wait(RUMPCV(cv), mtx->kmtx_mtx);
214 }
215
216 int
217 cv_wait_sig(kcondvar_t *cv, kmutex_t *mtx)
218 {
219
220 rumpuser_cv_wait(RUMPCV(cv), mtx->kmtx_mtx);
221 return 0;
222 }
223
224 int
225 cv_timedwait(kcondvar_t *cv, kmutex_t *mtx, int ticks)
226 {
227 #ifdef DIAGNOSTIC
228 extern int hz;
229 #endif
230
231 if (ticks == 0) {
232 cv_wait(cv, mtx);
233 return 0;
234 } else {
235 KASSERT(hz == 100);
236 return rumpuser_cv_timedwait(RUMPCV(cv), mtx->kmtx_mtx, ticks);
237 }
238 }
239
240 int
241 cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mtx, int ticks)
242 {
243
244 return cv_timedwait(cv, mtx, ticks);
245 }
246
247 void
248 cv_signal(kcondvar_t *cv)
249 {
250
251 rumpuser_cv_signal(RUMPCV(cv));
252 }
253
254 void
255 cv_broadcast(kcondvar_t *cv)
256 {
257
258 rumpuser_cv_broadcast(RUMPCV(cv));
259 }
260
261 bool
262 cv_has_waiters(kcondvar_t *cv)
263 {
264
265 return rumpuser_cv_has_waiters(RUMPCV(cv));
266 }
267
268 /*
269 * giant lock
270 */
271
272 static int lockcnt;
273 void
274 _kernel_lock(int nlocks)
275 {
276
277 while (nlocks--) {
278 mutex_enter(&rump_giantlock);
279 lockcnt++;
280 }
281 }
282
283 void
284 _kernel_unlock(int nlocks, int *countp)
285 {
286
287 if (!mutex_owned(&rump_giantlock)) {
288 KASSERT(nlocks == 0);
289 if (countp)
290 *countp = 0;
291 return;
292 }
293
294 if (countp)
295 *countp = lockcnt;
296 if (nlocks == 0)
297 nlocks = lockcnt;
298 if (nlocks == -1) {
299 KASSERT(lockcnt == 1);
300 nlocks = 1;
301 }
302 KASSERT(nlocks <= lockcnt);
303 while (nlocks--) {
304 lockcnt--;
305 mutex_exit(&rump_giantlock);
306 }
307 }
308
309 struct kmutexobj {
310 kmutex_t mo_lock;
311 u_int mo_refcnt;
312 };
313
314 kmutex_t *
315 mutex_obj_alloc(kmutex_type_t type, int ipl)
316 {
317 struct kmutexobj *mo;
318
319 mo = kmem_alloc(sizeof(*mo), KM_SLEEP);
320 mutex_init(&mo->mo_lock, type, ipl);
321 mo->mo_refcnt = 1;
322
323 return (kmutex_t *)mo;
324 }
325
326 void
327 mutex_obj_hold(kmutex_t *lock)
328 {
329 struct kmutexobj *mo = (struct kmutexobj *)lock;
330
331 atomic_inc_uint(&mo->mo_refcnt);
332 }
333
334 bool
335 mutex_obj_free(kmutex_t *lock)
336 {
337 struct kmutexobj *mo = (struct kmutexobj *)lock;
338
339 if (atomic_dec_uint_nv(&mo->mo_refcnt) > 0) {
340 return false;
341 }
342 mutex_destroy(&mo->mo_lock);
343 kmem_free(mo, sizeof(*mo));
344 return true;
345 }
346