; =============================================================================
;
; Litos - Spin-lock
;
; =============================================================================
; Spin-lock is used to lock bus between processors to avoid read partially
; modified variable. Spin-lock is a byte with value 1 (spin-lock is unlocked),
; 0 (any CPU has this spin-lock locked) or < 0 (another CPU tries for lock).
; Spin-lock supports 127 CPUs maximal. Spin-lock cannot be locket more times
; in the same CPU, so it should be used with interrupt disabled (to avoid
; task switching during lock).
; =============================================================================
CODE_SECTION 32
%define SPINLOCK dd 1 ; macro - initialized spin-lock
%ifdef SMP
; ------------- Macro - initialize spin-lock (%1 = pointer, uses EAX)
%macro LOCK_Init 1
xor eax,eax ; EAX <- 0
inc eax ; EAX <- 1
mov [%1],eax ; init spin-lock
%endmacro
; ------------- Macro - initialize spin-lock (%1=pointer, EAX=0, output EAX=1)
%macro LOCK0_Init 1
inc eax ; EAX <- 1
mov [%1],eax ; init spin-lock
%endmacro
; ------------- Macro - initialize spin-lock (%1=pointer, EAX=1)
%macro LOCK1_Init 1
mov [%1],eax ; init spin-lock
%endmacro
; ------------- Macro - initialize spin-lock (%1 = pointer)
%macro LOCK2_Init 1
mov dword [%1],1 ; init spin-lock
%endmacro
; ------------- Macro - initialize spin-lock from zero value (%1 = pointer)
%macro LOCK3_Init 1
inc dword [%1] ; init spin-lock
%endmacro
; ------------- Macro - initialize spin-lock locked (%1=pointer)
%macro LOCK_InitLock 1
and dword [%1],byte 0
%endmacro
; ------------- Macro - lock spin-lock (%1=pointer or address)
%macro LOCK_Lock 1
; --- Try to lock spin-lock
%%L1: lock ; CPU instruction lock
dec byte [%1] ; decrease spin-lock
jz %%L3 ; spin-lock is not locked
; --- Wait for unlocking spin-lock
%%L2: cmp byte [%1],1 ; is spin-lock locked?
rep nop ; CPU optimise hint (=Pentium 4 pause)
jne %%L2 ; spin-lock is locked, wait for unlock
jmp short %%L1 ; next try to lock spin-lock
%%L3:
%endmacro
; ------------- Macro - lock spin-lock function (%1=label, %2=register or address)
%macro LOCK_LockFnc 2
; --- Wait fot unlocking spin-lock
%%L1: cmp byte [%2],1 ; is spin-lock locked?
rep nop ; CPU optimise hint (=Pentium 4 pause)
jne %%L1 ; spin-lock is locked, wait for unlock
; --- Try to lock spin-lock
%1: lock ; CPU instruction lock
dec byte [%2] ; decrease spin-lock
jnz %%L1 ; spin-lock is already locked
ret ; else it got spin-lock
%endmacro
; ------------- Macro - unlock spin-lock (%1=pointer or address, saves FLAGS)
%macro LOCK_Unlock 1
mov byte [%1],1 ; unlock spin-lock
%endmacro
; -----------------------------------------------------------------------------
; Initialize/Unlock spin-lock
; -----------------------------------------------------------------------------
; INPUT: EBX = spin-lock entry
; NOTES: To initialize use SpinInit entry point.
; To unlock use SpinUnlock entry point.
; -----------------------------------------------------------------------------
SpinInit: and dword [ebx],byte 0 ; set spin-lock to 0
SpinUnlock: mov byte [ebx],1 ; unlock spin-lock
ret
; -----------------------------------------------------------------------------
; Lock spin-lock
; -----------------------------------------------------------------------------
; INPUT: EBX = spin-lock entry
; NOTES: Entry point is SpinLock label.
; -----------------------------------------------------------------------------
LOCK_LockFnc SpinLock,ebx
; -----------------------------------------------------------------------------
; Lock spin-lock (EAX)
; -----------------------------------------------------------------------------
; INPUT: EAX = spin-lock entry
; NOTES: Entry point is SpinLockEAX label.
; -----------------------------------------------------------------------------
LOCK_LockFnc SpinLockEAX,eax
; -----------------------------------------------------------------------------
; Lock spin-lock (EDX)
; -----------------------------------------------------------------------------
; INPUT: EDX = spin-lock entry
; NOTES: Entry point is SpinLockEDX label.
; -----------------------------------------------------------------------------
LOCK_LockFnc SpinLockEDX,edx
; -----------------------------------------------------------------------------
; Lock spin-lock (ESI)
; -----------------------------------------------------------------------------
; INPUT: ESI = spin-lock entry
; NOTES: Entry point is SpinLockESI label.
; -----------------------------------------------------------------------------
LOCK_LockFnc SpinLockESI,esi
; -----------------------------------------------------------------------------
; Try to lock spin-lock
; -----------------------------------------------------------------------------
; INPUT: EBX = spin-lock entry
; OUTPUT: EAX = 1 (successfully locked) or 0 (spin-lock is already locked)
; ZY = spin-lock was successfully locked (EAX = 1)
; -----------------------------------------------------------------------------
SpinTryLock: xor eax,eax ; EAX <- 0, locked value
xchg al,[ebx] ; try to lock spin-lock
cmp al,1 ; is spin-lock locked?
sete al ; EAX <- 1 success, 0 already locked
ret
%endif ; SMP
|