VirtualBox

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

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

iprt/lockvalidation: give better names to anonymous locks

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