From owner-freebsd-hackers@FreeBSD.ORG Mon Oct 11 13:10:46 2004 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8A51116A4CE for ; Mon, 11 Oct 2004 13:10:46 +0000 (GMT) Received: from postfix4-1.free.fr (postfix4-1.free.fr [213.228.0.62]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4FBE643D39 for ; Mon, 11 Oct 2004 13:10:46 +0000 (GMT) (envelope-from damien.bergamini@free.fr) Received: from imp1-q.free.fr (imp1-q.free.fr [212.27.42.1]) by postfix4-1.free.fr (Postfix) with ESMTP id 8C9F6182794; Mon, 11 Oct 2004 15:10:45 +0200 (CEST) Received: by imp1-q.free.fr (Postfix, from userid 33) id 809EB36F24; Mon, 11 Oct 2004 15:10:45 +0200 (MEST) Received: from ubac.inrialpes.fr (ubac.inrialpes.fr [194.199.23.66]) by imp1-q.free.fr (IMP) with HTTP for ; Mon, 11 Oct 2004 15:10:45 +0200 Message-ID: <1097500245.416a86556c692@imp1-q.free.fr> Date: Mon, 11 Oct 2004 15:10:45 +0200 From: damien.bergamini@free.fr To: freebsd-hackers@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit User-Agent: Internet Messaging Program (IMP) 3.2.5 X-Originating-IP: 194.199.23.66 cc: damien.bergamini@free.fr Subject: msleep(9) and recursed mutex X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Oct 2004 13:10:46 -0000 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); }