update for HEAD-2003091401
[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 /*
22  * @implemented
23  */
24 VOID STDCALL
25 RtlDeleteCriticalSection(PCRITICAL_SECTION CriticalSection)
26 {
27    NtClose(CriticalSection->LockSemaphore);
28    CriticalSection->Reserved = -1;
29 }
30
31 /*
32  * @implemented
33  */
34 VOID STDCALL
35 RtlEnterCriticalSection(PCRITICAL_SECTION CriticalSection)
36 {
37    HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;
38  
39    if (InterlockedIncrement(&CriticalSection->LockCount))
40      {
41         NTSTATUS Status;
42         
43         if (CriticalSection->OwningThread == Thread)
44           {
45              CriticalSection->RecursionCount++;
46              return;
47           }
48         
49 //      DbgPrint("Entering wait for critical section\n");
50         Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, 
51                                        0, FALSE);
52         if (!NT_SUCCESS(Status))
53           {
54              DbgPrint("RtlEnterCriticalSection: Failed to wait (Status %x)\n", 
55                       Status);
56           }
57 //      DbgPrint("Left wait for critical section\n");
58      }
59    CriticalSection->OwningThread = Thread;
60    CriticalSection->RecursionCount = 1;
61    
62 #if 0
63    if ((ret = InterlockedIncrement(&(CriticalSection->LockCount) )) != 1)
64      {
65         if (CriticalSection->OwningThread != Thread)
66           {
67              NtWaitForSingleObject(CriticalSection->LockSemaphore, 
68                                    0, 
69                                    FALSE);
70              CriticalSection->OwningThread = Thread;
71           }
72      }
73    else
74      {
75         CriticalSection->OwningThread = Thread;
76      }
77    
78    CriticalSection->RecursionCount++;
79 #endif
80 }
81
82 /*
83  * @implemented
84  */
85 NTSTATUS STDCALL
86 RtlInitializeCriticalSection(PCRITICAL_SECTION CriticalSection)
87 {
88    NTSTATUS Status;
89    
90    CriticalSection->LockCount = -1;
91    CriticalSection->RecursionCount = 0;
92    CriticalSection->OwningThread = (HANDLE)0;
93    CriticalSection->Reserved = 0;
94    
95    Status = NtCreateSemaphore(&CriticalSection->LockSemaphore,
96                               SEMAPHORE_ALL_ACCESS,
97                               NULL,
98                               0,
99                               1);
100    return Status;
101 }
102
103 /*
104  * @implemented
105  */
106 VOID STDCALL
107 RtlLeaveCriticalSection(PCRITICAL_SECTION CriticalSection)
108 {
109    HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;
110    
111    if (CriticalSection->OwningThread != Thread)
112      {
113         DbgPrint("Freeing critical section not owned\n");
114         return;
115      }
116    
117    CriticalSection->RecursionCount--;
118    if (CriticalSection->RecursionCount > 0)
119      {
120         InterlockedDecrement(&CriticalSection->LockCount);
121         return;
122      }
123    CriticalSection->OwningThread = 0;
124    if (InterlockedDecrement(&CriticalSection->LockCount) >= 0)
125      {
126         NTSTATUS Status;
127         
128         Status = NtReleaseSemaphore(CriticalSection->LockSemaphore, 1, NULL);
129         if (!NT_SUCCESS(Status))
130           {
131              DbgPrint("Failed to release semaphore (Status %x)\n",
132                       Status);
133           }
134      }
135    
136 #if 0
137    CriticalSection->RecursionCount--;
138    if (CriticalSection->RecursionCount == 0)
139      {
140         CriticalSection->OwningThread = (HANDLE)-1;
141         // if LockCount > 0 and RecursionCount == 0 there
142         // is a waiting thread 
143         // ReleaseSemaphore will fire up a waiting thread
144         if (InterlockedDecrement(&CriticalSection->LockCount) > 0)
145           {
146              NtReleaseSemaphore(CriticalSection->LockSemaphore,1,NULL);
147           }
148      }
149    else
150      {
151         InterlockedDecrement(&CriticalSection->LockCount);
152      }
153 #endif
154 }
155
156 /*
157  * @implemented
158  */
159 BOOLEAN STDCALL
160 RtlTryEnterCriticalSection(PCRITICAL_SECTION CriticalSection)
161 {
162    if (InterlockedCompareExchange((PVOID*)&CriticalSection->LockCount, 
163                                   (PVOID)0, (PVOID)-1 ) == (PVOID)-1)
164      {
165         CriticalSection->OwningThread = 
166           (HANDLE) NtCurrentTeb()->Cid.UniqueThread;
167         CriticalSection->RecursionCount = 1;
168         return TRUE;
169      }
170    if (CriticalSection->OwningThread == 
171        (HANDLE)NtCurrentTeb()->Cid.UniqueThread)
172      {
173         InterlockedIncrement(&CriticalSection->LockCount);
174         CriticalSection->RecursionCount++;
175         return TRUE;
176      }
177    return FALSE;
178 }
179
180 /* EOF */