Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Oct 2004 14:57:17 -0400
From:      John Baldwin <jhb@FreeBSD.org>
To:        freebsd-hackers@FreeBSD.org
Cc:        damien.bergamini@free.fr
Subject:   Re: msleep(9) and recursed mutex
Message-ID:  <200410111457.17529.jhb@FreeBSD.org>
In-Reply-To: <1097500245.416a86556c692@imp1-q.free.fr>
References:  <1097500245.416a86556c692@imp1-q.free.fr>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 11 October 2004 09:10 am, damien.bergamini@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@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200410111457.17529.jhb>