Bugfix: Install task-entry breakpoint *after* EXE module is initialized.
[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 (InterlockedIncrement( &crit->LockCount ))
68     {
69         if (crit->OwningThread == GetCurrentThreadId())
70         {
71             crit->RecursionCount++;
72             return;
73         }
74         /* Now wait for it */
75
76         if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
77         {
78             FIXME_(win32)("Crst %p belongs to process %ld, current is %ld!\n", 
79                           crit, crit->Reserved, GetCurrentProcessId() );
80             return;
81         }
82
83         res = WaitForSingleObject( crit->LockSemaphore, 5000L );
84         if ( res == WAIT_TIMEOUT )
85         {
86             ERR_(win32)("Critical section %p wait timed out, retrying (60 sec)\n", crit );
87             res = WaitForSingleObject( crit->LockSemaphore, 60000L );
88         }
89         if ( res == WAIT_TIMEOUT && TRACE_ON(relay) )
90         {
91             ERR_(win32)("Critical section %p wait timed out, retrying (5 min)\n", crit );
92             res = WaitForSingleObject( crit->LockSemaphore, 300000L );
93         }
94         if (res != STATUS_WAIT_0)
95         {
96             ERR_(win32)("Critical section %p wait failed err=%lx\n", crit, res );
97             /* FIXME: should raise an exception */
98         }
99     }
100     crit->OwningThread   = GetCurrentThreadId();
101     crit->RecursionCount = 1;
102 }
103
104
105 /***********************************************************************
106  *           TryEnterCriticalSection   (KERNEL32.898) (NTDLL.969)
107  */
108 BOOL WINAPI TryEnterCriticalSection( CRITICAL_SECTION *crit )
109 {
110     if (InterlockedIncrement( &crit->LockCount ))
111     {
112         if (crit->OwningThread == GetCurrentThreadId())
113         {
114             crit->RecursionCount++;
115             return TRUE;
116         }
117         /* FIXME: this doesn't work */
118         InterlockedDecrement( &crit->LockCount );
119         return FALSE;
120     }
121     crit->OwningThread   = GetCurrentThreadId();
122     crit->RecursionCount = 1;
123     return TRUE;
124 }
125
126
127 /***********************************************************************
128  *           LeaveCriticalSection   (KERNEL32.494) (NTDLL.426)
129  */
130 void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
131 {
132     if (crit->OwningThread != GetCurrentThreadId()) return;
133        
134     if (--crit->RecursionCount)
135     {
136         InterlockedDecrement( &crit->LockCount );
137         return;
138     }
139     crit->OwningThread = 0;
140     if (InterlockedDecrement( &crit->LockCount ) >= 0)
141     {
142         /* Someone is waiting */
143         ReleaseSemaphore( crit->LockSemaphore, 1, NULL );
144     }
145 }
146
147
148 /***********************************************************************
149  *           MakeCriticalSectionGlobal   (KERNEL32.515)
150  */
151 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
152 {
153     crit->LockSemaphore = ConvertToGlobalHandle( crit->LockSemaphore );
154     crit->Reserved      = 0L;
155 }
156
157
158 /***********************************************************************
159  *           ReinitializeCriticalSection   (KERNEL32.581)
160  */
161 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
162 {
163     if ( !crit->LockSemaphore )
164         InitializeCriticalSection( crit );
165
166     else if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
167     {
168         FIXME_(win32)("(%p) called for %08lx first, %08lx now: making global\n", 
169                crit, crit->Reserved, GetCurrentProcessId() );
170
171         MakeCriticalSectionGlobal( crit );
172     }
173 }
174
175
176 /***********************************************************************
177  *           UninitializeCriticalSection   (KERNEL32.703)
178  */
179 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
180 {
181     if ( crit->LockSemaphore )
182     {
183         if ( crit->Reserved )  /* not global */
184             DeleteCriticalSection( crit );
185         else
186             FIXME_(win32)("(%p) for %08lx: Crst is global, don't know whether to delete\n", 
187                    crit, GetCurrentProcessId() );
188     }
189 }
190