VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/semevent-win.cpp@ 57634

Last change on this file since 57634 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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