Skip to content

Commit

Permalink
docs: locking: convert docs to ReST and rename to *.rst
Browse files Browse the repository at this point in the history
Convert the locking documents to ReST and add them to the
kernel development book where it belongs.

Most of the stuff here is just to make Sphinx to properly
parse the text file, as they're already in good shape,
not requiring massive changes in order to be parsed.

The conversion is actually:
  - add blank lines and identation in order to identify paragraphs;
  - fix tables markups;
  - add some lists markups;
  - mark literal blocks;
  - adjust title markups.

At its new index.rst, let's add a :orphan: while this is not linked to
the main index.rst file, in order to avoid build warnings.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Acked-by: Federico Vaga <[email protected]>
  • Loading branch information
mchehab committed Jul 15, 2019
1 parent fec88ab commit 387b146
Show file tree
Hide file tree
Showing 20 changed files with 511 additions and 387 deletions.
2 changes: 1 addition & 1 deletion Documentation/kernel-hacking/locking.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1364,7 +1364,7 @@ Futex API reference
Further reading
===============

- ``Documentation/locking/spinlocks.txt``: Linus Torvalds' spinlocking
- ``Documentation/locking/spinlocks.rst``: Linus Torvalds' spinlocking
tutorial in the kernel sources.

- Unix Systems for Modern Architectures: Symmetric Multiprocessing and
Expand Down
24 changes: 24 additions & 0 deletions Documentation/locking/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
:orphan:

=======
locking
=======

.. toctree::
:maxdepth: 1

lockdep-design
lockstat
locktorture
mutex-design
rt-mutex-design
rt-mutex
spinlocks
ww-mutex-design

.. only:: subproject and html

Indices
=======

* :ref:`genindex`
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Runtime locking correctness validator
=====================================

started by Ingo Molnar <[email protected]>

additions by Arjan van de Ven <[email protected]>

Lock-class
Expand Down Expand Up @@ -56,7 +57,7 @@ where the last 1 category is:

When locking rules are violated, these usage bits are presented in the
locking error messages, inside curlies, with a total of 2 * n STATEs bits.
A contrived example:
A contrived example::

modprobe/2287 is trying to acquire lock:
(&sio_locks[i].lock){-.-.}, at: [<c02867fd>] mutex_lock+0x21/0x24
Expand All @@ -70,12 +71,14 @@ of the lock and readlock (if exists), for each of the n STATEs listed
above respectively, and the character displayed at each bit position
indicates:

=== ===================================================
'.' acquired while irqs disabled and not in irq context
'-' acquired in irq context
'+' acquired with irqs enabled
'?' acquired in irq context with irqs enabled.
=== ===================================================

The bits are illustrated with an example:
The bits are illustrated with an example::

(&sio_locks[i].lock){-.-.}, at: [<c02867fd>] mutex_lock+0x21/0x24
||||
Expand All @@ -90,13 +93,13 @@ context and whether that STATE is enabled yields four possible cases as
shown in the table below. The bit character is able to indicate which
exact case is for the lock as of the reporting time.

-------------------------------------------
+--------------+-------------+--------------+
| | irq enabled | irq disabled |
|-------------------------------------------|
+--------------+-------------+--------------+
| ever in irq | ? | - |
|-------------------------------------------|
+--------------+-------------+--------------+
| never in irq | + | . |
-------------------------------------------
+--------------+-------------+--------------+

The character '-' suggests irq is disabled because if otherwise the
charactor '?' would have been shown instead. Similar deduction can be
Expand All @@ -113,7 +116,7 @@ is irq-unsafe means it was ever acquired with irq enabled.

A softirq-unsafe lock-class is automatically hardirq-unsafe as well. The
following states must be exclusive: only one of them is allowed to be set
for any lock-class based on its usage:
for any lock-class based on its usage::

<hardirq-safe> or <hardirq-unsafe>
<softirq-safe> or <softirq-unsafe>
Expand All @@ -134,7 +137,7 @@ Multi-lock dependency rules:
The same lock-class must not be acquired twice, because this could lead
to lock recursion deadlocks.

Furthermore, two locks can not be taken in inverse order:
Furthermore, two locks can not be taken in inverse order::

<L1> -> <L2>
<L2> -> <L1>
Expand All @@ -148,7 +151,7 @@ operations; the validator will still find whether these locks can be
acquired in a circular fashion.

Furthermore, the following usage based lock dependencies are not allowed
between any two lock-classes:
between any two lock-classes::

<hardirq-safe> -> <hardirq-unsafe>
<softirq-safe> -> <softirq-unsafe>
Expand Down Expand Up @@ -204,16 +207,16 @@ the ordering is not static.
In order to teach the validator about this correct usage model, new
versions of the various locking primitives were added that allow you to
specify a "nesting level". An example call, for the block device mutex,
looks like this:
looks like this::

enum bdev_bd_mutex_lock_class
{
enum bdev_bd_mutex_lock_class
{
BD_MUTEX_NORMAL,
BD_MUTEX_WHOLE,
BD_MUTEX_PARTITION
};
};

mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);

In this case the locking is done on a bdev object that is known to be a
partition.
Expand All @@ -234,7 +237,7 @@ must be held: lockdep_assert_held*(&lock) and lockdep_*pin_lock(&lock).
As the name suggests, lockdep_assert_held* family of macros assert that a
particular lock is held at a certain time (and generate a WARN() otherwise).
This annotation is largely used all over the kernel, e.g. kernel/sched/
core.c
core.c::

void update_rq_clock(struct rq *rq)
{
Expand All @@ -253,7 +256,7 @@ out to be especially helpful to debug code with callbacks, where an upper
layer assumes a lock remains taken, but a lower layer thinks it can maybe drop
and reacquire the lock ("unwittingly" introducing races). lockdep_pin_lock()
returns a 'struct pin_cookie' that is then used by lockdep_unpin_lock() to check
that nobody tampered with the lock, e.g. kernel/sched/sched.h
that nobody tampered with the lock, e.g. kernel/sched/sched.h::

static inline void rq_pin_lock(struct rq *rq, struct rq_flags *rf)
{
Expand All @@ -280,7 +283,7 @@ correctness) in the sense that for every simple, standalone single-task
locking sequence that occurred at least once during the lifetime of the
kernel, the validator proves it with a 100% certainty that no
combination and timing of these locking sequences can cause any class of
lock related deadlock. [*]
lock related deadlock. [1]_

I.e. complex multi-CPU and multi-task locking scenarios do not have to
occur in practice to prove a deadlock: only the simple 'component'
Expand All @@ -299,7 +302,9 @@ possible combination of locking interaction between CPUs, combined with
every possible hardirq and softirq nesting scenario (which is impossible
to do in practice).

[*] assuming that the validator itself is 100% correct, and no other
.. [1]
assuming that the validator itself is 100% correct, and no other
part of the system corrupts the state of the validator in any way.
We also assume that all NMI/SMM paths [which could interrupt
even hardirq-disabled codepaths] are correct and do not interfere
Expand All @@ -310,7 +315,7 @@ to do in practice).
Performance:
------------

The above rules require _massive_ amounts of runtime checking. If we did
The above rules require **massive** amounts of runtime checking. If we did
that for every lock taken and for every irqs-enable event, it would
render the system practically unusably slow. The complexity of checking
is O(N^2), so even with just a few hundred lock-classes we'd have to do
Expand Down Expand Up @@ -369,17 +374,17 @@ be harder to do than to say.

Of course, if you do run out of lock classes, the next thing to do is
to find the offending lock classes. First, the following command gives
you the number of lock classes currently in use along with the maximum:
you the number of lock classes currently in use along with the maximum::

grep "lock-classes" /proc/lockdep_stats

This command produces the following output on a modest system:
This command produces the following output on a modest system::

lock-classes: 748 [max: 8191]
lock-classes: 748 [max: 8191]

If the number allocated (748 above) increases continually over time,
then there is likely a leak. The following command can be used to
identify the leaking lock classes:
identify the leaking lock classes::

grep "BD" /proc/lockdep

Expand Down
Loading

0 comments on commit 387b146

Please sign in to comment.