VirtualBox

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

Last change on this file since 395 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.3 KB
Line 
1/* $Id: semaphore-r0drv-nt.cpp 1 1970-01-01 00:00:00Z 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
35/*******************************************************************************
36* Structures and Typedefs *
37*******************************************************************************/
38/**
39 * NT event semaphore.
40 */
41typedef struct RTSEMEVENTINTERNAL
42{
43 /** Magic value (RTSEMEVENT_MAGIC). */
44 uint32_t volatile u32Magic;
45 /** The NT Event object. */
46 KEVENT Event;
47} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
48
49/** Magic for the NT event semaphore structure. (Neil Gaiman) */
50#define RTSEMEVENT_MAGIC 0x19601110
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/** Magic for the NT mutex semaphore structure. (Douglas Adams) */
70#define RTSEMMUTEX_MAGIC 0x19520311
71
72
73/**
74 * Wrapper for the linux semaphore structure.
75 */
76typedef struct RTSEMFASTMUTEXINTERNAL
77{
78 /** Magic value (RTSEMFASTMUTEX_MAGIC). */
79 uint32_t u32Magic;
80 /** the NT fast mutex. */
81 FAST_MUTEX Mutex;
82} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
83
84/** Magic value for RTSEMFASTMUTEXINTERNAL::u32Magic (John Ronald Reuel Tolkien). */
85#define RTSEMFASTMUTEX_MAGIC 0x18920102
86
87
88
89RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
90{
91 Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
92 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
93 if (pEventInt)
94 {
95 pEventInt->u32Magic = RTSEMEVENT_MAGIC;
96 KeInitializeEvent(&pEventInt->Event, SynchronizationEvent, FALSE);
97 *pEventSem = pEventInt;
98 return VINF_SUCCESS;
99 }
100 return VERR_NO_MEMORY;
101}
102
103
104RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
105{
106 /*
107 * Validate input.
108 */
109 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
110 if (!pEventInt)
111 return VERR_INVALID_PARAMETER;
112 if (pEventInt->u32Magic != RTSEMEVENT_MAGIC)
113 {
114 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt->u32Magic, pEventInt));
115 return VERR_INVALID_PARAMETER;
116 }
117
118 /*
119 * Invalidate it and signal the object just in case.
120 */
121 ASMAtomicIncU32(&pEventInt->u32Magic);
122 KeSetEvent(&pEventInt->Event, 0xfff, FALSE);
123 RTMemFree(pEventInt);
124 return VINF_SUCCESS;
125}
126
127
128RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
129{
130 /*
131 * Validate input.
132 */
133 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
134 if (!pEventInt)
135 return VERR_INVALID_PARAMETER;
136 if ( !pEventInt
137 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
138 {
139 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
140 return VERR_INVALID_PARAMETER;
141 }
142
143 /*
144 * Signal the event object.
145 */
146 KeSetEvent(&pEventInt->Event, 1, FALSE);
147 return VINF_SUCCESS;
148}
149
150
151RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
152{
153 /*
154 * Validate input.
155 */
156 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
157 if (!pEventInt)
158 return VERR_INVALID_PARAMETER;
159 if ( !pEventInt
160 || pEventInt->u32Magic != RTSEMEVENT_MAGIC)
161 {
162 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p\n", pEventInt ? pEventInt->u32Magic : 0, pEventInt));
163 return VERR_INVALID_PARAMETER;
164 }
165
166 /*
167 * Wait for it.
168 */
169 NTSTATUS rcNt;
170 if (cMillies == RT_INDEFINITE_WAIT)
171 rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, NULL);
172 else
173 {
174 LARGE_INTEGER Timeout;
175 Timeout.QuadPart = -(int64_t)cMillies * 10000;
176 rcNt = KeWaitForSingleObject(&pEventInt->Event, Executive, KernelMode, TRUE, &Timeout);
177 }
178 switch (rcNt)
179 {
180 case STATUS_SUCCESS:
181 if (pEventInt->u32Magic == RTSEMEVENT_MAGIC)
182 return VINF_SUCCESS;
183 return VERR_SEM_DESTROYED;
184 case STATUS_ALERTED:
185 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
186 case STATUS_USER_APC:
187 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
188 case STATUS_TIMEOUT:
189 return VERR_TIMEOUT;
190 default:
191 AssertMsgFailed(("pEventInt->u32Magic=%RX32 pEventInt=%p: wait returned %lx!\n",
192 pEventInt->u32Magic, pEventInt, (long)rcNt));
193 return VERR_INTERNAL_ERROR;
194 }
195}
196
197
198
199RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
200{
201 Assert(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
202 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pMutexInt));
203 if (pMutexInt)
204 {
205 pMutexInt->u32Magic = RTSEMMUTEX_MAGIC;
206#ifdef RT_USE_FAST_MUTEX
207 ExInitializeFastMutex(&pMutexInt->Mutex);
208#else
209 KeInitializeMutex(&pMutexInt->Mutex, 0);
210#endif
211 *pMutexSem = pMutexInt;
212 return VINF_SUCCESS;
213 }
214 return VERR_NO_MEMORY;
215}
216
217
218RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
219{
220 /*
221 * Validate input.
222 */
223 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
224 if (!pMutexInt)
225 return VERR_INVALID_PARAMETER;
226 if (pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
227 {
228 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt->u32Magic, pMutexInt));
229 return VERR_INVALID_PARAMETER;
230 }
231
232 /*
233 * Invalidate it and signal the object just in case.
234 */
235 ASMAtomicIncU32(&pMutexInt->u32Magic);
236 RTMemFree(pMutexInt);
237 return VINF_SUCCESS;
238}
239
240
241RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
242{
243 /*
244 * Validate input.
245 */
246 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
247 if (!pMutexInt)
248 return VERR_INVALID_PARAMETER;
249 if ( !pMutexInt
250 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
251 {
252 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
253 return VERR_INVALID_PARAMETER;
254 }
255
256 /*
257 * Get the mutex.
258 */
259#ifdef RT_USE_FAST_MUTEX
260 AssertMsg(cMillies == RT_INDEFINITE_WAIT, ("timeouts are not supported when using fast mutexes!\n"));
261 ExAcquireFastMutex(&pMutexInt->Mutex);
262#else
263 NTSTATUS rcNt;
264 if (cMillies == RT_INDEFINITE_WAIT)
265 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, NULL);
266 else
267 {
268 LARGE_INTEGER Timeout;
269 Timeout.QuadPart = -(int64_t)cMillies * 10000;
270 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, &Timeout);
271 }
272 switch (rcNt)
273 {
274 case STATUS_SUCCESS:
275 if (pMutexInt->u32Magic == RTSEMMUTEX_MAGIC)
276 return VINF_SUCCESS;
277 return VERR_SEM_DESTROYED;
278 case STATUS_ALERTED:
279 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
280 case STATUS_USER_APC:
281 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
282 case STATUS_TIMEOUT:
283 return VERR_TIMEOUT;
284 default:
285 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p: wait returned %lx!\n",
286 pMutexInt->u32Magic, pMutexInt, (long)rcNt));
287 return VERR_INTERNAL_ERROR;
288 }
289#endif
290 return VINF_SUCCESS;
291}
292
293
294RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
295{
296 /*
297 * Validate input.
298 */
299 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
300 if (!pMutexInt)
301 return VERR_INVALID_PARAMETER;
302 if ( !pMutexInt
303 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
304 {
305 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
306 return VERR_INVALID_PARAMETER;
307 }
308
309 /*
310 * Release the mutex.
311 */
312#ifdef RT_USE_FAST_MUTEX
313 ExReleaseFastMutex(&pMutexInt->Mutex);
314#else
315 KeReleaseMutex(&pMutexInt->Mutex, FALSE);
316#endif
317 return VINF_SUCCESS;
318}
319
320
321
322
323RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem)
324{
325 /*
326 * Allocate.
327 */
328 PRTSEMFASTMUTEXINTERNAL pFastInt;
329 Assert(sizeof(*pFastInt) > sizeof(void *));
330 pFastInt = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pFastInt));
331 if (!pFastInt)
332 return VERR_NO_MEMORY;
333
334 /*
335 * Initialize.
336 */
337 pFastInt->u32Magic = RTSEMFASTMUTEX_MAGIC;
338 ExInitializeFastMutex(&pFastInt->Mutex);
339 *pMutexSem = pFastInt;
340 return VINF_SUCCESS;
341}
342
343
344RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem)
345{
346 /*
347 * Validate.
348 */
349 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
350 if (!pFastInt)
351 return VERR_INVALID_PARAMETER;
352 if (pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
353 {
354 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt->u32Magic, pFastInt));
355 return VERR_INVALID_PARAMETER;
356 }
357
358 ASMAtomicIncU32(&pFastInt->u32Magic);
359 RTMemFree(pFastInt);
360 return VINF_SUCCESS;
361}
362
363
364RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem)
365{
366 /*
367 * Validate.
368 */
369 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
370 if ( !pFastInt
371 || pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
372 {
373 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
374 return VERR_INVALID_PARAMETER;
375 }
376
377 ExAcquireFastMutex(&pFastInt->Mutex);
378 return VINF_SUCCESS;
379}
380
381
382RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem)
383{
384 /*
385 * Validate.
386 */
387 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
388 if ( !pFastInt
389 || pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
390 {
391 AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
392 return VERR_INVALID_PARAMETER;
393 }
394
395 ExReleaseFastMutex(&pFastInt->Mutex);
396 return VINF_SUCCESS;
397}
398
399
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