Re: Questions of lock usage in NetBSD kernel code

Jia-Ju Bai <[email protected]> Mon, 26 Jun 2017 09:54:16 +0800
Newsgroups gmane.os.netbsd.devel.kernel,gmane.os.netbsd.devel.general,gmane.os.netbsd.devel.smp
Message-ID <[email protected]>
Thanks for you reply and detailed answers :)

On 06/26/2017 02:34 AM, Taylor R Campbell wrote:
>> Date: Sat, 24 Jun 2017 09:59:43 +0800
>> From: Jia-Ju Bai<[email protected]>
>>
>> I am a freshman in developing NetBSD drivers, and I have a question in
>> lock usage in NetBSD kernel code.
> Cool!
>
>> I find three kinds of locks which are often used in OpenBSD drivers,
>                                                        ^^^^^^^
> I assume you mean NetBSD here!  I'm afraid I'm not familiar enough
> with OpenBSD to answer any analogous questions over there.
Sorry for my mistake *_*, I mean NetBSD here.

>> namely "adaptive mutex lock", "spin mutex lock" and "rw lock".
>> I want to know  which locks can be held when the current thread can sleep.
>>
>> I have read NetBSD man pages:
>> http://netbsd.gw.com/cgi-bin/man-cgi?mutex+9+NetBSD-current
>> http://netbsd.gw.com/cgi-bin/man-cgi?rwlock+9+NetBSD-current
>>
>> I find two points:
>> (1) The "adaptive mutex lock" *can* be used in this situation.
>> (2) The "spin mutex lock" *can not* be used in this situation.
> It is technically possible to sleep while holding an adaptive lock,
> but the duration of sleep must be bounded -- you can't wait for
> external I/O, and any other processes that are trying to acquire the
> same adaptive lock are blocked uninterruptibly until you release it.
>
> Sleeping with a spin lock held is absolutely prohibited and does not
> work.
I am happy to see that my under standing is right.

>> But I still have three questions:
>> (1) Are my points right?
>> (2) What about "rw lock"?
>> (3) What about other kinds of locks if they exist?
> It is also technically possible to sleep while holding an rwlock, and
> file systems do so even when waiting for I/O, but this is an abuse of
> rwlocks because they're not interruptible and we should clean it up
> one of these days.  In general, if something might ever wait for I/O
> before returning to userland, it should be interruptible.
>
> There are other kinds of synchronization devices with related rules:
>
> - Blocking interrupts (splnet,&c.): Sleeping while interrupts are
>    blocked works, but it reenables interrupts.  Most new code doesn't
>    block interrupts directly -- instead uses mutex(9) or pserialize(9)
>    or other higher-level constructs that use it as a primitive.
>
> - Disabling preemption (kpreempt_disable): Currently the kernel
>    doesn't crash if you sleep while preemption is disabled, but we may
>    change that because doing so is very error-prone.  Also usually
>    limited to the internals of higher-level constructs.
>
> - Passive serialization (pserialize): Read sections run with
>    interrupts blocked, and must not sleep.
>
> - Passive references (psref): Users may sleep, but must be bound to a
>    CPU.
>
> - CPU-local reference counts (localcount): Readers may sleep and
>    migrate across CPUs.
Your introduction of synchronization primitives and rules is very 
detailed, and it is very helpful to me, thanks a lot :)

Thanks,
Jia-Ju Bai