VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/semaphore-r0drv-nt.cpp@ 2555

Last change on this file since 2555 was 1816, checked in by vboxsync, 18 years ago

moved magics to a common header to avoid duplicating the same defines all over the place.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.0 KB
Line 
1/* $Id: semaphore-r0drv-nt.cpp 1816 2007-03-29 18:59:35Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime - Semaphores, Ring-0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include "the-nt-kernel.h"
28#include <iprt/semaphore.h>
29#include <iprt/alloc.h>
30#include <iprt/assert.h>
31#include <iprt/asm.h>
32#include <iprt/err.h>
33
34#include "internal/magics.h"
35
36
37/*******************************************************************************
38* Structures and Typedefs *
39*******************************************************************************/
40/**
41 * NT event semaphore.
42 */
43typedef struct RTSEMEVENTINTERNAL
44{
45 /** Magic value (RTSEMEVENT_MAGIC). */
46 uint32_t volatile u32Magic;
47 /** The NT Event object. */
48 KEVENT Event;
49} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
50
51
52
53/**
54 * NT mutex semaphore.
55 */
56typedef struct RTSEMMUTEXINTERNAL
57{
58 /** Magic value (RTSEMMUTEX_MAGIC). */
59 uint32_t volatile u32Magic;
60#ifdef RT_USE_FAST_MUTEX
61 /** The fast mutex object. */
62 FAST_MUTEX Mutex;
63#else
64 /** The NT Mutex object. */
65 KMUTEX Mutex;
66#endif
67} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
68
69
70
71/**
72 * Wrapper for the linux semaphore structure.
73 */
74typedef struct RTSEMFASTMUTEXINTERNAL
75{
76 /** Magic value (RTSEMFASTMUTEX_MAGIC). */
77 uint32_t u32Magic;
78 /** the NT fast mutex. */
79 FAST_MUTEX Mutex;
80} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
81
82
83
84
85RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
86{
87 Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
88 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
89 if (pEventInt)
90 {
91 pEventInt->u32Magic = RTSEMEVENT_MAGIC;
92 KeInitializeEvent(&pEventInt->Event, SynchronizationEvent, FALSE);
93 *pEventSem = pEventInt;
94 return VINF_SUCCESS;
95 }
96 return VERR_NO_MEMORY;
97}
98
99
100RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
101{
102 /*
103 * Validate input.
104 */
105 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
106 if (!pEventInt)
107 return VERR_INVALID_PARAMETER;
108 if (pEventInt->u32Magic != RTSEMEVENT_MAGIC)
109 {
110 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt->u32Magic, pEventInt));
111 return VERR_INVALID_PARAMETER;
112 }
113
114 /*
115 * Invalidate it and signal the object just in case.
116 */
117 ASMAtomicIncU32(&pEventInt->u32Magic);
118 KeSetEvent(&pEventInt->Event, 0xfff, FALSE);
119 RTMemFree(pEventInt);
120 return VINF_SUCCESS;
121}
122
123
124RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
125{
126 /*
127 * Validate input.
128 */
129 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
130 if (!pEventInt)
131 return VERR_INVALID_PARAMETER;
132 if ( !pEventInt
133 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
134 {
135 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
136 return VERR_INVALID_PARAMETER;
137 }
138
139 /*
140 * Signal the event object.
141 */
142 KeSetEvent(&pEventInt->Event, 1, FALSE);
143 return VINF_SUCCESS;
144}
145
146
147RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
148{
149 /*
150 * Validate input.
151 */
152 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
153 if (!pEventInt)
154 return VERR_INVALID_PARAMETER;
155 if ( !pEventInt
156 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
157 {
158 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
159 return VERR_INVALID_PARAMETER;
160 }
161
162 /*
163 * Wait for it.
164 */
165 NTSTATUS rcNt;
166 if (cMillies == RT_INDEFINITE_WAIT)
167 rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, NULL);
168 else
169 {
170 LARGE_INTEGER Timeout;
171 Timeout.QuadPart = -(int64_t)cMillies * 10000;
172 rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, &Timeout);
173 }
174 switch (rcNt)
175 {
176 case STATUS_SUCCESS:
177 if (pEventInt->u32Magic == RTSEMEVENT_MAGIC)
178 return VINF_SUCCESS;
179 return VERR_SEM_DESTROYED;
180 case STATUS_ALERTED:
181 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
182 case STATUS_USER_APC:
183 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
184 case STATUS_TIMEOUT:
185 return VERR_TIMEOUT;
186 default:
187 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p: wait returned %lx!\n",
188 pEventInt->u32Magic, pEventInt, (long)rcNt));
189 return VERR_INTERNAL_ERROR;
190 }
191}
192
193
194
195RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
196{
197 Assert(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
198 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pMutexInt));
199 if (pMutexInt)
200 {
201 pMutexInt->u32Magic = RTSEMMUTEX_MAGIC;
202#ifdef RT_USE_FAST_MUTEX
203 ExInitializeFastMutex(&pMutexInt->Mutex);
204#else
205 KeInitializeMutex(&pMutexInt->Mutex, 0);
206#endif
207 *pMutexSem = pMutexInt;
208 return VINF_SUCCESS;
209 }
210 return VERR_NO_MEMORY;
211}
212
213
214RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
215{
216 /*
217 * Validate input.
218 */
219 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
220 if (!pMutexInt)
221 return VERR_INVALID_PARAMETER;
222 if (pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
223 {
224 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt->u32Magic, pMutexInt));
225 return VERR_INVALID_PARAMETER;
226 }
227
228 /*
229 * Invalidate it and signal the object just in case.
230 */
231 ASMAtomicIncU32(&pMutexInt->u32Magic);
232 RTMemFree(pMutexInt);
233 return VINF_SUCCESS;
234}
235
236
237RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
238{
239 /*
240 * Validate input.
241 */
242 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
243 if (!pMutexInt)
244 return VERR_INVALID_PARAMETER;
245 if ( !pMutexInt
246 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
247 {
248 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
249 return VERR_INVALID_PARAMETER;
250 }
251
252 /*
253 * Get the mutex.
254 */
255#ifdef RT_USE_FAST_MUTEX
256 AssertMsg(cMillies == RT_INDEFINITE_WAIT, ("timeouts are not supported when using fast mutexes!\n"));
257 ExAcquireFastMutex(&pMutexInt->Mutex);
258#else
259 NTSTATUS rcNt;
260 if (cMillies == RT_INDEFINITE_WAIT)
261 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, NULL);
262 else
263 {
264 LARGE_INTEGER Timeout;
265 Timeout.QuadPart = -(int64_t)cMillies * 10000;
266 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, &Timeout);
267 }
268 switch (rcNt)
269 {
270 case STATUS_SUCCESS:
271 if (pMutexInt->u32Magic == RTSEMMUTEX_MAGIC)
272 return VINF_SUCCESS;
273 return VERR_SEM_DESTROYED;
274 case STATUS_ALERTED:
275 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
276 case STATUS_USER_APC:
277 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
278 case STATUS_TIMEOUT:
279 return VERR_TIMEOUT;
280 default:
281 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p: wait returned %lx!\n",
282 pMutexInt->u32Magic, pMutexInt, (long)rcNt));
283 return VERR_INTERNAL_ERROR;
284 }
285#endif
286 return VINF_SUCCESS;
287}
288
289
290RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
291{
292 /*
293 * Validate input.
294 */
295 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
296 if (!pMutexInt)
297 return VERR_INVALID_PARAMETER;
298 if ( !pMutexInt
299 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
300 {
301 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
302 return VERR_INVALID_PARAMETER;
303 }
304
305 /*
306 * Release the mutex.
307 */
308#ifdef RT_USE_FAST_MUTEX
309 ExReleaseFastMutex(&pMutexInt->Mutex);
310#else
311 KeReleaseMutex(&pMutexInt->Mutex, FALSE);
312#endif
313 return VINF_SUCCESS;
314}
315
316
317
318
319RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem)
320{
321 /*
322 * Allocate.
323 */
324 PRTSEMFASTMUTEXINTERNAL pFastInt;
325 Assert(sizeof(*pFastInt) > sizeof(void *));
326 pFastInt = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pFastInt));
327 if (!pFastInt)
328 return VERR_NO_MEMORY;
329
330 /*
331 * Initialize.
332 */
333 pFastInt->u32Magic = RTSEMFASTMUTEX_MAGIC;
334 ExInitializeFastMutex(&pFastInt->Mutex);
335 *pMutexSem = pFastInt;
336 return VINF_SUCCESS;
337}
338
339
340RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem)
341{
342 /*
343 * Validate.
344 */
345 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
346 if (!pFastInt)
347 return VERR_INVALID_PARAMETER;
348 if (pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
349 {
350 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt->u32Magic, pFastInt));
351 return VERR_INVALID_PARAMETER;
352 }
353
354 ASMAtomicIncU32(&pFastInt->u32Magic);
355 RTMemFree(pFastInt);
356 return VINF_SUCCESS;
357}
358
359
360RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem)
361{
362 /*
363 * Validate.
364 */
365 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
366 if ( !pFastInt
367 || pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
368 {
369 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
370 return VERR_INVALID_PARAMETER;
371 }
372
373 ExAcquireFastMutex(&pFastInt->Mutex);
374 return VINF_SUCCESS;
375}
376
377
378RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem)
379{
380 /*
381 * Validate.
382 */
383 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
384 if ( !pFastInt
385 || pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
386 {
387 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
388 return VERR_INVALID_PARAMETER;
389 }
390
391 ExReleaseFastMutex(&pFastInt->Mutex);
392 return VINF_SUCCESS;
393}
394
395
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