static void TestNegative(void) { RTTestSub(g_hTest, "Negative"); bool fSavedAssertQuiet = RTAssertSetQuiet(true); bool fSavedAssertMayPanic = RTAssertSetMayPanic(false); bool fSavedLckValEnabled = RTLockValidatorSetEnabled(false); RTCRITSECTRW CritSectRw; RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwInit(&CritSectRw), VINF_SUCCESS); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VERR_NOT_OWNER); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VERR_NOT_OWNER); RTTEST_CHECK_RC(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VERR_NOT_OWNER); RTTEST_CHECK_RC(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VERR_WRONG_ORDER); /* cannot release the final write before the reads. */ RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS); RTTEST_CHECK_RC(g_hTest, RTCritSectRwDelete(&CritSectRw), VINF_SUCCESS); RTLockValidatorSetEnabled(fSavedLckValEnabled); RTAssertSetMayPanic(fSavedAssertMayPanic); RTAssertSetQuiet(fSavedAssertQuiet); }
/*virtual*/ void RWLockHandle::unlockRead() { #ifdef GLUE_USE_CRITSECTRW int vrc = RTCritSectRwLeaveShared(&m->CritSect); #else int vrc = RTSemRWReleaseRead(m->sem); #endif AssertRC(vrc); }
/** * Looks up the given user. * * @returns Pointer to the LOCKED and RETAINED per user data. * NULL if not found. * @param a_rStrUserSid The user SID. */ VBoxSDSPerUserData *VirtualBoxSDS::i_lookupPerUserData(com::Utf8Str const &a_rStrUserSid) { int vrc = RTCritSectRwEnterShared(&m_MapCritSect); if (RT_SUCCESS(vrc)) { UserDataMap_T::iterator it = m_UserDataMap.find(a_rStrUserSid); if (it != m_UserDataMap.end()) { VBoxSDSPerUserData *pUserData = it->second; pUserData->i_retain(); RTCritSectRwLeaveShared(&m_MapCritSect); pUserData->i_lock(); return pUserData; } RTCritSectRwLeaveShared(&m_MapCritSect); } return NULL; }
static DECLCALLBACK(int) Test4Thread(RTTHREAD ThreadSelf, void *pvUser) { /* Use randomization to get a little more variation of the sync pattern. We use a pseudo random generator here so that we don't end up testing the speed of the /dev/urandom implementation, but rather the read-write semaphores. */ int rc; RTRAND hRand; RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvCreateParkMiller(&hRand), rc); RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvSeed(hRand, (uintptr_t)ThreadSelf), rc); unsigned c100 = RTRandAdvU32Ex(hRand, 0, 99); uint64_t *pcItr = (uint64_t *)pvUser; bool fWrite; for (;;) { unsigned readrec = RTRandAdvU32Ex(hRand, 0, 3); unsigned writerec = RTRandAdvU32Ex(hRand, 0, 3); /* Don't overdo recursion testing. */ if (readrec > 1) readrec--; if (writerec > 1) writerec--; fWrite = (c100 < g_uWritePercent); if (fWrite) { for (unsigned i = 0; i <= writerec; i++) { rc = RTCritSectRwEnterExcl(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Write recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; if (ASMAtomicIncU32(&g_cConcurrentWriters) != 1) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after write locking it", g_cConcurrentWriters, RTThreadSelfName()); break; } if (g_cConcurrentReaders != 0) { RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s after write locking it", g_cConcurrentReaders, RTThreadSelfName()); break; } } else { rc = RTCritSectRwEnterShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read locking on %s failed with rc=%Rrc", RTThreadSelfName(), rc); break; } ASMAtomicIncU32(&g_cConcurrentReaders); if (g_cConcurrentWriters != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after read locking it", g_cConcurrentWriters, RTThreadSelfName()); break; } } for (unsigned i = 0; i < readrec; i++) { rc = RTCritSectRwEnterShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; /* * Check for fairness: The values of the threads should not differ too much */ (*pcItr)++; /* * Check for correctness: Give other threads a chance. If the implementation is * correct, no other thread will be able to enter this lock now. */ if (g_fYield) RTThreadYield(); for (unsigned i = 0; i < readrec; i++) { rc = RTCritSectRwLeaveShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; if (fWrite) { if (ASMAtomicDecU32(&g_cConcurrentWriters) != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before write release", g_cConcurrentWriters, RTThreadSelfName()); break; } if (g_cConcurrentReaders != 0) { RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s before write release", g_cConcurrentReaders, RTThreadSelfName()); break; } for (unsigned i = 0; i <= writerec; i++) { rc = RTCritSectRwLeaveExcl(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Write release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } } else { if (g_cConcurrentWriters != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before read release", g_cConcurrentWriters, RTThreadSelfName()); break; } ASMAtomicDecU32(&g_cConcurrentReaders); rc = RTCritSectRwLeaveShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read release on %s failed with rc=%Rrc", RTThreadSelfName(), rc); break; } } if (g_fTerminate) break; c100++; c100 %= 100; } if (!g_fQuiet) RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Thread %s exited with %lld\n", RTThreadSelfName(), *pcItr); RTRandAdvDestroy(hRand); return VINF_SUCCESS; }
static bool Test1(void) { RTTestSub(g_hTest, "Basics"); RTCRITSECTRW CritSectRw; RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwInit(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsInitialized(&CritSectRw), false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); for (int iRun = 0; iRun < 3; iRun++) { RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 1, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 3, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); /* midway */ RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 1, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == false, false); } RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsInitialized(&CritSectRw), false); RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwDelete(&CritSectRw), VINF_SUCCESS, false); RTTEST_CHECK_RET(g_hTest, !RTCritSectRwIsInitialized(&CritSectRw), false); return true; }