VirtualBox

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

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

todo

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