VirtualBox

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

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

IPRT,PDMCritSect,Main: Moved code dealing with lock counting from RTThread to RTLockValidator. Fixed thread termination assertion on windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.6 KB
Line 
1/* $Id: semmutex-win.cpp 25409 2009-12-15 15:04:41Z 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 /** The mutex handle. */
60 HANDLE hMtx;
61#ifdef RTSEMMUTEX_STRICT
62 /** Lock validator record associated with this mutex. */
63 RTLOCKVALIDATORREC ValidatorRec;
64#endif
65};
66
67
68/* Undefine debug mappings. */
69#undef RTSemMutexRequest
70#undef RTSemMutexRequestNoResume
71
72
73RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
74{
75 int rc;
76
77 /*
78 * Create the semaphore.
79 */
80 HANDLE hMtx = CreateMutex(NULL, FALSE, NULL);
81 if (hMtx)
82 {
83 RTSEMMUTEXINTERNAL *pThis = (RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(*pThis));
84 if (pThis)
85 {
86 pThis->u32Magic = RTSEMMUTEX_MAGIC;
87 pThis->hMtx = hMtx;
88#ifdef RTSEMMUTEX_STRICT
89 RTLockValidatorInit(&pThis->ValidatorRec, NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_NONE, NULL, pThis);
90#endif
91 *pMutexSem = pThis;
92 return VINF_SUCCESS;
93 }
94
95 rc = VERR_NO_MEMORY;
96 }
97 else
98 rc = RTErrConvertFromWin32(GetLastError());
99 return rc;
100}
101
102
103RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
104{
105 /*
106 * Validate.
107 */
108 RTSEMMUTEXINTERNAL *pThis = MutexSem;
109 if (pThis == NIL_RTSEMMUTEX)
110 return VINF_SUCCESS;
111 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
112 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
113
114 /*
115 * Close semaphore handle.
116 */
117 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
118 HANDLE hMtx = pThis->hMtx;
119 ASMAtomicWritePtr((void * volatile *)&pThis->hMtx, (void *)INVALID_HANDLE_VALUE);
120
121 int rc = VINF_SUCCESS;
122 if (!CloseHandle(hMtx))
123 {
124 rc = RTErrConvertFromWin32(GetLastError());
125 AssertMsgFailed(("%p rc=%d lasterr=%d\n", pThis->hMtx, rc, GetLastError()));
126 }
127
128#ifdef RTSEMMUTEX_STRICT
129 RTLockValidatorDelete(&pThis->ValidatorRec);
130#endif
131 RTMemFree(pThis);
132 return rc;
133}
134
135
136/**
137 * Internal worker for RTSemMutexRequestNoResume and it's debug companion.
138 *
139 * @returns Same as RTSEmMutexRequestNoResume
140 * @param MutexSem The mutex handle.
141 * @param cMillies The number of milliseconds to wait.
142 * @param TSEMMUTEX_STRICT_POS_DECL The source position of the caller.
143 */
144DECL_FORCE_INLINE(int) rtSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies, RTSEMMUTEX_STRICT_POS_DECL)
145{
146 /*
147 * Validate.
148 */
149 RTSEMMUTEXINTERNAL *pThis = MutexSem;
150 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
151 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
152
153#ifdef RTSEMMUTEX_STRICT
154 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
155 RTLockValidatorCheckOrder(&pThis->ValidatorRec, hThreadSelf, RTSEMMUTEX_STRICT_POS_ARGS);
156#else
157 RTTHREAD hThreadSelf = RTThreadSelf();
158#endif
159
160 /*
161 * Lock mutex semaphore.
162 */
163 if (cMillies > 0)
164 RTSEMMUTEX_STRICT_BLOCK(hThreadSelf, &pThis->ValidatorRec);
165 int rc = WaitForSingleObjectEx(pThis->hMtx,
166 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
167 TRUE /*bAlertable*/);
168 RTSEMMUTEX_STRICT_UNBLOCK(hThreadSelf);
169 switch (rc)
170 {
171 case WAIT_OBJECT_0:
172#ifdef RTSEMMUTEX_STRICT
173 RTLockValidatorWriteLockInc(RTLockValidatorSetOwner(&pThis->ValidatorRec, hThreadSelf, RTSEMMUTEX_STRICT_POS_ARGS));
174#endif
175 return VINF_SUCCESS;
176
177 case WAIT_TIMEOUT: return VERR_TIMEOUT;
178 case WAIT_IO_COMPLETION: return VERR_INTERRUPTED;
179 case WAIT_ABANDONED: return VERR_SEM_OWNER_DIED;
180 default:
181 {
182 AssertMsgFailed(("Wait on MutexSem %p failed, rc=%d lasterr=%d\n", MutexSem, rc, GetLastError()));
183 int rc2 = RTErrConvertFromWin32(GetLastError());
184 if (rc2 != 0)
185 return rc2;
186
187 AssertMsgFailed(("WaitForSingleObject(event) -> rc=%d while converted lasterr=%d\n", rc, rc2));
188 return VERR_INTERNAL_ERROR;
189 }
190 }
191}
192
193
194RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
195{
196#ifndef RTSEMMUTEX_STRICT
197 return rtSemMutexRequestNoResume(MutexSem, cMillies, RTSEMMUTEX_STRICT_POS_ARGS);
198#else
199 return RTSemMutexRequestNoResumeDebug(MutexSem, cMillies, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
200#endif
201}
202
203
204RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX MutexSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
205{
206#ifdef RTSEMMUTEX_STRICT
207 return rtSemMutexRequestNoResume(MutexSem, cMillies, RTSEMMUTEX_STRICT_POS_ARGS);
208#else
209 return RTSemMutexRequestNoResume(MutexSem, cMillies);
210#endif
211}
212
213
214RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
215{
216 /*
217 * Validate.
218 */
219 RTSEMMUTEXINTERNAL *pThis = MutexSem;
220 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
221 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
222
223 /*
224 * Unlock mutex semaphore.
225 */
226#ifdef RTSEMMUTEX_STRICT
227 if ( pThis->ValidatorRec.hThread != NIL_RTTHREAD
228 && pThis->ValidatorRec.hThread == RTThreadSelf())
229 RTLockValidatorWriteLockDec(RTLockValidatorUnsetOwner(&pThis->ValidatorRec));
230 else
231 AssertMsgFailed(("%p hThread=%RTthrd\n", pThis, pThis->ValidatorRec.hThread));
232#endif
233 if (ReleaseMutex(pThis->hMtx))
234 return VINF_SUCCESS;
235 int rc = RTErrConvertFromWin32(GetLastError());
236 AssertMsgFailed(("%p/%p, rc=%Rrc lasterr=%d\n", pThis, pThis->hMtx, rc, GetLastError()));
237 return rc;
238}
239
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