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