History

Documentation: locking: Describe seqlock design and usage

Proper documentation for the design and usage of sequence counters and sequential locks does not exist. Complete the seqlock.h documentation as follows: - Divide all documentation on a seqcount_t vs. seqlock_t basis. The description for both mechanisms was intermingled, which is incorrect since the usage constrains for each type are vastly different. - Add an introductory paragraph describing the internal design of, and rationale for, sequence counters. - Document seqcount_t writer non-preemptibility requirement, which was not previously documented anywhere, and provide a clear rationale. - Provide template code for seqcount_t and seqlock_t initialization and reader/writer critical sections. - Recommend using seqlock_t by default. It implicitly handles the serialization and non-preemptibility requirements of writers. At seqlock.h: - Remove references to brlocks as they've long been removed from the kernel. - Remove references to gcc-3.x since the kernel's minimum supported gcc version is 4.9.

Ahmed S. Darwish committed 6 years ago

Commit 0d24f651 parent f05d6713 files · +211 −45Browse files

Showing the changes to include/linux (1 of 3 files). Show all

Unified · Split

include/linux/seqlock.h+40−45
@@ -1,36 +1,15 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __LINUX_SEQLOCK_H2#ifndef __LINUX_SEQLOCK_H
3#define __LINUX_SEQLOCK_H3#define __LINUX_SEQLOCK_H
4
4/*5/*
5 * Reader/writer consistent mechanism without starving writers. This type of6 * seqcount_t / seqlock_t - a reader-writer consistency mechanism with
6 * lock for data where the reader wants a consistent set of information7 * lockless readers (read-only retry loops), and no writer starvation.
7 * and is willing to retry if the information changes. There are two types8 *
8 * of readers:9 * See Documentation/locking/seqlock.rst
9 * 1. Sequence readers which never block a writer but they may have to retry10 *
10 * if a writer is in progress by detecting change in sequence number.11 * Copyrights:
11 * Writers do not wait for a sequence reader.12 * - Based on x86_64 vsyscall gettimeofday: Keith Owens, Andrea Arcangeli
12 * 2. Locking readers which will wait if a writer or another locking reader
13 * is in progress. A locking reader in progress will also block a writer
14 * from going forward. Unlike the regular rwlock, the read lock here is
15 * exclusive so that only one locking reader can get it.
16 *
17 * This is not as cache friendly as brlock. Also, this may not work well
18 * for data that contains pointers, because any writer could
19 * invalidate a pointer that a reader was following.
20 *
21 * Expected non-blocking reader usage:
22 * do {
23 * seq = read_seqbegin(&foo);
24 * ...
25 * } while (read_seqretry(&foo, seq));
26 *
27 *
28 * On non-SMP the spin locks disappear but the writer still needs
29 * to increment the sequence variables because an interrupt routine could
30 * change the state of the data.
31 *
32 * Based on x86_64 vsyscall gettimeofday
33 * by Keith Owens and Andrea Arcangeli
34 */13 */
35 14
36#include <linux/spinlock.h>15#include <linux/spinlock.h>
@@ -41,8 +20,8 @@ · 4 unmodified lines
41#include <asm/processor.h>20#include <asm/processor.h>
42 21
43/*22/*
44 * The seqlock interface does not prescribe a precise sequence of read23 * The seqlock seqcount_t interface does not prescribe a precise sequence of
45 * begin/retry/end. For readers, typically there is a call to24 * read begin/retry/end. For readers, typically there is a call to
46 * read_seqcount_begin() and read_seqcount_retry(), however, there are more25 * read_seqcount_begin() and read_seqcount_retry(), however, there are more
47 * esoteric cases which do not follow this pattern.26 * esoteric cases which do not follow this pattern.
48 *27 *
@@ -50,16 +29,30 @@ · 1 unmodified line
50 * via seqcount_t under KCSAN: upon beginning a seq-reader critical section,29 * via seqcount_t under KCSAN: upon beginning a seq-reader critical section,
51 * pessimistically mark the next KCSAN_SEQLOCK_REGION_MAX memory accesses as30 * pessimistically mark the next KCSAN_SEQLOCK_REGION_MAX memory accesses as
52 * atomics; if there is a matching read_seqcount_retry() call, no following31 * atomics; if there is a matching read_seqcount_retry() call, no following
53 * memory operations are considered atomic. Usage of seqlocks via seqlock_t32 * memory operations are considered atomic. Usage of the seqlock_t interface
54 * interface is not affected.33 * is not affected.
55 */34 */
56#define KCSAN_SEQLOCK_REGION_MAX 100035#define KCSAN_SEQLOCK_REGION_MAX 1000
57 36
58/*37/*
59 * Version using sequence counter only.38 * Sequence counters (seqcount_t)
60 * This can be used when code has its own mutex protecting the39 *
61 * updating starting before the write_seqcountbeqin() and ending40 * This is the raw counting mechanism, without any writer protection.
62 * after the write_seqcount_end().41 *
42 * Write side critical sections must be serialized and non-preemptible.
43 *
44 * If readers can be invoked from hardirq or softirq contexts,
45 * interrupts or bottom halves must also be respectively disabled before
46 * entering the write section.
47 *
48 * This mechanism can't be used if the protected data contains pointers,
49 * as the writer can invalidate a pointer that a reader is following.
50 *
51 * If it's desired to automatically handle the sequence counter writer
52 * serialization and non-preemptibility requirements, use a sequential
53 * lock (seqlock_t) instead.
54 *
55 * See Documentation/locking/seqlock.rst
63 */56 */
64typedef struct seqcount {57typedef struct seqcount {
65 unsigned sequence;58 unsigned sequence;
@@ -398,10 +391,6 @@ static inline void raw_write_seqcount_latch(seqcount_t *s) · 332 unmodified lines
398 smp_wmb(); /* increment "sequence" before following stores */391 smp_wmb(); /* increment "sequence" before following stores */
399}392}
400 393
401/*
402 * Sequence counter only version assumes that callers are using their
403 * own mutexing.
404 */
405static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)394static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
406{395{
407 raw_write_seqcount_begin(s);396 raw_write_seqcount_begin(s);
@@ -434,15 +423,21 @@ static inline void write_seqcount_invalidate(seqcount_t *s) · 26 unmodified lines
434 kcsan_nestable_atomic_end();423 kcsan_nestable_atomic_end();
435}424}
436 425
426/*
427 * Sequential locks (seqlock_t)
428 *
429 * Sequence counters with an embedded spinlock for writer serialization
430 * and non-preemptibility.
431 *
432 * For more info, see:
433 * - Comments on top of seqcount_t
434 * - Documentation/locking/seqlock.rst
435 */
437typedef struct {436typedef struct {
438 struct seqcount seqcount;437 struct seqcount seqcount;
439 spinlock_t lock;438 spinlock_t lock;
440} seqlock_t;439} seqlock_t;
441 440
442/*
443 * These macros triggered gcc-3.x compile-time problems. We think these are
444 * OK now. Be cautious.
445 */
446#define __SEQLOCK_UNLOCKED(lockname) \441#define __SEQLOCK_UNLOCKED(lockname) \
447 { \442 { \
448 .seqcount = SEQCNT_ZERO(lockname), \443 .seqcount = SEQCNT_ZERO(lockname), \