#include "kpl.h" void kpl_task_queue_init(kpl_task_queue *task_queue) { __atomic_store_n(&task_queue->dummy.next, NULL, __ATOMIC_RELAXED); __atomic_store_n(&task_queue->head, &task_queue->dummy, __ATOMIC_RELAXED); task_queue->tail = (kpl_task*) &task_queue->dummy; } void kpl_task_queue_add(kpl_task_queue *task_queue, kpl_task *task) { __atomic_store_n(&task->next, NULL, __ATOMIC_RELAXED); kpl_task *head = __atomic_exchange_n(&task_queue->head, task, __ATOMIC_SEQ_CST); __atomic_store_n(&head->next, task, __ATOMIC_RELEASE); } kpl_task *kpl_task_queue_next(kpl_task_queue *task_queue) { kpl_task *task = NULL; for (;;) { kpl_task *tail = task_queue->tail, *next = __atomic_load_n(&tail->next, __ATOMIC_ACQUIRE); if (tail == (kpl_task*) &task_queue->dummy) { if (!next) break; tail = task_queue->tail = next; next = __atomic_load_n(&tail->next, __ATOMIC_ACQUIRE); } if (!next) { kpl_task *head = __atomic_load_n(&task_queue->head, __ATOMIC_ACQUIRE); if (tail != head) continue; kpl_task_queue_add(task_queue, (kpl_task*) &task_queue->dummy); next = __atomic_load_n(&tail->next, __ATOMIC_ACQUIRE); } if (next) { task_queue->tail = next; task = tail; break; } } if (task) __atomic_store_n(&task->next, NULL, __ATOMIC_RELAXED); return task; }