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 @@
11 /* SPDX-License-Identifier: GPL-2.0 */
22 #ifndef __LINUX_SEQLOCK_H
33 #define __LINUX_SEQLOCK_H
4+
45 /*
5− * Reader/writer consistent mechanism without starving writers. This type of
6− * lock for data where the reader wants a consistent set of information
7− * and is willing to retry if the information changes. There are two types
8− * of readers:
9− * 1. Sequence readers which never block a writer but they may have to retry
10− * if a writer is in progress by detecting change in sequence number.
11− * Writers do not wait for a sequence reader.
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
6+ * seqcount_t / seqlock_t - a reader-writer consistency mechanism with
7+ * lockless readers (read-only retry loops), and no writer starvation.
8+ *
9+ * See Documentation/locking/seqlock.rst
10+ *
11+ * Copyrights:
12+ * - Based on x86_64 vsyscall gettimeofday: Keith Owens, Andrea Arcangeli
3413 */
3514
3615 #include <linux/spinlock.h>
@@ -41,8 +20,8 @@ · 4 unmodified lines
4120 #include <asm/processor.h>
4221
4322 /*
44− * The seqlock interface does not prescribe a precise sequence of read
45− * begin/retry/end. For readers, typically there is a call to
23+ * The seqlock seqcount_t interface does not prescribe a precise sequence of
24+ * read begin/retry/end. For readers, typically there is a call to
4625 * read_seqcount_begin() and read_seqcount_retry(), however, there are more
4726 * esoteric cases which do not follow this pattern.
4827 *
@@ -50,16 +29,30 @@ · 1 unmodified line
5029 * via seqcount_t under KCSAN: upon beginning a seq-reader critical section,
5130 * pessimistically mark the next KCSAN_SEQLOCK_REGION_MAX memory accesses as
5231 * atomics; if there is a matching read_seqcount_retry() call, no following
53− * memory operations are considered atomic. Usage of seqlocks via seqlock_t
54− * interface is not affected.
32+ * memory operations are considered atomic. Usage of the seqlock_t interface
33+ * is not affected.
5534 */
5635 #define KCSAN_SEQLOCK_REGION_MAX 1000
5736
5837 /*
59− * Version using sequence counter only.
60− * This can be used when code has its own mutex protecting the
61− * updating starting before the write_seqcountbeqin() and ending
62− * after the write_seqcount_end().
38+ * Sequence counters (seqcount_t)
39+ *
40+ * This is the raw counting mechanism, without any writer protection.
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
6356 */
6457 typedef struct seqcount {
6558 unsigned sequence;
@@ -398,10 +391,6 @@ static inline void raw_write_seqcount_latch(seqcount_t *s) · 332 unmodified lines
398391 smp_wmb(); /* increment "sequence" before following stores */
399392 }
400393
401−/*
402− * Sequence counter only version assumes that callers are using their
403− * own mutexing.
404− */
405394 static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
406395 {
407396 raw_write_seqcount_begin(s);
@@ -434,15 +423,21 @@ static inline void write_seqcount_invalidate(seqcount_t *s) · 26 unmodified lines
434423 kcsan_nestable_atomic_end();
435424 }
436425
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+ */
437436 typedef struct {
438437 struct seqcount seqcount;
439438 spinlock_t lock;
440439 } seqlock_t;
441440
442−/*
443− * These macros triggered gcc-3.x compile-time problems. We think these are
444− * OK now. Be cautious.
445− */
446441 #define __SEQLOCK_UNLOCKED(lockname) \
447442 { \
448443 .seqcount = SEQCNT_ZERO(lockname), \