Skip to content

Commit 606d5c7

Browse files
committed
buf_ring: Use atomic accesses for head/tail values
Use explicit atomic load/store operations for all producer and consumer head and tail accesses. This allows us to remove the volatile annotation from these variables. Reviewed by: alc, imp, kib, markj Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D46380
1 parent 0cd97e1 commit 606d5c7

File tree

1 file changed

+33
-26
lines changed

1 file changed

+33
-26
lines changed

sys/sys/buf_ring.h

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@
5151
*
5252
*/
5353
struct buf_ring {
54-
volatile uint32_t br_prod_head;
55-
volatile uint32_t br_prod_tail;
54+
uint32_t br_prod_head;
55+
uint32_t br_prod_tail;
5656
int br_prod_size;
5757
int br_prod_mask;
5858
uint64_t br_drops;
59-
volatile uint32_t br_cons_head __aligned(CACHE_LINE_SIZE);
60-
volatile uint32_t br_cons_tail;
59+
uint32_t br_cons_head __aligned(CACHE_LINE_SIZE);
60+
uint32_t br_cons_tail;
6161
int br_cons_size;
6262
int br_cons_mask;
6363
#if defined(DEBUG_BUFRING) && defined(_KERNEL)
@@ -83,10 +83,12 @@ buf_ring_enqueue(struct buf_ring *br, void *buf)
8383
* via drbr_peek(), and then re-added via drbr_putback() and
8484
* trigger a spurious panic.
8585
*/
86-
for (uint32_t i = br->br_cons_head; i != br->br_prod_head; i++)
86+
for (uint32_t i = atomic_load_32(&br->br_cons_head);
87+
i != atomic_load_32(&br->br_prod_head); i++)
8788
if (br->br_ring[i & mask] == buf)
8889
panic("buf=%p already enqueue at %d prod=%d cons=%d",
89-
buf, i, br->br_prod_tail, br->br_cons_tail);
90+
buf, i, atomic_load_32(&br->br_prod_tail),
91+
atomic_load_32(&br->br_cons_tail));
9092
#endif
9193
critical_enter();
9294
do {
@@ -106,8 +108,8 @@ buf_ring_enqueue(struct buf_ring *br, void *buf)
106108

107109
if ((int32_t)(cons_tail + br->br_prod_size - prod_next) < 1) {
108110
rmb();
109-
if (prod_head == br->br_prod_head &&
110-
cons_tail == br->br_cons_tail) {
111+
if (prod_head == atomic_load_32(&br->br_prod_head) &&
112+
cons_tail == atomic_load_32(&br->br_cons_tail)) {
111113
br->br_drops++;
112114
critical_exit();
113115
return (ENOBUFS);
@@ -127,7 +129,7 @@ buf_ring_enqueue(struct buf_ring *br, void *buf)
127129
* that preceded us, we need to wait for them
128130
* to complete
129131
*/
130-
while (br->br_prod_tail != prod_head)
132+
while (atomic_load_32(&br->br_prod_tail) != prod_head)
131133
cpu_spinwait();
132134
atomic_store_rel_32(&br->br_prod_tail, prod_next);
133135
critical_exit();
@@ -173,7 +175,7 @@ buf_ring_dequeue_mc(struct buf_ring *br)
173175
* that preceded us, we need to wait for them
174176
* to complete
175177
*/
176-
while (br->br_cons_tail != cons_head)
178+
while (atomic_load_32(&br->br_cons_tail) != cons_head)
177179
cpu_spinwait();
178180

179181
atomic_store_rel_32(&br->br_cons_tail, cons_next);
@@ -195,7 +197,7 @@ buf_ring_dequeue_sc(struct buf_ring *br)
195197
void *buf;
196198

197199
mask = br->br_cons_mask;
198-
cons_head = br->br_cons_head;
200+
cons_head = atomic_load_32(&br->br_cons_head);
199201
prod_tail = atomic_load_acq_32(&br->br_prod_tail);
200202

201203
cons_next = cons_head + 1;
@@ -204,7 +206,7 @@ buf_ring_dequeue_sc(struct buf_ring *br)
204206
return (NULL);
205207

206208
cons_idx = cons_head & mask;
207-
br->br_cons_head = cons_next;
209+
atomic_store_32(&br->br_cons_head, cons_next);
208210
buf = br->br_ring[cons_idx];
209211

210212
#ifdef DEBUG_BUFRING
@@ -213,9 +215,9 @@ buf_ring_dequeue_sc(struct buf_ring *br)
213215
if (!mtx_owned(br->br_lock))
214216
panic("lock not held on single consumer dequeue");
215217
#endif
216-
if (br->br_cons_tail != cons_head)
218+
if (atomic_load_32(&br->br_cons_tail) != cons_head)
217219
panic("inconsistent list cons_tail=%d cons_head=%d",
218-
br->br_cons_tail, cons_head);
220+
atomic_load_32(&br->br_cons_tail), cons_head);
219221
#endif
220222
atomic_store_rel_32(&br->br_cons_tail, cons_next);
221223
return (buf);
@@ -235,13 +237,13 @@ buf_ring_advance_sc(struct buf_ring *br)
235237

236238
mask = br->br_cons_mask;
237239
#endif
238-
cons_head = br->br_cons_head;
239-
prod_tail = br->br_prod_tail;
240+
cons_head = atomic_load_32(&br->br_cons_head);
241+
prod_tail = atomic_load_32(&br->br_prod_tail);
240242

241243
cons_next = cons_head + 1;
242244
if (cons_head == prod_tail)
243245
return;
244-
br->br_cons_head = cons_next;
246+
atomic_store_32(&br->br_cons_head, cons_next);
245247
#ifdef DEBUG_BUFRING
246248
br->br_ring[cons_head & mask] = NULL;
247249
#endif
@@ -267,12 +269,13 @@ buf_ring_advance_sc(struct buf_ring *br)
267269
static __inline void
268270
buf_ring_putback_sc(struct buf_ring *br, void *new)
269271
{
270-
uint32_t mask;
272+
uint32_t cons_idx, mask;
271273

272274
mask = br->br_cons_mask;
273-
KASSERT((br->br_cons_head & mask) != (br->br_prod_tail & mask),
275+
cons_idx = atomic_load_32(&br->br_cons_head) & mask;
276+
KASSERT(cons_idx != (atomic_load_32(&br->br_prod_tail) & mask),
274277
("Buf-Ring has none in putback")) ;
275-
br->br_ring[br->br_cons_head & mask] = new;
278+
br->br_ring[cons_idx] = new;
276279
}
277280

278281
/*
@@ -291,7 +294,7 @@ buf_ring_peek(struct buf_ring *br)
291294
#endif
292295
mask = br->br_cons_mask;
293296
prod_tail = atomic_load_acq_32(&br->br_prod_tail);
294-
cons_head = br->br_cons_head;
297+
cons_head = atomic_load_32(&br->br_cons_head);
295298

296299
if (cons_head == prod_tail)
297300
return (NULL);
@@ -312,7 +315,7 @@ buf_ring_peek_clear_sc(struct buf_ring *br)
312315

313316
mask = br->br_cons_mask;
314317
prod_tail = atomic_load_acq_32(&br->br_prod_tail);
315-
cons_head = br->br_cons_head;
318+
cons_head = atomic_load_32(&br->br_cons_head);
316319

317320
if (cons_head == prod_tail)
318321
return (NULL);
@@ -332,22 +335,26 @@ static __inline int
332335
buf_ring_full(struct buf_ring *br)
333336
{
334337

335-
return (br->br_prod_head == br->br_cons_tail + br->br_cons_size - 1);
338+
return (atomic_load_32(&br->br_prod_head) ==
339+
atomic_load_32(&br->br_cons_tail) + br->br_cons_size - 1);
336340
}
337341

338342
static __inline int
339343
buf_ring_empty(struct buf_ring *br)
340344
{
341345

342-
return (br->br_cons_head == br->br_prod_tail);
346+
return (atomic_load_32(&br->br_cons_head) ==
347+
atomic_load_32(&br->br_prod_tail));
343348
}
344349

345350
static __inline int
346351
buf_ring_count(struct buf_ring *br)
347352
{
353+
uint32_t cons_tail, prod_tail;
348354

349-
return ((br->br_prod_size + br->br_prod_tail - br->br_cons_tail)
350-
& br->br_prod_mask);
355+
cons_tail = atomic_load_32(&br->br_cons_tail);
356+
prod_tail = atomic_load_32(&br->br_prod_tail);
357+
return ((br->br_prod_size + prod_tail - cons_tail) & br->br_prod_mask);
351358
}
352359

353360
#ifdef _KERNEL

0 commit comments

Comments
 (0)