tech-misc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Questions of lock usage in NetBSD kernel code

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<>

I am a freshman in developing NetBSD drivers, and I have a question in
lock usage in NetBSD kernel code.

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:

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
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-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 :)

Jia-Ju Bai

Home | Main Index | Thread Index | Old Index