Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Sep 2000 21:10:42 -0700
From:      Jason Evans <jasone@canonware.com>
To:        Alfred Perlstein <bright@wintelcom.net>
Cc:        arch@freebsd.org
Subject:   Re: Interruptable mutex aquires.
Message-ID:  <20000910211042.T19447@blitz.canonware.com>
In-Reply-To: <20000910193602.B12231@fw.wintelcom.net>; from bright@wintelcom.net on Sun, Sep 10, 2000 at 07:36:02PM -0700
References:  <20000910193602.B12231@fw.wintelcom.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, Sep 10, 2000 at 07:36:02PM -0700, Alfred Perlstein wrote:
> 
> There's a lot of code in the kernel that does this:
> 
> while(lock != mine) {
> 	error = tsleep(&lock, PRIBIO, "foo", PCATCH);
> 	if (error)
> 		return(error);
> }
> lock = mine;

I assume you're suggesting this become:

if (mtx_enter_interruptable(&lock) == EINTR)
	return EINTR;
/* We own the lock. */

Following are some other possibilities.

--------------------
(1) Gross way:

while (mtx_try_enter(lock, MTX_DEF))
	;
/* We own the lock. */

--------------------
(2) Or, to come closer to the original example:

while (mtx_try_enter(lock, MTX_DEF)) {
	if (someone_signaled_us)
		return EINTR;
}
/* We own the lock. */

--------------------
(3) Even more gross, but essentially the same as the original:

while (mtx_try_enter(lock, MTX_DEF)) {
	error = tsleep(lock, ?, "foo", 0);
	if (error)
		return(error);
}
/* We own the lock. */

--------------------
(4) Re-design:

mtx_enter(lock, MTX_DEF);
while (some_state != WHAT_WE_WANT) {
	cv_wait(condition, lock);
	if (some_state == BAD_DEAL) {
		mtx_exit(lock);
		return(error);
	}
}
/*
 * We own lock.  Drop it if it isn't protecting anything we need
 * to read or write.  Otherwise, keep it as long as necessary.
 *
 * It may be that an entirely different lock actually protects the
 * data we need to access.  If so, drop lock then acquire whatever
 * mutex we really need.
 */

....
mtx_exit(lock);

-------
Somewhere else:

some_state = WHAT_WE_WANT;
cv_signal(condition);

--------------------

The first three possibilities are basically equivalent to the original.
(4) appears very different, but it is actually just an explicit form of
your original.  Your original acquires a lock, unless told to abort the
acquisition (i.e. it's signaled).  Example (4) explicitly implements a
three state system: {NOT_READY, WHAT_WE_WANT, BAD_DEAL}.  The code starts
out in state NOT_READY, and progresses to WHAT_WE_WANT, unless something
bad happens, in which case it's a BAD_DEAL.  BAD_DEAL corresponds to being
signaled.

You may argue that this is way harder than using
mtx_enter_interruptable(), and so it indeed appears.  However, I would
argue that the real problem lies with the original, in that it muddles two
separate concepts, state and locking.

Yes, we're currently stuck with code that does this.  However, as seen
above, there is more than one way of dealing with that (IMO complex) coding
style without adding mtx_enter_interruptable().

Jason


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




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