Module Name: src Committed By: riastradh Date: Sun Dec 19 01:21:30 UTC 2021
Modified Files: src/sys/external/bsd/drm2/include/linux: seqlock.h Log Message: Revamp seqlock. Fix some stupid bugs. Add seqcount. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/include/linux/seqlock.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/include/linux/seqlock.h diff -u src/sys/external/bsd/drm2/include/linux/seqlock.h:1.2 src/sys/external/bsd/drm2/include/linux/seqlock.h:1.3 --- src/sys/external/bsd/drm2/include/linux/seqlock.h:1.2 Sun Dec 19 00:47:40 2021 +++ src/sys/external/bsd/drm2/include/linux/seqlock.h Sun Dec 19 01:21:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: seqlock.h,v 1.2 2021/12/19 00:47:40 riastradh Exp $ */ +/* $NetBSD: seqlock.h,v 1.3 2021/12/19 01:21:30 riastradh Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -38,8 +38,88 @@ #include <lib/libkern/libkern.h> +struct seqcount { + unsigned sqc_gen; +}; + +typedef struct seqcount seqcount_t; + +static inline void +seqcount_init(struct seqcount *seqcount) +{ + + seqcount->sqc_gen = 0; +} + +static inline void +seqcount_destroy(struct seqcount *seqcount) +{ + + KASSERT((seqcount->sqc_gen & 1) == 0); + seqcount->sqc_gen = -1; +} + +static inline void +write_seqcount_begin(struct seqcount *seqcount) +{ + + KASSERT((seqcount->sqc_gen & 1) == 0); + seqcount->sqc_gen |= 1; + membar_producer(); +} + +static inline void +write_seqcount_end(struct seqcount *seqcount) +{ + + KASSERT((seqcount->sqc_gen & 1) == 1); + membar_producer(); + seqcount->sqc_gen |= 1; /* paranoia */ + seqcount->sqc_gen++; +} + +static inline unsigned +__read_seqcount_begin(struct seqcount *seqcount) +{ + unsigned gen; + + while (__predict_false((gen = seqcount->sqc_gen) & 1)) + SPINLOCK_BACKOFF_HOOK; + __insn_barrier(); + + return gen; +} + +static inline bool +__read_seqcount_retry(struct seqcount *seqcount, unsigned gen) +{ + + __insn_barrier(); + return __predict_false(seqcount->sqc_gen != gen); +} + +static inline unsigned +read_seqcount_begin(struct seqcount *seqcount) +{ + unsigned gen; + + gen = __read_seqcount_begin(seqcount); + membar_consumer(); + + return gen; +} + +static inline bool +read_seqcount_retry(struct seqcount *seqcount, unsigned gen) +{ + + membar_consumer(); + return __read_seqcount_retry(seqcount, gen); +} + struct seqlock { - uint64_t sql_gen; + kmutex_t sql_lock; + struct seqcount sql_count; }; typedef struct seqlock seqlock_t; @@ -48,26 +128,32 @@ static inline void seqlock_init(struct seqlock *seqlock) { - seqlock->sql_gen = 0; + mutex_init(&seqlock->sql_lock, MUTEX_DEFAULT, IPL_VM); + seqcount_init(&seqlock->sql_count); +} + +static inline void +seqlock_destroy(struct seqlock *seqlock) +{ + + seqcount_destroy(&seqlock->sql_count); + mutex_destroy(&seqlock->sql_lock); } static inline void write_seqlock(struct seqlock *seqlock) { - KASSERT((seqlock->sql_gen & 1) == 0); - seqlock->sql_gen |= 1; - membar_producer(); + mutex_spin_enter(&seqlock->sql_lock); + write_seqcount_begin(&seqlock->sql_count); } static inline void write_sequnlock(struct seqlock *seqlock) { - KASSERT((seqlock->sql_gen & 1) == 1); - membar_producer(); - seqlock->sql_gen |= 1; /* paraonia */ - seqlock->sql_gen++; + write_seqcount_end(&seqlock->sql_count); + mutex_spin_exit(&seqlock->sql_lock); } #define write_seqlock_irqsave(SEQLOCK, FLAGS) do { \ @@ -76,27 +162,22 @@ write_sequnlock(struct seqlock *seqlock) } while (0) #define write_sequnlock_irqrestore(SEQLOCK, FLAGS) do { \ - write_seqlock(SEQLOCK); \ + write_sequnlock(SEQLOCK); \ splx((int)(FLAGS)); \ } while (0) -static inline uint64_t +static inline unsigned read_seqbegin(struct seqlock *seqlock) { - uint64_t gen; - while ((gen = seqlock->sql_gen) & 1) - SPINLOCK_BACKOFF_HOOK; - membar_consumer(); - - return gen; + return read_seqcount_begin(&seqlock->sql_count); } static inline bool -read_seqretry(struct seqlock *seqlock, uint64_t gen) +read_seqretry(struct seqlock *seqlock, unsigned gen) { - return gen != seqlock->sql_gen; + return read_seqcount_retry(&seqlock->sql_count, gen); } #endif /* _LINUX_SEQLOCK_H_ */