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