aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/win-x86/LockFreeLIFO.asm
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/nu/win-x86/LockFreeLIFO.asm
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/nu/win-x86/LockFreeLIFO.asm')
-rw-r--r--Src/replicant/nu/win-x86/LockFreeLIFO.asm50
1 files changed, 50 insertions, 0 deletions
diff --git a/Src/replicant/nu/win-x86/LockFreeLIFO.asm b/Src/replicant/nu/win-x86/LockFreeLIFO.asm
new file mode 100644
index 00000000..dd67e5b1
--- /dev/null
+++ b/Src/replicant/nu/win-x86/LockFreeLIFO.asm
@@ -0,0 +1,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
+