diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /include/linux/seqlock.h | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'include/linux/seqlock.h')
-rw-r--r-- | include/linux/seqlock.h | 88 |
1 files changed, 76 insertions, 12 deletions
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index 632205ccc25d..c6db9fb33c44 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/preempt.h> | 30 | #include <linux/preempt.h> |
31 | #include <asm/processor.h> | ||
31 | 32 | ||
32 | typedef struct { | 33 | typedef struct { |
33 | unsigned sequence; | 34 | unsigned sequence; |
@@ -41,9 +42,6 @@ typedef struct { | |||
41 | #define __SEQLOCK_UNLOCKED(lockname) \ | 42 | #define __SEQLOCK_UNLOCKED(lockname) \ |
42 | { 0, __SPIN_LOCK_UNLOCKED(lockname) } | 43 | { 0, __SPIN_LOCK_UNLOCKED(lockname) } |
43 | 44 | ||
44 | #define SEQLOCK_UNLOCKED \ | ||
45 | __SEQLOCK_UNLOCKED(old_style_seqlock_init) | ||
46 | |||
47 | #define seqlock_init(x) \ | 45 | #define seqlock_init(x) \ |
48 | do { \ | 46 | do { \ |
49 | (x)->sequence = 0; \ | 47 | (x)->sequence = 0; \ |
@@ -88,12 +86,12 @@ static __always_inline unsigned read_seqbegin(const seqlock_t *sl) | |||
88 | unsigned ret; | 86 | unsigned ret; |
89 | 87 | ||
90 | repeat: | 88 | repeat: |
91 | ret = sl->sequence; | 89 | ret = ACCESS_ONCE(sl->sequence); |
92 | smp_rmb(); | ||
93 | if (unlikely(ret & 1)) { | 90 | if (unlikely(ret & 1)) { |
94 | cpu_relax(); | 91 | cpu_relax(); |
95 | goto repeat; | 92 | goto repeat; |
96 | } | 93 | } |
94 | smp_rmb(); | ||
97 | 95 | ||
98 | return ret; | 96 | return ret; |
99 | } | 97 | } |
@@ -107,7 +105,7 @@ static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start) | |||
107 | { | 105 | { |
108 | smp_rmb(); | 106 | smp_rmb(); |
109 | 107 | ||
110 | return (sl->sequence != start); | 108 | return unlikely(sl->sequence != start); |
111 | } | 109 | } |
112 | 110 | ||
113 | 111 | ||
@@ -125,14 +123,25 @@ typedef struct seqcount { | |||
125 | #define SEQCNT_ZERO { 0 } | 123 | #define SEQCNT_ZERO { 0 } |
126 | #define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0) | 124 | #define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0) |
127 | 125 | ||
128 | /* Start of read using pointer to a sequence counter only. */ | 126 | /** |
129 | static inline unsigned read_seqcount_begin(const seqcount_t *s) | 127 | * __read_seqcount_begin - begin a seq-read critical section (without barrier) |
128 | * @s: pointer to seqcount_t | ||
129 | * Returns: count to be passed to read_seqcount_retry | ||
130 | * | ||
131 | * __read_seqcount_begin is like read_seqcount_begin, but has no smp_rmb() | ||
132 | * barrier. Callers should ensure that smp_rmb() or equivalent ordering is | ||
133 | * provided before actually loading any of the variables that are to be | ||
134 | * protected in this critical section. | ||
135 | * | ||
136 | * Use carefully, only in critical code, and comment how the barrier is | ||
137 | * provided. | ||
138 | */ | ||
139 | static inline unsigned __read_seqcount_begin(const seqcount_t *s) | ||
130 | { | 140 | { |
131 | unsigned ret; | 141 | unsigned ret; |
132 | 142 | ||
133 | repeat: | 143 | repeat: |
134 | ret = s->sequence; | 144 | ret = s->sequence; |
135 | smp_rmb(); | ||
136 | if (unlikely(ret & 1)) { | 145 | if (unlikely(ret & 1)) { |
137 | cpu_relax(); | 146 | cpu_relax(); |
138 | goto repeat; | 147 | goto repeat; |
@@ -140,14 +149,56 @@ repeat: | |||
140 | return ret; | 149 | return ret; |
141 | } | 150 | } |
142 | 151 | ||
143 | /* | 152 | /** |
144 | * Test if reader processed invalid data because sequence number has changed. | 153 | * read_seqcount_begin - begin a seq-read critical section |
154 | * @s: pointer to seqcount_t | ||
155 | * Returns: count to be passed to read_seqcount_retry | ||
156 | * | ||
157 | * read_seqcount_begin opens a read critical section of the given seqcount. | ||
158 | * Validity of the critical section is tested by checking read_seqcount_retry | ||
159 | * function. | ||
160 | */ | ||
161 | static inline unsigned read_seqcount_begin(const seqcount_t *s) | ||
162 | { | ||
163 | unsigned ret = __read_seqcount_begin(s); | ||
164 | smp_rmb(); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * __read_seqcount_retry - end a seq-read critical section (without barrier) | ||
170 | * @s: pointer to seqcount_t | ||
171 | * @start: count, from read_seqcount_begin | ||
172 | * Returns: 1 if retry is required, else 0 | ||
173 | * | ||
174 | * __read_seqcount_retry is like read_seqcount_retry, but has no smp_rmb() | ||
175 | * barrier. Callers should ensure that smp_rmb() or equivalent ordering is | ||
176 | * provided before actually loading any of the variables that are to be | ||
177 | * protected in this critical section. | ||
178 | * | ||
179 | * Use carefully, only in critical code, and comment how the barrier is | ||
180 | * provided. | ||
181 | */ | ||
182 | static inline int __read_seqcount_retry(const seqcount_t *s, unsigned start) | ||
183 | { | ||
184 | return unlikely(s->sequence != start); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * read_seqcount_retry - end a seq-read critical section | ||
189 | * @s: pointer to seqcount_t | ||
190 | * @start: count, from read_seqcount_begin | ||
191 | * Returns: 1 if retry is required, else 0 | ||
192 | * | ||
193 | * read_seqcount_retry closes a read critical section of the given seqcount. | ||
194 | * If the critical section was invalid, it must be ignored (and typically | ||
195 | * retried). | ||
145 | */ | 196 | */ |
146 | static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) | 197 | static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) |
147 | { | 198 | { |
148 | smp_rmb(); | 199 | smp_rmb(); |
149 | 200 | ||
150 | return s->sequence != start; | 201 | return __read_seqcount_retry(s, start); |
151 | } | 202 | } |
152 | 203 | ||
153 | 204 | ||
@@ -167,6 +218,19 @@ static inline void write_seqcount_end(seqcount_t *s) | |||
167 | s->sequence++; | 218 | s->sequence++; |
168 | } | 219 | } |
169 | 220 | ||
221 | /** | ||
222 | * write_seqcount_barrier - invalidate in-progress read-side seq operations | ||
223 | * @s: pointer to seqcount_t | ||
224 | * | ||
225 | * After write_seqcount_barrier, no read-side seq operations will complete | ||
226 | * successfully and see data older than this. | ||
227 | */ | ||
228 | static inline void write_seqcount_barrier(seqcount_t *s) | ||
229 | { | ||
230 | smp_wmb(); | ||
231 | s->sequence+=2; | ||
232 | } | ||
233 | |||
170 | /* | 234 | /* |
171 | * Possible sw/hw IRQ protected versions of the interfaces. | 235 | * Possible sw/hw IRQ protected versions of the interfaces. |
172 | */ | 236 | */ |