Code:
Procedure.q AtomicIncrement64(*Var64)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Var64]
!mov rax, 1
!lock xadd [rdx], rax
!add rax, 1
CompilerElse
; store non-volatile registers
!mov [esp - 4], ebx
!mov [esp - 8], edi
; load 64 bit value into edx:eax
!mov edi, [p.p_Var64]
!mov eax, [edi]
!mov edx, [edi + 4]
; 64 bit atomic increment
!.l:
!mov ebx, 1
!mov ecx, 0
!add ebx, eax
!adc ecx, edx
!lock cmpxchg8b [edi]
!jnz .l
!mov eax, ebx
!mov edx, ecx
; restore non-volatile registers
!mov edi, [esp - 8]
!mov ebx, [esp - 4]
CompilerEndIf
ProcedureReturn
EndProcedure
Procedure.q AtomicDecrement64(*Var64)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Var64]
!mov rax, -1
!lock xadd [rdx], rax
!add rax, -1
CompilerElse
; store non-volatile registers
!mov [esp - 4], ebx
!mov [esp - 8], edi
; load 64 bit value into edx:eax
!mov edi, [p.p_Var64]
!mov eax, [edi]
!mov edx, [edi + 4]
; 64 bit atomic decrement
!.l:
!mov ebx, -1
!mov ecx, -1
!add ebx, eax
!adc ecx, edx
!lock cmpxchg8b [edi]
!jnz .l
!mov eax, ebx
!mov edx, ecx
; restore non-volatile registers
!mov edi, [esp - 8]
!mov ebx, [esp - 4]
CompilerEndIf
ProcedureReturn
EndProcedure
A.q = 5
For i = 1 To 10
Debug AtomicIncrement64(@A)
Next
It's also possible to use one Add procedure and use -1 for decrement.
Code:
Procedure.q AtomicAdd64(*Var64, Value64.q)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Var64]
!mov rax, [p.v_Value64]
!lock xadd [rdx], rax
!add rax, [p.v_Value64]
CompilerElse
; store non-volatile registers
!mov [esp - 4], ebx
!mov [esp - 8], edi
; load 64 bit value into edx:eax
!mov edi, [p.p_Var64]
!mov eax, [edi]
!mov edx, [edi + 4]
; 64 bit atomic add
!.l:
!mov ebx, [p.v_Value64]
!mov ecx, [p.v_Value64 + 4]
!add ebx, eax
!adc ecx, edx
!lock cmpxchg8b [edi]
!jnz .l
!mov eax, ebx
!mov edx, ecx
; restore non-volatile registers
!mov edi, [esp - 8]
!mov ebx, [esp - 4]
CompilerEndIf
ProcedureReturn
EndProcedure
A.q = 5
For i = 1 To 10
Debug AtomicAdd64(@A, -1)
Next
For i = 1 To 6
Debug AtomicAdd64(@A, 1)
Next