rtmutex: update rt-mutex

The rtmutex remove a pending owner bit in in rt_mutex::owner, in
commit 8161239a8b ("rtmutex: Simplify PI algorithm and make highest prio task get lock")
But the document was changed accordingly. Updating it to a meaningful
state.

BTW, as 'Steven Rostedt' mentioned:
There is still technically a "Pending Owner", it's just not called
that anymore. The pending owner happens to be the top_waiter of a lock
that has no owner and has been woken up to grab the lock.

Signed-off-by: Alex Shi <alex.shi@linaro.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Juri Lelli <juri.lelli@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
To: linux-doc@vger.kernel.org
To: linux-kernel@vger.kernel.org
To: Jonathan Corbet <corbet@lwn.net>
To: Ingo Molnar <mingo@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
Alex Shi 2017-07-31 09:50:54 +08:00 committed by Jonathan Corbet
parent f1824df12e
commit 68a1e349ce

View File

@ -28,14 +28,13 @@ magic bullet for poorly designed applications, but it allows
well-designed applications to use userspace locks in critical parts of well-designed applications to use userspace locks in critical parts of
an high priority thread, without losing determinism. an high priority thread, without losing determinism.
The enqueueing of the waiters into the rtmutex waiter list is done in The enqueueing of the waiters into the rtmutex waiter tree is done in
priority order. For same priorities FIFO order is chosen. For each priority order. For same priorities FIFO order is chosen. For each
rtmutex, only the top priority waiter is enqueued into the owner's rtmutex, only the top priority waiter is enqueued into the owner's
priority waiters list. This list too queues in priority order. Whenever priority waiters tree. This tree too queues in priority order. Whenever
the top priority waiter of a task changes (for example it timed out or the top priority waiter of a task changes (for example it timed out or
got a signal), the priority of the owner task is readjusted. [The got a signal), the priority of the owner task is readjusted. The
priority enqueueing is handled by "plists", see include/linux/plist.h priority enqueueing is handled by "pi_waiters".
for more details.]
RT-mutexes are optimized for fastpath operations and have no internal RT-mutexes are optimized for fastpath operations and have no internal
locking overhead when locking an uncontended mutex or unlocking a mutex locking overhead when locking an uncontended mutex or unlocking a mutex
@ -46,34 +45,29 @@ is used]
The state of the rt-mutex is tracked via the owner field of the rt-mutex The state of the rt-mutex is tracked via the owner field of the rt-mutex
structure: structure:
rt_mutex->owner holds the task_struct pointer of the owner. Bit 0 and 1 lock->owner holds the task_struct pointer of the owner. Bit 0 is used to
are used to keep track of the "owner is pending" and "rtmutex has keep track of the "lock has waiters" state.
waiters" state.
owner bit1 bit0 owner bit0
NULL 0 0 mutex is free (fast acquire possible) NULL 0 lock is free (fast acquire possible)
NULL 0 1 invalid state NULL 1 lock is free and has waiters and the top waiter
NULL 1 0 Transitional state* is going to take the lock*
NULL 1 1 invalid state taskpointer 0 lock is held (fast release possible)
taskpointer 0 0 mutex is held (fast release possible) taskpointer 1 lock is held and has waiters**
taskpointer 0 1 task is pending owner
taskpointer 1 0 mutex is held and has waiters
taskpointer 1 1 task is pending owner and mutex has waiters
Pending-ownership handling is a performance optimization: The fast atomic compare exchange based acquire and release is only
pending-ownership is assigned to the first (highest priority) waiter of possible when bit 0 of lock->owner is 0.
the mutex, when the mutex is released. The thread is woken up and once
it starts executing it can acquire the mutex. Until the mutex is taken
by it (bit 0 is cleared) a competing higher priority thread can "steal"
the mutex which puts the woken up thread back on the waiters list.
The pending-ownership optimization is especially important for the (*) It also can be a transitional state when grabbing the lock
uninterrupted workflow of high-prio tasks which repeatedly with ->wait_lock is held. To prevent any fast path cmpxchg to the lock,
takes/releases locks that have lower-prio waiters. Without this we need to set the bit0 before looking at the lock, and the owner may be
optimization the higher-prio thread would ping-pong to the lower-prio NULL in this small time, hence this can be a transitional state.
task [because at unlock time we always assign a new owner].
(*) The "mutex has waiters" bit gets set to take the lock. If the lock (**) There is a small time when bit 0 is set but there are no
doesn't already have an owner, this bit is quickly cleared if there are waiters. This can happen when grabbing the lock in the slow path.
no waiters. So this is a transitional state to synchronize with looking To prevent a cmpxchg of the owner releasing the lock, we need to
at the owner field of the mutex and the mutex owner releasing the lock. set this bit before looking at the lock.
BTW, there is still technically a "Pending Owner", it's just not called
that anymore. The pending owner happens to be the top_waiter of a lock
that has no owner and has been woken up to grab the lock.