Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Sep 2000 11:51:54 -0700 (PDT)
From:      John Polstra <jdp@polstra.com>
To:        arch@freebsd.org
Cc:        tlambert@primenet.com
Subject:   Re: Mutexes and semaphores (was: cvs commit: src/sys/conf files
Message-ID:  <200009271851.LAA07258@vashon.polstra.com>
In-Reply-To: <200009260249.TAA08391@usr05.primenet.com>
References:  <200009260249.TAA08391@usr05.primenet.com>

next in thread | previous in thread | raw e-mail | index | archive | help
In article <200009260249.TAA08391@usr05.primenet.com>,
Terry Lambert  <tlambert@primenet.com> wrote:
> > 
> > That's simply a less efficient implementation of a recursive mutex.
> > Why not use the real thing?
> 
> No we're back to my original question:
> where in the code is there a perceived need for mutex recursion,

You'll have to ask somebody else.  I never said I knew of any.
A couple of folks said recursive mutexes are evil, and I said I
disagreed, and explained why.

> or is this just a case of the mutex code being bloated for no good
> reason?

No need to bloat it.  It could be a different data type for all I
care.

> > That's a pretty minor difference, and it doesn't have anything to
> > do with whether the mutexes are recursive or not.
>
> No, it has to do with how long they are held.  If they are never
> permitted to be held across recursive function calls -- or better,
> across _ANY_ function calls -- then you can spin on the mutex,
> instead of hoing to sleep.

With a mutex or a semaphore, you can spin or you can go to sleep
or you can spin for awhile and then go to sleep.  That's just an
implementation detail.

Your desire that a mutex not be held across any function calls seems
arbitrary and would lead to unstructured code.  It's perfectly
legitimate for frobbing the data to involve one or more function
calls.  It isn't always easy to frob. :-)

> So a mutex operation becomes:
> 
> 	1)	Acquire mutex
> 	2)	Frob data protected by mutex
> 	3)	Release mutex
> 
> If someone else needs the same data, they do the same thing.
> 
> If you want to wait until a condition is true, then use a
> condition variable, a semaphore, or something else you can wait
> on in order to be signalled.

I have no argument with any of that.

> The idea that you should ever go to sleep waitind for a mutex is
> antithetical to the very idea.

Are you assuming that mutexes spin but semaphores sleep?  You haven't
actually said so explicitly, but I'm starting to think that's your
assumption.

> There are likewise, few real situation in which you require to be
> able to hold two mutexes; these are degenerate cases, which are
> badly coded.

Well, I wouldn't put it that strongly.  Sometimes you have to maintain
two independent data structures in a consistent manner, and that
involves locking both of them at once.

> Consider that I may have a vnode freelist protected by a mutex, and
> a vnode protected by a mutex.  The perceived need to hold both of
> these simultaneously to put something on the freelist is an artifact
> of wrong-thinking: the pointer use to place a vnode on a freelist
> are the property of the freelist mutex, not the vnode mutex.

Agreed.

> Even if you can make a case for this not being true (e.g. moving
> a vnode from one list to another, using the same pointers in
> the vnode to track state on both lists, which is really just an
> acquire/remove/release/aquire/insert/release operation, where you
> have a window between the removal and the reinsertion), it can be
> handled by strictly controlling the order of operation on mutex
> acquisition, and inverting the release order, and backing off in
> case of conflict.

Yes, that's the standard way of avoiding deadlock.  Though as far as
I can see, the release order doesn't actually matter, since releasing
never blocks anybody.

> > If the mutex is recursively held, there is a problem in that some
> > other code grabbed the mutex and expected it to protect the data
> > structure from being changed underfoot.
>
> Worst case, set an "IN_USE" flag on the data in a flags field to
> bar reentry on a given data item.  Best case, fix the broken code.
> The vnode locking code does this today (I'd argue that it's broken
> code).

Well, we are dealing with a lot of legacy code that was never designed
with threads in mind.  I personally believe that the recursive mutex
is a reasonable primitive to deal with it, particularly during the
transition phase.

> > Using a semaphore to do the waiting doesn't solve that problem, or
> > even address it.
>
> It does.  Semaphores can be held across a sleep (a wait).

You must be assuming that mutexes always spin and semaphores don't.  I
don't agree with that assumption, but at least it would explain why we
can't seem to communicate effectively on this topic.

John
-- 
  John Polstra                                               jdp@polstra.com
  John D. Polstra & Co., Inc.                        Seattle, Washington USA
  "Disappointment is a good sign of basic intelligence."  -- Chögyam Trungpa



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?200009271851.LAA07258>