jcs's openbsd hax
openbsd
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
14typedef struct {
15 unsigned int sequence;
16} seqcount_t;
17
18static inline void
19__seqcount_init(seqcount_t *s, const char *name,
20 struct lock_class_key *key)
21{
22 s->sequence = 0;
23}
24
25static inline void
26seqcount_init(seqcount_t *s)
27{
28 __seqcount_init(s, NULL, NULL);
29}
30
31static inline unsigned int
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
44static inline unsigned int
45read_seqcount_begin(const seqcount_t *s)
46{
47 unsigned int r = __read_seqcount_begin(s);
48 membar_consumer();
49 return r;
50}
51
52static inline int
53__read_seqcount_retry(const seqcount_t *s, unsigned start)
54{
55 return (s->sequence != start);
56}
57
58static inline int
59read_seqcount_retry(const seqcount_t *s, unsigned start)
60{
61 membar_consumer();
62 return __read_seqcount_retry(s, start);
63}
64
65static inline void
66write_seqcount_begin(seqcount_t *s)
67{
68 s->sequence++;
69 membar_producer();
70}
71
72static inline void
73write_seqcount_end(seqcount_t *s)
74{
75 membar_producer();
76 s->sequence++;
77}
78
79static inline unsigned int
80raw_read_seqcount(const seqcount_t *s)
81{
82 unsigned int r = s->sequence;
83 membar_consumer();
84 return r;
85}
86
87typedef struct {
88 unsigned int seq;
89 struct mutex lock;
90} seqlock_t;
91
92static inline void
93seqlock_init(seqlock_t *sl, int wantipl)
94{
95 sl->seq = 0;
96 mtx_init(&sl->lock, wantipl);
97}
98
99static inline void
100write_seqlock(seqlock_t *sl)
101{
102 mtx_enter(&sl->lock);
103 sl->seq++;
104 membar_producer();
105}
106
107static inline void
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
119static inline void
120write_sequnlock(seqlock_t *sl)
121{
122 membar_producer();
123 sl->seq++;
124 mtx_leave(&sl->lock);
125}
126
127static inline void
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
139static inline unsigned int
140read_seqbegin(seqlock_t *sl)
141{
142 return READ_ONCE(sl->seq);
143}
144
145static inline unsigned int
146read_seqretry(seqlock_t *sl, unsigned int pos)
147{
148 return sl->seq != pos;
149}
150
151typedef 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
158static inline unsigned int
159seqprop_sequence(const seqcount_mutex_t *sm)
160{
161 return READ_ONCE(sm->seq.sequence);
162}
163
164#endif