From owner-freebsd-arch Sun Sep 10 21:10:51 2000 Delivered-To: freebsd-arch@freebsd.org Received: from magnesium.net (toxic.magnesium.net [207.154.84.15]) by hub.freebsd.org (Postfix) with SMTP id 9B16937B422 for ; Sun, 10 Sep 2000 21:10:48 -0700 (PDT) Received: (qmail 28867 invoked by uid 1142); 11 Sep 2000 04:10:47 -0000 Date: 10 Sep 2000 21:10:47 -0700 Date: Sun, 10 Sep 2000 21:10:42 -0700 From: Jason Evans To: Alfred Perlstein Cc: arch@freebsd.org Subject: Re: Interruptable mutex aquires. Message-ID: <20000910211042.T19447@blitz.canonware.com> References: <20000910193602.B12231@fw.wintelcom.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Mailer: Mutt 1.0.1i In-Reply-To: <20000910193602.B12231@fw.wintelcom.net>; from bright@wintelcom.net on Sun, Sep 10, 2000 at 07:36:02PM -0700 Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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