msleep() on recursivly locked mutexes
Hans Petter Selasky
hselasky at freebsd.org
Fri Apr 27 19:34:23 UTC 2007
On Friday 27 April 2007 20:01, Julian Elischer wrote:
> Hans Petter Selasky wrote:
> > First of all: Where is FreeBSD's locking strategy document?
>
> It is just started..
> man 9 locking. it needs a lot of work still.
Excellent.
>
> > We should have a
> > global strategy when we write device drivers, so that various modules can
> > be connected together without races and locking order reversals.
> >
> > In my view there are two categories of mutexes.
> >
> > 1) Global mutexes.
> >
> > 2) Private mutexes.
> >
> > Rule: The Global mutex is locked last.
>
> errr I'm not sure I'm following but this sounds kind-of reversed from
> normal behaviour.
Yes, it is. But you have to make a choice. Either this way or the other way.
But not both! The reason for my choice is that I consider it to be more
complicated to be a Global device than a private device. Complicated means
that the Global device, which is locked last, has to unlock its lock before
it calls back the "private" device, like I have explained below.
Hence there are fewer Global devices (e.g. USB host controllers), then private
devices (USB device drivers), we end up with less code/headache locking the
Global devices last. If that is unclear I can explain more.
>
> > How do we organize this.
> >
> > 1a) The global mutex protects interrupts/callbacks into a hardware
> > driver. This is the lowest level.
> >
> > 2a) Private mutexes protects sub-devices of the hardware driver. This
> > might be as simple as an IF-QUEUE.
>
> I'm having trouble following already.
> you mean subcomponents?
Yes, children of devices. Sub-devices.
>
> > I have chosen the following model:
> >
> > P0 indicates process 0. P1 indicates an optional second process.
> >
> > Up-call:
> >
> > P0 lock(2);
> > P0 lock(1);
The work done [here] might be to setup DMA-able memory, and link it into the
hardware.
> > P0 unlock(1);
> > P0 unlock(2);
>
> this looks "interesting".
> Can you give a more concrete example of this?
> what work is done in the upcall? WHo is upcalling to who?
For example an USB device driver might be up-calling to the USB host
controller driver. Down call is when the transfer finishes.
>
> > Down-call:
> >
> > P1 lock(1);
> > P1 wakeup P0 // for example
> > P1 unlock(1);
>
> pretty normal.
>
> > P0 //callback:
> > P0 lock(2); // the new USB stack currently uses P1 here
> > P0 unlock(2);
> >
> >
> >
> > Sure, in the up-call you lock #2 longer than lock #1, that is why lock #1
> > has got to be a short as possible. But it does not make sense to make
> > lock #2 lock shorter than lock #1. I cannot see that the system will go
> > faster that way.
> >
> > In the downcall I see no problems at all. #1 does its things as fast as
> > possible. In parallell #2 can still execute, until the "callback".
> >
> > I hope you understand my semantics.
> >
> > What do you want to change from what I have explained?
> >
> > Any comments?
> >
> > My conclusion: If you want more paralellism, then use more mutexes. Don't
> > try to push an existing mutex by unlocking it!
>
> that may or may not be true depending on how busy the mutex is..
> but I don't think there is an argument about this.
>
>
> shouldn't this be somewhere other than "hackers"?
I've CC'ed freebsd-arch.
--HPS
More information about the freebsd-hackers
mailing list