00001 ;++ 00002 ; 00003 ; Copyright (c) 1989 Microsoft Corporation 00004 ; 00005 ; Module Name: 00006 ; 00007 ; mac386.inc - 386 machine specific assembler macros 00008 ; 00009 ; Abstract: 00010 ; 00011 ; This module contains 386 machine specific (assembler) macros 00012 ; applicable to code outside the kernel. Note that 00013 ; ACQUIRE_SPINLOCK_DIRECT assumes the PCR is handy, so it won't 00014 ; work in user mode (with debugging turned on.) 00015 ; 00016 ; Author: 00017 ; 00018 ; Bryan Willman (bryanwi) 1 Aug 90 00019 ; 00020 00021 ;++ 00022 ; 00023 ; YIELD 00024 ; 00025 ; Macro Description: 00026 ; 00027 ; This macro implements the yield instruction 00028 ;-- 00029 00030 YIELD macro 00031 ifndef NT_UP 00032 db 0f3h 00033 db 090h 00034 endif 00035 endm 00036 00037 00038 if NT_INST 00039 else 00040 00041 ;++ 00042 ; 00043 ; ACQUIRE_SPINLOCK LockAddress, SpinLabel 00044 ; 00045 ; Macro Description: 00046 ; 00047 ; This macro acquires a kernel spin lock. 00048 ; 00049 ; N.B. This macro assumes that the current IRQL is set properly. 00050 ; It neither raises nor lowers IRQL. 00051 ; 00052 ; Arguments: 00053 ; 00054 ; (KSPIN_LOCK) LockAddress - address of SpinLock value 00055 ; SpinLabel - if acquire spinlock fail, the label to perform the 00056 ; spin checking. It could be simply a "label" or 00057 ; "short label" which means the label is within 128 00058 ; bytes in distant. 00059 ; 00060 ; NoChecking - Not blank, if no debugging code should be generated. 00061 ;-- 00062 00063 ACQUIRE_SPINLOCK macro LockAddress, SpinLabel, NoChecking 00064 00065 .errb <LockAddress> 00066 .errb <SpinLabel> 00067 00068 ifndef NT_UP 00069 00070 ; 00071 ; Attempt to assert the lock 00072 ; 00073 00074 lock bts dword ptr [LockAddress], 0 ; test and set the spinlock 00075 jc SpinLabel ; spinlock owned, go SpinLabe 00076 00077 if DBG 00078 ifb <NoChecking> 00079 push edi ; save edi 00080 mov edi,fs:PcPrcb 00081 mov edi, [edi].PbCurrentThread 00082 or edi, 1 ; spinlock owned 00083 mov [LockAddress], edi ; remember current thread 00084 pop edi ; restore edi 00085 endif ; NoChecking 00086 endif ; DBG 00087 endif ; NT_UP 00088 00089 endm 00090 00091 ;++ 00092 ; 00093 ; SPIN_ON_SPINLOCK LockAddress, AcquireLabel 00094 ; 00095 ; Macro Description: 00096 ; 00097 ; This macro spins on a kernel spin lock. 00098 ; 00099 ; N.B. This macro assumes that the current IRQL is set properly. 00100 ; It neither raises nor lowers IRQL. 00101 ; 00102 ; Arguments: 00103 ; 00104 ; (KSPIN_LOCK) LockAddress - address of a SpinLock value 00105 ; 00106 ; SpinLabel - if the test on cleared spinlock sucess, the label 00107 ; to assert the spin lock. It could be simply a 00108 ; "label" or "short label" which means the label is 00109 ; within 128 bytes in distance. 00110 ; 00111 ; NoChecking - Not blank, if no debugging code should be generated. 00112 ;-- 00113 00114 SPIN_ON_SPINLOCK macro LockAddress, AcquireLabel, NoChecking, PollDebugger, NoTimeout 00115 local a,flag ; define a local label 00116 00117 .errb <LockAddress> 00118 .errb <AcquireLabel> 00119 00120 ifndef NT_UP 00121 if DBG 00122 00123 EXTRNP Kii386SpinOnSpinLock,2 00124 flag = 0 00125 00126 ifb <NoChecking> 00127 flag = flag + 1 00128 endif 00129 00130 ifnb <Polldebugger> 00131 flag = flag + 2 00132 endif 00133 00134 ifb <NoTimeout> 00135 flag = flag + 4 00136 endif 00137 stdCall Kii386SpinOnSpinLock,<LockAddress,flag> 00138 jmp AcquireLabel 00139 00140 else ; DBG 00141 00142 ; 00143 ; Non-Debug version 00144 ; 00145 00146 a: test dword ptr [LockAddress], 1 ; Was spinlock cleared? 00147 jz AcquireLabel ; Yes, go get it 00148 YIELD 00149 jmp short a 00150 00151 endif ; DBG 00152 endif ; NT_UP 00153 00154 endm 00155 00156 00157 ;++ 00158 ; 00159 ; TEST_SPINLOCK LockAddress, BusyLabel 00160 ; 00161 ; Macro Description: 00162 ; 00163 ; This macro tests a kernel spin lock to see if it's busy. 00164 ; If it's not busy, ACQUIRE_SPINLOCK still needs to be called 00165 ; to obtain the spinlock in a locked manner. 00166 ; 00167 ; Arguments: 00168 ; 00169 ; (KSPIN_LOCK) LockAddress - address of a SpinLock value 00170 00171 00172 TEST_SPINLOCK macro LockAddress, BusyLabel 00173 test dword ptr [LockAddress], 1 ; spinlock clear? 00174 jnz BusyLabel ; No, then busy 00175 endm 00176 00177 00178 00179 00180 ;++ 00181 ; 00182 ; RELEASE_SPINLOCK LockAddress 00183 ; 00184 ; Macro Description: 00185 ; 00186 ; This macro releases a kernel spin lock. 00187 ; 00188 ; N.B. This macro assumes that the current IRQL is set properly. 00189 ; It neither raises nor lowers IRQL. 00190 ; 00191 ; Arguments: 00192 ; 00193 ; (KSPIN_LOCK) LockAddress - Supplies an address to a spin lock value 00194 ; NoChecking - Not blank, if no debugging code should be generated. 00195 ;-- 00196 00197 RELEASE_SPINLOCK macro LockAddress, NoChecking 00198 local a 00199 .errb <LockAddress> 00200 ifndef NT_UP 00201 if DBG 00202 ifb <NoChecking> 00203 EXTRNP _KeBugCheckEx,5 00204 00205 push edi ; save edi 00206 mov edi,fs:PcPrcb 00207 mov edi,[edi].PbCurrentThread 00208 or edi, 1 ; assume current thread owns the lock 00209 cmp edi, [LockAddress] ; Does current thread own the lock? 00210 pop edi ; restore edi 00211 jz short a ; if z, yes, goto a and release lock 00212 stdCall _KeBugCheckEx,<SPIN_LOCK_NOT_OWNED,LockAddress,0,0,0> 00213 a: 00214 endif 00215 mov dword ptr [LockAddress], 0 00216 else 00217 mov byte ptr [LockAddress], 0 00218 00219 endif ; DBG 00220 endif ; NT_UP 00221 endm 00222 00223 00224 endif 00225 if NT_INST 00226 00227 ; 00228 ; These are the instrumentation version of the above functions. 00229 ; internal use only 00230 ; 00231 00232 ACQUIRE_SPINLOCK macro LockAddress, SpinLabel, NoChecking 00233 EXTRNP KiInst_AcquireSpinLock,0 00234 ifidni <&LockAddress>, <eax> 00235 stdCall KiInst_AcquireSpinLock 00236 else 00237 push eax 00238 mov eax, LockAddress 00239 stdCall KiInst_AcquireSpinLock 00240 pop eax 00241 endif 00242 jc SpinLabel 00243 endm 00244 00245 SPIN_ON_SPINLOCK macro LockAddress, AcquireLabel, NoChecking, PollDebugger 00246 EXTRNP KiInst_SpinOnSpinLock,0 00247 ifidni <&LockAddress>, <eax> 00248 stdCall KiInst_SpinOnSpinLock 00249 else 00250 push eax 00251 mov eax, LockAddress 00252 stdCall KiInst_SpinOnSpinLock 00253 pop eax 00254 endif 00255 jmp AcquireLabel 00256 endm 00257 00258 TEST_SPINLOCK macro LockAddress, BusyLabel 00259 EXTRNP KiInst_TestSpinLock,0 00260 ifidni <&LockAddress>, <eax> 00261 stdCall KiInst_TestSpinLock 00262 else 00263 push eax 00264 mov eax, LockAddress 00265 stdCall KiInst_TestSpinLock 00266 pop eax 00267 endif 00268 jnc AcquireLabel 00269 endm 00270 00271 RELEASE_SPINLOCK macro LockAddress, NoChecking 00272 EXTRNP KiInst_ReleaseSpinLock,0 00273 ifidni <&LockAddress>, <eax> 00274 stdCall KiInst_ReleaseSpinLock 00275 else 00276 push eax 00277 mov eax, LockAddress 00278 stdCall KiInst_ReleaseSpinLock 00279 pop eax 00280 endif 00281 endm 00282 00283 endif 00284