Changeset 25648 in vbox
- Timestamp:
- Jan 5, 2010 2:32:58 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56363
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25645 r25648 1233 1233 rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos); 1234 1234 ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true); 1235 pThreadSelf->LockValidator.enmRecState = enmSleepState; 1235 1236 rtThreadSetState(pThreadSelf, enmSleepState); 1236 1237 … … 1260 1261 ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping); 1261 1262 else 1263 { 1262 1264 rtThreadSetState(pThreadSelf, enmThreadState); 1265 rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL); 1266 } 1263 1267 ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false); 1264 1268 return rc; … … 1434 1438 rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos); 1435 1439 ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true); 1440 pThreadSelf->LockValidator.enmRecState = enmSleepState; 1436 1441 rtThreadSetState(pThreadSelf, enmSleepState); 1437 1442 … … 1461 1466 ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping); 1462 1467 else 1468 { 1463 1469 rtThreadSetState(pThreadSelf, enmThreadState); 1470 rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL); 1471 } 1464 1472 ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false); 1465 1473 return rc; -
trunk/src/VBox/Runtime/common/misc/thread.cpp
r25645 r25648 1334 1334 Assert(pThread == RTThreadSelf()); 1335 1335 ASMAtomicWriteBool(&pThread->fReallySleeping, false); 1336 if (rtThreadGetState(pThread) == enmCurState) 1336 1337 RTTHREADSTATE enmActualState = rtThreadGetState(pThread); 1338 if (enmActualState == enmCurState) 1339 { 1337 1340 rtThreadSetState(pThread, RTTHREADSTATE_RUNNING); 1341 if ( pThread->LockValidator.pRec 1342 && pThread->LockValidator.enmRecState == enmCurState) 1343 ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL); 1344 } 1345 /* This is a bit ugly... :-/ */ 1346 else if ( ( enmActualState == RTTHREADSTATE_TERMINATED 1347 || enmActualState == RTTHREADSTATE_INITIALIZING) 1348 && pThread->LockValidator.pRec) 1349 ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL); 1350 Assert( pThread->LockValidator.pRec == NULL 1351 || RTTHREAD_IS_SLEEPING(enmActualState)); 1338 1352 } 1339 1353 } -
trunk/src/VBox/Runtime/include/internal/lockvalidator.h
r25638 r25648 59 59 /** Where we are blocking. */ 60 60 RTLOCKVALSRCPOS SrcPos; 61 /** What we're blocking on. */ 61 /** What we're blocking on. 62 * The lock validator sets this, RTThreadUnblock clears it. */ 62 63 PRTLOCKVALRECUNION volatile pRec; 64 /** The state in which pRec that goes with pRec. 65 * RTThreadUnblocking uses this to figure out when to clear pRec. */ 66 RTTHREADSTATE volatile enmRecState; 67 /** The thread is running inside the lock validator. */ 68 bool volatile fInValidator; 69 /** Reserved for alignment purposes. */ 70 bool afReserved[3]; 63 71 /** Number of registered write locks, mutexes and critsects that this thread owns. */ 64 72 int32_t volatile cWriteLocks; 65 73 /** Number of registered read locks that this thread owns, nesting included. */ 66 74 int32_t volatile cReadLocks; 67 /** The thread is running inside the lock validator. */68 bool volatile fInValidator;69 /** Reserved for alignment purposes. */70 bool afReserved[3];71 75 /** Bitmap indicating which entires are free (set) and allocated (clear). */ 72 76 uint32_t volatile bmFreeShrdOwners; 77 /** Reserved for alignment purposes. */ 78 uint32_t u32Reserved; 73 79 /** Statically allocated shared owner records */ 74 80 RTLOCKVALRECSHRDOWN aShrdOwners[32]; -
trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
r25640 r25648 52 52 *******************************************************************************/ 53 53 #include <iprt/semaphore.h> 54 #include "internal/iprt.h" 55 54 56 #include <iprt/assert.h> 55 #include <iprt/alloc.h>56 57 #include <iprt/asm.h> 57 58 #include <iprt/err.h> 59 #include <iprt/lockvalidator.h> 60 #include <iprt/mem.h> 58 61 #include <iprt/time.h> 59 62 #include "internal/magics.h" 63 #include "internal/strict.h" 64 60 65 61 66 #include <errno.h> … … 82 87 { 83 88 /** Magic value. */ 84 intptr_t volatile iMagic;89 uint32_t volatile u32Magic; 85 90 /** The futex state variable. 86 91 * -1 means signaled. … … 89 94 */ 90 95 int32_t volatile iState; 96 #ifdef RTSEMEVENTMULTI_STRICT 97 /** Signallers. */ 98 RTLOCKVALRECSHRD Signallers; 99 /** Indicates that lock validation should be performed. */ 100 bool volatile fEverHadSignallers; 101 #endif 91 102 }; 92 103 … … 116 127 if (pThis) 117 128 { 118 pThis->iMagic = RTSEMEVENTMULTI_MAGIC; 119 pThis->iState = 0; 129 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; 130 pThis->iState = 0; 131 #ifdef RTSEMEVENTMULTI_STRICT 132 RTLockValidatorRecSharedInit(&pThis->Signallers, 133 NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY, 134 "RTSemEventMulti", pThis, true /*fSignaller*/); 135 pThis->fEverHadSignallers = false; 136 #endif 120 137 *pEventMultiSem = pThis; 121 138 return VINF_SUCCESS; … … 131 148 */ 132 149 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 133 AssertReturn(VALID_PTR(pThis) && pThis-> iMagic == RTSEMEVENTMULTI_MAGIC,150 AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, 134 151 VERR_INVALID_HANDLE); 135 152 … … 137 154 * Invalidate the semaphore and wake up anyone waiting on it. 138 155 */ 139 ASMAtomicWriteSize(&pThis-> iMagic, RTSEMEVENTMULTI_MAGIC + 1);156 ASMAtomicWriteSize(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1); 140 157 if (ASMAtomicXchgS32(&pThis->iState, -1) == 1) 141 158 { … … 147 164 * Free the semaphore memory and be gone. 148 165 */ 166 #ifdef RTSEMEVENTMULTI_STRICT 167 RTLockValidatorRecSharedDelete(&pThis->Signallers); 168 #endif 149 169 RTMemFree(pThis); 150 170 return VINF_SUCCESS; … … 158 178 */ 159 179 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 160 AssertReturn(VALID_PTR(pThis) && pThis-> iMagic == RTSEMEVENTMULTI_MAGIC,180 AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, 161 181 VERR_INVALID_HANDLE); 182 183 #ifdef RTSEMEVENTMULTI_STRICT 184 if (pThis->fEverHadSignallers) 185 { 186 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD); 187 if (RT_FAILURE(rc9)) 188 return rc9; 189 } 190 #endif 191 192 162 193 /* 163 194 * Signal it. … … 181 212 */ 182 213 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 183 AssertReturn(VALID_PTR(pThis) && pThis-> iMagic == RTSEMEVENTMULTI_MAGIC,214 AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, 184 215 VERR_INVALID_HANDLE); 185 216 #ifdef RT_STRICT … … 198 229 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume) 199 230 { 231 PCRTLOCKVALSRCPOS pSrcPos = NULL; 232 200 233 /* 201 234 * Validate input. 202 235 */ 203 236 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 204 AssertReturn(VALID_PTR(pThis) && pThis-> iMagic == RTSEMEVENTMULTI_MAGIC,237 AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, 205 238 VERR_INVALID_HANDLE); 206 239 … … 221 254 if (cMillies != RT_INDEFINITE_WAIT) 222 255 { 256 /* If the timeout is zero, then we're done. */ 223 257 if (!cMillies) 224 258 return VERR_TIMEOUT; … … 232 266 * The wait loop. 233 267 */ 268 #ifdef RTSEMEVENTMULTI_STRICT 269 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt(); 270 #else 271 RTTHREAD hThreadSelf = RTThreadSelf(); 272 #endif 234 273 for (unsigned i = 0;; i++) 235 274 { … … 252 291 ts.tv_nsec = i64Diff % 1000000000; 253 292 } 293 #ifdef RTSEMEVENTMULTI_STRICT 294 if (pThis->fEverHadSignallers) 295 { 296 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 297 RTTHREADSTATE_EVENT_MULTI, true); 298 if (RT_FAILURE(rc9)) 299 return rc9; 300 } 301 #endif 302 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 254 303 long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 1, pTimeout, NULL, 0); 255 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENTMULTI_MAGIC)) 304 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 305 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) 256 306 return VERR_SEM_DESTROYED; 257 307 if (rc == 0) … … 263 313 if (rc == -ETIMEDOUT) 264 314 { 265 /** @something is broken here. shows up every now and again in the ata code. Should try to run the timeout against RTTimeMilliTS to check that it's doing the right thing... */ 315 /** @todo something is broken here. shows up every now and again in the ata 316 * code. Should try to run the timeout against RTTimeMilliTS to 317 * check that it's doing the right thing... */ 266 318 Assert(pTimeout); 267 319 return VERR_TIMEOUT; … … 303 355 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 304 356 { 305 /** @todo implement RTSemEventMultiSetSignaller on OS/2 */ 357 #ifdef RTSEMEVENTMULTI_STRICT 358 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 359 AssertPtrReturnVoid(pThis); 360 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 361 362 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true); 363 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL); 364 #endif 306 365 } 307 366 … … 309 368 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 310 369 { 370 #ifdef RTSEMEVENTMULTI_STRICT 371 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 372 AssertPtrReturnVoid(pThis); 373 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 374 375 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true); 376 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL); 377 #endif 311 378 } 312 379 … … 314 381 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 315 382 { 383 #ifdef RTSEMEVENTMULTI_STRICT 384 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 385 AssertPtrReturnVoid(pThis); 386 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC); 387 388 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread); 389 #endif 316 390 } 317 391 -
trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
r25640 r25648 124 124 RTLockValidatorRecSharedInit(&pThis->Signallers, 125 125 NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY, 126 "RTSemEvent ", pThis, true /*fSignaller*/);126 "RTSemEventMulti", pThis, true /*fSignaller*/); 127 127 pThis->fEverHadSignallers = false; 128 128 #endif -
trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
r25640 r25648 45 45 46 46 /******************************************************************************* 47 * Defined Constants And Macros * 48 *******************************************************************************/ 49 #define SECS_SIMPLE_TEST 1 50 #define SECS_RACE_TEST 3 51 #define TEST_SMALL_TIMEOUT ( 10*1000) 52 #define TEST_LARGE_TIMEOUT ( 60*1000) 53 #define TEST_DEBUG_TIMEOUT (3600*1000) 54 55 56 /******************************************************************************* 47 57 * Global Variables * 48 58 *******************************************************************************/ … … 52 62 bool volatile g_fDoNotSpin = false; 53 63 64 /** Set when the main thread wishes to terminate the test. */ 65 bool volatile g_fShutdown = false; 66 /** The number of threads. */ 54 67 static uint32_t g_cThreads; 55 68 static uint32_t g_iDeadlockThread; … … 63 76 /** Multiple release event semaphore that is signalled by the main thread after 64 77 * it has started all the threads. */ 65 static RTSEMEVENTMULTI g_hThreadStarteEvt; 66 78 static RTSEMEVENTMULTI g_hThreadsStartedEvt; 79 80 /** The number of threads that have called testThreadBlocking */ 81 static uint32_t volatile g_cThreadsBlocking; 82 /** Multiple release event semaphore that is signalled by the last thread to 83 * call testThreadBlocking. testWaitForAllOtherThreadsToSleep waits on this. */ 84 static RTSEMEVENTMULTI g_hThreadsBlockingEvt; 67 85 68 86 /** When to stop testing. */ … … 75 93 76 94 /** 77 * Spin until someone else has taken ownership of the critical section.95 * Spin until the callback stops returning VERR_TRY_AGAIN. 78 96 * 79 * @returns true on success, false on abort. 80 * @param pCritSect The critical section. 97 * @returns Callback result. VERR_TIMEOUT if too much time elapses. 98 * @param pfnCallback Callback for checking the state. 99 * @param pvWhat Callback parameter. 81 100 */ 82 static bool testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)101 static int testWaitForSomethingToBeOwned(int (*pfnCallback)(void *), void *pvWhat) 83 102 { 84 103 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 85 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000)); 86 87 unsigned iLoop = 0; 88 while (!RTCritSectIsOwned(pCritSect)) 89 { 90 if (!RTCritSectIsInitialized(pCritSect)) 91 return false; 92 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 93 iLoop++; 94 } 95 return true; 104 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsStartedEvt, TEST_SMALL_TIMEOUT)); 105 106 uint64_t u64StartMS = RTTimeMilliTS(); 107 for (unsigned iLoop = 0; ; iLoop++) 108 { 109 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 110 111 int rc = pfnCallback(pvWhat); 112 if (rc != VERR_TRY_AGAIN/* && !g_fDoNotSpin*/) 113 { 114 RTTEST_CHECK_RC_OK(g_hTest, rc); 115 return rc; 116 } 117 118 uint64_t cMsElapsed = RTTimeMilliTS() - u64StartMS; 119 if (!g_fDoNotSpin) 120 RTTEST_CHECK_RET(g_hTest, cMsElapsed <= TEST_SMALL_TIMEOUT, VERR_TIMEOUT); 121 122 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 123 RTThreadSleep(/*g_fDoNotSpin ? TEST_DEBUG_TIMEOUT :*/ iLoop > 256 ? 1 : 0); 124 } 125 } 126 127 128 static int testCheckIfCritSectIsOwned(void *pvWhat) 129 { 130 PRTCRITSECT pCritSect = (PRTCRITSECT)pvWhat; 131 if (!RTCritSectIsInitialized(pCritSect)) 132 return VERR_SEM_DESTROYED; 133 if (RTCritSectIsOwned(pCritSect)) 134 return VINF_SUCCESS; 135 return VERR_TRY_AGAIN; 136 } 137 138 139 static int testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect) 140 { 141 return testWaitForSomethingToBeOwned(testCheckIfCritSectIsOwned, pCritSect); 142 } 143 144 145 static int testCheckIfSemRWIsOwned(void *pvWhat) 146 { 147 RTSEMRW hSemRW = (RTSEMRW)pvWhat; 148 if (RTSemRWGetWriteRecursion(hSemRW) > 0) 149 return VINF_SUCCESS; 150 if (RTSemRWGetReadCount(hSemRW) > 0) 151 return VINF_SUCCESS; 152 return VERR_TRY_AGAIN; 153 } 154 155 static int testWaitForSemRWToBeOwned(RTSEMRW hSemRW) 156 { 157 return testWaitForSomethingToBeOwned(testCheckIfSemRWIsOwned, hSemRW); 158 } 159 160 161 static int testCheckIfSemMutexIsOwned(void *pvWhat) 162 { 163 RTSEMMUTEX hSemRW = (RTSEMMUTEX)pvWhat; 164 if (RTSemMutexIsOwned(hSemRW)) 165 return VINF_SUCCESS; 166 return VERR_TRY_AGAIN; 167 } 168 169 static int testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex) 170 { 171 return testWaitForSomethingToBeOwned(testCheckIfSemMutexIsOwned, hSemMutex); 96 172 } 97 173 98 174 99 175 /** 100 * Spin until someone else has taken ownership (any kind) of the read-write 101 * semaphore. 102 * 103 * @returns true on success, false on abort. 104 * @param hSemRW The read-write semaphore. 176 * For reducing spin in testWaitForAllOtherThreadsToSleep. 105 177 */ 106 static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW) 107 { 108 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 109 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000)); 110 111 unsigned iLoop = 0; 112 for (;;) 113 { 114 if (RTSemRWGetWriteRecursion(hSemRW) > 0) 115 return true; 116 if (RTSemRWGetReadCount(hSemRW) > 0) 117 return true; 118 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 119 iLoop++; 120 } 121 return true; 122 } 123 124 125 /** 126 * Spin until someone else has taken ownership of the mutex semaphore. 127 * 128 * @returns true on success, false on abort. 129 * @param hSemMutex The mutex sempahore. 130 */ 131 static bool testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex) 132 { 133 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 134 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000)); 135 136 unsigned iLoop = 0; 137 while (!RTSemMutexIsOwned(hSemMutex)) 138 { 139 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 140 iLoop++; 141 } 142 return true; 178 static void testThreadBlocking(void) 179 { 180 if (ASMAtomicIncU32(&g_cThreadsBlocking) == g_cThreads) 181 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt)); 143 182 } 144 183 … … 155 194 static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn) 156 195 { 196 testThreadBlocking(); 157 197 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 158 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThread StarteEvt, 10*1000));198 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsBlockingEvt, TEST_SMALL_TIMEOUT)); 159 199 160 200 RTTHREAD hThreadSelf = RTThreadSelf(); … … 207 247 && enmState != RTTHREADSTATE_INITIALIZING) 208 248 return VERR_INTERNAL_ERROR; 209 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop + iLoop > 256 ? 1 : 0); 249 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 250 RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop + iLoop > 256 ? 1 : 0); 251 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 210 252 cWaitedOn++; 211 253 } 212 254 } 255 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 213 256 } 214 257 215 258 if (!cMissing && !cWaitedOn) 216 259 break; 217 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop > 256 ? 1 : 0); 260 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 261 RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop > 256 ? 1 : 0); 262 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 218 263 } 219 264 220 265 RTThreadSleep(0); /* fudge factor */ 266 RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR); 221 267 return VINF_SUCCESS; 222 268 } … … 232 278 static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread) 233 279 { 234 RTSemEventMultiReset(g_hThread StarteEvt);280 RTSemEventMultiReset(g_hThreadsStartedEvt); 235 281 236 282 for (uint32_t i = 0; i < RT_ELEMENTS(g_ahThreads); i++) … … 247 293 } 248 294 249 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThread StarteEvt), rcCheck);295 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), rcCheck); 250 296 return rc; 251 297 } … … 276 322 277 323 278 static void testIt(uint32_t cThreads, uint32_t c Passes, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)324 static void testIt(uint32_t cThreads, uint32_t cSecs, bool fLoops, PFNRTTHREAD pfnThread, const char *pszName) 279 325 { 280 326 /* 281 327 * Init test. 282 328 */ 283 if (cSecs )284 RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);329 if (cSecs > 0) 330 RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs); 285 331 else 286 RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);332 RTTestSubF(g_hTest, "%s, %u threads, single pass", pszName, cThreads); 287 333 288 334 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads); … … 290 336 291 337 g_cThreads = cThreads; 338 g_fShutdown = false; 292 339 293 340 for (uint32_t i = 0; i < cThreads; i++) … … 299 346 RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventCreate(&g_hSemEvt), VINF_SUCCESS); 300 347 RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hSemEvtMulti), VINF_SUCCESS); 301 RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadStarteEvt), VINF_SUCCESS); 348 RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsStartedEvt), VINF_SUCCESS); 349 RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsBlockingEvt), VINF_SUCCESS); 302 350 303 351 /* 304 352 * The test loop. 305 353 */ 354 uint32_t cPasses = 0; 306 355 uint32_t cLoops = 0; 307 356 uint32_t cDeadlocks = 0; 308 357 uint32_t cErrors = RTTestErrorCount(g_hTest); 309 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++) 310 { 311 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads; 312 g_cLoops = 0; 313 g_cDeadlocks = 0; 314 g_NanoTSStop = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0; 358 uint64_t uStartNS = RTTimeNanoTS(); 359 g_NanoTSStop = uStartNS + cSecs * UINT64_C(1000000000); 360 do 361 { 362 g_iDeadlockThread = (cThreads - 1 + cPasses) % cThreads; 363 g_cLoops = 0; 364 g_cDeadlocks = 0; 365 g_cThreadsBlocking = 0; 366 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hThreadsBlockingEvt), VINF_SUCCESS); 315 367 316 368 int rc = testStartThreads(cThreads, pfnThread); 317 369 if (RT_SUCCESS(rc)) 318 testWaitForThreads(30*1000 + cSecs*1000, true); 319 320 RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0); 370 { 371 testWaitForThreads(TEST_LARGE_TIMEOUT + cSecs*1000, true); 372 if (g_fDoNotSpin && RTTestErrorCount(g_hTest) != cErrors) 373 testWaitForThreads(TEST_DEBUG_TIMEOUT, true); 374 } 375 376 RTTEST_CHECK(g_hTest, !fLoops || g_cLoops > 0); 321 377 cLoops += g_cLoops; 322 RTTEST_CHECK(g_hTest, ! cSecs || g_cDeadlocks > 0);378 RTTEST_CHECK(g_hTest, !fLoops || g_cDeadlocks > 0); 323 379 cDeadlocks += g_cDeadlocks; 324 } 380 cPasses++; 381 } while ( RTTestErrorCount(g_hTest) == cErrors 382 && !fLoops 383 && RTTimeNanoTS() < g_NanoTSStop); 325 384 326 385 /* 327 386 * Cleanup. 328 387 */ 388 ASMAtomicWriteBool(&g_fShutdown, true); 389 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt), VINF_SUCCESS); 390 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), VINF_SUCCESS); 391 RTThreadSleep(RTTestErrorCount(g_hTest) == cErrors ? 0 : 50); 392 329 393 for (uint32_t i = 0; i < cThreads; i++) 330 394 { … … 335 399 RTTEST_CHECK_RC(g_hTest, RTSemEventDestroy(g_hSemEvt), VINF_SUCCESS); 336 400 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hSemEvtMulti), VINF_SUCCESS); 337 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadStarteEvt), VINF_SUCCESS); 338 339 testWaitForThreads(10*1000, false); 401 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsStartedEvt), VINF_SUCCESS); 402 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsBlockingEvt), VINF_SUCCESS); 403 404 testWaitForThreads(TEST_SMALL_TIMEOUT, false); 340 405 341 406 /* … … 343 408 */ 344 409 if (cSecs) 345 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n", 346 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0); 410 { 411 if (fLoops) 412 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n", 413 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0); 414 else 415 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cPasses=%u\n", cPasses); 416 } 347 417 } 348 418 … … 357 427 if (i & 1) 358 428 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS); 359 if ( testWaitForCritSectToBeOwned(pNext))429 if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext))) 360 430 { 361 431 int rc; 362 432 if (i != g_iDeadlockThread) 433 { 434 testThreadBlocking(); 363 435 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS); 436 } 364 437 else 365 438 { … … 379 452 380 453 381 static void test1(uint32_t cThreads, uint32_t c Passes)382 { 383 testIt(cThreads, c Passes, 0, test1Thread, "critsect");454 static void test1(uint32_t cThreads, uint32_t cSecs) 455 { 456 testIt(cThreads, cSecs, false, test1Thread, "critsect"); 384 457 } 385 458 … … 400 473 else 401 474 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck); 402 if ( testWaitForSemRWToBeOwned(hNext))475 if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext))) 403 476 { 404 477 if (i != g_iDeadlockThread) 478 { 479 testThreadBlocking(); 405 480 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS); 481 } 406 482 else 407 483 { … … 432 508 433 509 434 static void test2(uint32_t cThreads, uint32_t c Passes)435 { 436 testIt(cThreads, c Passes, 0, test2Thread, "read-write");510 static void test2(uint32_t cThreads, uint32_t cSecs) 511 { 512 testIt(cThreads, cSecs, false, test2Thread, "read-write"); 437 513 } 438 514 … … 449 525 else 450 526 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck); 451 if ( testWaitForSemRWToBeOwned(hNext))527 if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext))) 452 528 { 453 529 do 454 530 { 455 rc = RTSemRWRequestWrite(hNext, 60*1000);531 rc = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT); 456 532 if (rc != VINF_SUCCESS && rc != VERR_SEM_LV_DEADLOCK && rc != VERR_SEM_LV_ILLEGAL_UPGRADE) 457 533 { … … 479 555 480 556 481 static void test3(uint32_t cThreads, uint32_t c Passes, uint32_t cSecs)482 { 483 testIt(cThreads, c Passes, cSecs, test3Thread, "read-write race");557 static void test3(uint32_t cThreads, uint32_t cSecs) 558 { 559 testIt(cThreads, cSecs, true, test3Thread, "read-write race"); 484 560 } 485 561 … … 493 569 do 494 570 { 495 int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, 60*1000); /* ugly ;-) */571 int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, TEST_SMALL_TIMEOUT); /* ugly ;-) */ 496 572 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 497 573 if (rc1 != VINF_SUCCESS && rc1 != VERR_SEM_LV_DEADLOCK && rc1 != VERR_SEM_LV_ILLEGAL_UPGRADE) … … 504 580 for (unsigned iInner = 0; iInner < 4; iInner++) 505 581 { 506 int rc2 = RTSemRWRequestWrite(hNext, 60*1000);582 int rc2 = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT); 507 583 if (rc2 != VINF_SUCCESS && rc2 != VERR_SEM_LV_DEADLOCK && rc2 != VERR_SEM_LV_ILLEGAL_UPGRADE) 508 584 { … … 535 611 536 612 537 static void test4(uint32_t cThreads, uint32_t c Passes, uint32_t cSecs)538 { 539 testIt(cThreads, c Passes, cSecs, test4Thread, "read-write race v2");613 static void test4(uint32_t cThreads, uint32_t cSecs) 614 { 615 testIt(cThreads, cSecs, true, test4Thread, "read-write race v2"); 540 616 } 541 617 … … 550 626 if (i & 1) 551 627 RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS); 552 if ( testWaitForSemMutexToBeOwned(hNext))628 if (RT_SUCCESS(testWaitForSemMutexToBeOwned(hNext))) 553 629 { 554 630 int rc; 555 631 if (i != g_iDeadlockThread) 632 { 633 testThreadBlocking(); 556 634 RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS); 635 } 557 636 else 558 637 { … … 572 651 573 652 574 static void test5(uint32_t cThreads, uint32_t c Passes)575 { 576 testIt(cThreads, c Passes, 0, test5Thread, "mutex");653 static void test5(uint32_t cThreads, uint32_t cSecs) 654 { 655 testIt(cThreads, cSecs, false, test5Thread, "mutex"); 577 656 } 578 657 … … 587 666 if (i & 1) 588 667 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS); 589 if ( testWaitForCritSectToBeOwned(pNext))668 if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext))) 590 669 { 591 670 int rc; 592 671 if (i != g_iDeadlockThread) 593 672 { 673 testThreadBlocking(); 594 674 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS); 595 675 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); … … 606 686 RTSemEventAddSignaller(g_hSemEvt, g_ahThreads[iThread]); 607 687 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 608 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VERR_SEM_LV_DEADLOCK);688 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK); 609 689 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 610 690 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_hSemEvt), VINF_SUCCESS); 611 691 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 612 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VINF_SUCCESS);692 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VINF_SUCCESS); 613 693 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 614 694 RTSemEventSetSignaller(g_hSemEvt, NIL_RTTHREAD); … … 624 704 625 705 626 static void test6(uint32_t cThreads, uint32_t c Passes)627 { 628 testIt(cThreads, c Passes, 0, test6Thread, "event");706 static void test6(uint32_t cThreads, uint32_t cSecs) 707 { 708 testIt(cThreads, cSecs, false, test6Thread, "event"); 629 709 } 630 710 … … 639 719 if (i & 1) 640 720 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS); 641 if ( testWaitForCritSectToBeOwned(pNext))721 if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext))) 642 722 { 643 723 int rc; 644 724 if (i != g_iDeadlockThread) 645 725 { 726 testThreadBlocking(); 646 727 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS); 647 728 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); … … 659 740 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 660 741 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hSemEvtMulti), VINF_SUCCESS); 661 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VERR_SEM_LV_DEADLOCK);742 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK); 662 743 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 663 744 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hSemEvtMulti), VINF_SUCCESS); 664 745 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 665 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VINF_SUCCESS);746 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VINF_SUCCESS); 666 747 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 667 748 RTSemEventMultiSetSignaller(g_hSemEvtMulti, NIL_RTTHREAD); … … 677 758 678 759 679 static void test7(uint32_t cThreads, uint32_t cPasses) 680 { 681 testIt(cThreads, cPasses, 0, test7Thread, "event multi"); 682 } 760 static void test7(uint32_t cThreads, uint32_t cSecs) 761 { 762 testIt(cThreads, cSecs, false, test7Thread, "event multi"); 763 } 764 683 765 684 766 static bool testIsLockValidationCompiledIn(void) … … 756 838 757 839 /* 758 * Some initial tests with verbose output .840 * Some initial tests with verbose output (all single pass). 759 841 */ 760 #if 1 761 test1(3, 1); 762 test2(1, 1); 763 test2(3, 1); 764 test5(3, 1); 765 test6(3, 1); 766 #endif 767 test7(3, 1); 842 test1(3, 0); 843 test2(1, 0); 844 test2(3, 0); 845 test5(3, 0); 846 test6(3, 0); 847 test7(3, 0); 768 848 769 849 /* 770 * More thorough testing without noisy output.850 * If successful, perform more thorough testing without noisy output. 771 851 */ 772 RTLockValidatorSetQuiet(true);773 #if 1 774 test1( 2, 256); /* 256 * 4ms = 1s (approx); 4ms == fudge factor */775 test1( 3, 256); 776 test1( 7, 256);777 test1(10, 256);778 test1(15, 256);779 test1(30, 256);780 781 test2( 1, 256);782 test2( 2, 256); 783 test2( 3, 256);784 test2( 7, 256);785 test2(10, 256);786 test2(15, 256);787 test2(30, 256);788 789 test3( 2, 1, 2);790 test3(10, 1, 2); 791 792 test4( 2, 1, 2);793 test4( 6, 1, 2); 794 test4(10, 1, 10);795 test4(30, 1, 10);796 797 test5( 2, 256);798 test5( 3, 256); 799 test5( 7, 256);800 test5(10, 256);801 test5(15, 256);802 test5(30, 256);803 804 test6( 2, 256);805 test6( 3, 256); 806 test6( 7, 256);807 test6(10, 256);808 test6(15, 256);809 test6(30, 256);810 #endif 811 812 #if 1 813 test7( 2, 256);814 test7( 3, 256);815 test7( 7, 256);816 test7(10, 256);817 test7(15, 256);818 test7(30, 256);819 #endif 852 if (RTTestErrorCount(g_hTest) == 0) 853 { 854 RTLockValidatorSetQuiet(true); 855 856 test1( 2, SECS_SIMPLE_TEST); 857 test1( 3, SECS_SIMPLE_TEST); 858 test1( 7, SECS_SIMPLE_TEST); 859 test1(10, SECS_SIMPLE_TEST); 860 test1(15, SECS_SIMPLE_TEST); 861 test1(30, SECS_SIMPLE_TEST); 862 863 test2( 1, SECS_SIMPLE_TEST); 864 test2( 2, SECS_SIMPLE_TEST); 865 test2( 3, SECS_SIMPLE_TEST); 866 test2( 7, SECS_SIMPLE_TEST); 867 test2(10, SECS_SIMPLE_TEST); 868 test2(15, SECS_SIMPLE_TEST); 869 test2(30, SECS_SIMPLE_TEST); 870 871 test3( 2, SECS_SIMPLE_TEST); 872 test3(10, SECS_SIMPLE_TEST); 873 874 test4( 2, SECS_RACE_TEST); 875 test4( 6, SECS_RACE_TEST); 876 test4(10, SECS_RACE_TEST); 877 test4(30, SECS_RACE_TEST); 878 879 test5( 2, SECS_RACE_TEST); 880 test5( 3, SECS_RACE_TEST); 881 test5( 7, SECS_RACE_TEST); 882 test5(10, SECS_RACE_TEST); 883 test5(15, SECS_RACE_TEST); 884 test5(30, SECS_RACE_TEST); 885 886 test6( 2, SECS_SIMPLE_TEST); 887 test6( 3, SECS_SIMPLE_TEST); 888 test6( 7, SECS_SIMPLE_TEST); 889 test6(10, SECS_SIMPLE_TEST); 890 test6(15, SECS_SIMPLE_TEST); 891 test6(30, SECS_SIMPLE_TEST); 892 893 test7( 2, SECS_SIMPLE_TEST); 894 test7( 3, SECS_SIMPLE_TEST); 895 test7( 7, SECS_SIMPLE_TEST); 896 test7(10, SECS_SIMPLE_TEST); 897 test7(15, SECS_SIMPLE_TEST); 898 test7(30, SECS_SIMPLE_TEST); 899 } 820 900 821 901 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.