VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.3 KB
Line 
1/* $Id: semmutex-r0drv-nt.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT - Mutex Semaphores, Ring-0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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 RT_NOREF3(hClass, uSubClass, pszNameFmt);
75
76 AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
77 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
78 if (!pThis)
79 return VERR_NO_MEMORY;
80
81 pThis->u32Magic = RTSEMMUTEX_MAGIC;
82#ifdef RT_USE_FAST_MUTEX
83 ExInitializeFastMutex(&pThis->Mutex);
84#else
85 KeInitializeMutex(&pThis->Mutex, 0);
86#endif
87
88 *phMutexSem = pThis;
89 return VINF_SUCCESS;
90}
91
92
93RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
94{
95 /*
96 * Validate input.
97 */
98 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
99 if (pThis == NIL_RTSEMMUTEX)
100 return VINF_SUCCESS;
101 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
102 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
103
104 /*
105 * Invalidate it and signal the object just in case.
106 */
107 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
108 RTMemFree(pThis);
109 return VINF_SUCCESS;
110}
111
112
113/**
114 * Internal worker for RTSemMutexRequest and RTSemMutexRequestNoResume
115 *
116 * @returns IPRT status code.
117 * @param hMutexSem The mutex handle.
118 * @param cMillies The timeout.
119 * @param fInterruptible Whether it's interruptible
120 * (RTSemMutexRequestNoResume) or not
121 * (RTSemMutexRequest).
122 */
123static int rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, BOOLEAN fInterruptible)
124{
125 /*
126 * Validate input.
127 */
128 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
129 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
130 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
131
132 /*
133 * Get the mutex.
134 */
135#ifdef RT_USE_FAST_MUTEX
136 AssertMsg(cMillies == RT_INDEFINITE_WAIT, ("timeouts are not supported when using fast mutexes!\n"));
137 ExAcquireFastMutex(&pThis->Mutex);
138 return VINF_SUCCESS;
139
140#else /* !RT_USE_FAST_MUTEX */
141 NTSTATUS rcNt;
142 if (cMillies == RT_INDEFINITE_WAIT)
143 rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, fInterruptible, NULL);
144 else
145 {
146 LARGE_INTEGER Timeout;
147 Timeout.QuadPart = -(int64_t)cMillies * 10000;
148 rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, fInterruptible, &Timeout);
149 }
150 switch (rcNt)
151 {
152 case STATUS_SUCCESS:
153 if (pThis->u32Magic == RTSEMMUTEX_MAGIC)
154 return VINF_SUCCESS;
155 return VERR_SEM_DESTROYED;
156
157 case STATUS_ALERTED:
158 case STATUS_USER_APC:
159 Assert(fInterruptible);
160 return VERR_INTERRUPTED;
161
162 case STATUS_TIMEOUT:
163 return VERR_TIMEOUT;
164
165 default:
166 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
167 pThis->u32Magic, pThis, (long)rcNt));
168 return VERR_INTERNAL_ERROR;
169 }
170#endif /* !RT_USE_FAST_MUTEX */
171}
172
173
174RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
175{
176 return rtSemMutexRequest(hMutexSem, cMillies, FALSE /*fInterruptible*/);
177}
178
179
180RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
181{
182 RT_NOREF1(uId); RT_SRC_POS_NOREF();
183 return RTSemMutexRequest(hMutexSem, cMillies);
184}
185
186
187RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
188{
189 return rtSemMutexRequest(hMutexSem, cMillies, TRUE /*fInterruptible*/);
190}
191
192
193RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
194{
195 RT_NOREF1(uId); RT_SRC_POS_NOREF();
196 return RTSemMutexRequestNoResume(hMutexSem, cMillies);
197}
198
199
200RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem)
201{
202 /*
203 * Validate input.
204 */
205 PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
206 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
207 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
208
209 /*
210 * Release the mutex.
211 */
212#ifdef RT_USE_FAST_MUTEX
213 ExReleaseFastMutex(&pThis->Mutex);
214#else
215 KeReleaseMutex(&pThis->Mutex, FALSE /*Wait*/);
216#endif
217 return VINF_SUCCESS;
218}
219
220
221RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
222{
223 /*
224 * Validate.
225 */
226 RTSEMMUTEXINTERNAL *pThis = hMutexSem;
227 AssertPtrReturn(pThis, false);
228 AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, false);
229
230#ifdef RT_USE_FAST_MUTEX
231 return pThis->Mutex && pThis->Mutex->Owner != NULL;
232#else
233 return KeReadStateMutex(&pThis->Mutex) == 0;
234#endif
235}
236
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