- new interface declaration for IShellfolder2
[wine] / scheduler / critsection.c
1 /*
2  * Win32 critical sections
3  *
4  * Copyright 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include "debugtools.h"
12 #include "winerror.h"
13 #include "winbase.h"
14 #include "heap.h"
15 #include "debugtools.h"
16 #include "thread.h"
17
18 DEFAULT_DEBUG_CHANNEL(win32)
19 DECLARE_DEBUG_CHANNEL(relay)
20
21
22 /***********************************************************************
23  *           InitializeCriticalSection   (KERNEL32.472) (NTDLL.406)
24  */
25 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
26 {
27     crit->LockCount      = -1;
28     crit->RecursionCount = 0;
29     crit->OwningThread   = 0;
30     crit->LockSemaphore  = CreateSemaphoreA( NULL, 0, 1, NULL );
31     crit->Reserved       = GetCurrentProcessId();
32 }
33
34
35 /***********************************************************************
36  *           DeleteCriticalSection   (KERNEL32.185) (NTDLL.327)
37  */
38 void WINAPI DeleteCriticalSection( CRITICAL_SECTION *crit )
39 {
40     if (crit->LockSemaphore)
41     {
42         if (crit->RecursionCount)  /* Should not happen */
43             ERR_(win32)("Deleting owned critical section (%p)\n", crit );
44
45         crit->LockCount      = -1;
46         crit->RecursionCount = 0;
47         crit->OwningThread   = 0;
48         CloseHandle( crit->LockSemaphore );
49         crit->LockSemaphore  = 0;
50         crit->Reserved       = (DWORD)-1;
51     }
52 }
53
54
55 /***********************************************************************
56  *           EnterCriticalSection   (KERNEL32.195) (NTDLL.344)
57  */
58 void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit )
59 {
60     DWORD res;
61
62     if (!crit->LockSemaphore)
63     {
64         FIXME_(win32)("entering uninitialized section(%p)?\n",crit);
65         InitializeCriticalSection(crit);
66     }
67     if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
68     {
69         FIXME_(win32)("Crst %p belongs to process %ld, current is %ld!\n", 
70                       crit, crit->Reserved, GetCurrentProcessId() );
71         return;
72     }
73     if (InterlockedIncrement( &crit->LockCount ))
74     {
75         if (crit->OwningThread == GetCurrentThreadId())
76         {
77             crit->RecursionCount++;
78             return;
79         }
80
81         /* Now wait for it */
82         res = WaitForSingleObject( crit->LockSemaphore, 5000L );
83         if ( res == WAIT_TIMEOUT )
84         {
85             ERR_(win32)("Critical section %p wait timed out, retrying (60 sec)\n", crit );
86             res = WaitForSingleObject( crit->LockSemaphore, 60000L );
87         }
88         if ( res == WAIT_TIMEOUT && TRACE_ON(relay) )
89         {
90             ERR_(win32)("Critical section %p wait timed out, retrying (5 min)\n", crit );
91             res = WaitForSingleObject( crit->LockSemaphore, 300000L );
92         }
93         if (res != STATUS_WAIT_0)
94         {
95             ERR_(win32)("Critical section %p wait failed err=%lx\n", crit, res );
96             /* FIXME: should raise an exception */
97         }
98     }
99     crit->OwningThread   = GetCurrentThreadId();
100     crit->RecursionCount = 1;
101 }
102
103
104 /***********************************************************************
105  *           TryEnterCriticalSection   (KERNEL32.898) (NTDLL.969)
106  */
107 BOOL WINAPI TryEnterCriticalSection( CRITICAL_SECTION *crit )
108 {
109     if (InterlockedIncrement( &crit->LockCount ))
110     {
111         if (crit->OwningThread == GetCurrentThreadId())
112         {
113             crit->RecursionCount++;
114             return TRUE;
115         }
116         /* FIXME: this doesn't work */
117         InterlockedDecrement( &crit->LockCount );
118         return FALSE;
119     }
120     crit->OwningThread   = GetCurrentThreadId();
121     crit->RecursionCount = 1;
122     return TRUE;
123 }
124
125
126 /***********************************************************************
127  *           LeaveCriticalSection   (KERNEL32.494) (NTDLL.426)
128  */
129 void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
130 {
131     if (crit->OwningThread != GetCurrentThreadId()) return;
132        
133     if (--crit->RecursionCount)
134     {
135         InterlockedDecrement( &crit->LockCount );
136         return;
137     }
138     crit->OwningThread = 0;
139     if (InterlockedDecrement( &crit->LockCount ) >= 0)
140     {
141         /* Someone is waiting */
142         ReleaseSemaphore( crit->LockSemaphore, 1, NULL );
143     }
144 }
145
146
147 /***********************************************************************
148  *           MakeCriticalSectionGlobal   (KERNEL32.515)
149  */
150 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
151 {
152     crit->LockSemaphore = ConvertToGlobalHandle( crit->LockSemaphore );
153     crit->Reserved      = 0L;
154 }
155
156
157 /***********************************************************************
158  *           ReinitializeCriticalSection   (KERNEL32.581)
159  */
160 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
161 {
162     if ( !crit->LockSemaphore )
163         InitializeCriticalSection( crit );
164
165     else if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
166     {
167         FIXME_(win32)("(%p) called for %08lx first, %08lx now: making global\n", 
168                crit, crit->Reserved, GetCurrentProcessId() );
169
170         MakeCriticalSectionGlobal( crit );
171     }
172 }
173
174
175 /***********************************************************************
176  *           UninitializeCriticalSection   (KERNEL32.703)
177  */
178 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
179 {
180     if ( crit->LockSemaphore )
181     {
182         if ( crit->Reserved )  /* not global */
183             DeleteCriticalSection( crit );
184         else
185             FIXME_(win32)("(%p) for %08lx: Crst is global, don't know whether to delete\n", 
186                    crit, GetCurrentProcessId() );
187     }
188 }
189