VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/darwin/semaphore-r0drv-darwin.cpp@ 199

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

fast mutex sems.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette