MCPcopy Create free account
hub / github.com/F-Stack/f-stack / buf_ring_dequeue_sc

Function buf_ring_dequeue_sc

freebsd/sys/buf_ring.h:159–229  ·  view source on GitHub ↗

* single-consumer dequeue * use where dequeue is protected by a lock * e.g. a network driver's tx queue lock */

Source from the content-addressed store, hash-verified

157 * e.g. a network driver's tx queue lock
158 */
159static __inline void *
160buf_ring_dequeue_sc(struct buf_ring *br)
161{
162 uint32_t cons_head, cons_next;
163#ifdef PREFETCH_DEFINED
164 uint32_t cons_next_next;
165#endif
166 uint32_t prod_tail;
167 void *buf;
168
169 /*
170 * This is a workaround to allow using buf_ring on ARM and ARM64.
171 * ARM64TODO: Fix buf_ring in a generic way.
172 * REMARKS: It is suspected that br_cons_head does not require
173 * load_acq operation, but this change was extensively tested
174 * and confirmed it's working. To be reviewed once again in
175 * FreeBSD-12.
176 *
177 * Preventing following situation:
178
179 * Core(0) - buf_ring_enqueue() Core(1) - buf_ring_dequeue_sc()
180 * ----------------------------------------- ----------------------------------------------
181 *
182 * cons_head = br->br_cons_head;
183 * atomic_cmpset_acq_32(&br->br_prod_head, ...));
184 * buf = br->br_ring[cons_head]; <see <1>>
185 * br->br_ring[prod_head] = buf;
186 * atomic_store_rel_32(&br->br_prod_tail, ...);
187 * prod_tail = br->br_prod_tail;
188 * if (cons_head == prod_tail)
189 * return (NULL);
190 * <condition is false and code uses invalid(old) buf>`
191 *
192 * <1> Load (on core 1) from br->br_ring[cons_head] can be reordered (speculative readed) by CPU.
193 */
194#if defined(__arm__) || defined(__aarch64__)
195 cons_head = atomic_load_acq_32(&br->br_cons_head);
196#else
197 cons_head = br->br_cons_head;
198#endif
199 prod_tail = atomic_load_acq_32(&br->br_prod_tail);
200
201 cons_next = (cons_head + 1) & br->br_cons_mask;
202#ifdef PREFETCH_DEFINED
203 cons_next_next = (cons_head + 2) & br->br_cons_mask;
204#endif
205
206 if (cons_head == prod_tail)
207 return (NULL);
208
209#ifdef PREFETCH_DEFINED
210 if (cons_next != prod_tail) {
211 prefetch(br->br_ring[cons_next]);
212 if (cons_next_next != prod_tail)
213 prefetch(br->br_ring[cons_next_next]);
214 }
215#endif
216 br->br_cons_head = cons_next;

Callers 3

drbr_flushFunction · 0.85
drbr_dequeueFunction · 0.85
drbr_dequeue_condFunction · 0.85

Calls 3

atomic_load_acq_32Function · 0.85
prefetchFunction · 0.85
panicFunction · 0.50

Tested by

no test coverage detected