--- a/sys/dev/drm/include/linux/seqlock.h +++ b/sys/dev/drm/include/linux/seqlock.h @@ -77,7 +77,11 @@ static inline void write_sequnlock(seqlock_t *sl) { - sl->sequence--; + /* Advance the sequence count monotonically instead of returning it + * to its pre-write value: a reader that started before this writer + * must observe a changed sequence on read_seqretry() or it will + * accept a torn snapshot. */ + sl->sequence++; spin_unlock(&sl->lock); cpu_sfence(); } @@ -90,7 +94,18 @@ static inline unsigned read_seqbegin(const seqlock_t *sl) { - return READ_ONCE(sl->sequence); + unsigned ret; + + /* Wait until the sequence count is even, i.e. no writer holds the + * seqlock write section (matches Linux read_seqcount_begin()). */ + do { + ret = READ_ONCE(sl->sequence); + if ((ret & 1) == 0) + break; + cpu_pause(); + } while (1); + + return ret; } static inline unsigned