xref: /openbsd-src/sys/dev/pci/drm/include/linux/seqlock.h (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
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 #include <linux/ww_mutex.h>
14 
15 typedef struct {
16 	unsigned int sequence;
17 } seqcount_t;
18 
19 static inline void
20 __seqcount_init(seqcount_t *s, const char *name,
21     struct lock_class_key *key)
22 {
23 	s->sequence = 0;
24 }
25 
26 static inline void
27 seqcount_init(seqcount_t *s)
28 {
29 	__seqcount_init(s, NULL, NULL);
30 }
31 
32 static inline unsigned int
33 __read_seqcount_begin(const seqcount_t *s)
34 {
35 	unsigned int r;
36 	for (;;) {
37 		r = s->sequence;
38 		if ((r & 1) == 0)
39 			break;
40 		cpu_relax();
41 	}
42 	return r;
43 }
44 
45 static inline unsigned int
46 read_seqcount_begin(const seqcount_t *s)
47 {
48 	unsigned int r = __read_seqcount_begin(s);
49 	membar_consumer();
50 	return r;
51 }
52 
53 static inline int
54 __read_seqcount_retry(const seqcount_t *s, unsigned start)
55 {
56 	return (s->sequence != start);
57 }
58 
59 static inline int
60 read_seqcount_retry(const seqcount_t *s, unsigned start)
61 {
62 	membar_consumer();
63 	return __read_seqcount_retry(s, start);
64 }
65 
66 static inline void
67 write_seqcount_begin(seqcount_t *s)
68 {
69 	s->sequence++;
70 	membar_producer();
71 }
72 
73 static inline void
74 write_seqcount_end(seqcount_t *s)
75 {
76 	membar_producer();
77 	s->sequence++;
78 }
79 
80 static inline unsigned int
81 raw_read_seqcount(const seqcount_t *s)
82 {
83 	unsigned int r = s->sequence;
84 	membar_consumer();
85 	return r;
86 }
87 
88 typedef struct {
89 	unsigned int seq;
90 	struct mutex lock;
91 } seqlock_t;
92 
93 static inline void
94 seqlock_init(seqlock_t *sl, int wantipl)
95 {
96 	sl->seq = 0;
97 	mtx_init(&sl->lock, wantipl);
98 }
99 
100 static inline void
101 write_seqlock(seqlock_t *sl)
102 {
103 	mtx_enter(&sl->lock);
104 	sl->seq++;
105 	membar_producer();
106 }
107 
108 static inline void
109 __write_seqlock_irqsave(seqlock_t *sl)
110 {
111 	mtx_enter(&sl->lock);
112 	sl->seq++;
113 	membar_producer();
114 }
115 #define write_seqlock_irqsave(_sl, _flags) do {			\
116 		_flags = 0;					\
117 		__write_seqlock_irqsave(_sl);			\
118 	} while (0)
119 
120 static inline void
121 write_sequnlock(seqlock_t *sl)
122 {
123 	membar_producer();
124 	sl->seq++;
125 	mtx_leave(&sl->lock);
126 }
127 
128 static inline void
129 __write_sequnlock_irqrestore(seqlock_t *sl)
130 {
131 	membar_producer();
132 	sl->seq++;
133 	mtx_leave(&sl->lock);
134 }
135 #define write_sequnlock_irqrestore(_sl, _flags) do {		\
136 		(void)(_flags);					\
137 		__write_sequnlock_irqrestore(_sl);		\
138 	} while (0)
139 
140 static inline unsigned int
141 read_seqbegin(seqlock_t *sl)
142 {
143 	return READ_ONCE(sl->seq);
144 }
145 
146 static inline unsigned int
147 read_seqretry(seqlock_t *sl, unsigned int pos)
148 {
149 	return sl->seq != pos;
150 }
151 
152 typedef struct {
153 	seqcount_t seq;
154 	struct ww_mutex lock;
155 } seqcount_ww_mutex_t;
156 
157 typedef struct {
158 	seqcount_t seq;
159 	struct rwlock lock;
160 } seqcount_mutex_t;
161 
162 #define seqcount_mutex_init(s, l)	seqcount_init(&(s)->seq)
163 
164 #endif
165