:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / ntdll / rtl / critical.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/ntdll/rtl/critical.c
6  * PURPOSE:         Critical sections
7  * UPDATE HISTORY:
8  *                  Created 30/09/98
9  */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <ntdll/rtl.h>
15 #include <ntos/synch.h>
16
17 #include <ntdll/ntdll.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 VOID STDCALL
22 RtlDeleteCriticalSection(PCRITICAL_SECTION CriticalSection)
23 {
24    NtClose(CriticalSection->LockSemaphore);
25    CriticalSection->Reserved = -1;
26 }
27
28 VOID STDCALL
29 RtlEnterCriticalSection(PCRITICAL_SECTION CriticalSection)
30 {
31    HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;
32    ULONG ret;
33  
34    if (InterlockedIncrement(&CriticalSection->LockCount))
35      {
36         NTSTATUS Status;
37         
38         if (CriticalSection->OwningThread == Thread)
39           {
40              CriticalSection->RecursionCount++;
41              return;
42           }
43         
44 //      DbgPrint("Entering wait for critical section\n");
45         Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, 
46                                        0, FALSE);
47         if (!NT_SUCCESS(Status))
48           {
49              DbgPrint("RtlEnterCriticalSection: Failed to wait (Status %x)\n", 
50                       Status);
51           }
52 //      DbgPrint("Left wait for critical section\n");
53      }
54    CriticalSection->OwningThread = Thread;
55    CriticalSection->RecursionCount = 1;
56    
57 #if 0
58    if ((ret = InterlockedIncrement(&(CriticalSection->LockCount) )) != 1)
59      {
60         if (CriticalSection->OwningThread != Thread)
61           {
62              NtWaitForSingleObject(CriticalSection->LockSemaphore, 
63                                    0, 
64                                    FALSE);
65              CriticalSection->OwningThread = Thread;
66           }
67      }
68    else
69      {
70         CriticalSection->OwningThread = Thread;
71      }
72    
73    CriticalSection->RecursionCount++;
74 #endif
75 }
76
77 NTSTATUS STDCALL
78 RtlInitializeCriticalSection(PCRITICAL_SECTION CriticalSection)
79 {
80    NTSTATUS Status;
81    
82    CriticalSection->LockCount = -1;
83    CriticalSection->RecursionCount = 0;
84    CriticalSection->OwningThread = (HANDLE)0;
85    CriticalSection->Reserved = 0;
86    
87    Status = NtCreateSemaphore(&CriticalSection->LockSemaphore,
88                               SEMAPHORE_ALL_ACCESS,
89                               NULL,
90                               0,
91                               1);
92    return Status;
93 }
94
95 VOID STDCALL
96 RtlLeaveCriticalSection(PCRITICAL_SECTION CriticalSection)
97 {
98    HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;
99    
100    if (CriticalSection->OwningThread != Thread)
101      {
102         DbgPrint("Freeing critical section not owned\n");
103         return;
104      }
105    
106    CriticalSection->RecursionCount--;
107    if (CriticalSection->RecursionCount > 0)
108      {
109         InterlockedDecrement(&CriticalSection->LockCount);
110         return;
111      }
112    CriticalSection->OwningThread = 0;
113    if (InterlockedIncrement(&CriticalSection->LockCount) >= 0)
114      {
115         NTSTATUS Status;
116         
117         Status = NtReleaseSemaphore(CriticalSection->LockSemaphore, 1, NULL);
118         if (!NT_SUCCESS(Status))
119           {
120              DbgPrint("Failed to release semaphore (Status %x)\n",
121                       Status);
122           }
123      }
124    
125 #if 0
126    CriticalSection->RecursionCount--;
127    if (CriticalSection->RecursionCount == 0)
128      {
129         CriticalSection->OwningThread = (HANDLE)-1;
130         // if LockCount > 0 and RecursionCount == 0 there
131         // is a waiting thread 
132         // ReleaseSemaphore will fire up a waiting thread
133         if (InterlockedDecrement(&CriticalSection->LockCount) > 0)
134           {
135              NtReleaseSemaphore(CriticalSection->LockSemaphore,1,NULL);
136           }
137      }
138    else
139      {
140         InterlockedDecrement(&CriticalSection->LockCount);
141      }
142 #endif
143 }
144
145 BOOLEAN STDCALL
146 RtlTryEnterCriticalSection(PCRITICAL_SECTION CriticalSection)
147 {
148    if (InterlockedCompareExchange((PVOID*)&CriticalSection->LockCount, 
149                                   (PVOID)1, (PVOID)0 ) == 0)
150      {
151         CriticalSection->OwningThread = 
152           (HANDLE) NtCurrentTeb()->Cid.UniqueThread;
153         CriticalSection->RecursionCount++;
154         return TRUE;
155      }
156    if (CriticalSection->OwningThread == 
157        (HANDLE)NtCurrentTeb()->Cid.UniqueThread)
158      {
159         CriticalSection->RecursionCount++;
160         return TRUE;
161      }
162    return FALSE;
163 }
164
165
166 /* EOF */
167
168
169
170
171