VirtualBox

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

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

Need RTThreadWait in ring-0 too when using the generic timers, so thread.cpp was ported to ring-0. Fixed a bug in RTTimerStart() (the generic code). (hope this doesn't break the other platforms...)

  • Property svn:keywords set to Id
File size: 22.7 KB
Line 
1/* $Id: semaphore-r0drv-darwin.cpp 403 2007-01-28 08:45:05Z 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/**
39 * Darwin event semaphore.
40 */
41typedef struct RTSEMEVENTINTERNAL
42{
43 /** Magic value (RTSEMEVENT_MAGIC). */
44 uint32_t volatile u32Magic;
45 /** The number of waiting threads. */
46 uint32_t volatile cWaiters;
47 /** Set if the event object is signaled. */
48 uint8_t volatile fSignaled;
49 /** The number of threads in the process of waking up. */
50 uint32_t volatile cWaking;
51 /** The spinlock protecting us. */
52 lck_spin_t *pSpinlock;
53} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
54
55/** Magic for the Darwin event semaphore structure. (Neil Gaiman) */
56#define RTSEMEVENT_MAGIC 0x19601110
57
58
59/**
60 * Darwin multiple release event semaphore.
61 */
62typedef struct RTSEMEVENTMULTIINTERNAL
63{
64 /** Magic value (RTSEMEVENTMULTI_MAGIC). */
65 uint32_t volatile u32Magic;
66 /** The number of waiting threads. */
67 uint32_t volatile cWaiters;
68 /** Set if the event object is signaled. */
69 uint8_t volatile fSignaled;
70 /** The number of threads in the process of waking up. */
71 uint32_t volatile cWaking;
72 /** The spinlock protecting us. */
73 lck_spin_t *pSpinlock;
74} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
75
76/** Magic for the Darwin multiple release event semaphore structure. (Isaac Asimov) */
77#define RTSEMEVENTMULTI_MAGIC 0x19200102
78
79
80#if 0 /** @todo */
81/**
82 * Darwin mutex semaphore.
83 */
84typedef struct RTSEMMUTEXINTERNAL
85{
86 /** Magic value (RTSEMMUTEX_MAGIC). */
87 uint32_t volatile u32Magic;
88 /** The mutex. */
89 lck_mtx_t *pMtx;
90} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
91
92/** Magic for the Darwin mutex semaphore structure. (Douglas Adams) */
93#define RTSEMMUTEX_MAGIC 0x19520311
94#endif
95
96
97/**
98 * Wrapper for the darwin semaphore structure.
99 */
100typedef struct RTSEMFASTMUTEXINTERNAL
101{
102 /** Magic value (RTSEMFASTMUTEX_MAGIC). */
103 uint32_t u32Magic;
104 /** The mutex. */
105 lck_mtx_t *pMtx;
106} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
107
108/** Magic value for RTSEMFASTMUTEXINTERNAL::u32Magic (John Ronald Reuel Tolkien). */
109#define RTSEMFASTMUTEX_MAGIC 0x18920102
110
111
112RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
113{
114 Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
115 AssertPtrReturn(pEventSem, VERR_INVALID_POINTER);
116
117 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
118 if (pEventInt)
119 {
120 pEventInt->u32Magic = RTSEMEVENT_MAGIC;
121 pEventInt->cWaiters = 0;
122 pEventInt->cWaking = 0;
123 pEventInt->fSignaled = 0;
124 Assert(g_pDarwinLockGroup);
125 pEventInt->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
126 if (pEventInt->pSpinlock)
127 {
128 *pEventSem = pEventInt;
129 return VINF_SUCCESS;
130 }
131
132 pEventInt->u32Magic = 0;
133 RTMemFree(pEventInt);
134 }
135 return VERR_NO_MEMORY;
136}
137
138
139RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
140{
141 if (EventSem == NIL_RTSEMEVENT) /* don't bitch */
142 return VERR_INVALID_HANDLE;
143 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
144 AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
145 AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
146 ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
147 VERR_INVALID_HANDLE);
148
149 lck_spin_lock(pEventInt->pSpinlock);
150 ASMAtomicIncU32(&pEventInt->u32Magic); /* make the handle invalid */
151 if (pEventInt->cWaiters > 0)
152 {
153 /* abort waiting thread, last man cleans up. */
154 ASMAtomicXchgU32(&pEventInt->cWaking, pEventInt->cWaking + pEventInt->cWaiters);
155 thread_wakeup_prim((event_t)pEventInt, FALSE /* all threads */, THREAD_RESTART);
156 lck_spin_unlock(pEventInt->pSpinlock);
157 }
158 else if (pEventInt->cWaking)
159 /* the last waking thread is gonna do the cleanup */
160 lck_spin_unlock(pEventInt->pSpinlock);
161 else
162 {
163 lck_spin_unlock(pEventInt->pSpinlock);
164 lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
165 RTMemFree(pEventInt);
166 }
167
168 return VINF_SUCCESS;
169}
170
171
172RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
173{
174 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
175 AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
176 AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
177 ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
178 VERR_INVALID_HANDLE);
179
180 lck_spin_lock(pEventInt->pSpinlock);
181
182 if (pEventInt->cWaiters > 0)
183 {
184 ASMAtomicDecU32(&pEventInt->cWaiters);
185 ASMAtomicIncU32(&pEventInt->cWaking);
186 thread_wakeup_prim((event_t)pEventInt, TRUE /* one thread */, THREAD_AWAKENED);
187 }
188 else
189 ASMAtomicXchgU8(&pEventInt->fSignaled, true);
190
191 lck_spin_unlock(pEventInt->pSpinlock);
192 return VINF_SUCCESS;
193}
194
195
196static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, wait_interrupt_t fInterruptible)
197{
198 PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
199 AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
200 AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
201 ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
202 VERR_INVALID_HANDLE);
203
204 lck_spin_lock(pEventInt->pSpinlock);
205
206 int rc;
207 if (pEventInt->fSignaled)
208 {
209 Assert(!pEventInt->cWaiters);
210 ASMAtomicXchgU8(&pEventInt->fSignaled, false);
211 rc = VINF_SUCCESS;
212 }
213 else
214 {
215 ASMAtomicIncU32(&pEventInt->cWaiters);
216
217 wait_result_t rcWait;
218 if (cMillies == RT_INDEFINITE_WAIT)
219 rcWait = lck_spin_sleep(pEventInt->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pEventInt, fInterruptible);
220 else
221 {
222 uint64_t u64AbsTime;
223 nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
224 u64AbsTime += mach_absolute_time();
225
226 rcWait = lck_spin_sleep_deadline(pEventInt->pSpinlock, LCK_SLEEP_DEFAULT,
227 (event_t)pEventInt, fInterruptible, u64AbsTime);
228 }
229 switch (rcWait)
230 {
231 case THREAD_AWAKENED:
232 Assert(pEventInt->cWaking > 0);
233 if ( !ASMAtomicDecU32(&pEventInt->cWaking)
234 && pEventInt->u32Magic != RTSEMEVENT_MAGIC)
235 {
236 /* the event was destroyed after we woke up, as the last thread do the cleanup. */
237 lck_spin_unlock(pEventInt->pSpinlock);
238 Assert(g_pDarwinLockGroup);
239 lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
240 RTMemFree(pEventInt);
241 return VINF_SUCCESS;
242 }
243 rc = VINF_SUCCESS;
244 break;
245
246 case THREAD_TIMED_OUT:
247 Assert(cMillies != RT_INDEFINITE_WAIT);
248 ASMAtomicDecU32(&pEventInt->cWaiters);
249 rc = VERR_TIMEOUT;
250 break;
251
252 case THREAD_INTERRUPTED:
253 Assert(fInterruptible);
254 ASMAtomicDecU32(&pEventInt->cWaiters);
255 rc = VERR_INTERRUPTED;
256 break;
257
258 case THREAD_RESTART:
259 /* Last one out does the cleanup. */
260 if (!ASMAtomicDecU32(&pEventInt->cWaking))
261 {
262 lck_spin_unlock(pEventInt->pSpinlock);
263 Assert(g_pDarwinLockGroup);
264 lck_spin_destroy(pEventInt->pSpinlock, g_pDarwinLockGroup);
265 RTMemFree(pEventInt);
266 return VERR_SEM_DESTROYED;
267 }
268
269 rc = VERR_SEM_DESTROYED;
270 break;
271
272 default:
273 AssertMsgFailed(("rcWait=%d\n", rcWait));
274 rc = VERR_GENERAL_FAILURE;
275 break;
276 }
277 }
278
279 lck_spin_unlock(pEventInt->pSpinlock);
280 return rc;
281}
282
283
284RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
285{
286 return rtSemEventWait(EventSem, cMillies, FALSE /* not interruptable */);
287}
288
289
290RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
291{
292 return rtSemEventWait(EventSem, cMillies, TRUE /* interruptable */);
293}
294
295
296
297RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
298{
299 Assert(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
300 AssertPtrReturn(pEventMultiSem, VERR_INVALID_POINTER);
301
302 PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pEventMultiInt));
303 if (pEventMultiInt)
304 {
305 pEventMultiInt->u32Magic = RTSEMEVENTMULTI_MAGIC;
306 pEventMultiInt->cWaiters = 0;
307 pEventMultiInt->cWaking = 0;
308 pEventMultiInt->fSignaled = 0;
309 Assert(g_pDarwinLockGroup);
310 pEventMultiInt->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
311 if (pEventMultiInt->pSpinlock)
312 {
313 *pEventMultiSem = pEventMultiInt;
314 return VINF_SUCCESS;
315 }
316
317 pEventMultiInt->u32Magic = 0;
318 RTMemFree(pEventMultiInt);
319 }
320 return VERR_NO_MEMORY;
321}
322
323
324RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
325{
326 if (EventMultiSem == NIL_RTSEMEVENTMULTI) /* don't bitch */
327 return VERR_INVALID_HANDLE;
328 PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
329 AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
330 AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
331 ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
332 VERR_INVALID_HANDLE);
333
334 lck_spin_lock(pEventMultiInt->pSpinlock);
335 ASMAtomicIncU32(&pEventMultiInt->u32Magic); /* make the handle invalid */
336 if (pEventMultiInt->cWaiters > 0)
337 {
338 /* abort waiting thread, last man cleans up. */
339 ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
340 thread_wakeup_prim((event_t)pEventMultiInt, FALSE /* all threads */, THREAD_RESTART);
341 lck_spin_unlock(pEventMultiInt->pSpinlock);
342 }
343 else if (pEventMultiInt->cWaking)
344 /* the last waking thread is gonna do the cleanup */
345 lck_spin_unlock(pEventMultiInt->pSpinlock);
346 else
347 {
348 lck_spin_unlock(pEventMultiInt->pSpinlock);
349 lck_spin_destroy(pEventMultiInt->pSpinlock, g_pDarwinLockGroup);
350 RTMemFree(pEventMultiInt);
351 }
352
353 return VINF_SUCCESS;
354}
355
356
357RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
358{
359 PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
360 AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
361 AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
362 ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
363 VERR_INVALID_HANDLE);
364
365 lck_spin_lock(pEventMultiInt->pSpinlock);
366
367 ASMAtomicXchgU8(&pEventMultiInt->fSignaled, true);
368 if (pEventMultiInt->cWaiters > 0)
369 {
370 ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
371 ASMAtomicXchgU32(&pEventMultiInt->cWaiters, 0);
372 thread_wakeup_prim((event_t)pEventMultiInt, FALSE /* all threads */, THREAD_AWAKENED);
373 }
374
375 lck_spin_unlock(pEventMultiInt->pSpinlock);
376 return VINF_SUCCESS;
377}
378
379
380RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
381{
382 PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
383 AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
384 AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
385 ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
386 VERR_INVALID_HANDLE);
387
388 lck_spin_lock(pEventMultiInt->pSpinlock);
389 ASMAtomicXchgU8(&pEventMultiInt->fSignaled, false);
390 lck_spin_unlock(pEventMultiInt->pSpinlock);
391 return VINF_SUCCESS;
392}
393
394
395static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, wait_interrupt_t fInterruptible)
396{
397 PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
398 AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
399 AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
400 ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
401 VERR_INVALID_HANDLE);
402
403 lck_spin_lock(pEventMultiInt->pSpinlock);
404
405 int rc;
406 if (pEventMultiInt->fSignaled)
407 {
408 ASMAtomicXchgU8(&pEventMultiInt->fSignaled, false);
409 rc = VINF_SUCCESS;
410 }
411 else
412 {
413 ASMAtomicIncU32(&pEventMultiInt->cWaiters);
414
415 wait_result_t rcWait;
416 if (cMillies == RT_INDEFINITE_WAIT)
417 rcWait = lck_spin_sleep(pEventMultiInt->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pEventMultiInt, fInterruptible);
418 else
419 {
420 uint64_t u64AbsTime;
421 nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
422 u64AbsTime += mach_absolute_time();
423
424 rcWait = lck_spin_sleep_deadline(pEventMultiInt->pSpinlock, LCK_SLEEP_DEFAULT,
425 (event_t)pEventMultiInt, fInterruptible, u64AbsTime);
426 }
427 switch (rcWait)
428 {
429 case THREAD_AWAKENED:
430 Assert(pEventMultiInt->cWaking > 0);
431 if ( !ASMAtomicDecU32(&pEventMultiInt->cWaking)
432 && pEventMultiInt->u32Magic != RTSEMEVENTMULTI_MAGIC)
433 {
434 /* the event was destroyed after we woke up, as the last thread do the cleanup. */
435 lck_spin_unlock(pEventMultiInt->pSpinlock);
436 Assert(g_pDarwinLockGroup);
437 lck_spin_destroy(pEventMultiInt->pSpinlock, g_pDarwinLockGroup);
438 RTMemFree(pEventMultiInt);
439 return VINF_SUCCESS;
440 }
441 rc = VINF_SUCCESS;
442 break;
443
444 case THREAD_TIMED_OUT:
445 Assert(cMillies != RT_INDEFINITE_WAIT);
446 ASMAtomicDecU32(&pEventMultiInt->cWaiters);
447 rc = VERR_TIMEOUT;
448 break;
449
450 case THREAD_INTERRUPTED:
451 Assert(fInterruptible);
452 ASMAtomicDecU32(&pEventMultiInt->cWaiters);
453 rc = VERR_INTERRUPTED;
454 break;
455
456 case THREAD_RESTART:
457 /* Last one out does the cleanup. */
458 if (!ASMAtomicDecU32(&pEventMultiInt->cWaking))
459 {
460 lck_spin_unlock(pEventMultiInt->pSpinlock);
461 Assert(g_pDarwinLockGroup);
462 lck_spin_destroy(pEventMultiInt->pSpinlock, g_pDarwinLockGroup);
463 RTMemFree(pEventMultiInt);
464 return VERR_SEM_DESTROYED;
465 }
466
467 rc = VERR_SEM_DESTROYED;
468 break;
469
470 default:
471 AssertMsgFailed(("rcWait=%d\n", rcWait));
472 rc = VERR_GENERAL_FAILURE;
473 break;
474 }
475 }
476
477 lck_spin_unlock(pEventMultiInt->pSpinlock);
478 return rc;
479}
480
481
482RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
483{
484 return rtSemEventMultiWait(EventMultiSem, cMillies, FALSE /* not interruptable */);
485}
486
487
488RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
489{
490 return rtSemEventMultiWait(EventMultiSem, cMillies, TRUE /* interruptable */);
491}
492
493
494
495
496
497#if 0 /* need proper timeout lock function! */
498RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
499{
500 AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
501 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pMutexInt));
502 if (pMutexInt)
503 {
504 pMutexInt->u32Magic = RTSEMMUTEX_MAGIC;
505 Assert(g_pDarwinLockGroup);
506 pMutexInt->pMtx = lck_mtx_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
507 if (pMutexInt->pMtx)
508 {
509 *pMutexSem = pMutexInt;
510 return VINF_SUCCESS;
511 }
512 RTMemFree(pMutexInt);
513 }
514 return VERR_NO_MEMORY;
515}
516
517
518RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
519{
520 /*
521 * Validate input.
522 */
523 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
524 if (!pMutexInt)
525 return VERR_INVALID_PARAMETER;
526 AssertPtrReturn(pMutexInt, VERR_INVALID_POINTER);
527 AssertMsg(pMutexInt->u32Magic == RTSEMMUTEX_MAGIC,
528 ("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt->u32Magic, pMutexInt)
529 VERR_INVALID_PARAMETER);
530
531 /*
532 * Invalidate it and signal the object just in case.
533 */
534 ASMAtomicIncU32(&pMutexInt->u32Magic);
535
536 Assert(g_pDarwinLockGroup);
537 lck_mtx_free(pMutexInt->pMtx, g_pDarwinLockGroup);
538 pMutexInt->pMtx = NULL;
539
540 RTMemFree(pMutexInt);
541 return VINF_SUCCESS;
542}
543
544
545RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
546{
547 /*
548 * Validate input.
549 */
550 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
551 if (!pMutexInt)
552 return VERR_INVALID_PARAMETER;
553 AssertPtrReturn(pMutexInt, VERR_INVALID_POINTER);
554 AssertMsg(pMutexInt->u32Magic == RTSEMMUTEX_MAGIC,
555 ("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt->u32Magic, pMutexInt)
556 VERR_INVALID_PARAMETER);
557
558 /*
559 * Get the mutex.
560 */
561 wait_result_t rc = lck_mtx_lock_deadlink
562#if 1
563#else
564 NTSTATUS rcNt;
565 if (cMillies == RT_INDEFINITE_WAIT)
566 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, NULL);
567 else
568 {
569 LARGE_INTEGER Timeout;
570 Timeout.QuadPart = -(int64_t)cMillies * 10000;
571 rcNt = KeWaitForSingleObject(&pMutexInt->Mutex, Executive, KernelMode, TRUE, &Timeout);
572 }
573 switch (rcNt)
574 {
575 case STATUS_SUCCESS:
576 if (pMutexInt->u32Magic == RTSEMMUTEX_MAGIC)
577 return VINF_SUCCESS;
578 return VERR_SEM_DESTROYED;
579 case STATUS_ALERTED:
580 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
581 case STATUS_USER_APC:
582 return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
583 case STATUS_TIMEOUT:
584 return VERR_TIMEOUT;
585 default:
586 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p: wait returned %lx!\n",
587 pMutexInt->u32Magic, pMutexInt, (long)rcNt));
588 return VERR_INTERNAL_ERROR;
589 }
590#endif
591 return VINF_SUCCESS;
592}
593
594
595RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
596{
597 /*
598 * Validate input.
599 */
600 PRTSEMMUTEXINTERNAL pMutexInt = (PRTSEMMUTEXINTERNAL)MutexSem;
601 if (!pMutexInt)
602 return VERR_INVALID_PARAMETER;
603 if ( !pMutexInt
604 || pMutexInt->u32Magic != RTSEMMUTEX_MAGIC)
605 {
606 AssertMsgFailed(("pMutexInt->u32Magic=%RX32 pMutexInt=%p\n", pMutexInt ? pMutexInt->u32Magic : 0, pMutexInt));
607 return VERR_INVALID_PARAMETER;
608 }
609
610 /*
611 * Release the mutex.
612 */
613#ifdef RT_USE_FAST_MUTEX
614 ExReleaseFastMutex(&pMutexInt->Mutex);
615#else
616 KeReleaseMutex(&pMutexInt->Mutex, FALSE);
617#endif
618 return VINF_SUCCESS;
619}
620
621#endif /* later */
622
623
624
625
626RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem)
627{
628 AssertCompile(sizeof(RTSEMFASTMUTEXINTERNAL) > sizeof(void *));
629 AssertPtrReturn(pMutexSem, VERR_INVALID_POINTER);
630
631 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pFastInt));
632 if (pFastInt)
633 {
634 pFastInt->u32Magic = RTSEMFASTMUTEX_MAGIC;
635 Assert(g_pDarwinLockGroup);
636 pFastInt->pMtx = lck_mtx_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
637 if (pFastInt->pMtx)
638 {
639 *pMutexSem = pFastInt;
640 return VINF_SUCCESS;
641 }
642
643 RTMemFree(pFastInt);
644 }
645 return VERR_NO_MEMORY;
646}
647
648
649RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem)
650{
651 if (MutexSem == NIL_RTSEMFASTMUTEX) /* don't bitch */
652 return VERR_INVALID_PARAMETER;
653 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
654 AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
655 AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
656 ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
657 VERR_INVALID_PARAMETER);
658
659 ASMAtomicIncU32(&pFastInt->u32Magic); /* make the handle invalid. */
660 Assert(g_pDarwinLockGroup);
661 lck_mtx_free(pFastInt->pMtx, g_pDarwinLockGroup);
662 pFastInt->pMtx = NULL;
663 RTMemFree(pFastInt);
664
665 return VINF_SUCCESS;
666}
667
668
669RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem)
670{
671 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
672 AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
673 AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
674 ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
675 VERR_INVALID_PARAMETER);
676 lck_mtx_lock(pFastInt->pMtx);
677 return VINF_SUCCESS;
678}
679
680
681RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem)
682{
683 PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
684 AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
685 AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
686 ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
687 VERR_INVALID_PARAMETER);
688 lck_mtx_unlock(pFastInt->pMtx);
689 return VINF_SUCCESS;
690}
691
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