msleep(9) and recursed mutex
damien.bergamini at free.fr
damien.bergamini at free.fr
Mon Oct 11 06:10:46 PDT 2004
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);
}
More information about the freebsd-hackers
mailing list