implement fancy devlock as we did on MacOS, for now
[arla.git] / nnpfs / bsd / nnpfs_dev-freebsd.c
blobe5f68418230df88e7bdc8edd69e9369790e346fa
1 /*
2 * Copyright (c) 1995 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
35 #include <nnpfs/nnpfs_locl.h>
36 #include <nnpfs/nnpfs_message.h>
37 #include <nnpfs/nnpfs_msg_locl.h>
38 #include <nnpfs/nnpfs_fs.h>
39 #include <nnpfs/nnpfs_dev.h>
40 #include <nnpfs/nnpfs_deb.h>
42 RCSID("$Id$");
44 #define NNPFS_FBSD_DEVLOCK
46 #if 1
47 void
48 nnpfs_dev_lock(struct nnpfs *chan)
50 d_thread_t *me = curthread;
52 NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock, me=%p\n", me));
54 mtx_lock(&chan->lock.lock);
56 while (chan->lock.recurse > 0 && chan->lock.locker != me) {
57 /* XXX PCATCH */
58 #if 1
59 (void)nnpfs_msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock");
60 #else
61 int ret = 0;
62 while msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock", 7 * hz);
64 #endif
67 chan->lock.locker = me;
68 nnpfs_assert(chan->lock.recurse >= 0);
69 chan->lock.recurse++;
71 NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock, locker %p\n", chan->lock.locker));
73 mtx_unlock(&chan->lock.lock);
76 void
77 nnpfs_dev_unlock(struct nnpfs *chan)
79 d_thread_t *me = curthread;
81 NNPFSDEB(XDEBDEV, ("nnpfs_dev_unlock, me=%p locker=%p r=%d\n", me,
82 chan->lock.locker, chan->lock.recurse));
84 mtx_lock(&chan->lock.lock);
86 chan->lock.recurse--;
87 nnpfs_assert(chan->lock.recurse >= 0);
88 nnpfs_assert(chan->lock.locker == me);
90 if (chan->lock.recurse == 0) {
91 chan->lock.locker = NULL;
92 wakeup(&chan->lock);
95 mtx_unlock(&chan->lock.lock);
98 int
99 nnpfs_dev_msleep(struct nnpfs *chan, caddr_t waitobj, int flags, const char *msg)
101 d_thread_t *me = curthread;
102 int ret, nlocks;
104 NNPFSDEB(XDEBDEV, ("nnpfs_dev_msleep %p %x %s, me %p\n", waitobj, flags, msg, me));
106 mtx_lock(&chan->lock.lock);
107 nlocks = chan->lock.recurse;
108 nnpfs_assert(chan->lock.recurse >= 0);
109 nnpfs_assert(chan->lock.locker == me);
111 chan->lock.recurse = 0;
112 chan->lock.locker = NULL;
113 wakeup(&chan->lock);
115 ret = nnpfs_msleep(waitobj, &chan->lock.lock, flags, msg);
117 while (chan->lock.recurse > 0)
118 /* XXX PCATCH, flags, ret? */
119 (void)nnpfs_msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock");
121 nnpfs_assert(chan->lock.recurse == 0);
122 chan->lock.locker = me;
123 chan->lock.recurse = nlocks;
125 mtx_unlock(&chan->lock.lock);
126 return ret;
130 nnpfs_dev_initlock(struct nnpfs *chan)
132 d_thread_t *me = curthread;
134 NNPFSDEB(XDEBDEV, ("nnpfs_dev_initlock\n"));
136 if (mtx_initialized(&chan->lock.lock))
137 panic("nnpfs_dev_initlock: already inited!");
139 mtx_init(&chan->lock.lock, "nnpfsdevlock", NULL, MTX_DEF);
141 mtx_lock(&chan->lock.lock);
142 chan->lock.locker = me;
143 chan->lock.recurse = 1;
144 mtx_unlock(&chan->lock.lock);
146 return 0;
149 void
150 nnpfs_dev_uninitlock(struct nnpfs *chan)
152 d_thread_t *me = curthread;
154 NNPFSDEB(XDEBDEV, ("nnpfs_dev_uninitlock\n"));
156 if (!mtx_initialized(&chan->lock.lock))
157 printf("nnpfs_dev_uninitlock: not inited!\n");
159 mtx_lock(&chan->lock.lock);
160 nnpfs_assert(chan->lock.recurse == 1);
161 nnpfs_assert(chan->lock.locker == me);
163 chan->lock.recurse = 0;
164 chan->lock.locker = NULL;
167 * contrary to man page, it seems we need to unlock the mutex before
168 * destroying it if we use spinlocks. Default mutexes are ok.
171 mtx_destroy(&chan->lock.lock);
173 #else
175 void
176 nnpfs_dev_lock(struct nnpfs *chan)
178 int ret;
179 NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock\n"));
180 ret = lockmgr(&chan->dev_lock, LK_EXCLUSIVE | LK_CANRECURSE, NULL);
181 nnpfs_assert(!ret);
184 void
185 nnpfs_dev_unlock(struct nnpfs *chan)
187 int ret;
188 NNPFSDEB(XDEBDEV, ("nnpfs_dev_unlock\n"));
189 ret = lockmgr(&chan->dev_lock, LK_RELEASE, NULL);
190 nnpfs_assert(!ret);
194 nnpfs_dev_msleep(struct nnpfs *chan, caddr_t waitobj, int flags, const char *msg)
196 d_thread_t *td = curthread;
197 int nlocks, i, ret;
199 NNPFSDEB(XDEBDEV, ("nnpfs_dev_msleep %p %x %s\n", waitobj, flags, msg));
201 ret = lockstatus(&chan->dev_lock, td);
202 nnpfs_assert(ret == LK_EXCLUSIVE);
204 nlocks = lockcount(&chan->dev_lock);
206 for (i = nlocks; i > 0 ; i--) {
207 ret = lockmgr(&chan->dev_lock, LK_RELEASE, NULL);
208 nnpfs_assert(!ret);
211 ret = nnpfs_msleep(waitobj, &chan->dev_lock, flags, msg);
212 return ret;
216 nnpfs_dev_initlock(struct nnpfs *chan)
218 NNPFSDEB(XDEBDEV, ("nnpfs_dev_initlock\n"));
219 lockinit(&chan->dev_lock, PRIBIO /* XXX */, "nnpfsdevlock", NULL, LK_CANRECURSE | LK_NOSHARE);
220 return lockmgr(&chan->dev_lock, LK_EXCLUSIVE, NULL);
223 void
224 nnpfs_dev_uninitlock(struct nnpfs *chan)
226 NNPFSDEB(XDEBDEV, ("nnpfs_dev_uninitlock\n"));
227 lockdestroy(&chan->dev_lock);
230 #endif
232 #ifndef NNPFS_FBSD_DEVLOCK
234 #ifndef D_NEEDGIANT
235 #define D_NEEDGIANT 0
236 #endif
238 #endif
240 struct cdevsw nnpfs_cdev = {
241 #if __FreeBSD_version >= 502103
242 d_version: D_VERSION,
243 #endif
244 d_name: "nnpfs",
245 d_open: nnpfs_devopen,
246 d_close: nnpfs_devclose,
247 d_read: nnpfs_devread,
248 d_write: nnpfs_devwrite,
249 d_ioctl: nnpfs_devioctl,
250 #ifdef HAVE_STRUCT_CDEVSW_D_MMAP
251 d_mmap: nommap,
252 #endif
253 #ifdef HAVE_STRUCT_CDEVSW_D_STRATEGY
254 d_strategy: nostrategy,
255 #endif
257 * Giant is no longer needed, nnpfs_node_find & friends are locked
258 * now, verify correctness before removing.
260 #ifdef NNPFS_FBSD_DEVLOCK
261 d_flags: 0,
262 #else
263 d_flags: D_NEEDGIANT,
264 #endif
266 #ifdef HAVE_STRUCT_CDEVSW_D_STOP
267 d_stop: nostop,
268 #endif
269 #ifdef HAVE_STRUCT_CDEVSW_D_RESET
270 d_reset: noreset,
271 #endif
272 #ifdef HAVE_STRUCT_CDEVSW_D_BOGORESET
273 d_bogoreset: noreset,
274 #endif
275 #ifdef HAVE_STRUCT_CDEVSW_D_DEVTOTTY
276 d_devtotty: nodevtotty,
277 #endif
278 #if defined(HAVE_VOP_SELECT)
279 d_select: nnpfs_devselect,
280 #elif defined(HAVE_VOP_POLL)
281 d_poll: nnpfs_devpoll,
282 #else
283 #error select or poll: that is the question
284 #endif
285 #ifdef HAVE_STRUCT_CDEVSW_D_BOGOPARMS
286 d_bogoparms: noparms,
287 #endif
288 #ifdef HAVE_STRUCT_CDEVSW_D_SPARE
289 d_spare: NULL,
290 #endif
291 #if __FreeBSD_version < 600007
292 d_maj: 128, /* XXX */
293 #endif
294 #ifdef HAVE_STRUCT_CDEVSW_D_DUMP
295 d_dump: nodump,
296 #endif
297 #ifdef HAVE_STRUCT_CDEVSW_D_PSIZE
298 d_psize: nopsize,
299 #endif
300 #ifdef HAVE_STRUCT_CDEVSW_D_MAXIO
301 d_maxio: 0,
302 #endif
303 #ifdef HAVE_STRUCT_CDEVSW_D_BMAJ
304 #ifdef NOUDEV
305 d_bmaj: NOUDEV
306 #else
307 d_bmaj: NODEV
308 #endif
309 #endif /* HAVE_STRUCT_CDEVSW_D_BMAJ */