Skip site navigation (1)Skip section navigation (2)
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>