VirtualBox

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

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

iprt/lockvalidation: give better names to anonymous locks

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1/* $Id: semeventmulti-win.cpp 25831 2010-01-14 15:12:53Z 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.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 * 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 if (!pszNameFmt)
98 {
99 static uint32_t volatile s_iSemEventMultiAnon = 0;
100 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
101 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
102 "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
103 }
104 else
105 {
106 va_list va;
107 va_start(va, pszNameFmt);
108 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
109 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
110 pszNameFmt, va);
111 va_end(va);
112 }
113 pThis->fEverHadSignallers = false;
114#endif
115
116 *phEventMultiSem = pThis;
117 return VINF_SUCCESS;
118 }
119
120 DWORD dwErr = GetLastError();
121 RTMemFree(pThis);
122 return RTErrConvertFromWin32(dwErr);
123}
124
125
126RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
127{
128 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
129 if (pThis == NIL_RTSEMEVENT) /* don't bitch */
130 return VINF_SUCCESS;
131 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
132 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
133
134 /*
135 * Invalidate the handle and close the semaphore.
136 */
137 int rc = VINF_SUCCESS;
138 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC, RTSEMEVENTMULTI_MAGIC), VERR_INVALID_HANDLE);
139 if (CloseHandle(pThis->hev))
140 {
141#ifdef RTSEMEVENT_STRICT
142 RTLockValidatorRecSharedDelete(&pThis->Signallers);
143#endif
144 RTMemFree(pThis);
145 }
146 else
147 {
148 DWORD dwErr = GetLastError();
149 rc = RTErrConvertFromWin32(dwErr);
150 AssertMsgFailed(("Destroy hEventMultiSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
151 /* Leak it. */
152 }
153
154 return rc;
155}
156
157
158RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
159{
160 /*
161 * Validate input.
162 */
163 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
164 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
165 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
166
167#ifdef RTSEMEVENT_STRICT
168 if (pThis->fEverHadSignallers)
169 {
170 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
171 if (RT_FAILURE(rc9))
172 return rc9;
173 }
174#endif
175
176 /*
177 * Signal the object.
178 */
179 if (SetEvent(pThis->hev))
180 return VINF_SUCCESS;
181 DWORD dwErr = GetLastError();
182 AssertMsgFailed(("Signaling hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
183 return RTErrConvertFromWin32(dwErr);
184}
185
186
187RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
188{
189 /*
190 * Validate input.
191 */
192 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
193 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
194 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
195
196 /*
197 * Reset the object.
198 */
199 if (ResetEvent(pThis->hev))
200 return VINF_SUCCESS;
201 DWORD dwErr = GetLastError();
202 AssertMsgFailed(("Resetting hEventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
203 return RTErrConvertFromWin32(dwErr);
204}
205
206
207/** Goto avoidance. */
208DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTMULTIINTERNAL *pThis, DWORD rc)
209{
210 switch (rc)
211 {
212 case WAIT_OBJECT_0: return VINF_SUCCESS;
213 case WAIT_TIMEOUT: return VERR_TIMEOUT;
214 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
215 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
216 default:
217 AssertMsgFailed(("%u\n", rc));
218 case WAIT_FAILED:
219 {
220 int rc2 = RTErrConvertFromWin32(GetLastError());
221 AssertMsgFailed(("Wait on hEventMultiSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
222 if (rc2)
223 return rc2;
224
225 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
226 return VERR_INTERNAL_ERROR;
227 }
228 }
229}
230
231
232#undef RTSemEventMultiWaitNoResume
233RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
234{
235 PCRTLOCKVALSRCPOS pSrcPos = NULL;
236
237 /*
238 * Validate input.
239 */
240 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
241 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
242 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
243
244 /*
245 * Wait for condition.
246 */
247#ifdef RTSEMEVENT_STRICT
248 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
249 if (pThis->fEverHadSignallers)
250 {
251 DWORD rc = WaitForSingleObjectEx(pThis->hev,
252 0 /*Timeout*/,
253 TRUE /*fAlertable*/);
254 if (rc != WAIT_TIMEOUT || cMillies == 0)
255 return rtSemEventWaitHandleStatus(pThis, rc);
256 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
257 cMillies, RTTHREADSTATE_EVENT_MULTI, true);
258 if (RT_FAILURE(rc9))
259 return rc9;
260 }
261#else
262 RTTHREAD hThreadSelf = RTThreadSelf();
263#endif
264 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
265 DWORD rc = WaitForSingleObjectEx(pThis->hev,
266 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
267 TRUE /*fAlertable*/);
268 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
269 return rtSemEventWaitHandleStatus(pThis, rc);
270}
271
272
273RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
274{
275#ifdef RTSEMEVENT_STRICT
276 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
277 AssertPtrReturnVoid(pThis);
278 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
279
280 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
281 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
282#endif
283}
284
285
286RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
287{
288#ifdef RTSEMEVENT_STRICT
289 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
290 AssertPtrReturnVoid(pThis);
291 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
292
293 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
294 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
295#endif
296}
297
298
299RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
300{
301#ifdef RTSEMEVENT_STRICT
302 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
303 AssertPtrReturnVoid(pThis);
304 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
305
306 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
307#endif
308}
309
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