aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/seqlock.h
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /include/linux/seqlock.h
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.h88
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
32typedef struct { 33typedef 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
90repeat: 88repeat:
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/**
129static 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 */
139static inline unsigned __read_seqcount_begin(const seqcount_t *s)
130{ 140{
131 unsigned ret; 141 unsigned ret;
132 142
133repeat: 143repeat:
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 */
161static 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 */
182static 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 */
146static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) 197static 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 */
228static 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 */