RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem) { /* * Validate input. */ struct RTSEMRWINTERNAL *pThis = hRWSem; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); /* * Check if it's the writer. */ pthread_t Self = pthread_self(); pthread_t Writer; ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer); if (Writer == Self) { AssertMsgReturn(pThis->cWriterReads > 0, ("pThis=%p\n", pThis), VERR_NOT_OWNER); #ifdef RTSEMRW_STRICT int rc9 = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core); if (RT_FAILURE(rc9)) return rc9; #endif pThis->cWriterReads--; return VINF_SUCCESS; } /* * Try unlock it. */ #ifdef RTSEMRW_STRICT int rc9 = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, RTThreadSelf()); if (RT_FAILURE(rc9)) return rc9; #endif #ifdef RT_OS_LINUX /* glibc (at least 2.8) may screw up when unlocking a lock we don't own. */ if (ASMAtomicReadU32(&pThis->cReaders) == 0) { AssertMsgFailed(("Not owner of %p\n", pThis)); return VERR_NOT_OWNER; } #endif ASMAtomicDecU32(&pThis->cReaders); int rc = pthread_rwlock_unlock(&pThis->RWLock); if (rc) { ASMAtomicIncU32(&pThis->cReaders); AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", hRWSem, rc)); return RTErrConvertFromErrno(rc); } return VINF_SUCCESS; }
RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem) { struct RTSEMRWINTERNAL *pThis = hRWSem; /* * Validate handle. */ AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTSEMRW_MAGIC, VERR_INVALID_HANDLE); /* * Take critsect. */ int rc = RTCritSectEnter(&pThis->CritSect); if (RT_SUCCESS(rc)) { if (pThis->hWriter == NIL_RTNATIVETHREAD) { #ifdef RTSEMRW_STRICT rc = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, NIL_RTTHREAD); if (RT_SUCCESS(rc)) #endif { if (RT_LIKELY(pThis->cReads > 0)) { pThis->cReads--; /* Kick off a writer if appropriate. */ if ( pThis->cWritesWaiting > 0 && !pThis->cReads) { rc = RTSemEventSignal(pThis->WriteEvent); AssertMsgRC(rc, ("Failed to signal writers on rwsem %p, rc=%Rrc\n", hRWSem, rc)); } } else { AssertFailed(); rc = VERR_NOT_OWNER; } } } else { RTNATIVETHREAD hNativeSelf = pThis->CritSect.NativeThreadOwner; if (pThis->hWriter == hNativeSelf) { if (pThis->cWriterReads > 0) { #ifdef RTSEMRW_STRICT rc = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core); if (RT_SUCCESS(rc)) #endif { pThis->cWriterReads--; } } else { AssertFailed(); rc = VERR_NOT_OWNER; } } else { AssertFailed(); rc = VERR_NOT_OWNER; } } RTCritSectLeave(&pThis->CritSect); } else AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", hRWSem, rc)); return rc; }