VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/semmutex-r0drv-nt.cpp@ 62448

Last change on this file since 62448 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.2 KB
Line 
1/* $Id: semmutex-r0drv-nt.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * IPRT - Mutex Semaphores, Ring-0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define RTSEMMUTEX_WITHOUT_REMAPPING
33#include "the-nt-kernel.h"
34#include <iprt/semaphore.h>
35#include <iprt/alloc.h>
36#include <iprt/assert.h>
37#include <iprt/asm.h>
38#include <iprt/err.h>
39
40#include "internal/magics.h"
41
42
43/*********************************************************************************************************************************
44* Structures and Typedefs *
45*********************************************************************************************************************************/
46/**
47 * NT mutex semaphore.
48 */
49typedef struct RTSEMMUTEXINTERNAL
50{
51 /** Magic value (RTSEMMUTEX_MAGIC). */
52 uint32_t volatile u32Magic;
53#ifdef RT_USE_FAST_MUTEX
54 /** The fast mutex object. */
55 FAST_MUTEX Mutex;
56#else
57 /** The NT Mutex object. */
58 KMUTEX Mutex;
59#endif
60} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
61
62
63
64RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
65{
66 return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
67}
68
69
70RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
71 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
72{
73 AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
74
75 AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
76 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
77 if (!pThis)
78 return VERR_NO_MEMORY;
79
80 pThis->u32Magic = RTSEMMUTEX_MAGIC;
81#ifdef RT_USE_FAST_MUTEX
82 ExInitializeFastMutex(&pThis->Mutex);
83#else
84 KeInitializeMutex(&pThis->Mutex, 0);
85#endif
86
87 *phMutexSem = pThis;
88 return VINF_SUCCESS;
89}
90
91
92RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
93{
94 /*
95 * Validate input.
96 */
97 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
98 if (pThis == NIL_RTSEMMUTEX)
99 return VINF_SUCCESS;
100 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
101 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
102
103 /*
104 * Invalidate it and signal the object just in case.
105 */
106 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
107 RTMemFree(pThis);
108 return VINF_SUCCESS;
109}
110
111
112/**
113 * Internal worker for RTSemMutexRequest and RTSemMutexRequestNoResume
114 *
115 * @returns IPRT status code.
116 * @param hMutexSem The mutex handle.
117 * @param cMillies The timeout.
118 * @param fInterruptible Whether it's interruptible
119 * (RTSemMutexRequestNoResume) or not
120 * (RTSemMutexRequest).
121 */
122static int rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, BOOLEAN fInterruptible)
123{
124 /*
125 * Validate input.
126 */
127 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
128 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
129 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
130
131 /*
132 * Get the mutex.
133 */
134#ifdef RT_USE_FAST_MUTEX
135 AssertMsg(cMillies == RT_INDEFINITE_WAIT, ("timeouts are not supported when using fast mutexes!\n"));
136 ExAcquireFastMutex(&pThis->Mutex);
137#else /* !RT_USE_FAST_MUTEX */
138 NTSTATUS rcNt;
139 if (cMillies == RT_INDEFINITE_WAIT)
140 rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, fInterruptible, NULL);
141 else
142 {
143 LARGE_INTEGER Timeout;
144 Timeout.QuadPart = -(int64_t)cMillies * 10000;
145 rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, fInterruptible, &Timeout);
146 }
147 switch (rcNt)
148 {
149 case STATUS_SUCCESS:
150 if (pThis->u32Magic == RTSEMMUTEX_MAGIC)
151 return VINF_SUCCESS;
152 return VERR_SEM_DESTROYED;
153
154 case STATUS_ALERTED:
155 case STATUS_USER_APC:
156 Assert(fInterruptible);
157 return VERR_INTERRUPTED;
158
159 case STATUS_TIMEOUT:
160 return VERR_TIMEOUT;
161
162 default:
163 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
164 pThis->u32Magic, pThis, (long)rcNt));
165 return VERR_INTERNAL_ERROR;
166 }
167#endif /* !RT_USE_FAST_MUTEX */
168 return VINF_SUCCESS;
169}
170
171
172RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
173{
174 return rtSemMutexRequest(hMutexSem, cMillies, FALSE /*fInterruptible*/);
175}
176
177
178RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
179{
180 return RTSemMutexRequest(hMutexSem, cMillies);
181}
182
183
184RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
185{
186 return rtSemMutexRequest(hMutexSem, cMillies, TRUE /*fInterruptible*/);
187}
188
189
190RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
191{
192 return RTSemMutexRequestNoResume(hMutexSem, cMillies);
193}
194
195
196RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem)
197{
198 /*
199 * Validate input.
200 */
201 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
202 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
203 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
204
205 /*
206 * Release the mutex.
207 */
208#ifdef RT_USE_FAST_MUTEX
209 ExReleaseFastMutex(&pThis->Mutex);
210#else
211 KeReleaseMutex(&pThis->Mutex, FALSE /*Wait*/);
212#endif
213 return VINF_SUCCESS;
214}
215
216
217RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
218{
219 /*
220 * Validate.
221 */
222 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
223 AssertPtrReturn(pThis, false);
224 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, false);
225
226#ifdef RT_USE_FAST_MUTEX
227 return pThis->Mutex && pThis->Mutex->Owner != NULL;
228#else
229 return KeReadStateMutex(&pThis->Mutex) == 1;
230#endif
231}
232
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