beamformer_work_queue.c (1558B)
1 /* See LICENSE for license details. */ 2 #include "beamformer_work_queue.h" 3 4 static BeamformWork * 5 beamform_work_queue_pop(BeamformWorkQueue *q) 6 { 7 BeamformWork *result = 0; 8 9 static_assert(ISPOWEROF2(ARRAY_COUNT(q->work_items)), "queue capacity must be a power of 2"); 10 u64 val = atomic_load(&q->queue); 11 u64 mask = ARRAY_COUNT(q->work_items) - 1; 12 u32 widx = val & mask; 13 u32 ridx = val >> 32 & mask; 14 15 if (ridx != widx) 16 result = q->work_items + ridx; 17 18 return result; 19 } 20 21 static void 22 beamform_work_queue_pop_commit(BeamformWorkQueue *q) 23 { 24 atomic_add(&q->queue, 0x100000000ULL); 25 } 26 27 DEBUG_EXPORT BEAMFORM_WORK_QUEUE_PUSH_FN(beamform_work_queue_push) 28 { 29 BeamformWork *result = 0; 30 31 static_assert(ISPOWEROF2(ARRAY_COUNT(q->work_items)), "queue capacity must be a power of 2"); 32 u64 val = atomic_load(&q->queue); 33 u64 mask = ARRAY_COUNT(q->work_items) - 1; 34 u32 widx = val & mask; 35 u32 ridx = val >> 32 & mask; 36 u32 next = (widx + 1) & mask; 37 38 if (val & 0x80000000) 39 atomic_and(&q->queue, ~0x80000000); 40 41 if (next != ridx) { 42 result = q->work_items + widx; 43 zero_struct(result); 44 } 45 46 return result; 47 } 48 49 DEBUG_EXPORT BEAMFORM_WORK_QUEUE_PUSH_COMMIT_FN(beamform_work_queue_push_commit) 50 { 51 atomic_add(&q->queue, 1); 52 } 53 54 static b32 55 try_wait_sync(i32 *sync, i32 timeout_ms, os_wait_on_value_fn *os_wait_on_value) 56 { 57 b32 result = 0; 58 for (;;) { 59 i32 current = atomic_load(sync); 60 if (current && atomic_cas(sync, ¤t, 0)) { 61 result = 1; 62 break; 63 } 64 if (!timeout_ms || !os_wait_on_value(sync, 0, timeout_ms)) 65 break; 66 } 67 return result; 68 }