1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| void p64_blkring_dequeue(p64_blkring_t *rb, void *elems[], uint32_t nelem, uint32_t *index) { uint32_t head = atomic_fetch_add(&rb->cons.head, nelem, RELAXED); blkring_dequeue(rb, elems, nelem, index, head); }
static void blkring_dequeue(rb, elems, nelem, index, sn) { uint32_t mask = *addr_dep(&rb->cons.mask, sn); *index = sn;
for (uint32_t i = 0; i < nelem; i++, sn++) { uint32_t idx = swizzle(sn) & mask;
struct ringslot old; do { #ifdef __ARM_FEATURE_ATOMICS old.i128 = atomic_icas_n(&rb->ring[idx].i128, ACQUIRE); #else PREFETCH_FOR_WRITE(&rb->ring[idx]); old.sn = atomic_load_n(&rb->ring[idx].sn, RELAXED); old.elem = atomic_load_ptr(addr_dep(&rb->ring[idx].elem, old.sn), ACQUIRE); #endif } while (old.sn != sn || old.elem == NULL);
#ifdef __ARM_FEATURE_ATOMICS struct ringslot swp = {sn + mask + 1, NULL}; atomic_cas_n(&rb->ring[idx].i128, old.i128, swp.i128, RELAXED); #else atomic_store_ptr(&rb->ring[idx].elem, NULL, RELAXED); atomic_store_n(&rb->ring[idx].sn, sn + mask + 1, RELEASE); #endif elems[i] = old.elem; } }
|