| 1 | ; $Id: locks.asm,v 1.2 2001-01-21 07:55:28 bird Exp $ | 
|---|
| 2 | ; | 
|---|
| 3 | ; R/W spinlocks. | 
|---|
| 4 | ; | 
|---|
| 5 | ; Copyright (c) 2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 6 | ; | 
|---|
| 7 | ; Project Odin Software License can be found in LICENSE.TXT | 
|---|
| 8 | ; | 
|---|
| 9 |  | 
|---|
| 10 | .486p | 
|---|
| 11 |  | 
|---|
| 12 | ; | 
|---|
| 13 | ;   Include files | 
|---|
| 14 | ; | 
|---|
| 15 | include devsegdf.inc | 
|---|
| 16 |  | 
|---|
| 17 |  | 
|---|
| 18 | ; | 
|---|
| 19 | ;   Exported symbols | 
|---|
| 20 | ; | 
|---|
| 21 | public RWLockAcquireRead | 
|---|
| 22 | public RWLockReleaseRead | 
|---|
| 23 | public RWLockAcquireWrite | 
|---|
| 24 | public RWLockReleaseWrite | 
|---|
| 25 |  | 
|---|
| 26 |  | 
|---|
| 27 | ; | 
|---|
| 28 | ;   Defined Constants And Macros | 
|---|
| 29 | ; | 
|---|
| 30 | ifdef DEBUG | 
|---|
| 31 | DEBUGINT3 EQU int 3 | 
|---|
| 32 | else | 
|---|
| 33 | DEBUGINT3 EQU ; | 
|---|
| 34 | endif | 
|---|
| 35 |  | 
|---|
| 36 |  | 
|---|
| 37 |  | 
|---|
| 38 | CODE32 segment | 
|---|
| 39 |  | 
|---|
| 40 |  | 
|---|
| 41 | ;; | 
|---|
| 42 | ; Acquires Read access to a R/W lock. | 
|---|
| 43 | ; @cproto   APIRET _Optlink RWLockAcquireRead(PRWLOCK pLock) | 
|---|
| 44 | ; @returns  NO_ERROR (never failes) | 
|---|
| 45 | ; @param    eax     pLock - pointer to lock structure. | 
|---|
| 46 | ; @uses     eax, ecx, edx | 
|---|
| 47 | ; @sketch   spin while write locked. | 
|---|
| 48 | ;           try increment. | 
|---|
| 49 | ;           if failed restart spin loop. | 
|---|
| 50 | ;           else return successfully. | 
|---|
| 51 | ; @status   completely implemented. | 
|---|
| 52 | ; @author   knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 53 | ; @remark   This is non-blocking. | 
|---|
| 54 | RWLockAcquireRead proc near | 
|---|
| 55 | ASSUME ds:FLAT | 
|---|
| 56 | mov     edx, eax                    ; edx = lock pointer. | 
|---|
| 57 | ; eax will be used later. | 
|---|
| 58 | rwlar_writeloop: | 
|---|
| 59 | mov     eax, dword ptr [edx]        ; get lock data. | 
|---|
| 60 | rwlar_reloop: | 
|---|
| 61 | bt      eax, 1fh                    ; test if write bit is set. | 
|---|
| 62 | jnc     rwlar_tryinc                ; spin until it's cleared. | 
|---|
| 63 | nop                                 ; We're not in a hurry any longer. | 
|---|
| 64 | nop | 
|---|
| 65 | nop | 
|---|
| 66 | jmp rwlar_writeloop                 ; spin. | 
|---|
| 67 |  | 
|---|
| 68 | rwlar_tryinc: | 
|---|
| 69 | les     ecx, [eax+1]                ; ecx <- new read lock count (eax + 1) | 
|---|
| 70 | lock cmpxchg dword ptr [edx], ecx | 
|---|
| 71 | jz      rwlar_ret                   ; ZF set ok success. | 
|---|
| 72 | jmp     rwlar_reloop                ; ZF clear on error, eax is [edx] - restart spin loop. | 
|---|
| 73 |  | 
|---|
| 74 | rwlar_ret: | 
|---|
| 75 | xor     eax, eax | 
|---|
| 76 | ret                                 ; Return successfully. | 
|---|
| 77 | RWLockAcquireRead endp | 
|---|
| 78 |  | 
|---|
| 79 |  | 
|---|
| 80 | ;; | 
|---|
| 81 | ; Releases a read lock. | 
|---|
| 82 | ; @cproto   APIRET _Optlink RWLockReleaseRead(PRWLOCK pLock) | 
|---|
| 83 | ; @returns  NO_ERROR on success. | 
|---|
| 84 | ;           -1 on error. | 
|---|
| 85 | ; @param    eax     pLock - Pointer to the lock structure. | 
|---|
| 86 | ; @uses     eax, edx | 
|---|
| 87 | ; @sketch   If the lock count is larger than zero Then | 
|---|
| 88 | ;               Descrement it and return successfully. | 
|---|
| 89 | ;           else | 
|---|
| 90 | ;               Fail. | 
|---|
| 91 | ; @status   completely implemented. | 
|---|
| 92 | ; @author   knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 93 | RWLockReleaseRead proc near | 
|---|
| 94 | mov     edx, dword ptr [eax]        ; Get lock count. | 
|---|
| 95 | and     edx, 7fffffffh              ; Sanity check. | 
|---|
| 96 | jnz     rwlrr_ok                    ; Jump if sane. | 
|---|
| 97 |  | 
|---|
| 98 | rwlrr_error:                            ; We're insane. | 
|---|
| 99 | DEBUGINT3                           ; This should _never_ _ever_ happen! | 
|---|
| 100 | mov     eax, 0ffffffffh             ; Return failure. | 
|---|
| 101 | ret | 
|---|
| 102 |  | 
|---|
| 103 | rwlrr_ok: | 
|---|
| 104 | lock dec dword ptr [eax]            ; Decrement the read count (works with write bit set too). | 
|---|
| 105 | xor     eax, eax                    ; Return successfully. | 
|---|
| 106 | ret | 
|---|
| 107 | RWLockReleaseRead endp | 
|---|
| 108 |  | 
|---|
| 109 |  | 
|---|
| 110 |  | 
|---|
| 111 | ;; | 
|---|
| 112 | ; Acquire write access to a R/W lock. | 
|---|
| 113 | ; @cproto   APIRET _Optlink RWLockAcquireWrite(PRWLOCK pLock) | 
|---|
| 114 | ; @returns  NO_ERROR (never failes) | 
|---|
| 115 | ; @param    eax     pLock - Pointer to lock structure. | 
|---|
| 116 | ; @uses     eax, edx | 
|---|
| 117 | ; @sketch   Spin while trying to set write lock flag (bit 31). | 
|---|
| 118 | ;           Spin while still read locked. (until lower 31 bits is zero) | 
|---|
| 119 | ; @status   completely implemented. | 
|---|
| 120 | ; @author   knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 121 | ; @remark   Will never block. | 
|---|
| 122 | RWLockAcquireWrite proc near | 
|---|
| 123 | ASSUME ds:FLAT | 
|---|
| 124 |  | 
|---|
| 125 | rwlaw_writeloop: | 
|---|
| 126 | lock bts dword ptr [eax], 01fh      ; Try set the write bit. | 
|---|
| 127 | jnc  rwlaw_readloop                 ; break loop - we set the write bit. | 
|---|
| 128 | nop                                 ; We're not in a hurry any longer. | 
|---|
| 129 | nop | 
|---|
| 130 | nop | 
|---|
| 131 | jmp rwlaw_writeloop                 ; Spin | 
|---|
| 132 |  | 
|---|
| 133 | ; Wait for reads to finish. | 
|---|
| 134 | rwlaw_readloop: | 
|---|
| 135 | mov     edx, dword ptr [eax]        ; Get lock value. | 
|---|
| 136 | bt      edx, 01fh                   ; Sanity check - Ensure that the write bit is not cleared. | 
|---|
| 137 | jc      rwlaw_ok                    ; Jump if sane. | 
|---|
| 138 |  | 
|---|
| 139 | rwlaw_error:                            ; We're insane! | 
|---|
| 140 | DEBUGINT3                           ; This should _never_ _ever_ happen! | 
|---|
| 141 | mov     eax, 0ffffffffh             ; Return failure. | 
|---|
| 142 | ret | 
|---|
| 143 |  | 
|---|
| 144 | rwlaw_ok: | 
|---|
| 145 | and     edx, 7fffffffh              ; Spin while until read lock count is 0. | 
|---|
| 146 | jz      rwlaw_ret                   ; break loop | 
|---|
| 147 | nop                                 ; We're not in a hurry any longer. | 
|---|
| 148 | nop | 
|---|
| 149 | nop | 
|---|
| 150 | jmp     rwlaw_ret                   ; Spin. | 
|---|
| 151 |  | 
|---|
| 152 | rwlaw_ret: | 
|---|
| 153 | xor     eax, eax                    ; successful return. | 
|---|
| 154 | ret | 
|---|
| 155 | RWLockAcquireWrite endp | 
|---|
| 156 |  | 
|---|
| 157 |  | 
|---|
| 158 | ;; | 
|---|
| 159 | ; Releases a Write lock. | 
|---|
| 160 | ; @cproto   APIRET _Optlink RWLockReleaseWrite(PRWLOCK pLock) | 
|---|
| 161 | ; @returns  NO_ERROR on success. | 
|---|
| 162 | ;           -1 on error. | 
|---|
| 163 | ; @param    eax     pLock - pointer to the lock structure. | 
|---|
| 164 | ; @uses     eax, edx | 
|---|
| 165 | ; @sketch   If write bit is set Then | 
|---|
| 166 | ;               Clear entire lock and return succesfully. | 
|---|
| 167 | ;           else | 
|---|
| 168 | ;               Return failure. | 
|---|
| 169 | ; @status   completely implemented. | 
|---|
| 170 | ; @author   knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 171 | RWLockReleaseWrite proc near | 
|---|
| 172 | cmp     dword ptr [eax], 80000000h  ; Sanity check - state should be write locked and no read locks. | 
|---|
| 173 | je      rwlrw_ok                    ; Jump if sane. | 
|---|
| 174 |  | 
|---|
| 175 | rwlrw_error: | 
|---|
| 176 | DEBUGINT3                           ; This should _never_ _ever_ happen! | 
|---|
| 177 | mov     eax, 0ffffffffh             ; Return failure. | 
|---|
| 178 | ret | 
|---|
| 179 |  | 
|---|
| 180 | rwlrw_ok: | 
|---|
| 181 | xor     edx, edx | 
|---|
| 182 | lock xchg edx, [eax]                ; Write 0 to the entire lock dword. | 
|---|
| 183 |  | 
|---|
| 184 | rwlrw_ret: | 
|---|
| 185 | xor     eax, eax                    ; Return successfully. | 
|---|
| 186 | ret | 
|---|
| 187 | RWLockReleaseWrite endp | 
|---|
| 188 |  | 
|---|
| 189 |  | 
|---|
| 190 |  | 
|---|
| 191 | CODE32 ends | 
|---|
| 192 |  | 
|---|
| 193 | end | 
|---|