VirtualBox

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

Last change on this file since 28800 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/* $Id: semevent-win.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * IPRT - Event Sempahore, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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/strict.h"
45
46
47/*******************************************************************************
48* Defined Constants And Macros *
49*******************************************************************************/
50struct RTSEMEVENTINTERNAL
51{
52 /** Magic value (RTSEMEVENT_MAGIC). */
53 uint32_t u32Magic;
54 /** The event handle. */
55 HANDLE hev;
56#ifdef RTSEMEVENT_STRICT
57 /** Signallers. */
58 RTLOCKVALRECSHRD Signallers;
59 /** Indicates that lock validation should be performed. */
60 bool volatile fEverHadSignallers;
61#endif
62};
63
64
65
66RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
67{
68 return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
69}
70
71
72RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
73{
74 AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
75
76 struct RTSEMEVENTINTERNAL *pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(*pThis));
77 if (!pThis)
78 return VERR_NO_MEMORY;
79
80 /*
81 * Create the semaphore.
82 * (Auto reset, not signaled, private event object.)
83 */
84 pThis->hev = CreateEvent(NULL, FALSE, FALSE, NULL);
85 if (pThis->hev != NULL) /* not INVALID_HANDLE_VALUE */
86 {
87 pThis->u32Magic = RTSEMEVENT_MAGIC;
88#ifdef RTSEMEVENT_STRICT
89 if (!pszNameFmt)
90 {
91 static uint32_t volatile s_iSemEventAnon = 0;
92 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
93 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
94 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
95 }
96 else
97 {
98 va_list va;
99 va_start(va, pszNameFmt);
100 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
101 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
102 pszNameFmt, va);
103 va_end(va);
104 }
105 pThis->fEverHadSignallers = false;
106#endif
107
108 *phEventSem = pThis;
109 return VINF_SUCCESS;
110 }
111
112 DWORD dwErr = GetLastError();
113 RTMemFree(pThis);
114 return RTErrConvertFromWin32(dwErr);
115}
116
117
118RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
119{
120 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
121 if (pThis == NIL_RTSEMEVENT)
122 return VINF_SUCCESS;
123 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
124 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
125
126 /*
127 * Invalidate the handle and close the semaphore.
128 */
129 int rc = VINF_SUCCESS;
130 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC, RTSEMEVENT_MAGIC), VERR_INVALID_HANDLE);
131 if (CloseHandle(pThis->hev))
132 {
133#ifdef RTSEMEVENT_STRICT
134 RTLockValidatorRecSharedDelete(&pThis->Signallers);
135#endif
136 RTMemFree(pThis);
137 }
138 else
139 {
140 DWORD dwErr = GetLastError();
141 rc = RTErrConvertFromWin32(dwErr);
142 AssertMsgFailed(("Destroy hEventSem %p failed, lasterr=%u (%Rrc)\n", pThis, dwErr, rc));
143 /* Leak it. */
144 }
145
146 return rc;
147}
148
149
150RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
151{
152 /*
153 * Validate input.
154 */
155 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
156 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
157 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
158
159#ifdef RTSEMEVENT_STRICT
160 if (pThis->fEverHadSignallers)
161 {
162 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
163 if (RT_FAILURE(rc9))
164 return rc9;
165 }
166#endif
167
168 /*
169 * Signal the object.
170 */
171 if (SetEvent(pThis->hev))
172 return VINF_SUCCESS;
173 DWORD dwErr = GetLastError();
174 AssertMsgFailed(("Signaling hEventSem %p failed, lasterr=%d\n", pThis, dwErr));
175 return RTErrConvertFromWin32(dwErr);
176}
177
178
179/** Goto avoidance. */
180DECL_FORCE_INLINE(int) rtSemEventWaitHandleStatus(struct RTSEMEVENTINTERNAL *pThis, DWORD rc)
181{
182 switch (rc)
183 {
184 case WAIT_OBJECT_0: return VINF_SUCCESS;
185 case WAIT_TIMEOUT: return VERR_TIMEOUT;
186 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
187 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
188 default:
189 AssertMsgFailed(("%u\n", rc));
190 case WAIT_FAILED:
191 {
192 int rc2 = RTErrConvertFromWin32(GetLastError());
193 AssertMsgFailed(("Wait on hEventSem %p failed, rc=%d lasterr=%d\n", pThis, rc, GetLastError()));
194 if (rc2)
195 return rc2;
196
197 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
198 return VERR_INTERNAL_ERROR;
199 }
200 }
201}
202
203
204#undef RTSemEventWaitNoResume
205RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
206{
207 PCRTLOCKVALSRCPOS pSrcPos = NULL;
208
209 /*
210 * Validate input.
211 */
212 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
213 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
214 AssertReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
215
216 /*
217 * Wait for condition.
218 */
219#ifdef RTSEMEVENT_STRICT
220 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
221 if (pThis->fEverHadSignallers)
222 {
223 DWORD rc = WaitForSingleObjectEx(pThis->hev,
224 0 /*Timeout*/,
225 TRUE /*fAlertable*/);
226 if (rc != WAIT_TIMEOUT || cMillies == 0)
227 return rtSemEventWaitHandleStatus(pThis, rc);
228 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
229 cMillies, RTTHREADSTATE_EVENT, true);
230 if (RT_FAILURE(rc9))
231 return rc9;
232 }
233#else
234 RTTHREAD hThreadSelf = RTThreadSelf();
235#endif
236 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
237 DWORD rc = WaitForSingleObjectEx(pThis->hev,
238 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
239 TRUE /*fAlertable*/);
240 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
241 return rtSemEventWaitHandleStatus(pThis, rc);
242}
243
244
245RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
246{
247#ifdef RTSEMEVENT_STRICT
248 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
249 AssertPtrReturnVoid(pThis);
250 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
251
252 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
253 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
254#endif
255}
256
257
258RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
259{
260#ifdef RTSEMEVENT_STRICT
261 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
262 AssertPtrReturnVoid(pThis);
263 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
264
265 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
266 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
267#endif
268}
269
270
271RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
272{
273#ifdef RTSEMEVENT_STRICT
274 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
275 AssertPtrReturnVoid(pThis);
276 AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
277
278 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
279#endif
280}
281
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