Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / cddl / osnet / lib / libzpool / kernel2.c
blobad5bf5ead674e1471f48da03374aeef2dc27b1a0
1 /* $NetBSD: kernel2.c,v 1.1 2009/03/26 22:11:44 ad Exp $ */
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
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.
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.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: kernel2.c,v 1.1 2009/03/26 22:11:44 ad Exp $");
35 #include <sys/zfs_context.h>
37 #include <assert.h>
38 #include <err.h>
40 #define GET(ptr) (*(void **)ptr)
41 #define SET(ptr, val) (*(void **)ptr = val)
43 void
44 mutex_init(kmutex_t *mtx, void *junk1, kmutex_type_t type, void *junk2)
46 pthread_mutex_t *mutex;
47 int rv;
49 mutex = malloc(sizeof(*mutex));
50 if (mutex == NULL) {
51 err(1, "mutex_init: malloc\n");
53 rv = pthread_mutex_init(mutex, NULL);
54 if (rv != 0) {
55 errx(1, "mutex_init: err %d\n", rv);
57 SET(mtx, mutex);
60 void
61 mutex_destroy(kmutex_t *mtx)
63 pthread_mutex_t *mutex = GET(mtx);
65 pthread_mutex_destroy(mutex);
66 free(mutex);
69 void
70 mutex_enter(kmutex_t *mtx)
73 pthread_mutex_lock(GET(mtx));
76 int
77 mutex_tryenter(kmutex_t *mtx)
80 return (pthread_mutex_trylock(GET(mtx)) == 0);
83 void
84 mutex_exit(kmutex_t *mtx)
87 pthread_mutex_unlock(GET(mtx));
90 void *
91 mutex_owner(kmutex_t *mtx)
94 return pthread_mutex_owner_np(GET(mtx));
97 int
98 mutex_owned(kmutex_t *mtx)
101 return pthread_mutex_held_np(GET(mtx));
104 void
105 rw_init(krwlock_t *rw, char *name, int type, void *arg)
107 pthread_rwlock_t *rwlock;
108 int rv;
110 rwlock = malloc(sizeof(*rwlock));
111 if (rwlock == NULL) {
112 err(1, "rw_init: malloc\n");
114 rv = pthread_rwlock_init(rwlock, NULL);
115 if (rv != 0) {
116 errx(1, "rw_init: err %d\n", rv);
118 SET(rw, rwlock);
121 void
122 rw_destroy(krwlock_t *rw)
124 pthread_rwlock_t *rwlock = GET(rw);
125 int rv;
127 rv = pthread_rwlock_destroy(rwlock);
128 if (rv != 0) {
129 errx(1, "rw_destroy: err %d\n", rv);
131 free(rwlock);
134 void
135 rw_enter(krwlock_t *rw, const krw_t op)
137 pthread_rwlock_t *rwlock = GET(rw);
138 int rv;
140 if (op == RW_WRITER) {
141 rv = pthread_rwlock_wrlock(rwlock);
142 if (rv != 0) {
143 errx(1, "rw_enter(RW_WRITER) err %d\n", rv);
145 } else {
146 rv = pthread_rwlock_rdlock(rwlock);
147 if (rv != 0) {
148 errx(1, "rw_enter(RW_READER) err %d\n", rv);
154 rw_tryenter(krwlock_t *rw, const krw_t op)
156 pthread_rwlock_t *rwlock = GET(rw);
157 int rv;
159 if (op == RW_WRITER) {
160 rv = pthread_rwlock_trywrlock(rwlock);
161 } else {
162 rv = pthread_rwlock_tryrdlock(rwlock);
165 return rv == 0;
168 void
169 rw_exit(krwlock_t *rw)
171 int rv;
173 rv = pthread_rwlock_unlock(GET(rw));
174 if (rv != 0) {
175 errx(1, "rw_exit: err %d\n", rv);
180 rw_tryupgrade(krwlock_t *rw)
183 return 0;
187 rw_lock_held(krwlock_t *rw)
190 return pthread_rwlock_held_np(GET(rw));
194 rw_read_held(krwlock_t *rw)
197 return pthread_rwlock_rdheld_np(GET(rw));
201 rw_write_held(krwlock_t *rw)
204 return pthread_rwlock_wrheld_np(GET(rw));
207 void
208 cv_init(kcondvar_t *cv, char *name, int type, void *arg)
210 pthread_cond_t *cond;
212 cond = malloc(sizeof(*cond));
213 pthread_cond_init(cond, NULL);
214 SET(cv, cond);
217 void
218 cv_destroy(kcondvar_t *cv)
220 pthread_cond_t *cond = GET(cv);
222 if (cond != NULL) {
223 pthread_cond_destroy(cond);
224 free(cond);
228 void
229 cv_wait(kcondvar_t *cv, kmutex_t *mtx)
232 if (GET(cv) == NULL) {
233 cv_init(cv, NULL, 0, NULL);
236 pthread_cond_wait(GET(cv), GET(mtx));
239 clock_t
240 cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
242 struct timespec ts;
243 uint64_t when;
244 int error;
246 if (GET(cv) == NULL) {
247 cv_init(cv, NULL, 0, NULL);
250 /* convert back from 119hz to nanoseconds. */
251 when = abstime << 23;
252 ts.tv_sec = (long)(abstime / 1000000000);
253 ts.tv_nsec = (long)(abstime % 1000000000);
255 do {
256 error = pthread_cond_timedwait(GET(cv), GET(mp), &ts);
257 } while (error == EINTR);
259 if (error == ETIMEDOUT)
260 return (-1);
261 assert(error == 0);
263 return (1);
266 void
267 cv_signal(kcondvar_t *cv)
270 if (GET(cv) == NULL) {
271 cv_init(cv, NULL, 0, NULL);
273 pthread_cond_signal(GET(cv));
276 void
277 cv_broadcast(kcondvar_t *cv)
280 if (GET(cv) == NULL) {
281 cv_init(cv, NULL, 0, NULL);
283 pthread_cond_broadcast(GET(cv));