aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/LockFreeLIFO.c
blob: eb9c1eb1f016c9035d0cc7bbc47d6db8009020f0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
	}