ReactOS  0.4.13-dev-687-g023794c
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  */
23 VOID
24 NTAPI
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  */
66 VOID
67 NTAPI
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  */
83 BOOLEAN
84 NTAPI
87  BOOLEAN Wait)
88 {
90  BOOLEAN retVal = FALSE;
91 
92 start:
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  }
107 wait:
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;
128 done:
130  return retVal;
131 }
132 
133 
134 /*
135  * @implemented
136  */
137 BOOLEAN
138 NTAPI
141  BOOLEAN Wait)
142 {
144  BOOLEAN retVal = FALSE;
145 
146 start:
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  }
175 done:
177  return retVal;
178 }
179 
180 
181 /*
182  * @implemented
183  */
184 VOID
185 NTAPI
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  */
219 VOID
220 NTAPI
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  */
254 VOID
255 NTAPI
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  {
267 wake_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  */
309 VOID
310 NTAPI
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 */
VOID NTAPI RtlDeleteResource(PRTL_RESOURCE Resource)
Definition: resource.c:68
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
VOID NTAPI RtlInitializeResource(PRTL_RESOURCE Resource)
Definition: resource.c:25
#define TRUE
Definition: types.h:120
#define DbgPrint
Definition: loader.c:25
LONG NTSTATUS
Definition: precomp.h:26
GLdouble n
Definition: glext.h:7729
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define STATUS_WAIT_0
Definition: ntstatus.h:223
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:848
VOID NTAPI RtlDumpResource(PRTL_RESOURCE Resource)
Definition: resource.c:311
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI RtlConvertSharedToExclusive(PRTL_RESOURCE Resource)
Definition: resource.c:221
BOOLEAN NTAPI RtlAcquireResourceShared(PRTL_RESOURCE Resource, BOOLEAN Wait)
Definition: resource.c:139
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
BOOLEAN NTAPI RtlAcquireResourceExclusive(PRTL_RESOURCE Resource, BOOLEAN Wait)
Definition: resource.c:85
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI NtReleaseSemaphore(IN HANDLE SemaphoreHandle, IN LONG ReleaseCount, OUT PLONG PreviousCount OPTIONAL)
Definition: sem.c:294
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
HANDLE UniqueThread
Definition: compat.h:475
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
Status
Definition: gdiplustypes.h:24
VOID NTAPI RtlReleaseResource(PRTL_RESOURCE Resource)
Definition: resource.c:256
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
GLuint start
Definition: gl.h:1545
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define SEMAPHORE_ALL_ACCESS
Definition: winbase.h:160
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
VOID NTAPI RtlConvertExclusiveToShared(PRTL_RESOURCE Resource)
Definition: resource.c:186
IN BOOLEAN Wait
Definition: fatprocs.h:1529
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)