Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

u64_stats: Document writer non-preemptibility requirement

The u64_stats mechanism uses sequence counters to protect against 64-bit
values tearing on 32-bit architectures. Updating such statistics is a
sequence counter write side critical section.

Preemption must be disabled before entering this seqcount write critical
section. Failing to do so, the seqcount read side can preempt the write
side section and spin for the entire scheduler tick. If that reader
belongs to a real-time scheduling class, it can spin forever and the
kernel will livelock.

Document this statistics update side non-preemptibility requirement.

Reword the introductory paragraph to highlight u64_stats raison d'être:
64-bit values tearing protection on 32-bit architectures. Divide
documentation on a basis of internal design vs. usage constraints.

Reword the u64_stats header file top comment to always mention "Reader"
or "Writer" at the start of each bullet point, making it easier to
follow which side each point is actually for.

Clarify the statement "whole thing is a NOOP on 64bit arches or UP
kernels". For 32-bit UP kernels, preemption is always disabled for the
statistics read side section.

Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ahmed S. Darwish and committed by
David S. Miller
6501bf87 79cbb6bc

+23 -20
+23 -20
include/linux/u64_stats_sync.h
··· 3 3 #define _LINUX_U64_STATS_SYNC_H 4 4 5 5 /* 6 - * To properly implement 64bits network statistics on 32bit and 64bit hosts, 7 - * we provide a synchronization point, that is a noop on 64bit or UP kernels. 6 + * Protect against 64-bit values tearing on 32-bit architectures. This is 7 + * typically used for statistics read/update in different subsystems. 8 8 * 9 9 * Key points : 10 - * 1) Use a seqcount on SMP 32bits, with low overhead. 11 - * 2) Whole thing is a noop on 64bit arches or UP kernels. 12 - * 3) Write side must ensure mutual exclusion or one seqcount update could 10 + * 11 + * - Use a seqcount on 32-bit SMP, only disable preemption for 32-bit UP. 12 + * - The whole thing is a no-op on 64-bit architectures. 13 + * 14 + * Usage constraints: 15 + * 16 + * 1) Write side must ensure mutual exclusion, or one seqcount update could 13 17 * be lost, thus blocking readers forever. 14 - * If this synchronization point is not a mutex, but a spinlock or 15 - * spinlock_bh() or disable_bh() : 16 - * 3.1) Write side should not sleep. 17 - * 3.2) Write side should not allow preemption. 18 - * 3.3) If applicable, interrupts should be disabled. 18 + * 19 + * 2) Write side must disable preemption, or a seqcount reader can preempt the 20 + * writer and also spin forever. 21 + * 22 + * 3) Write side must use the _irqsave() variant if other writers, or a reader, 23 + * can be invoked from an IRQ context. 19 24 * 20 25 * 4) If reader fetches several counters, there is no guarantee the whole values 21 - * are consistent (remember point 1) : this is a noop on 64bit arches anyway) 26 + * are consistent w.r.t. each other (remember point #2: seqcounts are not 27 + * used for 64bit architectures). 22 28 * 23 - * 5) readers are allowed to sleep or be preempted/interrupted : They perform 24 - * pure reads. But if they have to fetch many values, it's better to not allow 25 - * preemptions/interruptions to avoid many retries. 29 + * 5) Readers are allowed to sleep or be preempted/interrupted: they perform 30 + * pure reads. 26 31 * 27 - * 6) If counter might be written by an interrupt, readers should block interrupts. 28 - * (On UP, there is no seqcount_t protection, a reader allowing interrupts could 29 - * read partial values) 30 - * 31 - * 7) For irq and softirq uses, readers can use u64_stats_fetch_begin_irq() and 32 - * u64_stats_fetch_retry_irq() helpers 32 + * 6) Readers must use both u64_stats_fetch_{begin,retry}_irq() if the stats 33 + * might be updated from a hardirq or softirq context (remember point #1: 34 + * seqcounts are not used for UP kernels). 32-bit UP stat readers could read 35 + * corrupted 64-bit values otherwise. 33 36 * 34 37 * Usage : 35 38 *