62 lines
1.3 KiB
C
62 lines
1.3 KiB
C
|
#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
|
||
|
}
|