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