VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.2 KB
Line 
1/* $Id: semevent-win.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Event Semaphore, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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 <iprt/win/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#else
116 RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
117#endif
118
119 *phEventSem = pThis;
120 return VINF_SUCCESS;
121 }
122
123 DWORD dwErr = GetLastError();
124 if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
125 RTMemFree(pThis);
126 else
127 rtMemBaseFree(pThis);
128 return RTErrConvertFromWin32(dwErr);
129}
130
131
132RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
133{
134 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
135 if (pThis == NIL_RTSEMEVENT)
136 return VINF_SUCCESS;
137 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
138 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
139
140 /*
141 * Invalidate the handle and close the semaphore.
142 */
143 int rc = VINF_SUCCESS;
144 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC, RTSEMEVENT_MAGIC), VERR_INVALID_HANDLE);
145 if (CloseHandle(pThis->hev))
146 {
147#ifdef RTSEMEVENT_STRICT
148 RTLockValidatorRecSharedDelete(&pThis->Signallers);
149#endif
150 if (!(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
151 RTMemFree(pThis);
152 else
153 rtMemBaseFree(pThis);
154 }
155 else
156 {
157 DWORD dwErr = GetLastError();
158 rc = RTErrConvertFromWin32(dwErr);
159 AssertMsgFailed(("Destroy hEventSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
160 /* Leak it. */
161 }
162
163 return rc;
164}
165
166
167RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
168{
169 /*
170 * Validate input.
171 */
172 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
173 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
174 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
175
176#ifdef RTSEMEVENT_STRICT
177 if (pThis->fEverHadSignallers)
178 {
179 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
180 if (RT_FAILURE(rc9))
181 return rc9;
182 }
183#endif
184
185 /*
186 * Signal the object.
187 */
188 if (SetEvent(pThis->hev))
189 return VINF_SUCCESS;
190 DWORD dwErr = GetLastError();
191 AssertMsgFailed(("Signaling hEventSem %p failed, lasterr=%d\n", pThis, dwErr));
192 return RTErrConvertFromWin32(dwErr);
193}
194
195
196/** Goto avoidance. */
197DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTINTERNAL *pThis, DWORD rc)
198{
199 switch (rc)
200 {
201 case WAIT_OBJECT_0: return VINF_SUCCESS;
202 case WAIT_TIMEOUT: return VERR_TIMEOUT;
203 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
204 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
205 default:
206 AssertMsgFailed(("%u\n", rc));
207 case WAIT_FAILED:
208 {
209 int rc2 = RTErrConvertFromWin32(GetLastError());
210 AssertMsgFailed(("Wait on hEventSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
211 if (rc2)
212 return rc2;
213
214 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
215 RT_NOREF_PV(pThis);
216 return VERR_INTERNAL_ERROR;
217 }
218 }
219}
220
221
222#undef RTSemEventWaitNoResume
223RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
224{
225 /*
226 * Validate input.
227 */
228 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
229 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
230 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
231
232 /*
233 * Wait for condition.
234 */
235#ifdef RTSEMEVENT_STRICT
236 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
237 ? RTThreadSelfAutoAdopt()
238 : RTThreadSelf();
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, NULL /*pSrcPos*/, false,
247 cMillies, RTTHREADSTATE_EVENT, true);
248 if (RT_FAILURE(rc9))
249 return rc9;
250 }
251#else
252 RTTHREAD hThreadSelf = RTThreadSelf();
253#endif
254 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
255 DWORD rc = WaitForSingleObjectEx(pThis->hev,
256 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
257 TRUE /*fAlertable*/);
258 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
259 return rtSemEventWaitHandleStatus(pThis, rc);
260}
261
262
263RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
264{
265#ifdef RTSEMEVENT_STRICT
266 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
267 AssertPtrReturnVoid(pThis);
268 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
269
270 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
271 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
272#else
273 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
274#endif
275}
276
277
278RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
279{
280#ifdef RTSEMEVENT_STRICT
281 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
282 AssertPtrReturnVoid(pThis);
283 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
284
285 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
286 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
287#else
288 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
289#endif
290}
291
292
293RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
294{
295#ifdef RTSEMEVENT_STRICT
296 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
297 AssertPtrReturnVoid(pThis);
298 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
299
300 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
301#else
302 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
303#endif
304}
305
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use