Lock free queue implementation based on the paper by Michael and Scott: Nonblocking Algorithms and Preemption-Safe Locking on Multiprogrammed Shared Memory Multiprocessors
/* We need to put the job into memory before we do anything. */
pQueue->pJobs[ma_job_extract_slot(slot)] = *pJob;
pQueue->pJobs[ma_job_extract_slot(slot)].toc.allocation = slot; /* This will overwrite the job code. */
pQueue->pJobs[ma_job_extract_slot(slot)].toc.breakup.code = pJob->toc.breakup.code; /* The job code needs to be applied again because the line above overwrote it. */
pQueue->pJobs[ma_job_extract_slot(slot)].next = MA_JOB_ID_NONE; /* Reset for safety. */
#ifndef MA_USE_EXPERIMENTAL_LOCK_FREE_JOB_QUEUE
ma_spinlock_lock(&pQueue->lock);
#endif
{
/* The job is stored in memory so now we need to add it to our linked list. We only ever add items to the end of the list. */
for (;;) {
tail = c89atomic_load_64(&pQueue->tail);
next = c89atomic_load_64(&pQueue->pJobs[ma_job_extract_slot(tail)].next);
/* We need a new slot. */
result = ma_slot_allocator_alloc(&pQueue->allocator, &slot);
if (result == MA_SUCCESS) {
/* At this point we should have a slot to place the job. */
if (ma_job_toc_to_allocation(tail) == ma_job_toc_to_allocation(c89atomic_load_64(&pQueue->tail))) {
if (ma_job_extract_slot(next) == 0xFFFF) {
if (ma_job_queue_cas(&pQueue->pJobs[ma_job_extract_slot(tail)].next, next, slot)) {
break;
/* We need to put the job into memory before we do anything. */
pQueue->pJobs[ma_job_extract_slot(slot)] = *pJob;
pQueue->pJobs[ma_job_extract_slot(slot)].toc.allocation = slot; /* This will overwrite the job code. */
pQueue->pJobs[ma_job_extract_slot(slot)].toc.breakup.code = pJob->toc.breakup.code; /* The job code needs to be applied again because the line above overwrote it. */
pQueue->pJobs[ma_job_extract_slot(slot)].next = MA_JOB_ID_NONE; /* Reset for safety. */
/* The job is stored in memory so now we need to add it to our linked list. We only ever add items to the end of the list. */
for (;;) {
tail = c89atomic_load_64(&pQueue->tail);
next = c89atomic_load_64(&pQueue->pJobs[ma_job_extract_slot(tail)].next);
if (ma_job_toc_to_allocation(tail) == ma_job_toc_to_allocation(c89atomic_load_64(&pQueue->tail))) {
if (ma_job_extract_slot(next) == 0xFFFF) {
if (ma_job_queue_cas(&pQueue->pJobs[ma_job_extract_slot(tail)].next, next, slot)) {