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; }
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; }
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; }