xref: /openbsd-src/sys/dev/pci/drm/include/linux/seqlock.h (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /* Public domain. */
2 
3 #ifndef _LINUX_SEQLOCK_H
4 #define _LINUX_SEQLOCK_H
5 
6 #include <sys/types.h>
7 #include <sys/mutex.h>
8 #include <sys/atomic.h>
9 #include <linux/lockdep.h>
10 #include <linux/processor.h>
11 #include <linux/preempt.h>
12 #include <linux/compiler.h>
13 
14 typedef struct {
15 	unsigned int sequence;
16 } seqcount_t;
17 
18 static inline void
19 __seqcount_init(seqcount_t *s, const char *name,
20     struct lock_class_key *key)
21 {
22 	s->sequence = 0;
23 }
24 
25 static inline unsigned int
26 __read_seqcount_begin(const seqcount_t *s)
27 {
28 	unsigned int r;
29 	for (;;) {
30 		r = s->sequence;
31 		if ((r & 1) == 0)
32 			break;
33 		cpu_relax();
34 	}
35 	return r;
36 }
37 
38 static inline unsigned int
39 read_seqcount_begin(const seqcount_t *s)
40 {
41 	unsigned int r = __read_seqcount_begin(s);
42 	membar_consumer();
43 	return r;
44 }
45 
46 static inline int
47 __read_seqcount_retry(const seqcount_t *s, unsigned start)
48 {
49 	return (s->sequence != start);
50 }
51 
52 static inline int
53 read_seqcount_retry(const seqcount_t *s, unsigned start)
54 {
55 	membar_consumer();
56 	return __read_seqcount_retry(s, start);
57 }
58 
59 static inline void
60 write_seqcount_begin(seqcount_t *s)
61 {
62 	s->sequence++;
63 	membar_producer();
64 }
65 
66 static inline void
67 write_seqcount_end(seqcount_t *s)
68 {
69 	membar_producer();
70 	s->sequence++;
71 }
72 
73 static inline unsigned int
74 raw_read_seqcount(const seqcount_t *s)
75 {
76 	unsigned int r = s->sequence;
77 	membar_consumer();
78 	return r;
79 }
80 
81 typedef struct {
82 	unsigned int seq;
83 	struct mutex lock;
84 } seqlock_t;
85 
86 static inline void
87 seqlock_init(seqlock_t *sl, int wantipl)
88 {
89 	sl->seq = 0;
90 	mtx_init(&sl->lock, wantipl);
91 }
92 
93 static inline void
94 write_seqlock(seqlock_t *sl)
95 {
96 	mtx_enter(&sl->lock);
97 	sl->seq++;
98 	membar_producer();
99 }
100 
101 static inline void
102 write_seqlock_irqsave(seqlock_t *sl, __unused long flags)
103 {
104 	mtx_enter(&sl->lock);
105 	sl->seq++;
106 	membar_producer();
107 }
108 
109 static inline void
110 write_sequnlock(seqlock_t *sl)
111 {
112 	membar_producer();
113 	sl->seq++;
114 	mtx_leave(&sl->lock);
115 }
116 
117 static inline void
118 write_sequnlock_irqrestore(seqlock_t *sl, __unused long flags)
119 {
120 	membar_producer();
121 	sl->seq++;
122 	mtx_leave(&sl->lock);
123 }
124 
125 static inline unsigned int
126 read_seqbegin(seqlock_t *sl)
127 {
128 	return READ_ONCE(sl->seq);
129 }
130 
131 static inline unsigned int
132 read_seqretry(seqlock_t *sl, unsigned int pos)
133 {
134 	return sl->seq != pos;
135 }
136 
137 #endif
138