VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/semmutex-win.cpp@ 34801

Last change on this file since 34801 was 30111, checked in by vboxsync, 15 years ago

iprt/asm.h,*: Revised the ASMAtomic*Ptr functions and macros. The new saves lots of unsafe (void * volatile *) casts as well as adding some type safety when using GCC (typeof rulez).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.9 KB
Line 
1/* $Id: semmutex-win.cpp 30111 2010-06-09 12:14:59Z vboxsync $ */
2/** @file
3 * IPRT - Mutex Semaphores, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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*******************************************************************************/
50/** Posix internal representation of a Mutex semaphore. */
51struct RTSEMMUTEXINTERNAL
52{
53 /** Magic value (RTSEMMUTEX_MAGIC). */
54 uint32_t u32Magic;
55 /** Recursion count. */
56 uint32_t volatile cRecursions;
57 /** The owner thread. */
58 RTNATIVETHREAD volatile hNativeOwner;
59 /** The mutex handle. */
60 HANDLE hMtx;
61#ifdef RTSEMMUTEX_STRICT
62 /** Lock validator record associated with this mutex. */
63 RTLOCKVALRECEXCL ValidatorRec;
64#endif
65};
66
67
68
69#undef RTSemMutexCreate
70RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
71{
72 return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
73}
74
75
76RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
77 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
78{
79 AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
80
81 /*
82 * Create the semaphore.
83 */
84 int rc;
85 HANDLE hMtx = CreateMutex(NULL, FALSE, NULL);
86 if (hMtx)
87 {
88 RTSEMMUTEXINTERNAL *pThis = (RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(*pThis));
89 if (pThis)
90 {
91 pThis->u32Magic = RTSEMMUTEX_MAGIC;
92 pThis->hMtx = hMtx;
93 pThis->hNativeOwner = NIL_RTNATIVETHREAD;
94 pThis->cRecursions = 0;
95#ifdef RTSEMMUTEX_STRICT
96 if (!pszNameFmt)
97 {
98 static uint32_t volatile s_iMutexAnon = 0;
99 RTLockValidatorRecExclInit(&pThis->ValidatorRec, hClass, uSubClass, pThis,
100 !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL),
101 "RTSemMutex-%u", ASMAtomicIncU32(&s_iMutexAnon) - 1);
102 }
103 else
104 {
105 va_list va;
106 va_start(va, pszNameFmt);
107 RTLockValidatorRecExclInitV(&pThis->ValidatorRec, hClass, uSubClass, pThis,
108 !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
109 va_end(va);
110 }
111#endif
112 *phMutexSem = pThis;
113 return VINF_SUCCESS;
114 }
115
116 rc = VERR_NO_MEMORY;
117 }
118 else
119 rc = RTErrConvertFromWin32(GetLastError());
120 return rc;
121}
122
123
124RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
125{
126 /*
127 * Validate.
128 */
129 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
130 if (pThis == NIL_RTSEMMUTEX)
131 return VINF_SUCCESS;
132 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
133 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
134
135 /*
136 * Close semaphore handle.
137 */
138 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
139 HANDLE hMtx = pThis->hMtx;
140 ASMAtomicWritePtr(&pThis->hMtx, INVALID_HANDLE_VALUE);
141
142 int rc = VINF_SUCCESS;
143 if (!CloseHandle(hMtx))
144 {
145 rc = RTErrConvertFromWin32(GetLastError());
146 AssertMsgFailed(("%p rc=%d lasterr=%d\n", pThis->hMtx, rc, GetLastError()));
147 }
148
149#ifdef RTSEMMUTEX_STRICT
150 RTLockValidatorRecExclDelete(&pThis->ValidatorRec);
151#endif
152 RTMemFree(pThis);
153 return rc;
154}
155
156
157RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
158{
159#ifdef RTSEMMUTEX_STRICT
160 /*
161 * Validate.
162 */
163 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
164 AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
165 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
166
167 return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
168#else
169 return RTLOCKVAL_SUB_CLASS_INVALID;
170#endif
171}
172
173
174/**
175 * Internal worker for RTSemMutexRequestNoResume and it's debug companion.
176 *
177 * @returns Same as RTSEmMutexRequestNoResume
178 * @param hMutexSem The mutex handle.
179 * @param cMillies The number of milliseconds to wait.
180 * @param pSrcPos The source position of the caller.
181 */
182DECL_FORCE_INLINE(int) rtSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, PCRTLOCKVALSRCPOS pSrcPos)
183{
184 /*
185 * Validate.
186 */
187 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
188 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
189 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
190
191 /*
192 * Check for recursive entry.
193 */
194 RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
195 RTNATIVETHREAD hNativeOwner;
196 ASMAtomicReadHandle(&pThis->hNativeOwner, &hNativeOwner);
197 if (hNativeOwner == hNativeSelf)
198 {
199#ifdef RTSEMMUTEX_STRICT
200 int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorRec, pSrcPos);
201 if (RT_FAILURE(rc9))
202 return rc9;
203#endif
204 ASMAtomicIncU32(&pThis->cRecursions);
205 return VINF_SUCCESS;
206 }
207
208 /*
209 * Lock mutex semaphore.
210 */
211 RTTHREAD hThreadSelf = NIL_RTTHREAD;
212 if (cMillies > 0)
213 {
214#ifdef RTSEMMUTEX_STRICT
215 hThreadSelf = RTThreadSelfAutoAdopt();
216 int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true,
217 cMillies, RTTHREADSTATE_MUTEX, true);
218 if (RT_FAILURE(rc9))
219 return rc9;
220#else
221 hThreadSelf = RTThreadSelf();
222 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_MUTEX, true);
223#endif
224 }
225 DWORD rc = WaitForSingleObjectEx(pThis->hMtx,
226 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
227 TRUE /*fAlertable*/);
228 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
229 switch (rc)
230 {
231 case WAIT_OBJECT_0:
232#ifdef RTSEMMUTEX_STRICT
233 RTLockValidatorRecExclSetOwner(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true);
234#endif
235 ASMAtomicWriteHandle(&pThis->hNativeOwner, hNativeSelf);
236 ASMAtomicWriteU32(&pThis->cRecursions, 1);
237 return VINF_SUCCESS;
238
239 case WAIT_TIMEOUT: return VERR_TIMEOUT;
240 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
241 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
242 default:
243 AssertMsgFailed(("%u\n", rc));
244 case WAIT_FAILED:
245 {
246 int rc2 = RTErrConvertFromWin32(GetLastError());
247 AssertMsgFailed(("Wait on hMutexSem %p failed, rc=%d lasterr=%d\n", hMutexSem, rc, GetLastError()));
248 if (rc2 != VINF_SUCCESS)
249 return rc2;
250
251 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
252 return VERR_INTERNAL_ERROR;
253 }
254 }
255}
256
257
258#undef RTSemMutexRequestNoResume
259RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
260{
261#ifndef RTSEMMUTEX_STRICT
262 return rtSemMutexRequestNoResume(hMutexSem, cMillies, NULL);
263#else
264 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
265 return rtSemMutexRequestNoResume(hMutexSem, cMillies, &SrcPos);
266#endif
267}
268
269
270RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
271{
272 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
273 return rtSemMutexRequestNoResume(hMutexSem, cMillies, &SrcPos);
274}
275
276
277RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem)
278{
279 /*
280 * Validate.
281 */
282 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
283 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
284 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
285
286 /*
287 * Check ownership and recursions.
288 */
289 RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
290 RTNATIVETHREAD hNativeOwner;
291 ASMAtomicReadHandle(&pThis->hNativeOwner, &hNativeOwner);
292 if (RT_UNLIKELY(hNativeOwner != hNativeSelf))
293 {
294 AssertMsgFailed(("Not owner of mutex %p!! hNativeSelf=%RTntrd Owner=%RTntrd cRecursions=%d\n",
295 pThis, hNativeSelf, hNativeOwner, pThis->cRecursions));
296 return VERR_NOT_OWNER;
297 }
298 if (pThis->cRecursions > 1)
299 {
300#ifdef RTSEMMUTEX_STRICT
301 int rc9 = RTLockValidatorRecExclUnwind(&pThis->ValidatorRec);
302 if (RT_FAILURE(rc9))
303 return rc9;
304#endif
305 ASMAtomicDecU32(&pThis->cRecursions);
306 return VINF_SUCCESS;
307 }
308
309 /*
310 * Unlock mutex semaphore.
311 */
312#ifdef RTSEMMUTEX_STRICT
313 int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorRec, false);
314 if (RT_FAILURE(rc9))
315 return rc9;
316#endif
317 ASMAtomicWriteU32(&pThis->cRecursions, 0);
318 ASMAtomicWriteHandle(&pThis->hNativeOwner, NIL_RTNATIVETHREAD);
319
320 if (ReleaseMutex(pThis->hMtx))
321 return VINF_SUCCESS;
322
323 int rc = RTErrConvertFromWin32(GetLastError());
324 AssertMsgFailed(("%p/%p, rc=%Rrc lasterr=%d\n", pThis, pThis->hMtx, rc, GetLastError()));
325 return rc;
326}
327
328
329RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
330{
331 /*
332 * Validate.
333 */
334 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
335 AssertPtrReturn(pThis, false);
336 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, false);
337
338 RTNATIVETHREAD hNativeOwner;
339 ASMAtomicReadHandle(&pThis->hNativeOwner, &hNativeOwner);
340 return hNativeOwner != NIL_RTNATIVETHREAD;
341}
342
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