VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/semeventmulti-win.cpp@ 25724

Last change on this file since 25724 was 25724, checked in by vboxsync, 15 years ago

iprt: Use RTMSINTERVAL for timeouts. Fixed missing timeout underflow checks in two RTFileAioCtxWait implementations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1/* $Id: semeventmulti-win.cpp 25724 2010-01-11 14:45:34Z vboxsync $ */
2/** @file
3 * IPRT - Multiple Release Event Semaphore, Windows.
4 *
5 * @remarks This file is identical to semevent-win.cpp except for the 2nd
6 * CreateEvent parameter, the reset function and the "Multi" infix.
7 */
8
9/*
10 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.215389.xyz. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 *
20 * The contents of this file may alternatively be used under the terms
21 * of the Common Development and Distribution License Version 1.0
22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23 * VirtualBox OSE distribution, in which case the provisions of the
24 * CDDL are applicable instead of those of the GPL.
25 *
26 * You may elect to license modified versions of this file under the
27 * terms and conditions of either the GPL or the CDDL or both.
28 *
29 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
30 * Clara, CA 95054 USA or visit http://www.sun.com if you need
31 * additional information or have any questions.
32 */
33
34
35/*******************************************************************************
36* Header Files *
37*******************************************************************************/
38#define LOG_GROUP RTLOGGROUP_SEMAPHORE
39#include <Windows.h>
40
41#include <iprt/semaphore.h>
42#include "internal/iprt.h"
43
44#include <iprt/asm.h>
45#include <iprt/assert.h>
46#include <iprt/err.h>
47#include <iprt/lockvalidator.h>
48#include <iprt/mem.h>
49#include <iprt/thread.h>
50#include "internal/magics.h"
51#include "internal/strict.h"
52
53
54/*******************************************************************************
55* Defined Constants And Macros *
56*******************************************************************************/
57struct RTSEMEVENTMULTIINTERNAL
58{
59 /** Magic value (RTSEMEVENTMULTI_MAGIC). */
60 uint32_t u32Magic;
61 /** The event handle. */
62 HANDLE hev;
63#ifdef RTSEMEVENT_STRICT
64 /** Signallers. */
65 RTLOCKVALRECSHRD Signallers;
66 /** Indicates that lock validation should be performed. */
67 bool volatile fEverHadSignallers;
68#endif
69};
70
71
72
73RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
74{
75 return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
76}
77
78
79RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
80 const char *pszNameFmt, ...)
81{
82 AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
83
84 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(*pThis));
85 if (!pThis)
86 return VERR_NO_MEMORY;
87
88 /*
89 * Create the semaphore.
90 * (Manual reset, not signaled, private event object.)
91 */
92 pThis->hev = CreateEvent(NULL, TRUE, FALSE, NULL);
93 if (pThis->hev != NULL) /* not INVALID_HANDLE_VALUE */
94 {
95 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
96#ifdef RTSEMEVENT_STRICT
97 va_list va;
98 va_start(va, pszNameFmt);
99 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
100 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
101 pszNameFmt, va);
102 va_end(va);
103 pThis->fEverHadSignallers = false;
104#endif
105
106 *phEventMultiSem = pThis;
107 return VINF_SUCCESS;
108 }
109
110 DWORD dwErr = GetLastError();
111 RTMemFree(pThis);
112 return RTErrConvertFromWin32(dwErr);
113}
114
115
116RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
117{
118 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
119 if (pThis == NIL_RTSEMEVENT) /* don't bitch */
120 return VINF_SUCCESS;
121 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
122 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
123
124 /*
125 * Invalidate the handle and close the semaphore.
126 */
127 int rc = VINF_SUCCESS;
128 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC, RTSEMEVENTMULTI_MAGIC), VERR_INVALID_HANDLE);
129 if (CloseHandle(pThis->hev))
130 {
131#ifdef RTSEMEVENT_STRICT
132 RTLockValidatorRecSharedDelete(&pThis->Signallers);
133#endif
134 RTMemFree(pThis);
135 }
136 else
137 {
138 DWORD dwErr = GetLastError();
139 rc = RTErrConvertFromWin32(dwErr);
140 AssertMsgFailed(("Destroy hEventMultiSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
141 /* Leak it. */
142 }
143
144 return rc;
145}
146
147
148RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
149{
150 /*
151 * Validate input.
152 */
153 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
154 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
155 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
156
157#ifdef RTSEMEVENT_STRICT
158 if (pThis->fEverHadSignallers)
159 {
160 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
161 if (RT_FAILURE(rc9))
162 return rc9;
163 }
164#endif
165
166 /*
167 * Signal the object.
168 */
169 if (SetEvent(pThis->hev))
170 return VINF_SUCCESS;
171 DWORD dwErr = GetLastError();
172 AssertMsgFailed(("Signaling hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
173 return RTErrConvertFromWin32(dwErr);
174}
175
176
177RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
178{
179 /*
180 * Validate input.
181 */
182 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
183 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
184 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
185
186 /*
187 * Reset the object.
188 */
189 if (ResetEvent(pThis->hev))
190 return VINF_SUCCESS;
191 DWORD dwErr = GetLastError();
192 AssertMsgFailed(("Resetting hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
193 return RTErrConvertFromWin32(dwErr);
194}
195
196
197/** Goto avoidance. */
198DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTMULTIINTERNAL *pThis, DWORD rc)
199{
200 switch (rc)
201 {
202 case WAIT_OBJECT_0: return VINF_SUCCESS;
203 case WAIT_TIMEOUT: return VERR_TIMEOUT;
204 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
205 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
206 default:
207 AssertMsgFailed(("%u\n", rc));
208 case WAIT_FAILED:
209 {
210 int rc2 = RTErrConvertFromWin32(GetLastError());
211 AssertMsgFailed(("Wait on hEventMultiSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
212 if (rc2)
213 return rc2;
214
215 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
216 return VERR_INTERNAL_ERROR;
217 }
218 }
219}
220
221
222#undef RTSemEventMultiWaitNoResume
223RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
224{
225 PCRTLOCKVALSRCPOS pSrcPos = NULL;
226
227 /*
228 * Validate input.
229 */
230 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
231 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
232 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
233
234 /*
235 * Wait for condition.
236 */
237#ifdef RTSEMEVENT_STRICT
238 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
239 if (pThis->fEverHadSignallers)
240 {
241 DWORD rc = WaitForSingleObjectEx(pThis->hev,
242 0 /*Timeout*/,
243 TRUE /*fAlertable*/);
244 if (rc != WAIT_TIMEOUT || cMillies == 0)
245 return rtSemEventWaitHandleStatus(pThis, rc);
246 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
247 cMillies, RTTHREADSTATE_EVENT_MULTI, true);
248 if (RT_FAILURE(rc9))
249 return rc9;
250 }
251#else
252 RTTHREAD hThreadSelf = RTThreadSelf();
253#endif
254 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
255 DWORD rc = WaitForSingleObjectEx(pThis->hev,
256 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
257 TRUE /*fAlertable*/);
258 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
259 return rtSemEventWaitHandleStatus(pThis, rc);
260}
261
262
263RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
264{
265#ifdef RTSEMEVENT_STRICT
266 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
267 AssertPtrReturnVoid(pThis);
268 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
269
270 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
271 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
272#endif
273}
274
275
276RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
277{
278#ifdef RTSEMEVENT_STRICT
279 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
280 AssertPtrReturnVoid(pThis);
281 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
282
283 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
284 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
285#endif
286}
287
288
289RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
290{
291#ifdef RTSEMEVENT_STRICT
292 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
293 AssertPtrReturnVoid(pThis);
294 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
295
296 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
297#endif
298}
299
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette