VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.1 KB
Line 
1/* $Id: semeventmulti-win.cpp 28800 2010-04-27 08:22:32Z 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 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. 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
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#define LOG_GROUP RTLOGGROUP_SEMAPHORE
35#include <Windows.h>
36
37#include <iprt/semaphore.h>
38#include "internal/iprt.h"
39
40#include <iprt/asm.h>
41#include <iprt/assert.h>
42#include <iprt/err.h>
43#include <iprt/lockvalidator.h>
44#include <iprt/mem.h>
45#include <iprt/thread.h>
46#include "internal/magics.h"
47#include "internal/strict.h"
48
49
50/*******************************************************************************
51* Defined Constants And Macros *
52*******************************************************************************/
53struct RTSEMEVENTMULTIINTERNAL
54{
55 /** Magic value (RTSEMEVENTMULTI_MAGIC). */
56 uint32_t u32Magic;
57 /** The event handle. */
58 HANDLE hev;
59#ifdef RTSEMEVENT_STRICT
60 /** Signallers. */
61 RTLOCKVALRECSHRD Signallers;
62 /** Indicates that lock validation should be performed. */
63 bool volatile fEverHadSignallers;
64#endif
65};
66
67
68
69RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
70{
71 return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
72}
73
74
75RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
76 const char *pszNameFmt, ...)
77{
78 AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
79
80 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(*pThis));
81 if (!pThis)
82 return VERR_NO_MEMORY;
83
84 /*
85 * Create the semaphore.
86 * (Manual reset, not signaled, private event object.)
87 */
88 pThis->hev = CreateEvent(NULL, TRUE, FALSE, NULL);
89 if (pThis->hev != NULL) /* not INVALID_HANDLE_VALUE */
90 {
91 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
92#ifdef RTSEMEVENT_STRICT
93 if (!pszNameFmt)
94 {
95 static uint32_t volatile s_iSemEventMultiAnon = 0;
96 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
97 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
98 "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
99 }
100 else
101 {
102 va_list va;
103 va_start(va, pszNameFmt);
104 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
105 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
106 pszNameFmt, va);
107 va_end(va);
108 }
109 pThis->fEverHadSignallers = false;
110#endif
111
112 *phEventMultiSem = pThis;
113 return VINF_SUCCESS;
114 }
115
116 DWORD dwErr = GetLastError();
117 RTMemFree(pThis);
118 return RTErrConvertFromWin32(dwErr);
119}
120
121
122RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
123{
124 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
125 if (pThis == NIL_RTSEMEVENT) /* don't bitch */
126 return VINF_SUCCESS;
127 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
128 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
129
130 /*
131 * Invalidate the handle and close the semaphore.
132 */
133 int rc = VINF_SUCCESS;
134 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC, RTSEMEVENTMULTI_MAGIC), VERR_INVALID_HANDLE);
135 if (CloseHandle(pThis->hev))
136 {
137#ifdef RTSEMEVENT_STRICT
138 RTLockValidatorRecSharedDelete(&pThis->Signallers);
139#endif
140 RTMemFree(pThis);
141 }
142 else
143 {
144 DWORD dwErr = GetLastError();
145 rc = RTErrConvertFromWin32(dwErr);
146 AssertMsgFailed(("Destroy hEventMultiSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
147 /* Leak it. */
148 }
149
150 return rc;
151}
152
153
154RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
155{
156 /*
157 * Validate input.
158 */
159 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
160 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
161 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
162
163#ifdef RTSEMEVENT_STRICT
164 if (pThis->fEverHadSignallers)
165 {
166 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
167 if (RT_FAILURE(rc9))
168 return rc9;
169 }
170#endif
171
172 /*
173 * Signal the object.
174 */
175 if (SetEvent(pThis->hev))
176 return VINF_SUCCESS;
177 DWORD dwErr = GetLastError();
178 AssertMsgFailed(("Signaling hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
179 return RTErrConvertFromWin32(dwErr);
180}
181
182
183RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
184{
185 /*
186 * Validate input.
187 */
188 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
189 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
190 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
191
192 /*
193 * Reset the object.
194 */
195 if (ResetEvent(pThis->hev))
196 return VINF_SUCCESS;
197 DWORD dwErr = GetLastError();
198 AssertMsgFailed(("Resetting hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
199 return RTErrConvertFromWin32(dwErr);
200}
201
202
203/** Goto avoidance. */
204DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTMULTIINTERNAL *pThis, DWORD rc)
205{
206 switch (rc)
207 {
208 case WAIT_OBJECT_0: return VINF_SUCCESS;
209 case WAIT_TIMEOUT: return VERR_TIMEOUT;
210 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
211 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
212 default:
213 AssertMsgFailed(("%u\n", rc));
214 case WAIT_FAILED:
215 {
216 int rc2 = RTErrConvertFromWin32(GetLastError());
217 AssertMsgFailed(("Wait on hEventMultiSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
218 if (rc2)
219 return rc2;
220
221 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
222 return VERR_INTERNAL_ERROR;
223 }
224 }
225}
226
227
228#undef RTSemEventMultiWaitNoResume
229RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
230{
231 PCRTLOCKVALSRCPOS pSrcPos = NULL;
232
233 /*
234 * Validate input.
235 */
236 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
237 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
238 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
239
240 /*
241 * Wait for condition.
242 */
243#ifdef RTSEMEVENT_STRICT
244 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
245 if (pThis->fEverHadSignallers)
246 {
247 DWORD rc = WaitForSingleObjectEx(pThis->hev,
248 0 /*Timeout*/,
249 TRUE /*fAlertable*/);
250 if (rc != WAIT_TIMEOUT || cMillies == 0)
251 return rtSemEventWaitHandleStatus(pThis, rc);
252 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
253 cMillies, RTTHREADSTATE_EVENT_MULTI, true);
254 if (RT_FAILURE(rc9))
255 return rc9;
256 }
257#else
258 RTTHREAD hThreadSelf = RTThreadSelf();
259#endif
260 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
261 DWORD rc = WaitForSingleObjectEx(pThis->hev,
262 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
263 TRUE /*fAlertable*/);
264 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
265 return rtSemEventWaitHandleStatus(pThis, rc);
266}
267
268
269RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
270{
271#ifdef RTSEMEVENT_STRICT
272 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
273 AssertPtrReturnVoid(pThis);
274 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
275
276 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
277 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
278#endif
279}
280
281
282RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
283{
284#ifdef RTSEMEVENT_STRICT
285 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
286 AssertPtrReturnVoid(pThis);
287 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
288
289 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
290 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
291#endif
292}
293
294
295RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
296{
297#ifdef RTSEMEVENT_STRICT
298 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
299 AssertPtrReturnVoid(pThis);
300 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
301
302 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
303#endif
304}
305
Note: See TracBrowser for help on using the repository browser.

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