Changeset 25626 in vbox
- Timestamp:
- Jan 3, 2010 3:24:13 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
r25623 r25626 57 57 static RTCRITSECT g_aCritSects[32]; 58 58 static RTSEMRW g_ahSemRWs[32]; 59 static RTSEMMUTEX g_ahSemMtxes[32]; 59 60 60 61 /** When to stop testing. */ … … 103 104 if (RTSemRWGetReadCount(hSemRW) > 0) 104 105 return true; 106 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 107 iLoop++; 108 } 109 return true; 110 } 111 112 113 /** 114 * Spin until someone else has taken ownership of the mutex semaphore. 115 * 116 * @returns true on success, false on abort. 117 * @param hSemMutex The mutex sempahore. 118 */ 119 static bool testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex) 120 { 121 unsigned iLoop = 0; 122 while (!RTSemMutexIsOwned(hSemMutex)) 123 { 105 124 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 106 125 iLoop++; … … 169 188 case RTTHREADSTATE_RW_WRITE: 170 189 case RTTHREADSTATE_RW_READ: pvLock = g_ahSemRWs[j]; break; 190 case RTTHREADSTATE_MUTEX: pvLock = g_ahSemMtxes[j]; break; 171 191 default: break; 172 192 } … … 228 248 229 249 250 static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName) 251 { 252 if (cSecs) 253 RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses); 254 else 255 RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses); 256 257 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads); 258 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads); 259 260 g_cThreads = cThreads; 261 262 for (uint32_t i = 0; i < cThreads; i++) 263 { 264 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS); 265 RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS); 266 RTTEST_CHECK_RC_RETV(g_hTest, RTSemMutexCreate(&g_ahSemMtxes[i]), VINF_SUCCESS); 267 } 268 269 uint32_t cLoops = 0; 270 uint32_t cDeadlocks = 0; 271 uint32_t cErrors = RTTestErrorCount(g_hTest); 272 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++) 273 { 274 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads; 275 g_cLoops = 0; 276 g_cDeadlocks = 0; 277 g_NanoTSStop = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0; 278 279 int rc = testStartThreads(cThreads, pfnThread); 280 if (RT_SUCCESS(rc)) 281 testWaitForThreads(30*1000 + cSecs*1000, true); 282 283 RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0); 284 cLoops += g_cLoops; 285 RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0); 286 cDeadlocks += g_cDeadlocks; 287 } 288 289 for (uint32_t i = 0; i < cThreads; i++) 290 { 291 RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS); 292 RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS); 293 RTTEST_CHECK_RC(g_hTest, RTSemMutexDestroy(g_ahSemMtxes[i]), VINF_SUCCESS); 294 } 295 testWaitForThreads(10*1000, false); 296 297 if (cSecs) 298 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n", 299 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0); 300 } 301 302 230 303 static DECLCALLBACK(int) test1Thread(RTTHREAD ThreadSelf, void *pvUser) 231 304 { … … 256 329 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS); 257 330 return VINF_SUCCESS; 331 } 332 333 334 static void test1(uint32_t cThreads, uint32_t cPasses) 335 { 336 testIt(cThreads, cPasses, 0, test1Thread, "critsect"); 258 337 } 259 338 … … 303 382 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 304 383 return VINF_SUCCESS; 384 } 385 386 387 static void test2(uint32_t cThreads, uint32_t cPasses) 388 { 389 testIt(cThreads, cPasses, 0, test2Thread, "read-write"); 305 390 } 306 391 … … 344 429 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 345 430 return VINF_SUCCESS; 431 } 432 433 434 static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs) 435 { 436 testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race"); 346 437 } 347 438 … … 397 488 398 489 399 static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName) 400 { 401 if (cSecs) 402 RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses); 403 else 404 RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses); 405 406 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads); 407 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads); 408 409 g_cThreads = cThreads; 410 411 for (uint32_t i = 0; i < cThreads; i++) 412 { 413 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS); 414 RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS); 415 } 416 417 uint32_t cLoops = 0; 418 uint32_t cDeadlocks = 0; 419 uint32_t cErrors = RTTestErrorCount(g_hTest); 420 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++) 421 { 422 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads; 423 g_cLoops = 0; 424 g_cDeadlocks = 0; 425 g_NanoTSStop = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0; 426 427 int rc = testStartThreads(cThreads, pfnThread); 490 static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs) 491 { 492 testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2"); 493 } 494 495 496 static DECLCALLBACK(int) test5Thread(RTTHREAD ThreadSelf, void *pvUser) 497 { 498 uintptr_t i = (uintptr_t)pvUser; 499 RTSEMMUTEX hMine = g_ahSemMtxes[i]; 500 RTSEMMUTEX hNext = g_ahSemMtxes[(i + 1) % g_cThreads]; 501 502 RTTEST_CHECK_RC_RET(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck); 503 if (i & 1) 504 RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS); 505 if (testWaitForSemMutexToBeOwned(hNext)) 506 { 507 int rc; 508 if (i != g_iDeadlockThread) 509 RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS); 510 else 511 { 512 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_MUTEX, 1)); 513 if (RT_SUCCESS(rc)) 514 RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_DEADLOCK); 515 } 516 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 428 517 if (RT_SUCCESS(rc)) 429 testWaitForThreads(30*1000 + cSecs*1000, true); 430 431 RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0); 432 cLoops += g_cLoops; 433 RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0); 434 cDeadlocks += g_cDeadlocks; 435 } 436 437 for (uint32_t i = 0; i < cThreads; i++) 438 { 439 RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS); 440 RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS); 441 } 442 testWaitForThreads(10*1000, false); 443 444 if (cSecs) 445 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n", 446 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0); 447 } 448 449 450 static void test1(uint32_t cThreads, uint32_t cPasses) 451 { 452 testIt(cThreads, cPasses, 0, test1Thread, "critsect"); 453 } 454 455 456 static void test2(uint32_t cThreads, uint32_t cPasses) 457 { 458 testIt(cThreads, cPasses, 0, test2Thread, "read-write"); 459 } 460 461 462 static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs) 463 { 464 testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race"); 465 } 466 467 468 static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs) 469 { 470 testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2"); 518 RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRelease(hNext), VINF_SUCCESS); 519 } 520 if (i & 1) 521 RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(hMine), VINF_SUCCESS); 522 RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(hMine), VINF_SUCCESS); 523 return VINF_SUCCESS; 524 } 525 526 527 static void test5(uint32_t cThreads, uint32_t cPasses) 528 { 529 testIt(cThreads, cPasses, 0, test5Thread, "mutex"); 471 530 } 472 531 … … 518 577 * Some initial tests with verbose output. 519 578 */ 579 #if 0 520 580 test1(3, 1); 521 581 test2(1, 1); 522 582 test2(3, 1); 583 #endif 584 test5(3, 1); 523 585 524 586 /* … … 526 588 */ 527 589 RTLockValidatorSetQuiet(true); 528 590 #if 0 529 591 test1( 2, 256); /* 256 * 4ms = 1s (approx); 4ms == fudge factor */ 530 592 test1( 3, 256); … … 549 611 test4(10, 1, 10); 550 612 test4(30, 1, 10); 613 #endif 614 615 test5( 2, 256); 616 test5( 3, 256); 617 test5( 7, 256); 618 test5(10, 256); 619 test5(15, 256); 620 test5(30, 256); 551 621 552 622 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.

