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
|