VirtualBox

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

Last change on this file since 22052 was 22052, checked in by vboxsync, 16 years ago

IPRT: RT_MORE_STRICT for r0rdv and r0drv/darwin.

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