msleep(9) and recursed mutex

John Baldwin jhb at FreeBSD.org
Mon Oct 11 14:27:24 PDT 2004


On Monday 11 October 2004 09:10 am, damien.bergamini at free.fr wrote:
> 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.

This is a feature.  If you had INVARIANTS on you would get a panic here:

	if (mtx != NULL) {
		mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED);
		WITNESS_SAVE(&mtx->mtx_object, mtx);
		mtx_unlock(mtx);
	}

When developing kernel code it is highly recommended that you run with 
INVARIANTS and INVARIANT_SUPPORT turned on.

You should probably have your foo_g() function assert that the lock is held 
and fix all the callers.  Either that or add a wrapper around foo_g() for the 
callers that don't call with the mutex locked.

-- 
John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org


More information about the freebsd-hackers mailing list