VirtualBox

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

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

iprt,pdmcritsect: Some more lock validator code, almost there now... :-)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.3 KB
Line 
1/* $Id: semeventmulti-win.cpp 25685 2010-01-07 22:03:06Z 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/* Undefine debug mappings. */
73#undef RTSemEventMultiWait
74#undef RTSemEventMultiWaitNoResume
75
76
77RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
78{
79 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(*pThis));
80 if (!pThis)
81 return VERR_NO_MEMORY;
82
83 /*
84 * Create the semaphore.
85 * (Manual reset, not signaled, private event object.)
86 */
87 pThis->hev = CreateEvent(NULL, TRUE, FALSE, NULL);
88 if (pThis->hev != NULL) /* not INVALID_HANDLE_VALUE */
89 {
90 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
91#ifdef RTSEMEVENT_STRICT
92 RTLockValidatorRecSharedInit(&pThis->Signallers,
93 NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY,
94 "RTSemEvent", pThis, true /*fSignaller*/, true);
95 pThis->fEverHadSignallers = false;
96#endif
97
98 *pEventMultiSem = pThis;
99 return VINF_SUCCESS;
100 }
101
102 DWORD dwErr = GetLastError();
103 RTMemFree(pThis);
104 return RTErrConvertFromWin32(dwErr);
105}
106
107
108RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
109{
110 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
111 if (pThis == NIL_RTSEMEVENT) /* don't bitch */
112 return VERR_INVALID_HANDLE;
113 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
114 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
115
116 /*
117 * Invalidate the handle and close the semaphore.
118 */
119 int rc = VINF_SUCCESS;
120 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC, RTSEMEVENTMULTI_MAGIC), VERR_INVALID_HANDLE);
121 if (CloseHandle(pThis->hev))
122 {
123#ifdef RTSEMEVENT_STRICT
124 RTLockValidatorRecSharedDelete(&pThis->Signallers);
125#endif
126 RTMemFree(pThis);
127 }
128 else
129 {
130 DWORD dwErr = GetLastError();
131 rc = RTErrConvertFromWin32(dwErr);
132 AssertMsgFailed(("Destroy EventMultiSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
133 /* Leak it. */
134 }
135
136 return rc;
137}
138
139
140RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
141{
142 /*
143 * Validate input.
144 */
145 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
146 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
147 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
148
149#ifdef RTSEMEVENT_STRICT
150 if (pThis->fEverHadSignallers)
151 {
152 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
153 if (RT_FAILURE(rc9))
154 return rc9;
155 }
156#endif
157
158 /*
159 * Signal the object.
160 */
161 if (SetEvent(pThis->hev))
162 return VINF_SUCCESS;
163 DWORD dwErr = GetLastError();
164 AssertMsgFailed(("Signaling EventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
165 return RTErrConvertFromWin32(dwErr);
166}
167
168
169RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
170{
171 /*
172 * Validate input.
173 */
174 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
175 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
176 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
177
178 /*
179 * Reset the object.
180 */
181 if (ResetEvent(pThis->hev))
182 return VINF_SUCCESS;
183 DWORD dwErr = GetLastError();
184 AssertMsgFailed(("Resetting EventMultiSem %p failed, lasterr=%d\n", pThis, dwErr));
185 return RTErrConvertFromWin32(dwErr);
186}
187
188
189/** Goto avoidance. */
190DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTMULTIINTERNAL *pThis, DWORD rc)
191{
192 switch (rc)
193 {
194 case WAIT_OBJECT_0: return VINF_SUCCESS;
195 case WAIT_TIMEOUT: return VERR_TIMEOUT;
196 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
197 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
198 default:
199 AssertMsgFailed(("%u\n", rc));
200 case WAIT_FAILED:
201 {
202 int rc2 = RTErrConvertFromWin32(GetLastError());
203 AssertMsgFailed(("Wait on EventMultiSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
204 if (rc2)
205 return rc2;
206
207 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
208 return VERR_INTERNAL_ERROR;
209 }
210 }
211}
212
213
214RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
215{
216 PCRTLOCKVALSRCPOS pSrcPos = NULL;
217
218 /*
219 * Validate input.
220 */
221 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
222 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
223 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
224
225 /*
226 * Wait for condition.
227 */
228#ifdef RTSEMEVENT_STRICT
229 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
230 if (pThis->fEverHadSignallers)
231 {
232 DWORD rc = WaitForSingleObjectEx(pThis->hev,
233 0 /*Timeout*/,
234 TRUE /*fAlertable*/);
235 if (rc != WAIT_TIMEOUT || cMillies == 0)
236 return rtSemEventWaitHandleStatus(pThis, rc);
237 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
238 cMillies, RTTHREADSTATE_EVENT_MULTI, true);
239 if (RT_FAILURE(rc9))
240 return rc9;
241 }
242#else
243 RTTHREAD hThreadSelf = RTThreadSelf();
244#endif
245 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
246 DWORD rc = WaitForSingleObjectEx(pThis->hev,
247 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
248 TRUE /*fAlertable*/);
249 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
250 return rtSemEventWaitHandleStatus(pThis, rc);
251}
252
253
254RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
255{
256#ifdef RTSEMEVENT_STRICT
257 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
258 AssertPtrReturnVoid(pThis);
259 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
260
261 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
262 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
263#endif
264}
265
266
267RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
268{
269#ifdef RTSEMEVENT_STRICT
270 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
271 AssertPtrReturnVoid(pThis);
272 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
273
274 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
275 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
276#endif
277}
278
279
280RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
281{
282#ifdef RTSEMEVENT_STRICT
283 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
284 AssertPtrReturnVoid(pThis);
285 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
286
287 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
288#endif
289}
290
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