VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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