source: trunk/src/odincrt/critsect.cpp@ 8901

Last change on this file since 8901 was 8895, checked in by sandervl, 23 years ago

Dos*CriticalSection fixes

File size: 5.0 KB
Line 
1/* $Id: critsect.cpp,v 1.4 2002-07-19 11:06:45 sandervl Exp $ */
2/*
3 * Critical sections
4 *
5 * Copyright 2002 Sander van Leeuwen (sandervl@xs4all.nl)
6 * OS/2 port
7 *
8 * Based on Wine code
9 *
10 * Copyright 1998 Alexandre Julliard (991031 Port)
11 *
12 *
13 */
14#define INCL_DOSPROCESS
15#define INCL_DOSERRORS
16#define INCL_DOSSEMAPHORES
17#include <os2wrap.h>
18#include <win32type.h>
19#include <win32api.h>
20
21#include <assert.h>
22#include <stdio.h>
23
24#include <odincrt.h>
25
26#ifdef DEBUG
27#define DebugInt3() _interrupt(3)
28#else
29#define DebugInt3()
30#endif
31
32#define MAKE_THREADID(processid, threadid) ((processid << 16) | threadid)
33
34//******************************************************************************
35//******************************************************************************
36inline ULONG GetCurrentThreadId()
37{
38 PTIB ptib;
39 PPIB ppib;
40 APIRET rc;
41
42 rc = DosGetInfoBlocks(&ptib, &ppib);
43 if(rc == NO_ERROR) {
44 return MAKE_THREADID(ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
45 }
46 DebugInt3();
47 return 0;
48}
49//******************************************************************************
50//******************************************************************************
51inline ULONG GetCurrentProcessId()
52{
53 PTIB ptib;
54 PPIB ppib;
55 APIRET rc;
56
57 rc = DosGetInfoBlocks(&ptib, &ppib);
58 if(rc == NO_ERROR) {
59 return ppib->pib_ulpid;
60 }
61 DebugInt3();
62 return 0;
63}
64
65/***********************************************************************
66 * DosInitializeCriticalSection
67 */
68VOID WIN32API DosInitializeCriticalSection(CRITICAL_SECTION_OS2 *crit, PSZ pszSemName)
69{
70 APIRET rc;
71
72 crit->LockCount = -1;
73 crit->RecursionCount = 0;
74 crit->OwningThread = 0;
75
76 rc = DosCreateEventSem(pszSemName, &crit->hmtxLock, (pszSemName) ? DC_SEM_SHARED : 0, 0);
77 if(rc != NO_ERROR) {
78 DebugInt3();
79 crit->hmtxLock = 0;
80 }
81 crit->Reserved = GetCurrentProcessId();
82}
83
84
85/***********************************************************************
86 * DosAccessCriticalSection
87 */
88VOID WIN32API DosAccessCriticalSection(CRITICAL_SECTION_OS2 *, PSZ pszSemName)
89{
90 HMTX hmtxLock = 0;
91 APIRET rc;
92
93 if(pszSemName == NULL) {
94 DebugInt3();
95 return;
96 }
97
98 rc = DosOpenEventSem(pszSemName, &hmtxLock);
99 if(rc != NO_ERROR) {
100 DebugInt3();
101 }
102}
103/***********************************************************************
104 * DosDeleteCriticalSection
105 */
106void WIN32API DosDeleteCriticalSection( CRITICAL_SECTION_OS2 *crit )
107{
108 if (crit->hmtxLock)
109 {
110 if (crit->RecursionCount) /* Should not happen */
111 {
112 DebugInt3();
113 }
114 crit->LockCount = -1;
115 crit->RecursionCount = 0;
116 crit->OwningThread = 0;
117 DosCloseEventSem(crit->hmtxLock);
118 crit->hmtxLock = 0;
119 crit->Reserved = (DWORD)-1;
120 }
121}
122
123
124/***********************************************************************
125 * DosEnterCriticalSection
126 */
127void WIN32API DosEnterCriticalSection( CRITICAL_SECTION_OS2 *crit )
128{
129 DWORD res;
130 DWORD threadid = GetCurrentThreadId();
131
132 if (!crit->hmtxLock)
133 {
134 DosInitializeCriticalSection(crit, NULL);
135 }
136 if (DosInterlockedIncrement( &crit->LockCount ))
137 {
138testenter:
139 if (crit->OwningThread == threadid)
140 {
141 crit->RecursionCount++;
142 return;
143 }
144
145 if(DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0))
146 {
147 ULONG ulnrposts;
148
149 /* Now wait for it */
150 APIRET rc = DosWaitEventSem(crit->hmtxLock, SEM_INDEFINITE_WAIT);
151 if(rc != NO_ERROR) {
152 DebugInt3();
153 return;
154 }
155 DosResetEventSem(crit->hmtxLock, &ulnrposts);
156 goto testenter;
157 }
158 }
159 crit->OwningThread = GetCurrentThreadId();
160 crit->RecursionCount = 1;
161}
162
163
164/***********************************************************************
165 * DosTryEnterCriticalSection
166 */
167BOOL WIN32API DosTryEnterCriticalSection( CRITICAL_SECTION_OS2 *crit )
168{
169 if (DosInterlockedIncrement( &crit->LockCount ))
170 {
171 if (crit->OwningThread == GetCurrentThreadId())
172 {
173 crit->RecursionCount++;
174 return TRUE;
175 }
176 DosInterlockedDecrement( &crit->LockCount );
177 return FALSE;
178 }
179 crit->OwningThread = GetCurrentThreadId();
180 crit->RecursionCount = 1;
181 return TRUE;
182}
183
184
185/***********************************************************************
186 * DosLeaveCriticalSection
187 */
188void WIN32API DosLeaveCriticalSection( CRITICAL_SECTION_OS2 *crit )
189{
190 if (crit->OwningThread != GetCurrentThreadId()) return;
191
192 if (--crit->RecursionCount)
193 {
194 DosInterlockedDecrement( &crit->LockCount );
195 return;
196 }
197 crit->OwningThread = 0;
198 if (DosInterlockedDecrement( &crit->LockCount ) >= 0)
199 {
200 /* Someone is waiting */
201 DosPostEventSem(crit->hmtxLock);
202 }
203}
204
Note: See TracBrowser for help on using the repository browser.