From 31ef05ebf35eee24483f5d866347833b3eac4b65 Mon Sep 17 00:00:00 2001 From: tol Date: Tue, 6 Mar 2007 13:19:03 +0000 Subject: [PATCH] implement fancy devlock as we did on MacOS, for now --- nnpfs/bsd/nnpfs_dev-freebsd.c | 174 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 154 insertions(+), 20 deletions(-) diff --git a/nnpfs/bsd/nnpfs_dev-freebsd.c b/nnpfs/bsd/nnpfs_dev-freebsd.c index 49827ecf6..e5f684182 100644 --- a/nnpfs/bsd/nnpfs_dev-freebsd.c +++ b/nnpfs/bsd/nnpfs_dev-freebsd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan + * Copyright (c) 1995 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -43,59 +43,191 @@ RCSID("$Id$"); #define NNPFS_FBSD_DEVLOCK +#if 1 void nnpfs_dev_lock(struct nnpfs *chan) { -#ifdef NNPFS_FBSD_DEVLOCK - NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock\n")); - mtx_lock(&chan->dev_lock); + d_thread_t *me = curthread; + + NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock, me=%p\n", me)); + + mtx_lock(&chan->lock.lock); + + while (chan->lock.recurse > 0 && chan->lock.locker != me) { + /* XXX PCATCH */ +#if 1 + (void)nnpfs_msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock"); +#else + int ret = 0; + while msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock", 7 * hz); + #endif + } + + chan->lock.locker = me; + nnpfs_assert(chan->lock.recurse >= 0); + chan->lock.recurse++; + + NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock, locker %p\n", chan->lock.locker)); + + mtx_unlock(&chan->lock.lock); } void nnpfs_dev_unlock(struct nnpfs *chan) { -#ifdef NNPFS_FBSD_DEVLOCK - NNPFSDEB(XDEBDEV, ("nnpfs_dev_unlock\n")); - mtx_unlock(&chan->dev_lock); -#endif + d_thread_t *me = curthread; + + NNPFSDEB(XDEBDEV, ("nnpfs_dev_unlock, me=%p locker=%p r=%d\n", me, + chan->lock.locker, chan->lock.recurse)); + + mtx_lock(&chan->lock.lock); + + chan->lock.recurse--; + nnpfs_assert(chan->lock.recurse >= 0); + nnpfs_assert(chan->lock.locker == me); + + if (chan->lock.recurse == 0) { + chan->lock.locker = NULL; + wakeup(&chan->lock); + } + + mtx_unlock(&chan->lock.lock); } int nnpfs_dev_msleep(struct nnpfs *chan, caddr_t waitobj, int flags, const char *msg) { - int ret = EDOOFUS; -#ifdef NNPFS_FBSD_DEVLOCK - NNPFSDEB(XDEBDEV, ("nnpfs_dev_msleep %p %x %s\n", waitobj, flags, msg)); - ret = nnpfs_msleep(waitobj, &chan->dev_lock, flags, msg); -#endif + d_thread_t *me = curthread; + int ret, nlocks; + + NNPFSDEB(XDEBDEV, ("nnpfs_dev_msleep %p %x %s, me %p\n", waitobj, flags, msg, me)); + + mtx_lock(&chan->lock.lock); + nlocks = chan->lock.recurse; + nnpfs_assert(chan->lock.recurse >= 0); + nnpfs_assert(chan->lock.locker == me); + + chan->lock.recurse = 0; + chan->lock.locker = NULL; + wakeup(&chan->lock); + + ret = nnpfs_msleep(waitobj, &chan->lock.lock, flags, msg); + + while (chan->lock.recurse > 0) + /* XXX PCATCH, flags, ret? */ + (void)nnpfs_msleep(&chan->lock, &chan->lock.lock, (PZERO + 1), "nnpfslock"); + + nnpfs_assert(chan->lock.recurse == 0); + chan->lock.locker = me; + chan->lock.recurse = nlocks; + + mtx_unlock(&chan->lock.lock); return ret; } int nnpfs_dev_initlock(struct nnpfs *chan) { -#ifdef NNPFS_FBSD_DEVLOCK + d_thread_t *me = curthread; + NNPFSDEB(XDEBDEV, ("nnpfs_dev_initlock\n")); - mtx_init(&chan->dev_lock, "nnpfsdevlock", NULL, MTX_DEF); - mtx_lock(&chan->dev_lock); + + if (mtx_initialized(&chan->lock.lock)) + panic("nnpfs_dev_initlock: already inited!"); + + mtx_init(&chan->lock.lock, "nnpfsdevlock", NULL, MTX_DEF); + + mtx_lock(&chan->lock.lock); + chan->lock.locker = me; + chan->lock.recurse = 1; + mtx_unlock(&chan->lock.lock); + return 0; -#endif } void nnpfs_dev_uninitlock(struct nnpfs *chan) { -#ifdef NNPFS_FBSD_DEVLOCK + d_thread_t *me = curthread; + NNPFSDEB(XDEBDEV, ("nnpfs_dev_uninitlock\n")); + if (!mtx_initialized(&chan->lock.lock)) + printf("nnpfs_dev_uninitlock: not inited!\n"); + + mtx_lock(&chan->lock.lock); + nnpfs_assert(chan->lock.recurse == 1); + nnpfs_assert(chan->lock.locker == me); + + chan->lock.recurse = 0; + chan->lock.locker = NULL; + /* * contrary to man page, it seems we need to unlock the mutex before * destroying it if we use spinlocks. Default mutexes are ok. */ - mtx_destroy(&chan->dev_lock); -#endif + + mtx_destroy(&chan->lock.lock); } +#else + +void +nnpfs_dev_lock(struct nnpfs *chan) +{ + int ret; + NNPFSDEB(XDEBDEV, ("nnpfs_dev_lock\n")); + ret = lockmgr(&chan->dev_lock, LK_EXCLUSIVE | LK_CANRECURSE, NULL); + nnpfs_assert(!ret); +} + +void +nnpfs_dev_unlock(struct nnpfs *chan) +{ + int ret; + NNPFSDEB(XDEBDEV, ("nnpfs_dev_unlock\n")); + ret = lockmgr(&chan->dev_lock, LK_RELEASE, NULL); + nnpfs_assert(!ret); +} + +int +nnpfs_dev_msleep(struct nnpfs *chan, caddr_t waitobj, int flags, const char *msg) +{ + d_thread_t *td = curthread; + int nlocks, i, ret; + + NNPFSDEB(XDEBDEV, ("nnpfs_dev_msleep %p %x %s\n", waitobj, flags, msg)); + + ret = lockstatus(&chan->dev_lock, td); + nnpfs_assert(ret == LK_EXCLUSIVE); + + nlocks = lockcount(&chan->dev_lock); + + for (i = nlocks; i > 0 ; i--) { + ret = lockmgr(&chan->dev_lock, LK_RELEASE, NULL); + nnpfs_assert(!ret); + } + + ret = nnpfs_msleep(waitobj, &chan->dev_lock, flags, msg); + return ret; +} + +int +nnpfs_dev_initlock(struct nnpfs *chan) +{ + NNPFSDEB(XDEBDEV, ("nnpfs_dev_initlock\n")); + lockinit(&chan->dev_lock, PRIBIO /* XXX */, "nnpfsdevlock", NULL, LK_CANRECURSE | LK_NOSHARE); + return lockmgr(&chan->dev_lock, LK_EXCLUSIVE, NULL); +} + +void +nnpfs_dev_uninitlock(struct nnpfs *chan) +{ + NNPFSDEB(XDEBDEV, ("nnpfs_dev_uninitlock\n")); + lockdestroy(&chan->dev_lock); +} + +#endif #ifndef NNPFS_FBSD_DEVLOCK @@ -156,7 +288,9 @@ struct cdevsw nnpfs_cdev = { #ifdef HAVE_STRUCT_CDEVSW_D_SPARE d_spare: NULL, #endif +#if __FreeBSD_version < 600007 d_maj: 128, /* XXX */ +#endif #ifdef HAVE_STRUCT_CDEVSW_D_DUMP d_dump: nodump, #endif -- 2.11.4.GIT