xref: /openbsd-src/sys/dev/pci/drm/include/linux/seqlock.h (revision ec727ea710c91afd8ce4f788c5aaa8482b7b69b2)
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)
103 {
104 	mtx_enter(&sl->lock);
105 	sl->seq++;
106 	membar_producer();
107 }
108 #define write_seqlock_irqsave(_sl, _flags) do {			\
109 		_flags = 0;					\
110 		__write_seqlock_irqsave(_sl);			\
111 	} while (0)
112 
113 static inline void
114 write_sequnlock(seqlock_t *sl)
115 {
116 	membar_producer();
117 	sl->seq++;
118 	mtx_leave(&sl->lock);
119 }
120 
121 static inline void
122 __write_sequnlock_irqrestore(seqlock_t *sl)
123 {
124 	membar_producer();
125 	sl->seq++;
126 	mtx_leave(&sl->lock);
127 }
128 #define write_sequnlock_irqrestore(_sl, _flags) do {		\
129 		(void)(_flags);					\
130 		__write_sequnlock_irqrestore(_sl);		\
131 	} while (0)
132 
133 static inline unsigned int
134 read_seqbegin(seqlock_t *sl)
135 {
136 	return READ_ONCE(sl->seq);
137 }
138 
139 static inline unsigned int
140 read_seqretry(seqlock_t *sl, unsigned int pos)
141 {
142 	return sl->seq != pos;
143 }
144 
145 #endif
146