VirtualBox

Ignore:
Timestamp:
Feb 1, 2008 9:45:27 PM (17 years ago)
Author:
vboxsync
Message:

split up the linux and posix semaphore implementations (ring-3) to avoid code duplication and make it easier to select one or the other for each of the semaphore types.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp

    r6734 r6738  
    11/* $Id$ */
    22/** @file
    3  * innotek Portable Runtime - Semaphores, POSIX.
     3 * innotek Portable Runtime - Multiple Release Event Semaphore, POSIX.
    44 */
    55
     
    3939#include <sys/time.h>
    4040
    41 #ifdef RT_OS_DARWIN
    42 # define pthread_yield() pthread_yield_np()
    43 #endif
    44 
    45 #ifdef RT_OS_SOLARIS
    46 # include <sched.h>
    47 # define pthread_yield() sched_yield()
    48 #endif
    49 
    5041
    5142/*******************************************************************************
    5243*   Structures and Typedefs                                                    *
    5344*******************************************************************************/
    54 
    55 /** Internal representation of the POSIX implementation of an Event semaphore.
     45/** Posix internal representation of a Mutex Multi semaphore.
    5646 * The POSIX implementation uses a mutex and a condition variable to implement
    57  * the automatic reset event semaphore semantics.
    58  *
    59  * This must be identical to RTSEMEVENTMULTIINTERNAL!
    60  */
    61 struct RTSEMEVENTINTERNAL
     47 * the automatic reset event semaphore semantics. */
     48struct RTSEMEVENTMULTIINTERNAL
    6249{
    6350    /** pthread condition. */
     
    7259};
    7360
    74 /** Posix internal representation of a Mutex Multi semaphore.
    75  * This must be identical to RTSEMEVENTINTERNAL! */
    76 struct RTSEMEVENTMULTIINTERNAL
    77 {
    78     /** pthread condition. */
    79     pthread_cond_t      Cond;
    80     /** pthread mutex which protects the condition and the event state. */
    81     pthread_mutex_t     Mutex;
    82     /** The state of the semaphore.
    83      * This is operated while owning mutex and using atomic updating. */
    84     volatile uint32_t   u32State;
    85     /** Number of waiters. */
    86     volatile uint32_t   cWaiters;
    87 };
    88 
    89 /** The valus of the u32State variable in a RTSEMEVENTINTERNAL and RTSEMEVENTMULTIINTERNAL.
     61/** The valus of the u32State variable in RTSEMEVENTMULTIINTERNAL.
    9062 * @{ */
    9163/** The object isn't initialized. */
    92 #define EVENT_STATE_UNINITIALIZED   0
     64#define EVENTMULTI_STATE_UNINITIALIZED   0
    9365/** The semaphore is is signaled. */
    94 #define EVENT_STATE_SIGNALED        0xff00ff00
     66#define EVENTMULTI_STATE_SIGNALED        0xff00ff00
    9567/** The semaphore is not signaled. */
    96 #define EVENT_STATE_NOT_SIGNALED    0x00ff00ff
     68#define EVENTMULTI_STATE_NOT_SIGNALED    0x00ff00ff
    9769/** @} */
    9870
    9971
    100 /** Posix internal representation of a Mutex semaphore. */
    101 struct RTSEMMUTEXINTERNAL
    102 {
    103     /** pthread mutex. */
    104     pthread_mutex_t     Mutex;
    105     /** The owner of the mutex. */
    106     volatile pthread_t  Owner;
    107     /** Nesting count. */
    108     volatile uint32_t   cNesting;
    109 };
    110 
    111 /** Posix internal representation of a read-write semaphore. */
    112 struct RTSEMRWINTERNAL
    113 {
    114     /** pthread rwlock. */
    115     pthread_rwlock_t    RWLock;
    116     /** Variable to check if initialized.
    117      * 0 is uninitialized, ~0 is inititialized. */
    118     volatile unsigned   uCheck;
    119     /** The write owner of the lock. */
    120     volatile pthread_t  WROwner;
    121 };
    122 
    12372
    12473/**
    125  * Validate an Event semaphore handle passed to one of the interface.
     74 * Validate an event multi semaphore handle passed to one of the interface.
    12675 *
    12776 * @returns true if valid.
    12877 * @returns false if invalid.
    129  * @param   pIntEventSem    Pointer to the event semaphore to validate.
     78 * @param   pThis    Pointer to the event semaphore to validate.
    13079 */
    131 inline bool rtsemEventValid(struct RTSEMEVENTINTERNAL *pIntEventSem)
    132 {
    133     if ((uintptr_t)pIntEventSem < 0x10000)
     80inline bool rtsemEventMultiValid(struct RTSEMEVENTMULTIINTERNAL *pThis)
     81{
     82    if ((uintptr_t)pThis < 0x10000)
    13483        return false;
    13584
    136     uint32_t    u32 = pIntEventSem->u32State; /* this is volatile, so a explicit read like this is needed. */
    137     if (    u32 != EVENT_STATE_NOT_SIGNALED
    138         &&  u32 != EVENT_STATE_SIGNALED)
     85    uint32_t    u32 = pThis->u32State; /* this is volatile, so a explicit read like this is needed. */
     86    if (    u32 != EVENTMULTI_STATE_NOT_SIGNALED
     87        &&  u32 != EVENTMULTI_STATE_SIGNALED)
    13988        return false;
    14089
     
    14392
    14493
    145 RTDECL(int)  RTSemEventCreate(PRTSEMEVENT pEventSem)
     94RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
    14695{
    14796    int rc;
     
    15099     * Allocate semaphore handle.
    151100     */
    152     struct RTSEMEVENTINTERNAL *pIntEventSem = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTINTERNAL));
    153     if (pIntEventSem)
     101    struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
     102    if (pThis)
    154103    {
    155104        /*
     
    160109        if (!rc)
    161110        {
    162             rc = pthread_cond_init(&pIntEventSem->Cond, &CondAttr);
     111            rc = pthread_cond_init(&pThis->Cond, &CondAttr);
    163112            if (!rc)
    164113            {
     
    170119                if (!rc)
    171120                {
    172                     rc = pthread_mutex_init(&pIntEventSem->Mutex, &MutexAttr);
     121                    rc = pthread_mutex_init(&pThis->Mutex, &MutexAttr);
    173122                    if (!rc)
    174123                    {
     
    176125                        pthread_condattr_destroy(&CondAttr);
    177126
    178                         ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_NOT_SIGNALED);
    179                         ASMAtomicXchgU32(&pIntEventSem->cWaiters, 0);
    180 
    181                         *pEventSem = pIntEventSem;
     127                        ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
     128                        ASMAtomicXchgU32(&pThis->cWaiters, 0);
     129
     130                        *pEventMultiSem = pThis;
    182131                        return VINF_SUCCESS;
    183132                    }
     133
    184134                    pthread_mutexattr_destroy(&MutexAttr);
    185135                }
    186                 pthread_cond_destroy(&pIntEventSem->Cond);
     136                pthread_cond_destroy(&pThis->Cond);
    187137            }
    188138            pthread_condattr_destroy(&CondAttr);
     
    190140
    191141        rc = RTErrConvertFromErrno(rc);
    192         RTMemFree(pIntEventSem);
     142        RTMemFree(pThis);
    193143    }
    194144    else
     
    196146
    197147    return rc;
    198 }
    199 
    200 
    201 RTDECL(int)  RTSemEventDestroy(RTSEMEVENT EventSem)
     148
     149}
     150
     151
     152RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
    202153{
    203154    /*
    204155     * Validate handle.
    205156     */
    206     if (!rtsemEventValid(EventSem))
    207     {
    208         AssertMsgFailed(("Invalid handle %p!\n", EventSem));
     157    if (!rtsemEventMultiValid(EventMultiSem))
     158    {
     159        AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
    209160        return VERR_INVALID_HANDLE;
    210161    }
     
    212163    /*
    213164     * Abort all waiters forcing them to return failure.
    214      *
    215      */
    216     struct RTSEMEVENTINTERNAL *pIntEventSem = EventSem;
     165     */
     166    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    217167    int rc;
    218168    for (int i = 30; i > 0; i--)
    219169    {
    220         ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_UNINITIALIZED);
    221         rc = pthread_cond_destroy(&pIntEventSem->Cond);
     170        ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_UNINITIALIZED);
     171        rc = pthread_cond_destroy(&pThis->Cond);
    222172        if (rc != EBUSY)
    223173            break;
    224         pthread_cond_broadcast(&pIntEventSem->Cond);
     174        pthread_cond_broadcast(&pThis->Cond);
    225175        usleep(1000);
    226176    } while (rc == EBUSY);
    227177    if (rc)
    228178    {
    229         AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", EventSem, rc));
     179        AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", EventMultiSem, rc));
    230180        return RTErrConvertFromErrno(rc);
    231181    }
     
    237187    for (int i = 30; i > 0; i--)
    238188    {
    239         rc = pthread_mutex_destroy(&pIntEventSem->Mutex);
     189        rc = pthread_mutex_destroy(&pThis->Mutex);
    240190        if (rc != EBUSY)
    241191            break;
     
    244194    if (rc)
    245195    {
    246         AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", EventSem, rc));
     196        AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", EventMultiSem, rc));
    247197        return RTErrConvertFromErrno(rc);
    248198    }
     
    251201     * Free the semaphore memory and be gone.
    252202     */
    253     RTMemFree(pIntEventSem);
     203    RTMemFree(pThis);
    254204    return VINF_SUCCESS;
    255205}
    256206
    257207
    258 RTDECL(int)  RTSemEventSignal(RTSEMEVENT EventSem)
     208RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
    259209{
    260210    /*
    261211     * Validate input.
    262212     */
    263     if (!rtsemEventValid(EventSem))
    264     {
    265         AssertMsgFailed(("Invalid handle %p!\n", EventSem));
     213    if (!rtsemEventMultiValid(EventMultiSem))
     214    {
     215        AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
    266216        return VERR_INVALID_HANDLE;
    267217    }
     
    270220     * Lock the mutex semaphore.
    271221     */
    272     struct RTSEMEVENTINTERNAL *pIntEventSem = EventSem;
    273     int rc = pthread_mutex_lock(&pIntEventSem->Mutex);
    274     if (rc)
    275     {
    276         AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", EventSem, rc));
     222    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
     223    int rc = pthread_mutex_lock(&pThis->Mutex);
     224    if (rc)
     225    {
     226        AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", EventMultiSem, rc));
    277227        return RTErrConvertFromErrno(rc);
    278228    }
     
    281231     * Check the state.
    282232     */
    283     if (pIntEventSem->u32State == EVENT_STATE_NOT_SIGNALED)
    284     {
    285         ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_SIGNALED);
    286         rc = pthread_cond_signal(&pIntEventSem->Cond);
    287         AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", EventSem, rc));
    288     }
    289     else if (pIntEventSem->u32State == EVENT_STATE_SIGNALED)
    290     {
    291         rc = pthread_cond_signal(&pIntEventSem->Cond); /* give'm another kick... */
    292         AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", EventSem, rc));
     233    if (pThis->u32State == EVENTMULTI_STATE_NOT_SIGNALED)
     234    {
     235        ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_SIGNALED);
     236        rc = pthread_cond_signal(&pThis->Cond);
     237        AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", EventMultiSem, rc));
     238    }
     239    else if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
     240    {
     241        rc = pthread_cond_signal(&pThis->Cond); /* give'm another kick... */
     242        AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", EventMultiSem, rc));
    293243    }
    294244    else
     
    298248     * Release the mutex and return.
    299249     */
    300     int rc2 = pthread_mutex_unlock(&pIntEventSem->Mutex);
    301     AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc));
     250    int rc2 = pthread_mutex_unlock(&pThis->Mutex);
     251    AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", EventMultiSem, rc));
    302252    if (rc)
    303253        return RTErrConvertFromErrno(rc);
     
    309259
    310260
    311 static int  rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResume)
     261RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
    312262{
    313263    /*
    314264     * Validate input.
    315265     */
    316     if (!rtsemEventValid(EventSem))
    317     {
    318         AssertMsgFailed(("Invalid handle %p!\n", EventSem));
     266    if (!rtsemEventMultiValid(EventMultiSem))
     267    {
     268        AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
    319269        return VERR_INVALID_HANDLE;
    320270    }
    321271
    322272    /*
     273     * Lock the mutex semaphore.
     274     */
     275    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
     276    int rc = pthread_mutex_lock(&pThis->Mutex);
     277    if (rc)
     278    {
     279        AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
     280        return RTErrConvertFromErrno(rc);
     281    }
     282
     283    /*
     284     * Check the state.
     285     */
     286    if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
     287        ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
     288    else if (pThis->u32State != EVENTMULTI_STATE_NOT_SIGNALED)
     289        rc = VERR_SEM_DESTROYED;
     290
     291    /*
     292     * Release the mutex and return.
     293     */
     294    rc = pthread_mutex_unlock(&pThis->Mutex);
     295    if (rc)
     296    {
     297        AssertMsgFailed(("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
     298        return RTErrConvertFromErrno(rc);
     299    }
     300
     301    return VINF_SUCCESS;
     302
     303}
     304
     305
     306static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume)
     307{
     308    /*
     309     * Validate input.
     310     */
     311    if (!rtsemEventMultiValid(EventMultiSem))
     312    {
     313        AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
     314        return VERR_INVALID_HANDLE;
     315    }
     316
     317    /*
    323318     * Timed or indefinite wait?
    324319     */
    325     struct RTSEMEVENTINTERNAL *pIntEventSem = EventSem;
     320    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    326321    if (cMillies == RT_INDEFINITE_WAIT)
    327322    {
    328         /* for fairness, yield before going to sleep. */
    329         if (    ASMAtomicIncU32(&pIntEventSem->cWaiters) > 1
    330             &&  pIntEventSem->u32State == EVENT_STATE_SIGNALED)
    331             pthread_yield();
    332 
    333          /* take mutex */
    334         int rc = pthread_mutex_lock(&pIntEventSem->Mutex);
     323        /* take mutex */
     324        int rc = pthread_mutex_lock(&pThis->Mutex);
    335325        if (rc)
    336326        {
    337             ASMAtomicDecU32(&pIntEventSem->cWaiters);
    338             AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", EventSem, rc));
     327            AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    339328            return RTErrConvertFromErrno(rc);
    340329        }
     330        ASMAtomicIncU32(&pThis->cWaiters);
    341331
    342332        for (;;)
    343333        {
    344334            /* check state. */
    345             if (pIntEventSem->u32State == EVENT_STATE_SIGNALED)
    346             {
    347                 ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_NOT_SIGNALED);
    348                 ASMAtomicDecU32(&pIntEventSem->cWaiters);
    349                 rc = pthread_mutex_unlock(&pIntEventSem->Mutex);
    350                 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc);
     335            if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
     336            {
     337                ASMAtomicDecU32(&pThis->cWaiters);
     338                rc = pthread_mutex_unlock(&pThis->Mutex);
     339                AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    351340                return VINF_SUCCESS;
    352341            }
    353             if (pIntEventSem->u32State == EVENT_STATE_UNINITIALIZED)
    354             {
    355                 rc = pthread_mutex_unlock(&pIntEventSem->Mutex);
    356                 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc);
     342            if (pThis->u32State == EVENTMULTI_STATE_UNINITIALIZED)
     343            {
     344                rc = pthread_mutex_unlock(&pThis->Mutex);
     345                AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    357346                return VERR_SEM_DESTROYED;
    358347            }
    359348
    360349            /* wait */
    361             rc = pthread_cond_wait(&pIntEventSem->Cond, &pIntEventSem->Mutex);
     350            rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex);
    362351            if (rc)
    363352            {
    364                 AssertMsgFailed(("Failed to wait on event sem %p, rc=%d.\n", EventSem, rc));
    365                 ASMAtomicDecU32(&pIntEventSem->cWaiters);
    366                 int rc2 = pthread_mutex_unlock(&pIntEventSem->Mutex);
    367                 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc2)); NOREF(rc2);
     353                AssertMsgFailed(("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc));
     354                ASMAtomicDecU32(&pThis->cWaiters);
     355                int rc2 = pthread_mutex_unlock(&pThis->Mutex);
     356                AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2);
    368357                return RTErrConvertFromErrno(rc);
    369358            }
     
    395384        }
    396385
    397         /* for fairness, yield before going to sleep. */
    398         if (ASMAtomicIncU32(&pIntEventSem->cWaiters) > 1)
    399             pthread_yield();
    400 
    401386        /* take mutex */
    402387#ifdef RT_OS_DARWIN
    403         int rc = pthread_mutex_lock(&pIntEventSem->Mutex);
     388        int rc = pthread_mutex_lock(&pThis->Mutex);
    404389#else
    405         int rc = pthread_mutex_timedlock(&pIntEventSem->Mutex, &ts);
     390        int rc = pthread_mutex_timedlock(&pThis->Mutex, &ts);
    406391#endif
    407392        if (rc)
    408393        {
    409             ASMAtomicDecU32(&pIntEventSem->cWaiters);
    410             AssertMsg(rc == ETIMEDOUT, ("Failed to lock event sem %p, rc=%d.\n", EventSem, rc));
     394            AssertMsg(rc == ETIMEDOUT, ("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    411395            return RTErrConvertFromErrno(rc);
    412396        }
     397        ASMAtomicIncU32(&pThis->cWaiters);
    413398
    414399        for (;;)
    415400        {
    416401            /* check state. */
    417             if (pIntEventSem->u32State == EVENT_STATE_SIGNALED)
    418             {
    419                 ASMAtomicXchgU32(&pIntEventSem->u32State, EVENT_STATE_NOT_SIGNALED);
    420                 ASMAtomicDecU32(&pIntEventSem->cWaiters);
    421                 rc = pthread_mutex_unlock(&pIntEventSem->Mutex);
    422                 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc);
    423                 return VINF_SUCCESS;
    424             }
    425             if (pIntEventSem->u32State == EVENT_STATE_UNINITIALIZED)
    426             {
    427                 rc = pthread_mutex_unlock(&pIntEventSem->Mutex);
    428                 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", EventSem, rc)); NOREF(rc);
    429                 return VERR_SEM_DESTROYED;
    430             }
    431 
    432             /* wait */
    433             rc = pthread_cond_timedwait(&pIntEventSem->Cond, &pIntEventSem->Mutex, &ts);
    434             if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */
    435             {
    436                 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event sem %p, rc=%d.\n", EventSem, rc));
    437                 ASMAtomicDecU32(&pIntEventSem->cWaiters);
    438                 int rc2 = pthread_mutex_unlock(&pIntEventSem->Mutex);
    439                 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", EventSem, rc2)); NOREF(rc2);
    440                 return RTErrConvertFromErrno(rc);
    441             }
    442         } /* for (;;) */
    443     }
    444 }
    445 
    446 
    447 RTDECL(int)  RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
    448 {
    449     int rc = rtSemEventWait(EventSem, cMillies, true);
    450     Assert(rc != VERR_INTERRUPTED);
    451     return rc;
    452 }
    453 
    454 
    455 RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
    456 {
    457     return rtSemEventWait(EventSem, cMillies, false);
    458 }
    459 
    460 
    461 
    462 
    463 
    464 
    465 /**
    466  * Validate an event multi semaphore handle passed to one of the interface.
    467  *
    468  * @returns true if valid.
    469  * @returns false if invalid.
    470  * @param   pIntEventMultiSem    Pointer to the event semaphore to validate.
    471  */
    472 inline bool rtsemEventMultiValid(struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem)
    473 {
    474     if ((uintptr_t)pIntEventMultiSem < 0x10000)
    475         return false;
    476 
    477     uint32_t    u32 = pIntEventMultiSem->u32State; /* this is volatile, so a explicit read like this is needed. */
    478     if (    u32 != EVENT_STATE_NOT_SIGNALED
    479         &&  u32 != EVENT_STATE_SIGNALED)
    480         return false;
    481 
    482     return true;
    483 }
    484 
    485 
    486 RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
    487 {
    488     /* the code and the structure is identical with other type for this function. */
    489     return RTSemEventCreate((PRTSEMEVENT)pEventMultiSem);
    490 }
    491 
    492 
    493 RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
    494 {
    495     /* the code and the structure is identical with other type for this function. */
    496     return RTSemEventDestroy((RTSEMEVENT)EventMultiSem);
    497 }
    498 
    499 
    500 RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
    501 {
    502     /* the code and the structure is identical with other type for this function. */
    503     return RTSemEventSignal((RTSEMEVENT)EventMultiSem);
    504 }
    505 
    506 
    507 RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
    508 {
    509     /*
    510      * Validate input.
    511      */
    512     if (!rtsemEventMultiValid(EventMultiSem))
    513     {
    514         AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
    515         return VERR_INVALID_HANDLE;
    516     }
    517 
    518     /*
    519      * Lock the mutex semaphore.
    520      */
    521     struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem = EventMultiSem;
    522     int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex);
    523     if (rc)
    524     {
    525         AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    526         return RTErrConvertFromErrno(rc);
    527     }
    528 
    529     /*
    530      * Check the state.
    531      */
    532     if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED)
    533         ASMAtomicXchgU32(&pIntEventMultiSem->u32State, EVENT_STATE_NOT_SIGNALED);
    534     else if (pIntEventMultiSem->u32State != EVENT_STATE_NOT_SIGNALED)
    535         rc = VERR_SEM_DESTROYED;
    536 
    537     /*
    538      * Release the mutex and return.
    539      */
    540     rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
    541     if (rc)
    542     {
    543         AssertMsgFailed(("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    544         return RTErrConvertFromErrno(rc);
    545     }
    546 
    547     return VINF_SUCCESS;
    548 
    549 }
    550 
    551 
    552 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume)
    553 {
    554     /*
    555      * Validate input.
    556      */
    557     if (!rtsemEventMultiValid(EventMultiSem))
    558     {
    559         AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem));
    560         return VERR_INVALID_HANDLE;
    561     }
    562 
    563     /*
    564      * Timed or indefinite wait?
    565      */
    566     struct RTSEMEVENTMULTIINTERNAL *pIntEventMultiSem = EventMultiSem;
    567     if (cMillies == RT_INDEFINITE_WAIT)
    568     {
    569         /* take mutex */
    570         int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex);
    571         if (rc)
    572         {
    573             AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    574             return RTErrConvertFromErrno(rc);
    575         }
    576         ASMAtomicIncU32(&pIntEventMultiSem->cWaiters);
    577 
    578         for (;;)
    579         {
    580             /* check state. */
    581             if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED)
    582             {
    583                 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters);
    584                 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
     402            if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
     403            {
     404                ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
     405                ASMAtomicDecU32(&pThis->cWaiters);
     406                rc = pthread_mutex_unlock(&pThis->Mutex);
    585407                AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    586408                return VINF_SUCCESS;
    587409            }
    588             if (pIntEventMultiSem->u32State == EVENT_STATE_UNINITIALIZED)
    589             {
    590                 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
     410            if (pThis->u32State == EVENTMULTI_STATE_UNINITIALIZED)
     411            {
     412                rc = pthread_mutex_unlock(&pThis->Mutex);
    591413                AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    592414                return VERR_SEM_DESTROYED;
     
    594416
    595417            /* wait */
    596             rc = pthread_cond_wait(&pIntEventMultiSem->Cond, &pIntEventMultiSem->Mutex);
    597             if (rc)
    598             {
    599                 AssertMsgFailed(("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    600                 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters);
    601                 int rc2 = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
    602                 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2);
    603                 return RTErrConvertFromErrno(rc);
    604             }
    605         }
    606     }
    607     else
    608     {
    609         /*
    610          * Get current time and calc end of wait time.
    611          */
    612         struct timespec     ts = {0,0};
    613 #ifdef RT_OS_DARWIN
    614         struct timeval      tv = {0,0};
    615         gettimeofday(&tv, NULL);
    616         ts.tv_sec = tv.tv_sec;
    617         ts.tv_nsec = tv.tv_usec * 1000;
    618 #else
    619         clock_gettime(CLOCK_REALTIME, &ts);
    620 #endif
    621         if (cMillies != 0)
    622         {
    623             ts.tv_nsec += (cMillies % 1000) * 1000000;
    624             ts.tv_sec  += cMillies / 1000;
    625             if (ts.tv_nsec >= 1000000000)
    626             {
    627                 ts.tv_nsec -= 1000000000;
    628                 ts.tv_sec++;
    629             }
    630         }
    631 
    632         /* take mutex */
    633 #ifdef RT_OS_DARWIN
    634         int rc = pthread_mutex_lock(&pIntEventMultiSem->Mutex);
    635 #else
    636         int rc = pthread_mutex_timedlock(&pIntEventMultiSem->Mutex, &ts);
    637 #endif
    638         if (rc)
    639         {
    640             AssertMsg(rc == ETIMEDOUT, ("Failed to lock event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    641             return RTErrConvertFromErrno(rc);
    642         }
    643         ASMAtomicIncU32(&pIntEventMultiSem->cWaiters);
    644 
    645         for (;;)
    646         {
    647             /* check state. */
    648             if (pIntEventMultiSem->u32State == EVENT_STATE_SIGNALED)
    649             {
    650                 ASMAtomicXchgU32(&pIntEventMultiSem->u32State, EVENT_STATE_NOT_SIGNALED);
    651                 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters);
    652                 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
    653                 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    654                 return VINF_SUCCESS;
    655             }
    656             if (pIntEventMultiSem->u32State == EVENT_STATE_UNINITIALIZED)
    657             {
    658                 rc = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
    659                 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc)); NOREF(rc);
    660                 return VERR_SEM_DESTROYED;
    661             }
    662 
    663             /* wait */
    664             rc = pthread_cond_timedwait(&pIntEventMultiSem->Cond, &pIntEventMultiSem->Mutex, &ts);
     418            rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &ts);
    665419            if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */
    666420            {
    667421                AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event multi sem %p, rc=%d.\n", EventMultiSem, rc));
    668                 ASMAtomicDecU32(&pIntEventMultiSem->cWaiters);
    669                 int rc2 = pthread_mutex_unlock(&pIntEventMultiSem->Mutex);
     422                ASMAtomicDecU32(&pThis->cWaiters);
     423                int rc2 = pthread_mutex_unlock(&pThis->Mutex);
    670424                AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", EventMultiSem, rc2)); NOREF(rc2);
    671425                return RTErrConvertFromErrno(rc);
     
    689443}
    690444
    691 
    692 
    693 
    694 
    695 /**
    696  * Validate a Mutex semaphore handle passed to one of the interface.
    697  *
    698  * @returns true if valid.
    699  * @returns false if invalid.
    700  * @param   pIntMutexSem    Pointer to the mutex semaphore to validate.
    701  */
    702 inline bool rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)
    703 {
    704     if ((uintptr_t)pIntMutexSem < 0x10000)
    705         return false;
    706 
    707     if (pIntMutexSem->cNesting == (uint32_t)~0)
    708         return false;
    709 
    710     return true;
    711 }
    712 
    713 
    714 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    715 {
    716     int rc;
    717 
    718     /*
    719      * Allocate semaphore handle.
    720      */
    721     struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
    722     if (pIntMutexSem)
    723     {
    724         /*
    725          * Create the semaphore.
    726          */
    727         pthread_mutexattr_t MutexAttr;
    728         rc = pthread_mutexattr_init(&MutexAttr);
    729         if (!rc)
    730         {
    731             rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);
    732             if (!rc)
    733             {
    734                 pthread_mutexattr_destroy(&MutexAttr);
    735 
    736                 pIntMutexSem->Owner    = (pthread_t)-1;
    737                 pIntMutexSem->cNesting = 0;
    738 
    739                 *pMutexSem = pIntMutexSem;
    740                 return VINF_SUCCESS;
    741             }
    742             pthread_mutexattr_destroy(&MutexAttr);
    743         }
    744         RTMemFree(pIntMutexSem);
    745     }
    746     else
    747         rc = VERR_NO_MEMORY;
    748 
    749     return rc;
    750 }
    751 
    752 
    753 RTDECL(int)  RTSemMutexDestroy(RTSEMMUTEX MutexSem)
    754 {
    755     /*
    756      * Validate input.
    757      */
    758     if (!rtsemMutexValid(MutexSem))
    759     {
    760         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    761         return VERR_INVALID_HANDLE;
    762     }
    763 
    764     /*
    765      * Try destroy it.
    766      */
    767     struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
    768     int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);
    769     if (rc)
    770     {
    771         AssertMsgFailed(("Failed to destroy mutex sem %p, rc=%d.\n", MutexSem, rc));
    772         return RTErrConvertFromErrno(rc);
    773     }
    774 
    775     /*
    776      * Free the memory and be gone.
    777      */
    778     pIntMutexSem->Owner    = (pthread_t)-1;
    779     pIntMutexSem->cNesting = ~0;
    780     RTMemTmpFree(pIntMutexSem);
    781 
    782     return VINF_SUCCESS;
    783 }
    784 
    785 
    786 RTDECL(int)  RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
    787 {
    788     /*
    789      * Validate input.
    790      */
    791     if (!rtsemMutexValid(MutexSem))
    792     {
    793         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    794         return VERR_INVALID_HANDLE;
    795     }
    796 
    797     /*
    798      * Check if nested request.
    799      */
    800     pthread_t                     Self = pthread_self();
    801     struct RTSEMMUTEXINTERNAL    *pIntMutexSem = MutexSem;
    802     if (    pIntMutexSem->Owner == Self
    803         &&  pIntMutexSem->cNesting > 0)
    804     {
    805         pIntMutexSem->cNesting++;
    806         return VINF_SUCCESS;
    807     }
    808 
    809     /*
    810      * Lock it.
    811      */
    812     if (cMillies == RT_INDEFINITE_WAIT)
    813     {
    814         /* take mutex */
    815         int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);
    816         if (rc)
    817         {
    818             AssertMsgFailed(("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
    819             return RTErrConvertFromErrno(rc);
    820         }
    821     }
    822     else
    823     {
    824 #ifdef RT_OS_DARWIN
    825         AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
    826         return VERR_NOT_IMPLEMENTED;
    827 #else /* !RT_OS_DARWIN */
    828         /*
    829          * Get current time and calc end of wait time.
    830          */
    831         struct timespec     ts = {0,0};
    832         clock_gettime(CLOCK_REALTIME, &ts);
    833         if (cMillies != 0)
    834         {
    835             ts.tv_nsec += (cMillies % 1000) * 1000000;
    836             ts.tv_sec  += cMillies / 1000;
    837             if (ts.tv_nsec >= 1000000000)
    838             {
    839                 ts.tv_nsec -= 1000000000;
    840                 ts.tv_sec++;
    841             }
    842         }
    843 
    844         /* take mutex */
    845         int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);
    846         if (rc)
    847         {
    848             AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
    849             return RTErrConvertFromErrno(rc);
    850         }
    851 #endif /* !RT_OS_DARWIN */
    852     }
    853 
    854     /*
    855      * Set the owner and nesting.
    856      */
    857     pIntMutexSem->Owner = Self;
    858     ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
    859 
    860     return VINF_SUCCESS;
    861 }
    862 
    863 
    864 RTDECL(int)  RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
    865 {
    866     /* EINTR isn't returned by the wait functions we're using. */
    867     return RTSemMutexRequest(MutexSem, cMillies);
    868 }
    869 
    870 
    871 RTDECL(int)  RTSemMutexRelease(RTSEMMUTEX MutexSem)
    872 {
    873     /*
    874      * Validate input.
    875      */
    876     if (!rtsemMutexValid(MutexSem))
    877     {
    878         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    879         return VERR_INVALID_HANDLE;
    880     }
    881 
    882     /*
    883      * Check if nested.
    884      */
    885     pthread_t                     Self = pthread_self();
    886     struct RTSEMMUTEXINTERNAL    *pIntMutexSem = MutexSem;
    887     if (    pIntMutexSem->Owner != Self
    888         ||  pIntMutexSem->cNesting == (uint32_t)~0)
    889     {
    890         AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
    891                          pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
    892         return VERR_NOT_OWNER;
    893     }
    894 
    895     /*
    896      * If nested we'll just pop a nesting.
    897      */
    898     if (pIntMutexSem->cNesting > 1)
    899     {
    900         pIntMutexSem->cNesting--;
    901         return VINF_SUCCESS;
    902     }
    903 
    904     /*
    905      * Clear the state. (cNesting == 1)
    906      */
    907     pIntMutexSem->Owner    = (pthread_t)-1;
    908     ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
    909 
    910     /*
    911      * Unlock mutex semaphore.
    912      */
    913     int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);
    914     if (rc)
    915     {
    916         AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
    917         return RTErrConvertFromErrno(rc);
    918     }
    919 
    920     return VINF_SUCCESS;
    921 }
    922 
    923 
    924 
    925 
    926 
    927 /**
    928  * Validate a read-write semaphore handle passed to one of the interface.
    929  *
    930  * @returns true if valid.
    931  * @returns false if invalid.
    932  * @param   pIntRWSem   Pointer to the read-write semaphore to validate.
    933  */
    934 inline bool rtsemRWValid(struct RTSEMRWINTERNAL *pIntRWSem)
    935 {
    936     if ((uintptr_t)pIntRWSem < 0x10000)
    937         return false;
    938 
    939     if (pIntRWSem->uCheck != (unsigned)~0)
    940         return false;
    941 
    942     return true;
    943 }
    944 
    945 
    946 RTDECL(int)   RTSemRWCreate(PRTSEMRW pRWSem)
    947 {
    948     int rc;
    949 
    950     /*
    951      * Allocate handle.
    952      */
    953     struct RTSEMRWINTERNAL *pIntRWSem = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
    954     if (pIntRWSem)
    955     {
    956         /*
    957          * Create the rwlock.
    958          */
    959         pthread_rwlockattr_t    Attr;
    960         rc = pthread_rwlockattr_init(&Attr);
    961         if (!rc)
    962         {
    963             rc = pthread_rwlock_init(&pIntRWSem->RWLock, &Attr);
    964             if (!rc)
    965             {
    966                 pIntRWSem->uCheck = ~0;
    967                 pIntRWSem->WROwner = (pthread_t)-1;
    968                 *pRWSem = pIntRWSem;
    969                 return VINF_SUCCESS;
    970             }
    971         }
    972 
    973         rc = RTErrConvertFromErrno(rc);
    974         RTMemFree(pIntRWSem);
    975     }
    976     else
    977         rc = VERR_NO_MEMORY;
    978 
    979     return rc;
    980 }
    981 
    982 
    983 RTDECL(int)   RTSemRWDestroy(RTSEMRW RWSem)
    984 {
    985     /*
    986      * Validate input.
    987      */
    988     if (!rtsemRWValid(RWSem))
    989     {
    990         AssertMsgFailed(("Invalid handle %p!\n", RWSem));
    991         return VERR_INVALID_HANDLE;
    992     }
    993 
    994     /*
    995      * Try destroy it.
    996      */
    997     struct RTSEMRWINTERNAL *pIntRWSem = RWSem;
    998     int rc = pthread_rwlock_destroy(&pIntRWSem->RWLock);
    999     if (!rc)
    1000     {
    1001         pIntRWSem->uCheck = 0;
    1002         RTMemFree(pIntRWSem);
    1003         rc = VINF_SUCCESS;
    1004     }
    1005     else
    1006     {
    1007         AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));
    1008         rc = RTErrConvertFromErrno(rc);
    1009     }
    1010 
    1011     return rc;
    1012 }
    1013 
    1014 
    1015 RTDECL(int)   RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)
    1016 {
    1017     /*
    1018      * Validate input.
    1019      */
    1020     if (!rtsemRWValid(RWSem))
    1021     {
    1022         AssertMsgFailed(("Invalid handle %p!\n", RWSem));
    1023         return VERR_INVALID_HANDLE;
    1024     }
    1025 
    1026     /*
    1027      * Try lock it.
    1028      */
    1029     struct RTSEMRWINTERNAL *pIntRWSem = RWSem;
    1030     if (cMillies == RT_INDEFINITE_WAIT)
    1031     {
    1032         /* take rwlock */
    1033         int rc = pthread_rwlock_rdlock(&pIntRWSem->RWLock);
    1034         if (rc)
    1035         {
    1036             AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
    1037             return RTErrConvertFromErrno(rc);
    1038         }
    1039     }
    1040     else
    1041     {
    1042 #ifdef RT_OS_DARWIN
    1043         AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
    1044         return VERR_NOT_IMPLEMENTED;
    1045 #else /* !RT_OS_DARWIN */
    1046         /*
    1047          * Get current time and calc end of wait time.
    1048          */
    1049         struct timespec     ts = {0,0};
    1050         clock_gettime(CLOCK_REALTIME, &ts);
    1051         if (cMillies != 0)
    1052         {
    1053             ts.tv_nsec += (cMillies % 1000) * 1000000;
    1054             ts.tv_sec  += cMillies / 1000;
    1055             if (ts.tv_nsec >= 1000000000)
    1056             {
    1057                 ts.tv_nsec -= 1000000000;
    1058                 ts.tv_sec++;
    1059             }
    1060         }
    1061 
    1062         /* take rwlock */
    1063         int rc = pthread_rwlock_timedrdlock(&pIntRWSem->RWLock, &ts);
    1064         if (rc)
    1065         {
    1066             AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
    1067             return RTErrConvertFromErrno(rc);
    1068         }
    1069 #endif /* !RT_OS_DARWIN */
    1070     }
    1071 
    1072     return VINF_SUCCESS;
    1073 }
    1074 
    1075 
    1076 RTDECL(int)   RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)
    1077 {
    1078     /* EINTR isn't returned by the wait functions we're using. */
    1079     return RTSemRWRequestRead(RWSem, cMillies);
    1080 }
    1081 
    1082 
    1083 RTDECL(int)   RTSemRWReleaseRead(RTSEMRW RWSem)
    1084 {
    1085     /*
    1086      * Validate input.
    1087      */
    1088     if (!rtsemRWValid(RWSem))
    1089     {
    1090         AssertMsgFailed(("Invalid handle %p!\n", RWSem));
    1091         return VERR_INVALID_HANDLE;
    1092     }
    1093 
    1094     /*
    1095      * Try unlock it.
    1096      */
    1097     struct RTSEMRWINTERNAL *pIntRWSem = RWSem;
    1098     if (pIntRWSem->WROwner == pthread_self())
    1099     {
    1100         AssertMsgFailed(("Tried to read unlock when write owner - read-write sem %p.\n", RWSem));
    1101         return VERR_NOT_OWNER;
    1102     }
    1103     int rc = pthread_rwlock_unlock(&pIntRWSem->RWLock);
    1104     if (rc)
    1105     {
    1106         AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));
    1107         return RTErrConvertFromErrno(rc);
    1108     }
    1109 
    1110     return VINF_SUCCESS;
    1111 }
    1112 
    1113 
    1114 RTDECL(int)   RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)
    1115 {
    1116     /*
    1117      * Validate input.
    1118      */
    1119     if (!rtsemRWValid(RWSem))
    1120     {
    1121         AssertMsgFailed(("Invalid handle %p!\n", RWSem));
    1122         return VERR_INVALID_HANDLE;
    1123     }
    1124 
    1125     /*
    1126      * Try lock it.
    1127      */
    1128     struct RTSEMRWINTERNAL *pIntRWSem = RWSem;
    1129     if (cMillies == RT_INDEFINITE_WAIT)
    1130     {
    1131         /* take rwlock */
    1132         int rc = pthread_rwlock_wrlock(&pIntRWSem->RWLock);
    1133         if (rc)
    1134         {
    1135             AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));
    1136             return RTErrConvertFromErrno(rc);
    1137         }
    1138     }
    1139     else
    1140     {
    1141 #ifdef RT_OS_DARWIN
    1142         AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
    1143         return VERR_NOT_IMPLEMENTED;
    1144 #else /* !RT_OS_DARWIN */
    1145         /*
    1146          * Get current time and calc end of wait time.
    1147          */
    1148         struct timespec     ts = {0,0};
    1149         clock_gettime(CLOCK_REALTIME, &ts);
    1150         if (cMillies != 0)
    1151         {
    1152             ts.tv_nsec += (cMillies % 1000) * 1000000;
    1153             ts.tv_sec  += cMillies / 1000;
    1154             if (ts.tv_nsec >= 1000000000)
    1155             {
    1156                 ts.tv_nsec -= 1000000000;
    1157                 ts.tv_sec++;
    1158             }
    1159         }
    1160 
    1161         /* take rwlock */
    1162         int rc = pthread_rwlock_timedwrlock(&pIntRWSem->RWLock, &ts);
    1163         if (rc)
    1164         {
    1165             AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
    1166             return RTErrConvertFromErrno(rc);
    1167         }
    1168 #endif /* !RT_OS_DARWIN */
    1169     }
    1170 
    1171 #ifdef RT_OS_SOLARIS
    1172     ASMAtomicXchgSize(&pIntRWSem->WROwner, pthread_self());
    1173 #else
    1174     ASMAtomicXchgPtr((void * volatile *)&pIntRWSem->WROwner, (void *)pthread_self());
    1175 #endif
    1176 
    1177     return VINF_SUCCESS;
    1178 }
    1179 
    1180 
    1181 RTDECL(int)   RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)
    1182 {
    1183     /* EINTR isn't returned by the wait functions we're using. */
    1184     return RTSemRWRequestWrite(RWSem, cMillies);
    1185 }
    1186 
    1187 
    1188 RTDECL(int)   RTSemRWReleaseWrite(RTSEMRW RWSem)
    1189 {
    1190     /*
    1191      * Validate input.
    1192      */
    1193     if (!rtsemRWValid(RWSem))
    1194     {
    1195         AssertMsgFailed(("Invalid handle %p!\n", RWSem));
    1196         return VERR_INVALID_HANDLE;
    1197     }
    1198 
    1199     /*
    1200      * Try unlock it.
    1201      */
    1202     pthread_t                 Self = pthread_self();
    1203     struct RTSEMRWINTERNAL   *pIntRWSem = RWSem;
    1204     if (pIntRWSem->WROwner != Self)
    1205     {
    1206         AssertMsgFailed(("Not Write owner!\n"));
    1207         return VERR_NOT_OWNER;
    1208     }
    1209 
    1210     /*
    1211      * Try unlock it.
    1212      */
    1213 #ifdef RT_OS_SOLARIS
    1214     ASMAtomicXchgSize(&pIntRWSem->WROwner, (pthread_t)-1);
    1215 #else
    1216     AssertMsg(sizeof(pthread_t) == sizeof(void *), ("pthread_t is not the size of a pointer but %d bytes\n", sizeof(pthread_t)));
    1217     ASMAtomicXchgPtr((void * volatile *)&pIntRWSem->WROwner, (void *)(pthread_t)-1);
    1218 #endif
    1219     int rc = pthread_rwlock_unlock(&pIntRWSem->RWLock);
    1220     if (rc)
    1221     {
    1222         AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));
    1223         return RTErrConvertFromErrno(rc);
    1224     }
    1225 
    1226     return VINF_SUCCESS;
    1227 }
    1228 
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