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