Example #1
0
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;
}
Example #2
0
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;
}