; =============================================================================
;
; Litos - Read/write spin-lock
;
; =============================================================================
; Read/write spin-lock is used to lock bus between processors to allow one
; writer OR multiple readers.
; =============================================================================
CODE_SECTION 32
; Currently not used - locked places are very short, it would not be efficient.
%ifdef _UNUSED_
RWSPIN_BIAS EQU 01000000h ; bias for writer
%define RWLOCK dd RWSPIN_BIAS ; macro - initialized r/w spin-lock
%ifdef SMP
; -----------------------------------------------------------------------------
; Initialize read/write spin-lock
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; -----------------------------------------------------------------------------
RWSpinInit: mov dword [ebx],RWSPIN_BIAS ; init read/write spin-lock
ret
; -----------------------------------------------------------------------------
; Lock read/write spin-lock for reading
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; NOTES: Entry point is RWReadLock label.
; -----------------------------------------------------------------------------
; ------------- Return old value of read/write spin-lock
RWReadLock2: lock ; CPU instruction lock
inc dword [ebx] ; return old value of the spin-lock
; ------------- Wait for releasing read/write spin-lock
RWReadLock4: rep nop ; CPU optimise hint (=Pentium 4 pause)
cmp dword [ebx],byte 0 ; is the lock still locked?
jle RWReadLock4 ; wait for releasing the lock
; ------------- Try to lock for reading
RWReadLock: lock ; CPU instruction lock
dec dword [ebx] ; try to lock for reading
js RWReadLock2 ; read/write lock is locked for writing
ret
; -----------------------------------------------------------------------------
; Lock read/write spin-lock for writing
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; NOTES: Entry point is RWWriteLock label.
; -----------------------------------------------------------------------------
; ------------- Return old value of read/write spin-lock
RWWriteLock2: lock ; CPU instruction lock
add dword [ebx],RWSPIN_BIAS ; return old value of the lock
; ------------- Wait for releasing read/write spin-lock
RWWriteLock4: rep nop ; CPU optimise hint (=Pentium 4 pause)
cmp dword [ebx],RWSPIN_BIAS; is the lock still locked?
jne RWWriteLock4 ; wait for releasing the lock
; ------------- Try to lock for reading
RWWriteLock: lock ; CPU instruction lock
sub dword [ebx],RWSPIN_BIAS ; try to lock for writing
jnz RWWriteLock2 ; read/write lock is already locked
ret
; -----------------------------------------------------------------------------
; Unlock read/write spin-lock locked for reading
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; -----------------------------------------------------------------------------
RWReadUnlock: lock ; CPU instruction lock
inc dword [ebx] ; return old value of the spin-lock
ret
; -----------------------------------------------------------------------------
; Unlock read/write spin-lock locked for writing
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; -----------------------------------------------------------------------------
RWWriteUnlock: lock ; CPU instruction lock
add dword [ebx],RWSPIN_BIAS ; return old value of the lock
ret
; -----------------------------------------------------------------------------
; Try to lock read/write spin-lock for reading
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; OUTPUT: EAX = 1 (successfully locked) or 0 (the lock is already locked)
; ZY = spin-lock was successfully locked for reading (EAX = 1)
; -----------------------------------------------------------------------------
RWReadTryLock: xor eax,eax ; EAX <- 0
lock ; CPU instruction lock
dec dword [ebx] ; try to lock for reading
setns al ; AL <- 1 locked, 0 error
jns RWReadTryLock2 ; locked
lock ; CPU instruction lock
inc dword [ebx] ; return old value of the spin-lock
RWReadTryLock2: cmp al,1 ; test state (1=locked, 0=error)
ret
; -----------------------------------------------------------------------------
; Try to lock read/write spin-lock for writing
; -----------------------------------------------------------------------------
; INPUT: EBX = read/write spin-lock entry
; OUTPUT: EAX = 1 (successfully locked) or 0 (the lock is already locked)
; ZY = spin-lock was successfully locked for writing (EAX = 1)
; -----------------------------------------------------------------------------
RWWriteTryLock: xor eax,eax ; EAX <- 0
lock ; CPU instruction lock
sub dword [ebx],RWSPIN_BIAS ; try to lock for writing
setz al ; AL <- 1 locked, 0 error
jz RWWriteTryLock2 ; locked
lock ; CPU instruction lock
add dword [ebx],RWSPIN_BIAS ; return old value of the lock
RWWriteTryLock2:cmp al,1 ; test state (1=locked, 0=error)
ret
; -----------------------------------------------------------------------------
; Test if read/write spin-lock can be locked for reading
; -----------------------------------------------------------------------------
; INPUT: EBX = spin-lock entry
; OUTPUT: EAX = 1 (can be locked) or 0 (is already locked)
; ZY = spin-lock can be locked for reading (EAX = 1)
; -----------------------------------------------------------------------------
RWReadTest: xor eax,eax ; EAX <- 0
cmp dword [ebx],byte 0 ; can be locked?
setg al ; EAX <- 1 can be locked, 0 cannot
cmp al,1 ; test state
ret
; -----------------------------------------------------------------------------
; Test if read/write spin-lock can be locked for writing
; -----------------------------------------------------------------------------
; INPUT: EBX = spin-lock entry
; OUTPUT: EAX = 1 (can be locked) or 0 (is already locked)
; ZY = spin-lock can be locked for writing (EAX = 1)
; -----------------------------------------------------------------------------
RWWriteTest: xor eax,eax ; EAX <- 0
cmp dword [ebx],RWSPIN_BIAS ; can be locked?
sete al ; EAX <- 1 can be locked, 0 cannot
ret
%endif ; SMP
%endif ; _UNUSED_
|