ReactOS 0.4.15-dev-7918-g2a2556c
resource.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/resource.c
5 * PURPOSE: Resource (multiple-reader-single-writer lock) functions
6 * PROGRAMMER: Partially takem from Wine:
7 * Copyright 1996-1998 Marcus Meissner
8 * 1999 Alex Korobka
9 */
10
11/* INCLUDES *****************************************************************/
12
13#include <rtl.h>
14
15#define NDEBUG
16#include <debug.h>
17
18/* FUNCTIONS ***************************************************************/
19
20/*
21 * @implemented
22 */
23VOID
26{
28
30 if (!NT_SUCCESS(Status))
31 {
33 }
34
35 Status = NtCreateSemaphore(&Resource->SharedSemaphore,
37 NULL,
38 0,
39 65535);
40 if (!NT_SUCCESS(Status))
41 {
43 }
44 Resource->SharedWaiters = 0;
45
46 Status = NtCreateSemaphore(&Resource->ExclusiveSemaphore,
48 NULL,
49 0,
50 65535);
51 if (!NT_SUCCESS(Status))
52 {
54 }
55
56 Resource->ExclusiveWaiters = 0;
57 Resource->NumberActive = 0;
58 Resource->OwningThread = NULL;
59 Resource->TimeoutBoost = 0; /* no info on this one, default value is 0 */
60}
61
62
63/*
64 * @implemented
65 */
66VOID
69{
71 NtClose(Resource->ExclusiveSemaphore);
72 NtClose(Resource->SharedSemaphore);
73 Resource->OwningThread = NULL;
74 Resource->ExclusiveWaiters = 0;
75 Resource->SharedWaiters = 0;
76 Resource->NumberActive = 0;
77}
78
79
80/*
81 * @implemented
82 */
88{
90 BOOLEAN retVal = FALSE;
91
92start:
94 if (Resource->NumberActive == 0) /* lock is free */
95 {
96 Resource->NumberActive = -1;
97 retVal = TRUE;
98 }
99 else if (Resource->NumberActive < 0) /* exclusive lock in progress */
100 {
101 if (Resource->OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
102 {
103 retVal = TRUE;
104 Resource->NumberActive--;
105 goto done;
106 }
107wait:
108 if (Wait)
109 {
110 Resource->ExclusiveWaiters++;
111
113 Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore,
114 FALSE,
115 NULL);
116 if (!NT_SUCCESS(Status))
117 goto done;
118 goto start; /* restart the acquisition to avoid deadlocks */
119 }
120 }
121 else /* one or more shared locks are in progress */
122 {
123 if (Wait)
124 goto wait;
125 }
126 if (retVal)
127 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread;
128done:
130 return retVal;
131}
132
133
134/*
135 * @implemented
136 */
138NTAPI
142{
144 BOOLEAN retVal = FALSE;
145
146start:
148 if (Resource->NumberActive < 0)
149 {
150 if (Resource->OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
151 {
152 Resource->NumberActive--;
153 retVal = TRUE;
154 goto done;
155 }
156
157 if (Wait)
158 {
159 Resource->SharedWaiters++;
161 Status = NtWaitForSingleObject(Resource->SharedSemaphore,
162 FALSE,
163 NULL);
164 if (!NT_SUCCESS(Status))
165 goto done;
166 goto start;
167 }
168 }
169 else
170 {
171 if (Status != STATUS_WAIT_0) /* otherwise RtlReleaseResource() has already done it */
172 Resource->NumberActive++;
173 retVal = TRUE;
174 }
175done:
177 return retVal;
178}
179
180
181/*
182 * @implemented
183 */
184VOID
185NTAPI
187{
189
190 if (Resource->NumberActive == -1)
191 {
192 Resource->OwningThread = NULL;
193
194 if (Resource->SharedWaiters > 0)
195 {
196 ULONG n;
197 /* prevent new writers from joining until
198 * all queued readers have done their thing */
199 n = Resource->SharedWaiters;
200 Resource->NumberActive = Resource->SharedWaiters + 1;
201 Resource->SharedWaiters = 0;
202 NtReleaseSemaphore(Resource->SharedSemaphore,
203 n,
204 NULL);
205 }
206 else
207 {
208 Resource->NumberActive = 1;
209 }
210 }
211
213}
214
215
216/*
217 * @implemented
218 */
219VOID
220NTAPI
222{
224
226
227 if (Resource->NumberActive == 1)
228 {
229 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread;
230 Resource->NumberActive = -1;
231 }
232 else
233 {
234 Resource->ExclusiveWaiters++;
235
237 Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore,
238 FALSE,
239 NULL);
240 if (!NT_SUCCESS(Status))
241 return;
242
244 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread;
245 Resource->NumberActive = -1;
246 }
248}
249
250
251/*
252 * @implemented
253 */
254VOID
255NTAPI
257{
259
260 if (Resource->NumberActive > 0) /* have one or more readers */
261 {
262 Resource->NumberActive--;
263 if (Resource->NumberActive == 0)
264 {
265 if (Resource->ExclusiveWaiters > 0)
266 {
267wake_exclusive:
268 Resource->ExclusiveWaiters--;
269 NtReleaseSemaphore(Resource->ExclusiveSemaphore,
270 1,
271 NULL);
272 }
273 }
274 }
275 else if (Resource->NumberActive < 0) /* have a writer, possibly recursive */
276 {
277 Resource->NumberActive++;
278 if (Resource->NumberActive == 0)
279 {
280 Resource->OwningThread = 0;
281 if (Resource->ExclusiveWaiters > 0)
282 {
283 goto wake_exclusive;
284 }
285 else
286 {
287 if (Resource->SharedWaiters > 0)
288 {
289 ULONG n;
290 /* prevent new writers from joining until
291 * all queued readers have done their thing */
292 n = Resource->SharedWaiters;
293 Resource->NumberActive = Resource->SharedWaiters;
294 Resource->SharedWaiters = 0;
295 NtReleaseSemaphore(Resource->SharedSemaphore,
296 n,
297 NULL);
298 }
299 }
300 }
301 }
303}
304
305
306/*
307 * @implemented
308 */
309VOID
310NTAPI
312{
313 DbgPrint("RtlDumpResource(%p):\n\tactive count = %d\n\twaiting readers = %u\n\twaiting writers = %u\n",
314 Resource,
315 Resource->NumberActive,
316 Resource->SharedWaiters,
317 Resource->ExclusiveWaiters);
318
319 if (Resource->NumberActive != 0)
320 {
321 DbgPrint("\towner thread = %p\n",
322 Resource->OwningThread);
323 }
324}
325
326/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
GLuint start
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
#define DbgPrint
Definition: hal.h:12
#define NtCurrentTeb
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
#define STATUS_WAIT_0
Definition: ntstatus.h:237
VOID NTAPI RtlDeleteResource(PRTL_RESOURCE Resource)
Definition: resource.c:68
VOID NTAPI RtlReleaseResource(PRTL_RESOURCE Resource)
Definition: resource.c:256
VOID NTAPI RtlInitializeResource(PRTL_RESOURCE Resource)
Definition: resource.c:25
VOID NTAPI RtlDumpResource(PRTL_RESOURCE Resource)
Definition: resource.c:311
BOOLEAN NTAPI RtlAcquireResourceExclusive(PRTL_RESOURCE Resource, BOOLEAN Wait)
Definition: resource.c:85
BOOLEAN NTAPI RtlAcquireResourceShared(PRTL_RESOURCE Resource, BOOLEAN Wait)
Definition: resource.c:139
VOID NTAPI RtlConvertSharedToExclusive(PRTL_RESOURCE Resource)
Definition: resource.c:221
VOID NTAPI RtlConvertExclusiveToShared(PRTL_RESOURCE Resource)
Definition: resource.c:186
NTSTATUS NTAPI NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN LONG InitialCount, IN LONG MaximumCount)
Definition: sem.c:69
NTSTATUS NTAPI NtReleaseSemaphore(IN HANDLE SemaphoreHandle, IN LONG ReleaseCount, OUT PLONG PreviousCount OPTIONAL)
Definition: sem.c:295
HANDLE UniqueThread
Definition: compat.h:826
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define SEMAPHORE_ALL_ACCESS
Definition: winbase.h:160
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151