Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2/include/linux Revamp seqlock. Fix some...



details:   https://anonhg.NetBSD.org/src/rev/1db4e75c35c6
branches:  trunk
changeset: 1027957:1db4e75c35c6
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Dec 19 01:21:30 2021 +0000

description:
Revamp seqlock. Fix some stupid bugs. Add seqcount.

diffstat:

 sys/external/bsd/drm2/include/linux/seqlock.h |  121 +++++++++++++++++++++----
 1 files changed, 101 insertions(+), 20 deletions(-)

diffs (173 lines):

diff -r c7dfb3f5240e -r 1db4e75c35c6 sys/external/bsd/drm2/include/linux/seqlock.h
--- a/sys/external/bsd/drm2/include/linux/seqlock.h     Sun Dec 19 01:21:22 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/seqlock.h     Sun Dec 19 01:21:30 2021 +0000
@@ -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 @@
 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 @@
 } 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_ */



Home | Main Index | Thread Index | Old Index