source: trunk/src/kernel32/hmsemaphore.cpp@ 6069

Last change on this file since 6069 was 6069, checked in by sandervl, 24 years ago

semaphore update

File size: 16.9 KB
Line 
1/* $Id: hmsemaphore.cpp,v 1.6 2001-06-22 19:40:28 sandervl Exp $ */
2
3/*
4 * Win32 Semaphore implementation
5 *
6 * TODO: Inheritance
7 * TODO: Does DCE_POSTONE work in Warp 3 or 4 with no FP applied?
8 * TODO: No inheritance when CreateSemaphore is called for existing named event semaphore?
9 * (see HMCreateSemaphore in handlemanager.cpp)
10 * TODO: OpenSemaphore does not work. (get SEM_INFO pointer)
11 * TODO: Name collisions with files & mutex not allowed. Check if this can happen in OS/2
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 * Copyright 2001 Sander van Leeuwen (sandervl@xs4all.nl)
16 */
17
18#undef DEBUG_LOCAL
19//#define DEBUG_LOCAL
20
21
22/*****************************************************************************
23 * Remark *
24 *****************************************************************************
25
26 */
27
28
29/*****************************************************************************
30 * Includes *
31 *****************************************************************************/
32
33#ifdef USE_OS2SEMAPHORES
34#define INCL_DOSSEMAPHORES
35#define INCL_DOSERRORS
36#include <os2wrap.h>
37#include <win32type.h>
38#include <win32api.h>
39#include <winconst.h>
40#else
41#include <os2win.h>
42#endif
43#include <stdlib.h>
44#include <string.h>
45#include <heapshared.h>
46#include "unicode.h"
47#include "misc.h"
48
49#include "HandleManager.H"
50#include "HMSemaphore.h"
51#include "oslibdos.h"
52
53#define DBG_LOCALLOG DBG_hmsemaphore
54#include "dbglocal.h"
55
56#ifndef DCE_AUTORESET
57#define DCE_AUTORESET 0x1000 /* DosCreateEventSem option to auto-reset */
58 /* event semaphore on post. */
59#define DCE_POSTONE 0x0800 /* DosCreateEventSem option to post only */
60 /* waiter and auto-reset the semaphore when*/
61 /* there are multiple waiters. */
62#endif
63
64typedef struct {
65 LONG currentCount;
66 LONG maximumCount;
67 LONG refCount;
68 HEV hev;
69} SEM_INFO, *PSEM_INFO;
70
71/*****************************************************************************
72 * Defines *
73 *****************************************************************************/
74
75/*****************************************************************************
76 * Structures *
77 *****************************************************************************/
78
79/*****************************************************************************
80 * Local Prototypes *
81 *****************************************************************************/
82
83
84/*****************************************************************************
85 * Name : HMCreateSemaphore
86 * Purpose : router function for CreateSemaphore
87 * Parameters:
88 * Variables :
89 * Result :
90 * Remark :
91 * Status :
92 *
93 * Author : Patrick Haller [Tue, 1999/07/06 20:44]
94 *****************************************************************************/
95
96DWORD HMDeviceSemaphoreClass::CreateSemaphore(PHMHANDLEDATA pHMHandleData,
97 LPSECURITY_ATTRIBUTES lpsa,
98 LONG lInitialCount,
99 LONG lMaximumCount,
100 LPCTSTR lpszSemaphoreName)
101{
102#ifdef USE_OS2SEMAPHORES
103 APIRET rc;
104 HEV hev;
105 char szSemName[CCHMAXPATH];
106
107
108 dprintf(("KERNEL32: HandleManager::Semaphore::CreateSemaphore(%08xh,%08xh,%08xh,%08xh,%s)\n",
109 pHMHandleData,
110 lpsa,
111 lInitialCount,
112 lMaximumCount,
113 lpszSemaphoreName));
114
115 if(lMaximumCount <= 0 || lInitialCount < 0 || lInitialCount > lMaximumCount) {
116 dprintf(("ERROR: invalid parameter"));
117 return ERROR_INVALID_PARAMETER_W;
118 }
119
120 if(lpszSemaphoreName) {
121 strcpy(szSemName, "\\SEM32\\");
122 strcat(szSemName, lpszSemaphoreName);
123 lpszSemaphoreName = szSemName;
124 }
125 rc = DosCreateEventSem(lpszSemaphoreName, &hev, DCE_POSTONE, lInitialCount);
126
127 if(rc) {
128 dprintf(("DosCreateEventSem %x failed with rc %d", pHMHandleData->hHMHandle, rc));
129 pHMHandleData->hHMHandle = 0;
130 return error2WinError(rc);
131 }
132 pHMHandleData->dwAccess = SEMAPHORE_ALL_ACCESS_W;
133 PSEM_INFO pSemInfo = (PSEM_INFO)_smalloc(sizeof(SEM_INFO));
134 pSemInfo->refCount = 1;
135 pSemInfo->hev = hev;
136 pSemInfo->maximumCount = lMaximumCount;
137 pSemInfo->currentCount = lInitialCount;
138 pHMHandleData->hHMHandle = (DWORD)pSemInfo;
139 pHMHandleData->dwInternalType = HMTYPE_SEMAPHORE;
140 return ERROR_SUCCESS_W;
141#else
142 HANDLE hOpen32;
143
144 dprintf(("KERNEL32: HandleManager::Semaphore::CreateSemaphore(%08xh,%08xh,%08xh,%08xh,%s)\n",
145 pHMHandleData,
146 lpsa,
147 lInitialCount,
148 lMaximumCount,
149 lpszSemaphoreName));
150
151 hOpen32 = O32_CreateSemaphore(lpsa, // call Open32
152 lInitialCount,
153 lMaximumCount,
154 (LPTSTR)lpszSemaphoreName);
155
156 if (0 != hOpen32) // check success
157 {
158 pHMHandleData->hHMHandle = hOpen32; // save handle
159 return (NO_ERROR);
160 }
161 else
162 return (O32_GetLastError());
163#endif
164}
165
166
167/*****************************************************************************
168 * Name : HMOpenSemaphore
169 * Purpose : router function for OpenSemaphore
170 * Parameters:
171 * Variables :
172 * Result :
173 * Remark :
174 * Status :
175 *
176 * Author : Patrick Haller [Tue, 1999/07/06 20:44]
177 *****************************************************************************/
178
179DWORD HMDeviceSemaphoreClass::OpenSemaphore(PHMHANDLEDATA pHMHandleData,
180 BOOL fInheritHandle,
181 LPCTSTR lpszSemaphoreName)
182{
183#ifdef USE_OS2SEMAPHORES
184 HEV hev;
185 APIRET rc;
186 char szSemName[CCHMAXPATH];
187
188 //TODO: NOT WORKING (initialcount/maximumcount)
189 dprintf(("KERNEL32: HandleManager::Semaphore::OpenSemaphore(%08xh,%08xh,%s)\n",
190 pHMHandleData,
191 fInheritHandle,
192 lpszSemaphoreName));
193
194 if(lpszSemaphoreName == NULL) {
195 pHMHandleData->hHMHandle = 0;
196 return ERROR_INVALID_PARAMETER_W;
197 }
198
199 strcpy(szSemName, "\\SEM32\\");
200 strcat(szSemName, lpszSemaphoreName);
201 rc = DosOpenEventSem(szSemName, &hev);
202 if(rc) {
203 dprintf(("DosOpenEventSem %x failed with rc %d", pHMHandleData->hHMHandle, rc));
204 pHMHandleData->hHMHandle = 0;
205 return error2WinError(rc);
206 }
207 pHMHandleData->hHMHandle = hev;
208 pHMHandleData->dwInternalType = HMTYPE_SEMAPHORE;
209 return ERROR_SUCCESS_W;
210#else
211 HANDLE hOpen32;
212
213 dprintf(("KERNEL32: HandleManager::Semaphore::OpenSemaphore(%08xh,%08xh,%s)\n",
214 pHMHandleData,
215 fInheritHandle,
216 lpszSemaphoreName));
217
218 hOpen32 = O32_OpenSemaphore(pHMHandleData->dwAccess, // call Open32
219 fInheritHandle,
220 lpszSemaphoreName);
221
222 if (0 != hOpen32) // check success
223 {
224 pHMHandleData->hHMHandle = hOpen32; // save handle
225 return (NO_ERROR);
226 }
227 else
228 return (O32_GetLastError());
229#endif
230}
231
232/*****************************************************************************
233 * Name : HMDeviceEventClass::CloseHandle
234 * Purpose : close the handle
235 * Parameters: PHMHANDLEDATA pHMHandleData
236 * Variables :
237 * Result : API returncode
238 * Remark :
239 * Status :
240 *
241 * Author :
242 *****************************************************************************/
243
244#ifdef USE_OS2SEMAPHORES
245BOOL HMDeviceSemaphoreClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
246{
247 APIRET rc;
248 PSEM_INFO pSemInfo = (PSEM_INFO)pHMHandleData->hHMHandle;
249
250 if(pSemInfo) {
251 rc = DosCloseEventSem(pSemInfo->hev);
252 if(rc) {
253 dprintf(("DosCloseEventSem %x failed with rc %d", pSemInfo->hev, rc));
254 SetLastError(error2WinError(rc));
255 return FALSE;
256 }
257 if(InterlockedDecrement(&pSemInfo->refCount) == 0) {
258 free(pSemInfo);
259 }
260 }
261 return TRUE;
262}
263#endif
264
265
266/*****************************************************************************
267 * Name : HMDeviceEventClass::DuplicateHandle
268 * Purpose :
269 * Parameters:
270 * various parameters as required
271 * Variables :
272 * Result :
273 * Remark : the standard behaviour is to return an error code for non-
274 * existant request codes
275 * Status :
276 *
277 * Author :
278 *****************************************************************************/
279#ifdef USE_OS2SEMAPHORES
280BOOL HMDeviceSemaphoreClass::DuplicateHandle(PHMHANDLEDATA pHMHandleData, HANDLE srcprocess,
281 PHMHANDLEDATA pHMSrcHandle,
282 HANDLE destprocess,
283 PHANDLE desthandle,
284 DWORD fdwAccess,
285 BOOL fInherit,
286 DWORD fdwOptions,
287 DWORD fdwOdinOptions)
288{
289 APIRET rc;
290 HEV hev;
291 PSEM_INFO pSemInfo = (PSEM_INFO)pHMSrcHandle->hHMHandle;
292
293 dprintf(("KERNEL32:HandleManager::DuplicateHandle %s(%08x,%08x,%08x,%08x,%08x)",
294 lpHMDeviceName,
295 pHMHandleData,
296 srcprocess, pHMSrcHandle, destprocess, desthandle));
297
298 if(srcprocess != destprocess) {
299 DebugInt3();
300 SetLastError(ERROR_ACCESS_DENIED_W);
301 return FALSE;
302 }
303 InterlockedIncrement(&pSemInfo->refCount);
304 pHMHandleData->dwAccess = fdwAccess;
305 pHMHandleData->hHMHandle = (DWORD)pSemInfo;
306 pHMHandleData->dwInternalType = HMTYPE_SEMAPHORE;
307 SetLastError(ERROR_SUCCESS_W);
308 return TRUE;
309}
310#endif
311
312#ifdef USE_OS2SEMAPHORES
313/*****************************************************************************
314 * Name : DWORD HMDeviceSemaphoreClass::WaitForSingleObject
315 * Purpose : object synchronization
316 * Parameters: PHMHANDLEDATA pHMHandleData
317 * DWORD dwTimeout
318 * Variables :
319 * Result : API returncode
320 * Remark :
321 * Status :
322 *
323 * Author : SvL
324 *****************************************************************************/
325
326DWORD HMDeviceSemaphoreClass::WaitForSingleObject(PHMHANDLEDATA pHMHandleData,
327 DWORD dwTimeout)
328{
329 DWORD rc;
330
331 dprintf2(("KERNEL32: HMDeviceSemaphoreClass::WaitForSingleObject(%08xh %08xh)",
332 pHMHandleData->hHMHandle, dwTimeout));
333
334 if(!(pHMHandleData->dwAccess & SYNCHRONIZE_W) )
335 {
336 dprintf(("ERROR: Access denied!!"));
337 SetLastError(ERROR_ACCESS_DENIED_W);
338 return WAIT_FAILED_W;
339 }
340
341 PSEM_INFO pSemInfo = (PSEM_INFO)pHMHandleData->hHMHandle;
342
343 if(InterlockedDecrement(&pSemInfo->currentCount) >= 0) {
344 SetLastError(ERROR_SUCCESS_W);
345 return WAIT_OBJECT_0_W;
346 }
347
348 rc = DosWaitEventSem(pSemInfo->hev, dwTimeout);
349 if(rc && rc != ERROR_INTERRUPT && rc != ERROR_TIMEOUT && rc != ERROR_SEM_OWNER_DIED) {
350 dprintf(("DosWaitEventSem %x failed with rc %d", pSemInfo->hev, rc));
351 SetLastError(error2WinError(rc));
352 return WAIT_FAILED_W;
353 }
354 SetLastError(ERROR_SUCCESS_W);
355 if(rc == ERROR_INTERRUPT || rc == ERROR_SEM_OWNER_DIED) {
356 return WAIT_ABANDONED_W;
357 }
358 else
359 if(rc == ERROR_TIMEOUT) {
360 return WAIT_TIMEOUT_W;
361 }
362 return WAIT_OBJECT_0_W;
363}
364#endif
365
366#ifdef USE_OS2SEMAPHORES
367/*****************************************************************************
368 * Name : DWORD HMDeviceSemaphoreClass::WaitForSingleObjectEx
369 * Purpose : object synchronization
370 * Parameters: PHMHANDLEDATA pHMHandleData
371 * DWORD dwTimeout
372 * BOOL fAlertable
373 * Variables :
374 * Result : API returncode
375 * Remark :
376 * Status :
377 *
378 * Author : SvL
379 *****************************************************************************/
380
381DWORD HMDeviceSemaphoreClass::WaitForSingleObjectEx(PHMHANDLEDATA pHMHandleData,
382 DWORD dwTimeout,
383 BOOL fAlertable)
384{
385 dprintf2(("KERNEL32: HMDeviceSemaphoreClass::WaitForSingleObjectEx(%08xh,%08h,%08xh) not implemented correctly.\n",
386 pHMHandleData->hHMHandle, dwTimeout, fAlertable));
387
388 if(!(pHMHandleData->dwAccess & SYNCHRONIZE_W) )
389 {
390 dprintf(("ERROR: Access denied!!"));
391 SetLastError(ERROR_ACCESS_DENIED_W);
392 return WAIT_FAILED_W;
393 }
394
395 return WaitForSingleObject(pHMHandleData, dwTimeout);
396}
397#endif
398
399#ifdef USE_OS2SEMAPHORES
400/*****************************************************************************
401 * Name : BOOL HMDeviceSemaphoreClass::MsgWaitForMultipleObjects
402 * Purpose :
403 * Variables :
404 * Result :
405 * Remark :
406 * Status :
407 *
408 * Author : SvL
409 *****************************************************************************/
410DWORD HMDeviceSemaphoreClass::MsgWaitForMultipleObjects(PHMHANDLEDATA pHMHandleData,
411 DWORD nCount,
412 PHANDLE pHandles,
413 BOOL fWaitAll,
414 DWORD dwMilliseconds,
415 DWORD dwWakeMask)
416{
417 dprintf(("KERNEL32: ERROR: HandleManager::DeviceHandler::MsgWaitForMultipleObjects %08x %d %x %d %d %x",
418 pHMHandleData->hHMHandle, nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask));
419
420 if(!(pHMHandleData->dwAccess & SYNCHRONIZE_W) )
421 {
422 dprintf(("ERROR: Access denied!!"));
423 SetLastError(ERROR_ACCESS_DENIED_W);
424 return WAIT_FAILED_W;
425 }
426
427 return WAIT_FAILED_W;
428}
429#endif
430
431#ifdef USE_OS2SEMAPHORES
432/*****************************************************************************
433 * Name : BOOL HMDeviceSemaphoreClass::WaitForMultipleObjects
434 * Purpose :
435 * Variables :
436 * Result :
437 * Remark :
438 * Status :
439 *
440 * Author : SvL
441 *****************************************************************************/
442DWORD HMDeviceSemaphoreClass::WaitForMultipleObjects(PHMHANDLEDATA pHMHandleData,
443 DWORD cObjects,
444 PHANDLE lphObjects,
445 BOOL fWaitAll,
446 DWORD dwTimeout)
447{
448 dprintf(("KERNEL32: ERROR: HandleManager::DeviceHandler::WaitForMultipleObjects %08x %d %x %d %x",
449 pHMHandleData->hHMHandle, cObjects, lphObjects, fWaitAll, dwTimeout));
450
451 if(!(pHMHandleData->dwAccess & SYNCHRONIZE_W) )
452 {
453 dprintf(("ERROR: Access denied!!"));
454 SetLastError(ERROR_ACCESS_DENIED_W);
455 return WAIT_FAILED_W;
456 }
457
458 return WAIT_FAILED_W;
459}
460#endif
461
462/*****************************************************************************
463 * Name : HMReleaseSemaphore
464 * Purpose : router function for ReleaseSemaphore
465 * Parameters:
466 * Variables :
467 * Result :
468 * Remark :
469 * Status :
470 *
471 * Author : Patrick Haller [Tue, 1999/07/06 20:44]
472 *****************************************************************************/
473
474BOOL HMDeviceSemaphoreClass::ReleaseSemaphore(PHMHANDLEDATA pHMHandleData,
475 LONG cReleaseCount,
476 LPLONG lpPreviousCount)
477{
478#ifdef USE_OS2SEMAPHORES
479 APIRET rc;
480 ULONG count;
481
482 dprintf2(("KERNEL32: HandleManager::Semaphore::ReleaseSemaphore(%08xh,%08xh,%08xh)\n",
483 pHMHandleData->hHMHandle,
484 cReleaseCount,
485 lpPreviousCount));
486
487 if(!(pHMHandleData->dwAccess & SEMAPHORE_MODIFY_STATE_W) )
488 {
489 dprintf(("ERROR: Access denied!!"));
490 SetLastError(ERROR_ACCESS_DENIED_W);
491 return FALSE;
492 }
493
494 PSEM_INFO pSemInfo = (PSEM_INFO)pHMHandleData->hHMHandle;
495
496 if(InterlockedIncrement(&pSemInfo->currentCount) > 0) {
497 //TODO: this is NOT thread safe:
498 if(pSemInfo->currentCount > pSemInfo->maximumCount) {
499 pSemInfo->currentCount = pSemInfo->maximumCount;
500 }
501 SetLastError(ERROR_SUCCESS_W);
502 return TRUE;
503 }
504
505 rc = DosResetEventSem(pSemInfo->hev, &count);
506 if(rc) {
507 dprintf(("DosResetEventSem %x failed with rc %d", pSemInfo->hev, rc));
508 SetLastError(error2WinError(rc));
509 return FALSE;
510 }
511 SetLastError(ERROR_SUCCESS_W);
512 return TRUE;
513#else
514 dprintf(("KERNEL32: HandleManager::Semaphore::ReleaseSemaphore(%08xh,%08xh,%08xh)\n",
515 pHMHandleData->hHMHandle,
516 cReleaseCount,
517 lpPreviousCount));
518
519 return (O32_ReleaseSemaphore(pHMHandleData->hHMHandle,
520 cReleaseCount,
521 lpPreviousCount));
522#endif
523}
524
Note: See TracBrowser for help on using the repository browser.