/* * KPL specific objects */ #pragma once // for atomic linked list queue // size in bytes, index on the kpl_threads array #define KPL_OBJECT_HEADER(STRUCT_NAME) \ struct STRUCT_NAME *_Atomic queue_next; \ int32_t object_size, thread_id typedef struct _kpl_object { KPL_OBJECT_HEADER(_kpl_object); } kpl_object; // all kpl objects allocated by the kpl memory allocator extend this header /* * Atomic linked list queue any thread can add, only owner thread can remove */ typedef struct { kpl_object *_Atomic head, *tail; // head is modified with atomic exchange struct { kpl_object *_Atomic queue_next; } dummy; // head and tail are never null will always point to this } kpl_object_queue; /* * Only owner thread can call this */ inline void kpl_object_queue_init(kpl_object_queue *object_queue) { __atomic_store_n(&object_queue->dummy.queue_next, NULL, __ATOMIC_RELAXED); __atomic_store_n(&object_queue->head, &object_queue->dummy, __ATOMIC_RELAXED); object_queue->tail = (kpl_object*) &object_queue->dummy; } /* * Always succeeds, any thread can call this */ inline void kpl_object_queue_enqueue(kpl_object_queue *object_queue, void *object) { kpl_object *obj = object; __atomic_store_n(&obj->queue_next, NULL, __ATOMIC_RELAXED); kpl_object *head = __atomic_exchange_n(&object_queue->head, obj, __ATOMIC_SEQ_CST); __atomic_store_n(&head->queue_next, obj, __ATOMIC_RELEASE); } /* * Null for not found, only owner thread can call this */ void *kpl_object_queue_dequeue(kpl_object_queue *object_queue); typedef void kpl_task_fn(kpl_task *task, kpl_env *env); typedef struct _kpl_task { KPL_OBJECT_HEADER(_kpl_task); // TODO } kpl_task;