Date: Mon, 11 Oct 2004 15:10:45 +0200 From: damien.bergamini@free.fr To: freebsd-hackers@freebsd.org Cc: damien.bergamini@free.fr Subject: msleep(9) and recursed mutex Message-ID: <1097500245.416a86556c692@imp1-q.free.fr>
next in thread | raw e-mail | index | archive | help
msleep(9) behaves strangely with recursed mutexes. In the attached code, calling foo_f() will make the kernel hang for two seconds. It seems like msleep does not release the mtx mutex completely but simply decrement its reference count by one. When calling msleep, the mtx mutex is still held which prevent the interrupt from happening. msleep will then return error code EWOULDBLOCK after two seconds. If I remove calls to mtx_lock/unlock from function foo_g(), it works without problem but this is not a solution since foo_g() can be called outside of function foo_f(). Of course, the mtx mutex was created with the MTX_RECURSE flag set. Is it an expected behaviour? In msleep(9) it is said: "The msleep() function is a variation on tsleep. The parameter mtx is a mutex which will be released before sleeping and reacquired before msleep() returns." Seems like the mutex is not *really* released if it recurses. Thanks, Damien Bergamini ---- void foo_intr(void *arg) { struct foo_softc *sc = arg; mtx_lock(&sc->mtx); ... wakeup(sc); ... mtx_unlock(&sc->mtx); } void foo_f(struct foo_softc *sc) { mtx_lock(&sc->mtx); ... foo_g(sc); ... mtx_unlock(&sc->mtx); } void foo_g(struct foo_softc *sc) { /* mtx will recurse if called from foo_f() */ mtx_lock(&sc->mtx); ... /* do something that will make hardware raise an interrupt */ ... /* wait at most 2 second for the interrupt */ msleep(sc, &sc->mtx, 0, "foo", 2 * hz); ... mtx_unlock(&sc->mtx); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1097500245.416a86556c692>