spinlock impl
COPYRIGHT NOTICE: text and code copied or derived from git commit message, mailinglist, or codebase are subject to the linux kernel licensing rules
documentations:
Lock types and their rules
https://docs.kernel.org/locking/locktypes.html
Synchronization primitives in the Linux kernel. (from the Linux Inside blog series) https://0xax.gitbooks.io/linux-insides/content/SyncPrim/
MCS locks and qspinlocks
https://lwn.net/Articles/590243/
SEMANTICS:
spinlocks are
raw_spinlock_t
(ALL)bit spinlocks
(ALL)spinlock_t
(NON-PREEMPT)rwlock_t
(NON-PREEMPT)
- on
PREEMPT_RT
kernels - {
spinlock_t
,rwlock_t
,local_lock
} are converted to sleeping locks
Well, on PREEMPT_RT
kernels the spinlock_t
is actually not a spinning lock.
spinlock apis
spin_lock_init
- suffix
bh
: disables software interrupts (bottomhalves) - suffix
irq / irqsave
: disable interrupts on local processors, do or do not preserve the interrupt state in theflags
(restore via_irqrestore
) spin_lock
andspin_unlock
: acquire and release the lock
raw_spinlock_t
raw_spinlock_t
is strict spinning lock for all kernels. On NON-PREEMPT kernels
spinlock_t
and raw_spinlock_t
have same semantics.
consider the following threads
|
|
The hard irq handler MUST NOT block. Below is a deadlock even with one single thread.
|
|
linux code:
raw_spinlock_t
is defined in spinlock_types_raw.h- the underlying
arch_spinlock_t
could be implemented as either queued spinlock; ticket lock arm or a primitive int.
queued spinlock
/*
* By using the whole 2nd least significant byte for the
* pending bit, we can allow better optimization of the lock
* acquisition for the pending bit holder.
*/
typedef struct qspinlock {
union {
atomic_t val;
struct {
u8 locked;
u8 pending;
};
struct {
u16 locked_pending;
u16 tail;
};
};
} arch_spinlock_t;
SOURCE CODE FILES
- include/linux/spinlock.h
- generic spinlock/rwlock declarations
here’s the role of the various spinlock/rwlock related include files:
on SMP builds:
- asm/spinlock_types.h
- contains the arch_spinlock_t/arch_rwlock_t and the initializers
- linux/spinlock_types_raw
- The raw types and initializers
- linux/spinlock_types.h
- defines the generic type and initializers
- asm/spinlock.h
- contains the arch_spin_*()/etc. lowlevel implementations, mostly inline assembly code
(also included on UP-debug builds:)
- linux/spinlock_api_smp.h
- contains the prototypes for the spin*() APIs.
- linux/spinlock.h
- builds the final spin_*() APIs.
on UP builds:
- linux/spinlock_type_up.h
- contains the generic, simplified UP spinlock type. (which is an empty structure on non-debug builds)
- linux/spinlock_types_raw
- The raw RT types and initializers linux/spinlock_types.h:
- defines the generic type and initializers linux/spinlock_up.h:
- contains the arch_spin_*()/etc. version of UP builds. (which are NOPs on non-debug, non-preempt builds)
(included on UP-non-debug builds:)
- linux/spinlock_api_up.h
- builds the spin*() APIs.
- linux/spinlock.h
- builds the final spin_*() APIs.