VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use