aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/win-x86/LockFreeLIFO.asm
blob: dd67e5b15ed6f5bca4aa6c8e5cffcce6f3c37b23 (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
.686
.model FLAT

PUBLIC _lifo_push
_TEXT SEGMENT
lifo = 4      ; size = 4
entry = 8      ; size = 4
_lifo_push PROC
	mov ecx, DWORD PTR 4[esp] ; ecx holds lifo
	mov edx, DWORD PTR 8[esp] ; edx holds the new entry
again:
	mov eax, DWORD PTR [ecx] ; eax holds the old head
	mov DWORD PTR[edx], eax ; new node's 'next' is set to the old head
	lock cmpxchg DWORD PTR [ecx], edx
	jnz again
	ret	0
_lifo_push ENDP

PUBLIC _lifo_pop
_TEXT SEGMENT
lifo = 4      ; size = 4
_lifo_pop PROC
	push esi
	push ebx
	mov	esi, DWORD PTR 12[esp] ; esi holds lifo
again:
    ; if re-ordered loads become an issue, we could use cmpxchg8b to read in (after zeroing ebx/ecx) or maybe use movq
	mov edx, DWORD PTR [esi+4] ; counter
	; or we could put an LFENCE here
	mov eax, DWORD PTR [esi] ; pointer
	test eax, eax
	jz bail

	mov ecx, edx ; counter
	mov ebx, DWORD PTR [eax] ; pointer->next
	inc ecx

	lock cmpxchg8b QWORD PTR [esi]
	jnz again

bail:
	pop ebx
	pop esi
	ret 0
_lifo_pop ENDP

_TEXT ENDS

END