VirtualBox

Ignore:
Timestamp:
Apr 20, 2010 7:19:05 AM (15 years ago)
Author:
vboxsync
Message:

IPRT: Split up r0drv/darwin/semaphore-r0drv-darwin.cpp.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/darwin/semfastmutex-r0drv-darwin.cpp

    r28501 r28503  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Semaphores, Ring-0 Driver, Darwin.
     3 * IPRT - Fast Mutex Semaphores, Ring-0 Driver, Darwin.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5151*******************************************************************************/
    5252/**
    53  * Darwin event semaphore.
    54  */
    55 typedef 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  */
    73 typedef 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  */
    92 typedef 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 /**
    10453 * Wrapper for the darwin semaphore structure.
    10554 */
     
    11160    lck_mtx_t          *pMtx;
    11261} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
    113 
    114 
    115 
    116 RTDECL(int)  RTSemEventCreate(PRTSEMEVENT phEventSem)
    117 {
    118     return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
    119 }
    120 
    121 
    122 RTDECL(int)  RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
    123 {
    124     AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
    125     AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
    126     AssertPtrReturn(phEventSem, VERR_INVALID_POINTER);
    127     RT_ASSERT_PREEMPTIBLE();
    128 
    129     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
    130     if (pThis)
    131     {
    132         pThis->u32Magic = RTSEMEVENT_MAGIC;
    133         pThis->cWaiters = 0;
    134         pThis->cWaking = 0;
    135         pThis->fSignaled = 0;
    136         Assert(g_pDarwinLockGroup);
    137         pThis->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
    138         if (pThis->pSpinlock)
    139         {
    140             *phEventSem = pThis;
    141             return VINF_SUCCESS;
    142         }
    143 
    144         pThis->u32Magic = 0;
    145         RTMemFree(pThis);
    146     }
    147     return VERR_NO_MEMORY;
    148 }
    149 
    150 
    151 RTDECL(int)  RTSemEventDestroy(RTSEMEVENT hEventSem)
    152 {
    153     PRTSEMEVENTINTERNAL pThis = hEventSem;
    154     if (pThis == NIL_RTSEMEVENT)
    155         return VINF_SUCCESS;
    156     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    157     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    158     RT_ASSERT_INTS_ON();
    159 
    160     lck_spin_lock(pThis->pSpinlock);
    161     ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
    162     if (pThis->cWaiters > 0)
    163     {
    164         /* abort waiting thread, last man cleans up. */
    165         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
    166         thread_wakeup_prim((event_t)pThis, FALSE /* all threads */, THREAD_RESTART);
    167         lck_spin_unlock(pThis->pSpinlock);
    168     }
    169     else if (pThis->cWaking)
    170         /* the last waking thread is gonna do the cleanup */
    171         lck_spin_unlock(pThis->pSpinlock);
    172     else
    173     {
    174         lck_spin_unlock(pThis->pSpinlock);
    175         lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    176         RTMemFree(pThis);
    177     }
    178 
    179     return VINF_SUCCESS;
    180 }
    181 
    182 
    183 RTDECL(int)  RTSemEventSignal(RTSEMEVENT hEventSem)
    184 {
    185     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
    186     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    187     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC,
    188                     ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
    189                     VERR_INVALID_HANDLE);
    190     RT_ASSERT_PREEMPT_CPUID_VAR();
    191     RT_ASSERT_INTS_ON();
    192 
    193     /** @todo should probably disable interrupts here... update
    194      *        semspinmutex-r0drv-generic.c when done. */
    195     lck_spin_lock(pThis->pSpinlock);
    196 
    197     if (pThis->cWaiters > 0)
    198     {
    199         ASMAtomicDecU32(&pThis->cWaiters);
    200         ASMAtomicIncU32(&pThis->cWaking);
    201         thread_wakeup_prim((event_t)pThis, TRUE /* one thread */, THREAD_AWAKENED);
    202         /** @todo this isn't safe. a scheduling interrupt on the other cpu while we're in here
    203          * could cause the thread to be timed out before we manage to wake it up and the event
    204          * ends up in the wrong state. ditto for posix signals.
    205          * Update: check the return code; it will return KERN_NOT_WAITING if no one is around. */
    206     }
    207     else
    208         ASMAtomicXchgU8(&pThis->fSignaled, true);
    209 
    210     lck_spin_unlock(pThis->pSpinlock);
    211 
    212     RT_ASSERT_PREEMPT_CPUID();
    213     return VINF_SUCCESS;
    214 }
    215 
    216 
    217 static int rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, wait_interrupt_t fInterruptible)
    218 {
    219     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
    220     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    221     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    222     if (cMillies)
    223         RT_ASSERT_PREEMPTIBLE();
    224 
    225     lck_spin_lock(pThis->pSpinlock);
    226 
    227     int rc;
    228     if (pThis->fSignaled)
    229     {
    230         Assert(!pThis->cWaiters);
    231         ASMAtomicXchgU8(&pThis->fSignaled, false);
    232         rc = VINF_SUCCESS;
    233     }
    234     else if (!cMillies)
    235         rc = VERR_TIMEOUT;
    236     else
    237     {
    238         ASMAtomicIncU32(&pThis->cWaiters);
    239 
    240         wait_result_t rcWait;
    241         if (cMillies == RT_INDEFINITE_WAIT)
    242             rcWait = lck_spin_sleep(pThis->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pThis, fInterruptible);
    243         else
    244         {
    245             uint64_t u64AbsTime;
    246             nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
    247             u64AbsTime += mach_absolute_time();
    248 
    249             rcWait = lck_spin_sleep_deadline(pThis->pSpinlock, LCK_SLEEP_DEFAULT,
    250                                              (event_t)pThis, fInterruptible, u64AbsTime);
    251         }
    252         switch (rcWait)
    253         {
    254             case THREAD_AWAKENED:
    255                 Assert(pThis->cWaking > 0);
    256                 if (    !ASMAtomicDecU32(&pThis->cWaking)
    257                     &&  pThis->u32Magic != RTSEMEVENT_MAGIC)
    258                 {
    259                     /* the event was destroyed after we woke up, as the last thread do the cleanup. */
    260                     lck_spin_unlock(pThis->pSpinlock);
    261                     Assert(g_pDarwinLockGroup);
    262                     lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    263                     RTMemFree(pThis);
    264                     return VINF_SUCCESS;
    265                 }
    266                 rc = VINF_SUCCESS;
    267                 break;
    268 
    269             case THREAD_TIMED_OUT:
    270                 Assert(cMillies != RT_INDEFINITE_WAIT);
    271                 ASMAtomicDecU32(&pThis->cWaiters);
    272                 rc = VERR_TIMEOUT;
    273                 break;
    274 
    275             case THREAD_INTERRUPTED:
    276                 Assert(fInterruptible);
    277                 ASMAtomicDecU32(&pThis->cWaiters);
    278                 rc = VERR_INTERRUPTED;
    279                 break;
    280 
    281             case THREAD_RESTART:
    282                 /* Last one out does the cleanup. */
    283                 if (!ASMAtomicDecU32(&pThis->cWaking))
    284                 {
    285                     lck_spin_unlock(pThis->pSpinlock);
    286                     Assert(g_pDarwinLockGroup);
    287                     lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    288                     RTMemFree(pThis);
    289                     return VERR_SEM_DESTROYED;
    290                 }
    291 
    292                 rc = VERR_SEM_DESTROYED;
    293                 break;
    294 
    295             default:
    296                 AssertMsgFailed(("rcWait=%d\n", rcWait));
    297                 rc = VERR_GENERAL_FAILURE;
    298                 break;
    299         }
    300     }
    301 
    302     lck_spin_unlock(pThis->pSpinlock);
    303     return rc;
    304 }
    305 
    306 
    307 RTDECL(int)  RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    308 {
    309     return rtSemEventWait(hEventSem, cMillies, THREAD_UNINT);
    310 }
    311 
    312 
    313 RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    314 {
    315     return rtSemEventWait(hEventSem, cMillies, THREAD_ABORTSAFE);
    316 }
    317 
    318 
    319 
    320 RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
    321 {
    322     return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
    323 }
    324 
    325 
    326 RTDECL(int)  RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
    327                                      const char *pszNameFmt, ...)
    328 {
    329     AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
    330     AssertCompile(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
    331     AssertPtrReturn(phEventMultiSem, VERR_INVALID_POINTER);
    332     RT_ASSERT_PREEMPTIBLE();
    333 
    334     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
    335     if (pThis)
    336     {
    337         pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
    338         pThis->cWaiters = 0;
    339         pThis->cWaking = 0;
    340         pThis->fSignaled = 0;
    341         Assert(g_pDarwinLockGroup);
    342         pThis->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
    343         if (pThis->pSpinlock)
    344         {
    345             *phEventMultiSem = pThis;
    346             return VINF_SUCCESS;
    347         }
    348 
    349         pThis->u32Magic = 0;
    350         RTMemFree(pThis);
    351     }
    352     return VERR_NO_MEMORY;
    353 }
    354 
    355 
    356 RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
    357 {
    358     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
    359     if (pThis == NIL_RTSEMEVENTMULTI)
    360         return VINF_SUCCESS;
    361     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    362     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    363     RT_ASSERT_INTS_ON();
    364 
    365     lck_spin_lock(pThis->pSpinlock);
    366     ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
    367     if (pThis->cWaiters > 0)
    368     {
    369         /* abort waiting thread, last man cleans up. */
    370         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
    371         thread_wakeup_prim((event_t)pThis, FALSE /* all threads */, THREAD_RESTART);
    372         lck_spin_unlock(pThis->pSpinlock);
    373     }
    374     else if (pThis->cWaking)
    375         /* the last waking thread is gonna do the cleanup */
    376         lck_spin_unlock(pThis->pSpinlock);
    377     else
    378     {
    379         lck_spin_unlock(pThis->pSpinlock);
    380         lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    381         RTMemFree(pThis);
    382     }
    383 
    384     return VINF_SUCCESS;
    385 }
    386 
    387 
    388 RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
    389 {
    390     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
    391     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    392     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    393     RT_ASSERT_PREEMPT_CPUID_VAR();
    394     RT_ASSERT_INTS_ON();
    395 
    396     lck_spin_lock(pThis->pSpinlock);
    397 
    398     ASMAtomicXchgU8(&pThis->fSignaled, true);
    399     if (pThis->cWaiters > 0)
    400     {
    401         ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
    402         ASMAtomicXchgU32(&pThis->cWaiters, 0);
    403         thread_wakeup_prim((event_t)pThis, FALSE /* all threads */, THREAD_AWAKENED);
    404     }
    405 
    406     lck_spin_unlock(pThis->pSpinlock);
    407 
    408     RT_ASSERT_PREEMPT_CPUID();
    409     return VINF_SUCCESS;
    410 }
    411 
    412 
    413 RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
    414 {
    415     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
    416     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    417     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    418     RT_ASSERT_PREEMPT_CPUID_VAR();
    419     RT_ASSERT_INTS_ON();
    420 
    421     lck_spin_lock(pThis->pSpinlock);
    422     ASMAtomicXchgU8(&pThis->fSignaled, false);
    423     lck_spin_unlock(pThis->pSpinlock);
    424 
    425     RT_ASSERT_PREEMPT_CPUID();
    426     return VINF_SUCCESS;
    427 }
    428 
    429 
    430 static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, wait_interrupt_t fInterruptible)
    431 {
    432     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
    433     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    434     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    435     if (cMillies)
    436         RT_ASSERT_PREEMPTIBLE();
    437 
    438     lck_spin_lock(pThis->pSpinlock);
    439 
    440     int rc;
    441     if (pThis->fSignaled)
    442         rc = VINF_SUCCESS;
    443     else if (!cMillies)
    444         rc = VERR_TIMEOUT;
    445     else
    446     {
    447         ASMAtomicIncU32(&pThis->cWaiters);
    448 
    449         wait_result_t rcWait;
    450         if (cMillies == RT_INDEFINITE_WAIT)
    451             rcWait = lck_spin_sleep(pThis->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pThis, fInterruptible);
    452         else
    453         {
    454             uint64_t u64AbsTime;
    455             nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
    456             u64AbsTime += mach_absolute_time();
    457 
    458             rcWait = lck_spin_sleep_deadline(pThis->pSpinlock, LCK_SLEEP_DEFAULT,
    459                                              (event_t)pThis, fInterruptible, u64AbsTime);
    460         }
    461         switch (rcWait)
    462         {
    463             case THREAD_AWAKENED:
    464                 Assert(pThis->cWaking > 0);
    465                 if (    !ASMAtomicDecU32(&pThis->cWaking)
    466                     &&  pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)
    467                 {
    468                     /* the event was destroyed after we woke up, as the last thread do the cleanup. */
    469                     lck_spin_unlock(pThis->pSpinlock);
    470                     Assert(g_pDarwinLockGroup);
    471                     lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    472                     RTMemFree(pThis);
    473                     return VINF_SUCCESS;
    474                 }
    475                 rc = VINF_SUCCESS;
    476                 break;
    477 
    478             case THREAD_TIMED_OUT:
    479                 Assert(cMillies != RT_INDEFINITE_WAIT);
    480                 ASMAtomicDecU32(&pThis->cWaiters);
    481                 rc = VERR_TIMEOUT;
    482                 break;
    483 
    484             case THREAD_INTERRUPTED:
    485                 Assert(fInterruptible);
    486                 ASMAtomicDecU32(&pThis->cWaiters);
    487                 rc = VERR_INTERRUPTED;
    488                 break;
    489 
    490             case THREAD_RESTART:
    491                 /* Last one out does the cleanup. */
    492                 if (!ASMAtomicDecU32(&pThis->cWaking))
    493                 {
    494                     lck_spin_unlock(pThis->pSpinlock);
    495                     Assert(g_pDarwinLockGroup);
    496                     lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
    497                     RTMemFree(pThis);
    498                     return VERR_SEM_DESTROYED;
    499                 }
    500 
    501                 rc = VERR_SEM_DESTROYED;
    502                 break;
    503 
    504             default:
    505                 AssertMsgFailed(("rcWait=%d\n", rcWait));
    506                 rc = VERR_GENERAL_FAILURE;
    507                 break;
    508         }
    509     }
    510 
    511     lck_spin_unlock(pThis->pSpinlock);
    512     return rc;
    513 }
    514 
    515 
    516 RTDECL(int)  RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
    517 {
    518     return rtSemEventMultiWait(hEventMultiSem, cMillies, THREAD_UNINT);
    519 }
    520 
    521 
    522 RTDECL(int)  RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
    523 {
    524     return rtSemEventMultiWait(hEventMultiSem, cMillies, THREAD_ABORTSAFE);
    525 }
    526 
    527 
    528 
    529 
    530 
    531 #if 0 /* need proper timeout lock function! */
    532 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phFastMtx)
    533 {
    534     RT_ASSERT_PREEMPTIBLE();
    535     AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
    536     PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
    537     if (pThis)
    538     {
    539         pThis->u32Magic = RTSEMMUTEX_MAGIC;
    540         Assert(g_pDarwinLockGroup);
    541         pThis->pMtx = lck_mtx_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
    542         if (pThis->pMtx)
    543         {
    544             *phFastMtx = pThis;
    545             return VINF_SUCCESS;
    546         }
    547         RTMemFree(pThis);
    548     }
    549     return VERR_NO_MEMORY;
    550 }
    551 
    552 
    553 RTDECL(int)  RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
    554 {
    555     /*
    556      * Validate input.
    557      */
    558     PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
    559     if (!pThis)
    560         return VERR_INVALID_PARAMETER;
    561     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    562     AssertMsg(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
    563     RT_ASSERT_INTS_ON();
    564 
    565     /*
    566      * Invalidate it and signal the object just in case.
    567      */
    568     ASMAtomicIncU32(&pThis->u32Magic);
    569 
    570     Assert(g_pDarwinLockGroup);
    571     lck_mtx_free(pThis->pMtx, g_pDarwinLockGroup);
    572     pThis->pMtx = NULL;
    573 
    574     RTMemFree(pThis);
    575     return VINF_SUCCESS;
    576 }
    577 
    578 
    579 RTDECL(int)  RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
    580 {
    581     /*
    582      * Validate input.
    583      */
    584     PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
    585     if (!pThis)
    586         return VERR_INVALID_PARAMETER;
    587     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    588     AssertMsg(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
    589     if (cMillies)
    590         RT_ASSERT_PREEMPTIBLE();
    591 
    592     /*
    593      * Get the mutex.
    594      */
    595     wait_result_t rc = lck_mtx_lock_deadlink
    596 #if 1
    597 #else
    598     NTSTATUS rcNt;
    599     if (cMillies == RT_INDEFINITE_WAIT)
    600         rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, TRUE, NULL);
    601     else
    602     {
    603         LARGE_INTEGER Timeout;
    604         Timeout.QuadPart = -(int64_t)cMillies * 10000;
    605         rcNt = KeWaitForSingleObject(&pThis->Mutex, Executive, KernelMode, TRUE, &Timeout);
    606     }
    607     switch (rcNt)
    608     {
    609         case STATUS_SUCCESS:
    610             if (pThis->u32Magic == RTSEMMUTEX_MAGIC)
    611                 return VINF_SUCCESS;
    612             return VERR_SEM_DESTROYED;
    613         case STATUS_ALERTED:
    614             return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
    615         case STATUS_USER_APC:
    616             return VERR_INTERRUPTED; /** @todo VERR_INTERRUPTED isn't correct anylonger. please fix r0drv stuff! */
    617         case STATUS_TIMEOUT:
    618             return VERR_TIMEOUT;
    619         default:
    620             AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
    621                              pThis->u32Magic, pThis, (long)rcNt));
    622             return VERR_INTERNAL_ERROR;
    623     }
    624 #endif
    625     return VINF_SUCCESS;
    626 }
    627 
    628 
    629 RTDECL(int)  RTSemMutexRelease(RTSEMMUTEX hMutexSem)
    630 {
    631     /*
    632      * Validate input.
    633      */
    634     PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
    635     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    636     AssertMsg(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
    637     RT_ASSERT_PREEMPTIBLE();
    638 
    639     /*
    640      * Release the mutex.
    641      */
    642 #ifdef RT_USE_FAST_MUTEX
    643     ExReleaseFastMutex(&pThis->Mutex);
    644 #else
    645     KeReleaseMutex(&pThis->Mutex, FALSE);
    646 #endif
    647     return VINF_SUCCESS;
    648 }
    649 
    650 #endif /* later */
    651 
    65262
    65363
Note: See TracChangeset for help on using the changeset viewer.

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