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

Last change on this file since 1711 was 1641, checked in by sandervl, 26 years ago

Critical section Wine port + mmap fix (limit size of mmap files)

File size: 6.0 KB
Line 
1/* $Id: critsection.cpp,v 1.1 1999-11-08 20:53:24 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
20DEFAULT_DEBUG_CHANNEL(win32)
21DECLARE_DEBUG_CHANNEL(relay)
22
23
24HANDLE ODIN_EXTERN(CreateSemaphoreA) (LPSECURITY_ATTRIBUTES arg1, LONG arg2, LONG arg3,
25 LPCSTR arg4);
26
27DWORD ODIN_EXTERN(WaitForSingleObject)(HANDLE hObject, DWORD timeout);
28
29HANDLE ODIN_EXTERN(ConvertToGlobalHandle)(HANDLE hHandle);
30
31/***********************************************************************
32 * InitializeCriticalSection (KERNEL32.472) (NTDLL.406)
33 */
34void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
35{
36 dprintf(("InitializeCriticalSection %x", crit));
37 crit->LockCount = -1;
38 crit->RecursionCount = 0;
39 crit->OwningThread = 0;
40 crit->LockSemaphore = ODIN_CreateSemaphoreA( NULL, 0, 1, NULL );
41 crit->Reserved = GetCurrentProcessId();
42}
43
44
45/***********************************************************************
46 * DeleteCriticalSection (KERNEL32.185) (NTDLL.327)
47 */
48void WINAPI DeleteCriticalSection( CRITICAL_SECTION *crit )
49{
50 dprintf(("DeleteCriticalSection %x", crit));
51
52 if (crit->LockSemaphore)
53 {
54 if (crit->RecursionCount) /* Should not happen */
55 dprintf(("Deleting owned critical section (%p)\n", crit ));
56
57 crit->LockCount = -1;
58 crit->RecursionCount = 0;
59 crit->OwningThread = 0;
60 CloseHandle( crit->LockSemaphore );
61 crit->LockSemaphore = 0;
62 crit->Reserved = (DWORD)-1;
63 }
64}
65
66
67/***********************************************************************
68 * EnterCriticalSection (KERNEL32.195) (NTDLL.344)
69 */
70void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit )
71{
72 DWORD res;
73
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 if (InterlockedIncrement( &crit->LockCount ))
123 {
124 if (crit->OwningThread == GetCurrentThreadId())
125 {
126 crit->RecursionCount++;
127 return TRUE;
128 }
129 /* FIXME: this doesn't work */
130 InterlockedDecrement( &crit->LockCount );
131 return FALSE;
132 }
133 crit->OwningThread = GetCurrentThreadId();
134 crit->RecursionCount = 1;
135 return TRUE;
136}
137
138
139/***********************************************************************
140 * LeaveCriticalSection (KERNEL32.494) (NTDLL.426)
141 */
142void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
143{
144 if (crit->OwningThread != GetCurrentThreadId()) return;
145
146 if (--crit->RecursionCount)
147 {
148 InterlockedDecrement( &crit->LockCount );
149 return;
150 }
151 crit->OwningThread = 0;
152 if (InterlockedDecrement( &crit->LockCount ) >= 0)
153 {
154 /* Someone is waiting */
155 ReleaseSemaphore( crit->LockSemaphore, 1, NULL );
156 }
157}
158
159
160/***********************************************************************
161 * MakeCriticalSectionGlobal (KERNEL32.515)
162 */
163void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
164{
165 dprintf(("MakeCriticalSectionGlobal %x", crit));
166 crit->LockSemaphore = ODIN_ConvertToGlobalHandle( crit->LockSemaphore );
167 crit->Reserved = 0L;
168}
169
170
171/***********************************************************************
172 * ReinitializeCriticalSection (KERNEL32.581)
173 */
174void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
175{
176 dprintf(("ReinitializeCriticalSection %x", crit));
177
178 if ( !crit->LockSemaphore )
179 InitializeCriticalSection( crit );
180
181 else if ( crit->Reserved && crit->Reserved != GetCurrentProcessId() )
182 {
183 dprintf(("(%p) called for %08lx first, %08lx now: making global\n",
184 crit, crit->Reserved, GetCurrentProcessId() ));
185
186 MakeCriticalSectionGlobal( crit );
187 }
188}
189
190
191/***********************************************************************
192 * UninitializeCriticalSection (KERNEL32.703)
193 */
194void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
195{
196 dprintf(("UninitializeCriticalSection %x", crit));
197 if ( crit->LockSemaphore )
198 {
199 if ( crit->Reserved ) /* not global */
200 DeleteCriticalSection( crit );
201 else
202 dprintf(("(%p) for %08lx: Crst is global, don't know whether to delete\n",
203 crit, GetCurrentProcessId() ));
204 }
205}
206
Note: See TracBrowser for help on using the repository browser.