RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
                            RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    /*
     * Allocate handle.
     */
    int rc;
    struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
    if (pThis)
    {
        /*
         * Create the rwlock.
         */
        pthread_rwlockattr_t Attr;
        rc = pthread_rwlockattr_init(&Attr);
        if (!rc)
        {
            rc = pthread_rwlock_init(&pThis->RWLock, &Attr);
            if (!rc)
            {
                pThis->u32Magic     = RTSEMRW_MAGIC;
                pThis->cReaders     = 0;
                pThis->cWrites      = 0;
                pThis->cWriterReads = 0;
                pThis->Writer       = (pthread_t)-1;
#ifdef RTSEMRW_STRICT
                bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
                if (!pszNameFmt)
                {
                    static uint32_t volatile s_iSemRWAnon = 0;
                    uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1;
                    RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                               fLVEnabled, "RTSemRW-%u", i);
                    RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                 false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i);
                }
                else
                {
                    va_list va;
                    va_start(va, pszNameFmt);
                    RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                fLVEnabled, pszNameFmt, va);
                    va_end(va);
                    va_start(va, pszNameFmt);
                    RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                  false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
                    va_end(va);
                }
                RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
#endif
                *phRWSem = pThis;
                return VINF_SUCCESS;
            }
        }

        rc = RTErrConvertFromErrno(rc);
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}
Exemple #2
0
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
                            RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    /*
     * Allocate memory.
     */
    int rc;
    struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
    if (pThis)
    {
        /*
         * Create the semaphores.
         */
        rc = RTSemEventCreateEx(&pThis->WriteEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
        if (RT_SUCCESS(rc))
        {
            rc = RTSemEventMultiCreateEx(&pThis->ReadEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
            if (RT_SUCCESS(rc))
            {
                rc = RTCritSectInitEx(&pThis->CritSect, RTCRITSECT_FLAGS_NO_LOCK_VAL,
                                      NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
                if (RT_SUCCESS(rc))
                {
                    /*
                     * Signal the read semaphore and initialize other variables.
                     */
                    rc = RTSemEventMultiSignal(pThis->ReadEvent);
                    if (RT_SUCCESS(rc))
                    {
                        pThis->u32Padding           = UINT32_C(0xa5a55a5a);
                        pThis->cReads               = 0;
                        pThis->cWrites              = 0;
                        pThis->cWriterReads         = 0;
                        pThis->cWritesWaiting       = 0;
                        pThis->hWriter              = NIL_RTNATIVETHREAD;
                        pThis->fNeedResetReadEvent  = true;
                        pThis->u32Magic             = RTSEMRW_MAGIC;
#ifdef RTSEMRW_STRICT
                        bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
                        if (!pszNameFmt)
                        {
                            static uint32_t volatile s_iSemRWAnon = 0;
                            uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1;
                            RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                       fLVEnabled, "RTSemRW-%u", i);
                            RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                         false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i);
                        }
                        else
                        {
                            va_list va;
                            va_start(va, pszNameFmt);
                            RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                        fLVEnabled, pszNameFmt, va);
                            va_end(va);
                            va_start(va, pszNameFmt);
                            RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                          false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
                            va_end(va);
                        }
                        RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
#endif
                        *phRWSem = pThis;
                        return VINF_SUCCESS;
                    }
                    RTCritSectDelete(&pThis->CritSect);
                }
                RTSemEventMultiDestroy(pThis->ReadEvent);
            }
            RTSemEventDestroy(pThis->WriteEvent);
        }
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}
Exemple #3
0
RTDECL(int)  RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
                                     const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    /*
     * Allocate semaphore handle.
     */
    int rc;
    struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
    if (pThis)
    {
        /*
         * Create the condition variable.
         */
        pthread_condattr_t CondAttr;
        rc = pthread_condattr_init(&CondAttr);
        if (!rc)
        {
#if defined(CLOCK_MONOTONIC) && defined(IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK)
            /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */
            rc = pthread_condattr_setclock(&CondAttr, CLOCK_MONOTONIC);
            pThis->fMonotonicClock = rc == 0;
#else
            pThis->fMonotonicClock = false;
#endif
            rc = pthread_cond_init(&pThis->Cond, &CondAttr);
            if (!rc)
            {
                /*
                 * Create the semaphore.
                 */
                pthread_mutexattr_t MutexAttr;
                rc = pthread_mutexattr_init(&MutexAttr);
                if (!rc)
                {
                    rc = pthread_mutex_init(&pThis->Mutex, &MutexAttr);
                    if (!rc)
                    {
                        pthread_mutexattr_destroy(&MutexAttr);
                        pthread_condattr_destroy(&CondAttr);

                        ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
                        ASMAtomicXchgU32(&pThis->cWaiters, 0);
#ifdef RTSEMEVENTMULTI_STRICT
                        if (!pszNameFmt)
                        {
                            static uint32_t volatile s_iSemEventMultiAnon = 0;
                            RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
                                                         true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
                                                         "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
                        }
                        else
                        {
                            va_list va;
                            va_start(va, pszNameFmt);
                            RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
                                                          true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
                                                          pszNameFmt, va);
                            va_end(va);
                        }
                        pThis->fEverHadSignallers = false;
#endif

                        *phEventMultiSem = pThis;
                        return VINF_SUCCESS;
                    }

                    pthread_mutexattr_destroy(&MutexAttr);
                }
                pthread_cond_destroy(&pThis->Cond);
            }
            pthread_condattr_destroy(&CondAttr);
        }

        rc = RTErrConvertFromErrno(rc);
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;

}
RTDECL(int)  RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
    Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));

    /*
     * Allocate semaphore handle.
     */
    int rc;
    struct RTSEMEVENTINTERNAL *pThis;
    if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
        pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(*pThis));
    else
        pThis = (struct RTSEMEVENTINTERNAL *)rtMemBaseAlloc(sizeof(*pThis));
    if (pThis)
    {
        /*
         * Create the condition variable.
         */
        rc = pthread_cond_init(&pThis->Cond, NULL);
        if (!rc)
        {
            /*
             * Create the semaphore.
             */
            rc = pthread_mutex_init(&pThis->Mutex, NULL);
            if (!rc)
            {
                ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED);
                ASMAtomicWriteU32(&pThis->cWaiters, 0);
                pThis->fFlags = fFlags;
#ifdef RTSEMEVENT_STRICT
                if (!pszNameFmt)
                {
                    static uint32_t volatile s_iSemEventAnon = 0;
                    RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
                                                 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
                                                 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
                }
                else
                {
                    va_list va;
                    va_start(va, pszNameFmt);
                    RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
                                                  true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
                                                  pszNameFmt, va);
                    va_end(va);
                }
                pThis->fEverHadSignallers = false;
#else
                RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
#endif

                *phEventSem = pThis;
                return VINF_SUCCESS;
            }
            pthread_cond_destroy(&pThis->Cond);
        }

        rc = RTErrConvertFromErrno(rc);
        if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
            RTMemFree(pThis);
        else
            rtMemBaseFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}