Documentation/locking/mutex-design: Update to reflect latest changes
Commit 3ca0ff571b
("locking/mutex: Rework mutex::owner") reworked the
basic mutex implementation to deal with several problems. Documentation
was however left unchanged and became stale.
Update mutex-design.txt to reflect changes introduced by the above commit.
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-doc@vger.kernel.org
Link: http://lkml.kernel.org/r/20180209160114.19980-1-juri.lelli@redhat.com
[ Small readability tweaks to the text. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
f1517df870
commit
79e9023826
|
@ -21,37 +21,23 @@ Implementation
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Mutexes are represented by 'struct mutex', defined in include/linux/mutex.h
|
Mutexes are represented by 'struct mutex', defined in include/linux/mutex.h
|
||||||
and implemented in kernel/locking/mutex.c. These locks use a three
|
and implemented in kernel/locking/mutex.c. These locks use an atomic variable
|
||||||
state atomic counter (->count) to represent the different possible
|
(->owner) to keep track of the lock state during its lifetime. Field owner
|
||||||
transitions that can occur during the lifetime of a lock:
|
actually contains 'struct task_struct *' to the current lock owner and it is
|
||||||
|
therefore NULL if not currently owned. Since task_struct pointers are aligned
|
||||||
1: unlocked
|
at at least L1_CACHE_BYTES, low bits (3) are used to store extra state (e.g.,
|
||||||
0: locked, no waiters
|
if waiter list is non-empty). In its most basic form it also includes a
|
||||||
negative: locked, with potential waiters
|
wait-queue and a spinlock that serializes access to it. Furthermore,
|
||||||
|
CONFIG_MUTEX_SPIN_ON_OWNER=y systems use a spinner MCS lock (->osq), described
|
||||||
In its most basic form it also includes a wait-queue and a spinlock
|
below in (ii).
|
||||||
that serializes access to it. CONFIG_SMP systems can also include
|
|
||||||
a pointer to the lock task owner (->owner) as well as a spinner MCS
|
|
||||||
lock (->osq), both described below in (ii).
|
|
||||||
|
|
||||||
When acquiring a mutex, there are three possible paths that can be
|
When acquiring a mutex, there are three possible paths that can be
|
||||||
taken, depending on the state of the lock:
|
taken, depending on the state of the lock:
|
||||||
|
|
||||||
(i) fastpath: tries to atomically acquire the lock by decrementing the
|
(i) fastpath: tries to atomically acquire the lock by cmpxchg()ing the owner with
|
||||||
counter. If it was already taken by another task it goes to the next
|
the current task. This only works in the uncontended case (cmpxchg() checks
|
||||||
possible path. This logic is architecture specific. On x86-64, the
|
against 0UL, so all 3 state bits above have to be 0). If the lock is
|
||||||
locking fastpath is 2 instructions:
|
contended it goes to the next possible path.
|
||||||
|
|
||||||
0000000000000e10 <mutex_lock>:
|
|
||||||
e21: f0 ff 0b lock decl (%rbx)
|
|
||||||
e24: 79 08 jns e2e <mutex_lock+0x1e>
|
|
||||||
|
|
||||||
the unlocking fastpath is equally tight:
|
|
||||||
|
|
||||||
0000000000000bc0 <mutex_unlock>:
|
|
||||||
bc8: f0 ff 07 lock incl (%rdi)
|
|
||||||
bcb: 7f 0a jg bd7 <mutex_unlock+0x17>
|
|
||||||
|
|
||||||
|
|
||||||
(ii) midpath: aka optimistic spinning, tries to spin for acquisition
|
(ii) midpath: aka optimistic spinning, tries to spin for acquisition
|
||||||
while the lock owner is running and there are no other tasks ready
|
while the lock owner is running and there are no other tasks ready
|
||||||
|
@ -143,11 +129,10 @@ Test if the mutex is taken:
|
||||||
Disadvantages
|
Disadvantages
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Unlike its original design and purpose, 'struct mutex' is larger than
|
Unlike its original design and purpose, 'struct mutex' is among the largest
|
||||||
most locks in the kernel. E.g: on x86-64 it is 40 bytes, almost twice
|
locks in the kernel. E.g: on x86-64 it is 32 bytes, where 'struct semaphore'
|
||||||
as large as 'struct semaphore' (24 bytes) and tied, along with rwsems,
|
is 24 bytes and rw_semaphore is 40 bytes. Larger structure sizes mean more CPU
|
||||||
for the largest lock in the kernel. Larger structure sizes mean more
|
cache and memory footprint.
|
||||||
CPU cache and memory footprint.
|
|
||||||
|
|
||||||
When to use mutexes
|
When to use mutexes
|
||||||
-------------------
|
-------------------
|
||||||
|
|
Loading…
Reference in a new issue