diff options
Diffstat (limited to 'Src/replicant/nu/LockFreeLIFO.c')
-rw-r--r-- | Src/replicant/nu/LockFreeLIFO.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/Src/replicant/nu/LockFreeLIFO.c b/Src/replicant/nu/LockFreeLIFO.c new file mode 100644 index 00000000..eb9c1eb1 --- /dev/null +++ b/Src/replicant/nu/LockFreeLIFO.c @@ -0,0 +1,61 @@ +#include "LockFreeLIFO.h" +#include "foundation/atomics.h" + +/* TODO: on windows, replace with InitializeSListHead/InterlockedPushEntrySList/InterlockedPopEntrySList just to be safe */ +void lifo_init(lifo_t *lifo) +{ + lifo->head = 0; +} + +void lifo_push(lifo_t *lifo, queue_node_t *cl) +{ + queue_node_t *new_head = cl; + queue_node_t *old_head = 0; + do + { + old_head = (queue_node_t *)lifo->head; + new_head->Next = old_head; + } while (!nx_atomic_cmpxchg_pointer(old_head, new_head, (void * volatile *)&lifo->head)); +} + +queue_node_t *lifo_pop(lifo_t *lifo) +{ + queue_node_t *new_head = 0, *old_head = 0; + do + { + old_head = (queue_node_t *)lifo->head; + if (old_head) + new_head = old_head->Next; + else + new_head = 0; + } while (!nx_atomic_cmpxchg_pointer(old_head, new_head, (void * volatile *)&lifo->head)); + return old_head; +} + + queue_node_t *lifo_malloc(size_t bytes) + { +#ifdef __GNUC__ +# ifdef __APPLE__ + void *v = 0; + (void) posix_memalign(&v, sizeof(void *), bytes); + return v; +# else + return memalign(bytes, sizeof(void *)); +# endif +#elif defined(_WIN32) + return _aligned_malloc(bytes, MEMORY_ALLOCATION_ALIGNMENT); +#else +#error port me! +#endif + } + + void lifo_free(queue_node_t *ptr) + { +#ifdef __GNUC__ + free(ptr); +#elif defined(_WIN32) + _aligned_free(ptr); +#else +#error port me! +#endif + } |