VirtualBox

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

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

iprt/semmutex*: Added RTSemMutexIsOwned. Rewrote mutex recursion handling for windows (semmutex-win.cpp).

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