summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/i386/critsect.asm
blob: 4b1f87cb4151b5fd2b6885b4b3b04d9d8dba1390 (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
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
        title   "Critical Section Support"
;++
;
;  Copyright (c) 1991  Microsoft Corporation
;
;  Module Name:
;
;     critsect.asm
;
;  Abstract:
;
;     This module implements functions to support user mode critical sections.
;
;  Author:
;
;     Bryan M. Willman (bryanwi) 2-Oct-91
;
;  Environment:
;
;     Any mode.
;
;  Revision History:
;
;
;
;   WARNING!!!!!!!!!! This code is duplicated in
;   windows\base\client\i386\critsect.asm
;
;   Some day we should put it in a .inc file that both include.
;
;--

.486p
        .xlist
include ks386.inc
include callconv.inc                    ; calling convention macros
        .list

_DATA   SEGMENT DWORD PUBLIC 'DATA'
    public _LdrpLockPrefixTable
_LdrpLockPrefixTable    label dword
        dd offset FLAT:Lock1
        dd offset FLAT:Lock2
        dd offset FLAT:Lock3
        dd offset FLAT:Lock4
        dd offset FLAT:Lock5
        dd 0
_DATA   ENDS

_TEXT   SEGMENT PARA PUBLIC 'CODE'
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

        EXTRNP  _RtlpWaitForCriticalSection,1
        EXTRNP  _RtlpUnWaitCriticalSection,1
if DEVL
        EXTRNP  _RtlpNotOwnerCriticalSection,1
endif

CriticalSection equ     [esp + 4]

        page , 132
        subttl  "RtlEnterCriticalSection"

;++
;
; NTSTATUS
; RtlEnterCriticalSection(
;    IN PRTL_CRITICAL_SECTION CriticalSection
;    )
;
; Routine Description:
;
;    This function enters a critical section.
;
; Arguments:
;
;    CriticalSection - supplies a pointer to a critical section.
;
; Return Value:
;
;   STATUS_SUCCESS or raises an exception if an error occured.
;
;--

        align   16
cPublicProc _RtlEnterCriticalSection,1
cPublicFpo 1,0

        mov     ecx,fs:PcTeb                ; (ecx) == NtCurrentTeb()
        mov     edx,CriticalSection         ; interlocked inc of
        mov     eax,TbClientId+4[ecx]       ; (eax) == NtCurrentTeb()->ClientId.UniqueThread

if DBG
        cmp     dword ptr TbSpare1[ecx],0
        jz      @f
        int     3
@@:
endif ; DBG
Lock1:
   lock inc     dword ptr CsLockCount[edx]  ; ... CriticalSection->LockCount
        jnz     @F

setowner:
        mov     CsOwningThread[edx],eax
        mov     dword ptr CsRecursionCount[edx],1

if DBG
        inc     dword ptr TbCountOfOwnedCriticalSections[ecx]
        push    edi
        mov     edi,CsDebugInfo[edx]
        inc     dword ptr CsEntryCount[edi]
        pop     edi
endif ; DBG

        xor     eax,eax
        stdRET  _RtlEnterCriticalSection

        align   16
@@:
        cmp     CsOwningThread[edx],eax
        jne     @F
        inc     dword ptr CsRecursionCount[edx]
if DBG
        mov     eax,CsDebugInfo[edx]
        inc     dword ptr CsEntryCount[eax]
endif ; DBG
        xor     eax,eax
        stdRET  _RtlEnterCriticalSection

@@:
        stdCall _RtlpWaitForCriticalSection, <edx>
        mov     ecx,fs:PcTeb                ; (ecx) == NtCurrentTeb()
        mov     eax,TbClientId+4[ecx]       ; (eax) == NtCurrentTeb()->ClientId.UniqueThread
        mov     edx,CriticalSection
        jmp     setowner

stdENDP _RtlEnterCriticalSection

        page , 132
        subttl  "RtlLeaveCriticalSection"
;++
;
; NTSTATUS
; RtlLeaveCriticalSection(
;    IN PRTL_CRITICAL_SECTION CriticalSection
;    )
;
; Routine Description:
;
;    This function leaves a critical section.
;
; Arguments:
;
;    CriticalSection - supplies a pointer to a critical section.
;
; Return Value:
;
;   STATUS_SUCCESS or raises an exception if an error occured.
;
;--

        align   16
cPublicProc _RtlLeaveCriticalSection,1
cPublicFpo 1,0

        mov     edx,CriticalSection
if DBG
        mov     ecx,fs:PcTeb                ; (ecx) == NtCurrentTeb()
        mov     eax,TbClientId+4[ecx]       ; (eax) == NtCurrentTeb()->ClientId.UniqueThread
        cmp     eax,CsOwningThread[edx]
        je      @F
        stdCall _RtlpNotOwnerCriticalSection, <edx>
        mov     eax,STATUS_INVALID_OWNER
        stdRET  _RtlLeaveCriticalSection
@@:
endif ; DBG
        xor     eax,eax                     ; Assume STATUS_SUCCESS
        dec     dword ptr CsRecursionCount[edx]
        jnz     leave_recurs                ; skip if only leaving recursion

        mov     CsOwningThread[edx],eax     ; clear owning thread id

if DBG
        mov     ecx,fs:PcTeb                ; (ecx) == NtCurrentTeb()
        dec     dword ptr TbCountOfOwnedCriticalSections[ecx]
endif ; DBG

Lock2:
   lock dec     dword ptr CsLockCount[edx]  ; interlocked dec of
                                            ; ... CriticalSection->LockCount
        jge     @F
        stdRET  _RtlLeaveCriticalSection

@@:
        stdCall _RtlpUnWaitCriticalSection, <edx>
        xor     eax,eax                     ; return STATUS_SUCCESS
        stdRET  _RtlLeaveCriticalSection

        align   16
leave_recurs:
Lock3:
   lock dec     dword ptr CsLockCount[edx]  ; interlocked dec of
                                            ; ... CriticalSection->LockCount
        stdRET  _RtlLeaveCriticalSection

_RtlLeaveCriticalSection    endp

        page    ,132
        subttl  "RtlTryEnterCriticalSection"
;++
;
; BOOL
; RtlTryEnterCriticalSection(
;    IN PRTL_CRITICAL_SECTION CriticalSection
;    )
;
; Routine Description:
;
;    This function attempts to enter a critical section without blocking.
;
; Arguments:
;
;    CriticalSection (a0) - Supplies a pointer to a critical section.
;
; Return Value:
;
;    If the critical section was successfully entered, then a value of TRUE
;    is returned as the function value. Otherwise, a value of FALSE is returned.
;
;--

CriticalSection equ     [esp + 4]

cPublicProc _RtlTryEnterCriticalSection,1
cPublicFpo 1,0

        mov     ecx,CriticalSection         ; interlocked inc of
        mov     eax, -1                     ; set value to compare against
        mov     edx, 0                      ; set value to set
Lock4:
   lock cmpxchg dword ptr CsLockCount[ecx],edx  ; Attempt to acquire critsect
        jnz     short tec10                 ; if nz, critsect already owned

        mov     eax,fs:TbClientId+4         ; (eax) == NtCurrentTeb()->ClientId.UniqueThread
        mov     CsOwningThread[ecx],eax
        mov     dword ptr CsRecursionCount[ecx],1

if DBG
        mov     eax,fs:PcTeb                ; (ecx) == NtCurrentTeb()
        inc     dword ptr TbCountOfOwnedCriticalSections[eax]
endif ; DBG

        mov     eax, 1                      ; set successful status

        stdRET  _RtlTryEnterCriticalSection

tec10:
;
; The critical section is already owned. If it is owned by another thread,
; return FALSE immediately. If it is owned by this thread, we must increment
; the lock count here.
;
        mov     eax, fs:TbClientId+4        ; (eax) == NtCurrentTeb()->ClientId.UniqueThread
        cmp     CsOwningThread[ecx], eax
        jz      tec20                       ; if eq, this thread is already the owner
        xor     eax, eax                    ; set failure status
        stdRET  _RtlTryEnterCriticalSection

tec20:
;
; This thread is already the owner of the critical section. Perform an atomic
; increment of the LockCount and a normal increment of the RecursionCount and
; return success.
;
Lock5:
   lock inc     dword ptr CsLockCount[ecx]
        inc     dword ptr CsRecursionCount[ecx]
        mov     eax, 1
        stdRET  _RtlTryEnterCriticalSection

stdENDP _RtlTryEnterCriticalSection


_TEXT   ends
        end