source: trunk/src/kernel32/critsection.cpp@ 2523

Last change on this file since 2523 was 2348, checked in by sandervl, 26 years ago

compile fix

File size: 6.1 KB
Line 
1/* $Id: critsection.cpp,v 1.3 2000-01-06 20:24:25 sandervl Exp $ */
2/*
3 * Win32 critical sections
4 *
5 *
6 *
7 * Copyright 1998 Alexandre Julliard (991031 Port)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#include <os2win.h>
14#include <assert.h>
15#include <stdio.h>
16#include "debugtools.h"
17#include <misc.h>
18#include <odinwrap.h>
19
20DECLARE_DEBUG_CHANNEL(relay)
21
22
23HANDLE ODIN_EXTERN(CreateSemaphoreA) (LPSECURITY_ATTRIBUTES arg1, LONG arg2, LONG arg3,
24 LPCSTR arg4);
25
26DWORD ODIN_EXTERN(WaitForSingleObject)(HANDLE hObject, DWORD timeout);
27
28HANDLE ODIN_EXTERN(ConvertToGlobalHandle)(HANDLE hHandle);
29
30/***********************************************************************
31 * InitializeCriticalSection (KERNEL32.472) (NTDLL.406)
32 */
33void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
34{
35 dprintf(("InitializeCriticalSection %x", crit));
36 crit->LockCount = -1;
37 crit->RecursionCount = 0;
38 crit->OwningThread = 0;
39 crit->LockSemaphore = ODIN_CreateSemaphoreA( NULL, 0, 1, NULL );
40 crit->Reserved = GetCurrentProcessId();
41}
42
43
44/***********************************************************************
45 * DeleteCriticalSection (KERNEL32.185) (NTDLL.327)
46 */
47void WINAPI DeleteCriticalSection( CRITICAL_SECTION *crit )
48{
49 dprintf(("DeleteCriticalSection %x", crit));
50
51 if (crit->LockSemaphore)
52 {
53 if (crit->RecursionCount) /* Should not happen */
54 dprintf(("Deleting owned critical section (%p)\n", crit ));
55
56 crit->LockCount = -1;
57 crit->RecursionCount = 0;
58 crit->OwningThread = 0;
59 CloseHandle( crit->LockSemaphore );
60 crit->LockSemaphore = 0;
61 crit->Reserved = (DWORD)-1;
62 }
63}
64
65
66/***********************************************************************
67 * EnterCriticalSection (KERNEL32.195) (NTDLL.344)
68 */
69void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit )
70{
71 DWORD res;
72
73 dprintf2(("EnterCriticalSection %x", crit));
74 if (!crit->LockSemaphore)
75 {
76 dprintf(("entering uninitialized section(%p)?\n",crit));
77 InitializeCriticalSection(crit);
78 }
79 if (InterlockedIncrement( &crit->LockCount ))
80 {
81 if (crit->OwningThread == GetCurrentThreadId())
82 {
83 crit->RecursionCount++;
84 return;
85 }
86 /* Now wait for it */
87
88 if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
89 {
90 dprintf(("Crst %p belongs to process %ld, current is %ld!\n",
91 crit, crit->Reserved, GetCurrentProcessId() ));
92 return;
93 }
94
95 res = ODIN_WaitForSingleObject( crit->LockSemaphore, 5000L );
96 if ( res == WAIT_TIMEOUT )
97 {
98 dprintf(("Critical section %p wait timed out, retrying (60 sec)\n", crit ));
99 res = WaitForSingleObject( crit->LockSemaphore, 60000L );
100 }
101 if ( res == WAIT_TIMEOUT && TRACE_ON(relay) )
102 {
103 dprintf(("Critical section %p wait timed out, retrying (5 min)\n", crit ));
104 res = WaitForSingleObject( crit->LockSemaphore, 300000L );
105 }
106 if (res != STATUS_WAIT_0)
107 {
108 dprintf(("Critical section %p wait failed err=%lx\n", crit, res ));
109 /* FIXME: should raise an exception */
110 }
111 }
112 crit->OwningThread = GetCurrentThreadId();
113 crit->RecursionCount = 1;
114}
115
116
117/***********************************************************************
118 * TryEnterCriticalSection (KERNEL32.898) (NTDLL.969)
119 */
120BOOL WINAPI TryEnterCriticalSection( CRITICAL_SECTION *crit )
121{
122 dprintf2(("TryEnterCriticalSection %x", crit));
123 if (InterlockedIncrement( &crit->LockCount ))
124 {
125 if (crit->OwningThread == GetCurrentThreadId())
126 {
127 crit->RecursionCount++;
128 return TRUE;
129 }
130 /* FIXME: this doesn't work */
131 InterlockedDecrement( &crit->LockCount );
132 return FALSE;
133 }
134 crit->OwningThread = GetCurrentThreadId();
135 crit->RecursionCount = 1;
136 return TRUE;
137}
138
139
140/***********************************************************************
141 * LeaveCriticalSection (KERNEL32.494) (NTDLL.426)
142 */
143void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
144{
145 dprintf2(("LeaveCriticalSection %x", crit));
146 if (crit->OwningThread != GetCurrentThreadId()) return;
147
148 if (--crit->RecursionCount)
149 {
150 InterlockedDecrement( &crit->LockCount );
151 return;
152 }
153 crit->OwningThread = 0;
154 if (InterlockedDecrement( &crit->LockCount ) >= 0)
155 {
156 /* Someone is waiting */
157 ReleaseSemaphore( crit->LockSemaphore, 1, NULL );
158 }
159}
160
161
162/***********************************************************************
163 * MakeCriticalSectionGlobal (KERNEL32.515)
164 */
165void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
166{
167 dprintf(("MakeCriticalSectionGlobal %x", crit));
168 crit->LockSemaphore = ODIN_ConvertToGlobalHandle( crit->LockSemaphore );
169 crit->Reserved = 0L;
170}
171
172
173/***********************************************************************
174 * ReinitializeCriticalSection (KERNEL32.581)
175 */
176void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
177{
178 dprintf(("ReinitializeCriticalSection %x", crit));
179
180 if ( !crit->LockSemaphore )
181 InitializeCriticalSection( crit );
182
183 else if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
184 {
185 dprintf(("(%p) called for %08lx first, %08lx now: making global\n",
186 crit, crit->Reserved, GetCurrentProcessId() ));
187
188 MakeCriticalSectionGlobal( crit );
189 }
190}
191
192
193/***********************************************************************
194 * UninitializeCriticalSection (KERNEL32.703)
195 */
196void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
197{
198 dprintf(("UninitializeCriticalSection %x", crit));
199 if ( crit->LockSemaphore )
200 {
201 if ( crit->Reserved ) /* not global */
202 DeleteCriticalSection( crit );
203 else
204 dprintf(("(%p) for %08lx: Crst is global, don't know whether to delete\n",
205 crit, GetCurrentProcessId() ));
206 }
207}
208
Note: See TracBrowser for help on using the repository browser.