Half of the read_seqbegin_or_lock's users are buggy (I'll send the fixes), and I guess this is because the documentation and the pseudo code in Documentation/locking/seqlock.rst are wrong. Pseudo code: int seq = 0; do { read_seqbegin_or_lock(&foo_seqlock, &seq); /* ... [[read-side critical section]] ... */ } while (need_seqretry(&foo_seqlock, seq)); read_seqbegin_or_lock() returns with the even seq, need_seqretry() doesn't change this counter. This means that seq is always even and thus the locking pass is simply impossible. IOW, "_or_lock" has no effect and this code doesn't differ from do { seq = read_seqbegin(&foo_seqlock); /* ... [[read-side critical section]] ... */ } while (read_seqretry(&foo_seqlock, seq)); Signed-off-by: Oleg Nesterov <oleg@xxxxxxxxxx> --- Documentation/locking/seqlock.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/locking/seqlock.rst b/Documentation/locking/seqlock.rst index bfda1a5fecad..4bdf8d4ed2a2 100644 --- a/Documentation/locking/seqlock.rst +++ b/Documentation/locking/seqlock.rst @@ -218,13 +218,14 @@ Read path, three categories: according to a passed marker. This is used to avoid lockless readers starvation (too much retry loops) in case of a sharp spike in write activity. First, a lockless read is tried (even marker passed). If - that trial fails (odd sequence counter is returned, which is used as - the next iteration marker), the lockless read is transformed to a - full locking read and no retry loop is necessary:: + that trial fails (sequence counter doesn't match), make the marker + odd for the next iteration, the lockless read is transformed to a + full locking read and no retry loop is necessary, for example:: /* marker; even initialization */ - int seq = 0; + int seq = 1; do { + seq++; /* 2 on the 1st/lockless path, otherwise odd */ read_seqbegin_or_lock(&foo_seqlock, &seq); /* ... [[read-side critical section]] ... */ -- 2.25.1.362.g51ebf55