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