summaryrefslogtreecommitdiffstats
path: root/public/sdk/inc/mac386.inc
blob: 982df197c96910b3ad7676ca025635af6a2c5ef7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
;++
;
; Copyright (c) 1989  Microsoft Corporation
;
; Module Name:
;
;    mac386.inc - 386 machine specific assembler macros
;
; Abstract:
;
;   This module contains 386 machine specific (assembler) macros
;   applicable to code outside the kernel.  Note that
;   ACQUIRE_SPINLOCK_DIRECT assumes the PCR is handy, so it won't
;   work in user mode (with debugging turned on.)
;
; Author:
;
;   Bryan Willman (bryanwi)  1 Aug 90
;

if NT_INST
else

;++
;
;  ACQUIRE_SPINLOCK LockAddress, SpinLabel
;
;  Macro Description:
;
;     This macro acquires a kernel spin lock.
;
;     N.B. This macro assumes that the current IRQL is set properly.
;        It neither raises nor lowers IRQL.
;
;  Arguments:
;
;     (KSPIN_LOCK) LockAddress - address of SpinLock value
;     SpinLabel   - if acquire spinlock fail, the label to perform the
;                   spin checking.  It could be simply a "label" or
;                   "short label" which means the label is within 128
;                   bytes in distant.
;
;     NoChecking - Not blank, if no debugging code should be generated.
;--

ACQUIRE_SPINLOCK macro   LockAddress, SpinLabel, NoChecking

.errb <LockAddress>
.errb <SpinLabel>

ifndef NT_UP

;
; Attempt to assert the lock
;

        lock bts dword ptr [LockAddress], 0     ; test and set the spinlock
        jc      SpinLabel               ; spinlock owned, go SpinLabe

if    DBG
ifb   <NoChecking>
        push    edi                     ; save edi
        mov     edi,fs:PcPrcb
        mov     edi, [edi].PbCurrentThread
        or      edi, 1                  ; spinlock owned
        mov     [LockAddress], edi      ; remember current thread
        pop     edi                     ; restore edi
endif ; NoChecking
endif ; DBG
endif ; NT_UP

endm

;++
;
;  SPIN_ON_SPINLOCK   LockAddress, AcquireLabel
;
;  Macro Description:
;
;     This macro spins on a kernel spin lock.
;
;     N.B. This macro assumes that the current IRQL is set properly.
;        It neither raises nor lowers IRQL.
;
;  Arguments:
;
;     (KSPIN_LOCK) LockAddress - address of a SpinLock value
;
;     SpinLabel    - if the test on cleared spinlock sucess, the label
;                    to assert the spin lock.  It could be simply a
;                    "label" or  "short label" which means the label is
;                    within 128 bytes in distance.
;
;     NoChecking - Not blank, if no debugging code should be generated.
;--

SPIN_ON_SPINLOCK macro   LockAddress, AcquireLabel, NoChecking, PollDebugger, NoTimeout
local   a,flag                          ; define a local label

.errb <LockAddress>
.errb <AcquireLabel>

ifndef NT_UP
if    DBG

EXTRNP  Kii386SpinOnSpinLock,2
        flag = 0

ifb   <NoChecking>
        flag = flag + 1
endif

ifnb  <Polldebugger>
        flag = flag + 2
endif

ifb   <NoTimeout>
        flag = flag + 4
endif
        stdCall Kii386SpinOnSpinLock,<LockAddress,flag>
        jmp     AcquireLabel

else    ; DBG

;
; Non-Debug version
;

a:      test    dword ptr [LockAddress], 1 ; Was spinlock cleared?
        jz      AcquireLabel            ; Yes, go get it
        jmp     short a

endif   ; DBG
endif   ; NT_UP

endm


;++
;
;  TEST_SPINLOCK   LockAddress, BusyLabel
;
;  Macro Description:
;
;     This macro tests a kernel spin lock to see if it's busy.
;     If it's not busy, ACQUIRE_SPINLOCK still needs to be called
;     to obtain the spinlock in a locked manner.
;
;  Arguments:
;
;     (KSPIN_LOCK) LockAddress - address of a SpinLock value


TEST_SPINLOCK macro   LockAddress, BusyLabel
        test    dword ptr [LockAddress], 1 ; spinlock clear?
        jnz     BusyLabel                  ; No, then busy
endm




;++
;
;  RELEASE_SPINLOCK  LockAddress
;
;  Macro Description:
;
;     This macro releases a kernel spin lock.
;
;     N.B. This macro assumes that the current IRQL is set properly.
;        It neither raises nor lowers IRQL.
;
;  Arguments:
;
;     (KSPIN_LOCK) LockAddress - Supplies an address to a spin lock value
;     NoChecking - Not blank, if no debugging code should be generated.
;--

RELEASE_SPINLOCK macro   LockAddress, NoChecking
local a
.errb <LockAddress>
ifndef NT_UP
if    DBG
ifb   <NoChecking>
EXTRNP  _KeBugCheck,1

        push    edi                     ; save edi
        mov     edi,fs:PcPrcb
        mov     edi,[edi].PbCurrentThread
        or      edi, 1                  ; assume current thread owns the lock
        cmp     edi, [LockAddress]      ; Does current thread own the lock?
        pop     edi                     ; restore edi
        jz      short a                 ; if z, yes, goto a and release lock
        stdCall _KeBugCheck,<LockAddress>    ; Never return ...
a:
endif
        mov     dword ptr [LockAddress], 0
else
        mov     byte ptr [LockAddress], 0

endif   ; DBG
endif   ; NT_UP
endm


endif
if NT_INST

;
; These are the instrumentation version of the above functions.
; internal use only
;

ACQUIRE_SPINLOCK macro   LockAddress, SpinLabel, NoChecking
EXTRNP  KiInst_AcquireSpinLock,0
ifidni  <&LockAddress>, <eax>
        stdCall KiInst_AcquireSpinLock
else
        push    eax
        mov     eax, LockAddress
        stdCall KiInst_AcquireSpinLock
        pop     eax
endif
        jc      SpinLabel
endm

SPIN_ON_SPINLOCK macro   LockAddress, AcquireLabel, NoChecking, PollDebugger
EXTRNP  KiInst_SpinOnSpinLock,0
ifidni  <&LockAddress>, <eax>
        stdCall KiInst_SpinOnSpinLock
else
        push    eax
        mov     eax, LockAddress
        stdCall KiInst_SpinOnSpinLock
        pop     eax
endif
        jmp     AcquireLabel
endm

TEST_SPINLOCK macro   LockAddress, BusyLabel
EXTRNP  KiInst_TestSpinLock,0
ifidni  <&LockAddress>, <eax>
        stdCall KiInst_TestSpinLock
else
        push    eax
        mov     eax, LockAddress
        stdCall KiInst_TestSpinLock
        pop     eax
endif
        jnc     AcquireLabel
endm

RELEASE_SPINLOCK macro   LockAddress, NoChecking
EXTRNP  KiInst_ReleaseSpinLock,0
ifidni  <&LockAddress>, <eax>
        stdCall KiInst_ReleaseSpinLock
else
        push    eax
        mov     eax, LockAddress
        stdCall KiInst_ReleaseSpinLock
        pop     eax
endif
endm

endif