Changeset 25617 in vbox
- Timestamp:
- Jan 2, 2010 12:14:47 AM (15 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
-
include/iprt/lockvalidator.h (modified) (1 diff)
-
src/VBox/Runtime/common/misc/lockvalidator.cpp (modified) (14 diffs)
-
src/VBox/Runtime/testcase/tstRTLockValidator.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/lockvalidator.h
r25614 r25617 637 637 RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread); 638 638 639 /** 640 * Query which lock the specified thread is waiting on. 641 * 642 * @returns The lock handle value or NULL. 643 * @param hThread The thread in question. 644 */ 645 RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread); 646 639 647 640 648 -
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25614 r25617 86 86 /** Pointer to a deadlock detction stack. */ 87 87 typedef RTLOCKVALDDSTACK *PRTLOCKVALDDSTACK; 88 89 90 /******************************************************************************* 91 * Defined Constants And Macros * 92 *******************************************************************************/ 93 /** Macro that asserts that a pointer is aligned correctly. 94 * Only used when fighting bugs. */ 95 #if 1 96 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \ 97 AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p))); 98 #else 99 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) do { } while (0) 100 #endif 88 101 89 102 … … 121 134 DECL_FORCE_INLINE(PRTLOCKVALRECUNION) rtLockValidatorReadRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec) 122 135 { 123 return (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec); 136 PRTLOCKVALRECUNION p = (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec); 137 RTLOCKVAL_ASSERT_PTR_ALIGN(p); 138 return p; 124 139 } 125 140 … … 128 143 DECL_FORCE_INLINE(void) rtLockValidatorWriteRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec, PRTLOCKVALRECUNION pRecNew) 129 144 { 145 RTLOCKVAL_ASSERT_PTR_ALIGN(pRecNew); 130 146 ASMAtomicWritePtr((void * volatile *)ppRec, pRecNew); 131 147 } … … 135 151 DECL_FORCE_INLINE(PRTTHREADINT) rtLockValidatorReadThreadHandle(RTTHREAD volatile *phThread) 136 152 { 137 return (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread); 153 PRTTHREADINT p = (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread); 154 RTLOCKVAL_ASSERT_PTR_ALIGN(p); 155 return p; 138 156 } 139 157 … … 142 160 DECL_FORCE_INLINE(PRTLOCKVALRECSHRDOWN) rtLockValidatorUoReadSharedOwner(PRTLOCKVALRECSHRDOWN volatile *ppOwner) 143 161 { 144 return (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner); 162 PRTLOCKVALRECSHRDOWN p = (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner); 163 RTLOCKVAL_ASSERT_PTR_ALIGN(p); 164 return p; 145 165 } 146 166 … … 456 476 457 477 /** 458 * Worker for rtLockValidatorDoDeadlockCheck that checks if there is more work459 * to be done during unwind.460 *461 * @returns true if there is more work left for this lock, false if not.462 * @param pRec The current record.463 * @param iEntry The current index.464 * @param pFirstSibling The first record we examined.465 */466 DECL_FORCE_INLINE(bool) rtLockValidatorDdMoreWorkLeft(PRTLOCKVALRECUNION pRec, uint32_t iEntry, PRTLOCKVALRECUNION pFirstSibling)467 {468 PRTLOCKVALRECUNION pSibling;469 470 switch (pRec->Core.u32Magic)471 {472 case RTLOCKVALRECEXCL_MAGIC:473 pSibling = pRec->Excl.pSibling;474 break;475 476 case RTLOCKVALRECSHRD_MAGIC:477 if (iEntry + 1 < pRec->Shared.cAllocated)478 return true;479 pSibling = pRec->Excl.pSibling;480 break;481 482 default:483 return false;484 }485 return pSibling != NULL486 && pSibling != pFirstSibling;487 }488 489 490 /**491 478 * Worker for rtLockValidatorDeadlockDetection that does the actual deadlock 492 479 * detection. … … 519 506 * Process the current record. 520 507 */ 508 RTLOCKVAL_ASSERT_PTR_ALIGN(pRec); 509 521 510 /* Find the next relevant owner thread. */ 522 511 PRTTHREADINT pNextThread; … … 526 515 Assert(iEntry == UINT32_MAX); 527 516 pNextThread = rtLockValidatorReadThreadHandle(&pRec->Excl.hThread); 528 if ( pNextThread 529 && pNextThread->u32Magic == RTTHREADINT_MAGIC 530 && !RTTHREAD_IS_SLEEPING(pNextThread->enmState) 531 && pNextThread != pThreadSelf) 532 pNextThread = NIL_RTTHREAD; 533 534 if ( pNextThread == NIL_RTTHREAD 535 && pRec->Excl.pSibling 536 && pRec->Excl.pSibling != pFirstSibling) 517 if ( !pNextThread 518 || ( pNextThread != pThreadSelf 519 && ( pNextThread->u32Magic != RTTHREADINT_MAGIC 520 || !RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread)) ) 521 ) 522 ) 537 523 { 538 524 pRec = pRec->Excl.pSibling; 539 continue; 525 if ( pRec 526 && pRec != pFirstSibling) 527 continue; 528 pNextThread = NIL_RTTHREAD; 540 529 } 541 530 break; … … 580 569 { 581 570 if ( pNextThread->u32Magic == RTTHREADINT_MAGIC 582 && ( RTTHREAD_IS_SLEEPING( pNextThread->enmState)571 && ( RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread)) 583 572 || pNextThread == pThreadSelf)) 584 573 break; … … 589 578 Assert(!pEntry || pEntry->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC_DEAD); 590 579 } 591 if (pNextThread == NIL_RTTHREAD)580 if (pNextThread != NIL_RTTHREAD) 592 581 break; 593 582 } 594 583 595 584 /* Advance to the next sibling, if any. */ 596 if ( pRec->Shared.pSibling != NULL 597 && pRec->Shared.pSibling != pFirstSibling) 585 pRec = pRec->Shared.pSibling; 586 if ( pRec != NULL 587 && pRec != pFirstSibling) 598 588 { 599 pRec = pRec->Shared.pSibling;600 589 iEntry = UINT32_MAX; 601 590 continue; 602 591 } 592 Assert(pNextThread == NIL_RTTHREAD); 603 593 break; 604 594 … … 673 663 return VINF_SUCCESS; 674 664 i--; 675 676 /* examine it. */ 677 pRec = pStack->a[i].pRec; 678 pFirstSibling = pStack->a[i].pFirstSibling; 679 iEntry = pStack->a[i].iEntry; 680 if (rtLockValidatorDdMoreWorkLeft(pRec, iEntry, pFirstSibling)) 665 pRec = pStack->a[i].pRec; 666 iEntry = pStack->a[i].iEntry; 667 668 /* Examine it. */ 669 uint32_t u32Magic = pRec->Core.u32Magic; 670 if (u32Magic == RTLOCKVALRECEXCL_MAGIC) 671 pRec = pRec->Excl.pSibling; 672 else if (u32Magic == RTLOCKVALRECSHRD_MAGIC) 681 673 { 682 enmState = pStack->a[i].enmState; 683 pThread = pStack->a[i].pThread; 684 pStack->c = i; 685 break; 674 if (iEntry + 1 < pRec->Shared.cAllocated) 675 break; /* continue processing this record. */ 676 pRec = pRec->Shared.pSibling; 686 677 } 678 else 679 { 680 Assert( u32Magic == RTLOCKVALRECEXCL_MAGIC_DEAD 681 || u32Magic == RTLOCKVALRECSHRD_MAGIC_DEAD); 682 continue; 683 } 684 685 /* Any next record to advance to? */ 686 if ( !pRec 687 || pRec == pStack->a[i].pFirstSibling) 688 continue; 689 iEntry = UINT32_MAX; 690 break; 687 691 } 692 693 /* Restore the rest of the state and update the stack. */ 694 pFirstSibling = pStack->a[i].pFirstSibling; 695 enmState = pStack->a[i].enmState; 696 pThread = pStack->a[i].pThread; 697 pStack->c = i; 688 698 } 689 699 /* else: see if there is another thread to check for this lock. */ … … 888 898 uint32_t uSubClass, const char *pszName, void *hLock) 889 899 { 900 RTLOCKVAL_ASSERT_PTR_ALIGN(pRec); 901 RTLOCKVAL_ASSERT_PTR_ALIGN(hLock); 902 890 903 pRec->Core.u32Magic = RTLOCKVALRECEXCL_MAGIC; 891 904 pRec->fEnabled = RTLockValidatorIsEnabled(); … … 1187 1200 uint32_t uSubClass, const char *pszName, void *hLock) 1188 1201 { 1202 RTLOCKVAL_ASSERT_PTR_ALIGN(pRec); 1203 RTLOCKVAL_ASSERT_PTR_ALIGN(hLock); 1204 1189 1205 pRec->Core.u32Magic = RTLOCKVALRECSHRD_MAGIC; 1190 1206 pRec->uSubClass = uSubClass; … … 1770 1786 1771 1787 1788 RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread) 1789 { 1790 void *pvLock = NULL; 1791 PRTTHREADINT pThread = rtThreadGet(hThread); 1792 if (pThread) 1793 { 1794 RTTHREADSTATE enmState = rtThreadGetState(pThread); 1795 if (RTTHREAD_IS_SLEEPING(enmState)) 1796 { 1797 rtLockValidatorSerializeDetectionEnter(); 1798 1799 enmState = rtThreadGetState(pThread); 1800 if (RTTHREAD_IS_SLEEPING(enmState)) 1801 { 1802 PRTLOCKVALRECUNION pRec = rtLockValidatorReadRecUnionPtr(&pThread->LockValidator.pRec); 1803 if (pRec) 1804 { 1805 switch (pRec->Core.u32Magic) 1806 { 1807 case RTLOCKVALRECEXCL_MAGIC: 1808 pvLock = pRec->Excl.hLock; 1809 break; 1810 1811 case RTLOCKVALRECSHRDOWN_MAGIC: 1812 pRec = (PRTLOCKVALRECUNION)pRec->ShrdOwner.pSharedRec; 1813 if (!pRec || pRec->Core.u32Magic != RTLOCKVALRECSHRD_MAGIC) 1814 break; 1815 case RTLOCKVALRECSHRD_MAGIC: 1816 pvLock = pRec->Shared.hLock; 1817 break; 1818 } 1819 if (RTThreadGetState(pThread) != enmState) 1820 pvLock = NULL; 1821 } 1822 } 1823 1824 rtLockValidatorSerializeDetectionLeave(); 1825 } 1826 rtThreadRelease(pThread); 1827 } 1828 return pvLock; 1829 } 1830 RT_EXPORT_SYMBOL(RTLockValidatorQueryBlocking); 1831 1832 1772 1833 RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled) 1773 1834 { -
trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
r25614 r25617 46 46 * Global Variables * 47 47 *******************************************************************************/ 48 /** The testcase handle. */ 48 49 static RTTEST g_hTest; 49 50 static uint32_t g_cThreads; 51 static RTTHREAD g_ahThreads[32]; 52 static RTCRITSECT g_aCritSects[32]; 50 /** Flip this in the debugger to get some peace to single step wild code. */ 51 bool volatile g_fDoNotSpin = false; 52 53 static uint32_t g_cThreads; 54 static uint32_t volatile g_iDeadlockThread; 55 static RTTHREAD g_ahThreads[32]; 56 static RTCRITSECT g_aCritSects[32]; 57 static RTSEMRW g_ahSemRWs[32]; 53 58 54 59 … … 66 71 if (!RTCritSectIsInitialized(pCritSect)) 67 72 return false; 68 RTThreadSleep( iLoop > 256 ? 1 : 0);73 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 69 74 iLoop++; 70 75 } … … 74 79 75 80 /** 81 * Spin until someone else has taken ownership (any kind) of the read-write 82 * semaphore. 83 * 84 * @returns true on success, false on abort. 85 * @param hSemRW The read-write semaphore. 86 */ 87 static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW) 88 { 89 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 90 unsigned iLoop = 0; 91 for (;;) 92 { 93 if (RTSemRWGetWriteRecursion(hSemRW) > 0) 94 return true; 95 if (RTSemRWGetReadCount(hSemRW) > 0) 96 return true; 97 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 98 iLoop++; 99 } 100 return true; 101 } 102 103 104 /** 76 105 * Waits for a thread to enter a sleeping state. 77 106 * 78 107 * @returns true on success, false on abort. 79 * @param hThread The thread. 80 */ 81 static bool testWaitForThreadToSleep(RTTHREAD hThread) 82 { 108 * @param hThread The thread. 109 * @param enmDesiredState The desired thread sleep state. 110 * @param pvLock The lock it should be sleeping on. 111 */ 112 static bool testWaitForThreadToSleep(RTTHREAD hThread, RTTHREADSTATE enmDesiredState, void *pvLock) 113 { 114 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 83 115 for (unsigned iLoop = 0; ; iLoop++) 84 116 { 85 117 RTTHREADSTATE enmState = RTThreadGetState(hThread); 86 118 if (RTTHREAD_IS_SLEEPING(enmState)) 87 return true; 88 if (enmState != RTTHREADSTATE_RUNNING) 119 { 120 if ( enmState == enmDesiredState 121 && ( !pvLock 122 || pvLock == RTLockValidatorQueryBlocking(hThread))) 123 return true; 124 } 125 else if (enmState != RTTHREADSTATE_RUNNING) 89 126 return false; 90 RTThreadSleep(iLoop > 256 ? 1 : 0); 91 } 127 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0); 128 } 129 } 130 131 132 /** 133 * Waits for all the other threads to enter sleeping states. 134 * 135 * @returns VINF_SUCCESS on success, VERR_INTERNAL_ERROR on failure. 136 * @param enmDesiredState The desired thread sleep state. 137 * @param cWaitOn The distance to the lock they'll be waiting on, 138 * the lock type is derived from the desired state. 139 * UINT32_MAX means no special lock. 140 */ 141 static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn) 142 { 143 RTTHREAD hThreadSelf = RTThreadSelf(); 144 for (uint32_t i = 0; i < g_cThreads; i++) 145 { 146 RTTHREAD hThread = g_ahThreads[i]; 147 if ( hThread != NIL_RTTHREAD 148 && hThread != hThreadSelf) 149 { 150 void *pvLock = NULL; 151 if (cWaitOn != UINT32_MAX) 152 { 153 uint32_t j = (i + cWaitOn) % g_cThreads; 154 switch (enmDesiredState) 155 { 156 case RTTHREADSTATE_CRITSECT: pvLock = &g_aCritSects[j]; break; 157 case RTTHREADSTATE_RW_WRITE: 158 case RTTHREADSTATE_RW_READ: pvLock = g_ahSemRWs[j]; break; 159 default: break; 160 } 161 } 162 bool fRet = testWaitForThreadToSleep(hThread, enmDesiredState, pvLock); 163 if (!fRet) 164 return VERR_INTERNAL_ERROR; 165 } 166 } 167 return VINF_SUCCESS; 168 } 169 170 171 /** 172 * Worker that starts the threads. 173 * 174 * @returns Same as RTThreadCreate. 175 * @param cThreads The number of threads to start. 176 * @param pfnThread Thread function. 177 */ 178 static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread) 179 { 180 uint32_t i; 181 for (i = 0; i < RT_ELEMENTS(g_ahThreads); i++) 182 g_ahThreads[i] = NIL_RTTHREAD; 183 184 for (i = 0; i < cThreads; i++) 185 RTTEST_CHECK_RC_OK_RET(g_hTest, 186 RTThreadCreateF(&g_ahThreads[i], pfnThread, (void *)(uintptr_t)i, 0, 187 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "thread-%02u", i), 188 rcCheck); 189 return VINF_SUCCESS; 190 } 191 192 193 /** 194 * Worker that waits for the threads to complete. 195 * 196 * @param cMillies How long to wait for each. 197 * @param fStopOnError Whether to stop on error and heed the thread 198 * return status. 199 */ 200 static void testWaitForThreads(uint32_t cMillies, bool fStopOnError) 201 { 202 uint32_t i = RT_ELEMENTS(g_ahThreads); 203 while (i-- > 0) 204 if (g_ahThreads[i] != NIL_RTTHREAD) 205 { 206 int rcThread; 207 int rc2; 208 RTTEST_CHECK_RC_OK(g_hTest, rc2 = RTThreadWait(g_ahThreads[i], cMillies, &rcThread)); 209 if (RT_SUCCESS(rc2)) 210 g_ahThreads[i] = NIL_RTTHREAD; 211 if (fStopOnError && (RT_FAILURE(rc2) || RT_FAILURE(rcThread))) 212 return; 213 } 92 214 } 93 215 … … 103 225 { 104 226 int rc; 105 if (i != g_ cThreads - 1)227 if (i != g_iDeadlockThread) 106 228 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS); 107 229 else 108 230 { 109 /* the last thread triggers the deadlock. */ 110 for (unsigned i = 0; i < g_cThreads - 1; i++) 111 RTTEST_CHECK_RET(g_hTest, testWaitForThreadToSleep(g_ahThreads[i]), VINF_SUCCESS); 112 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK); 231 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_CRITSECT, 1)); 232 if (RT_SUCCESS(rc)) 233 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK); 113 234 } 235 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 114 236 if (RT_SUCCESS(rc)) 115 237 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(pNext), VINF_SUCCESS); … … 120 242 121 243 122 static void test1(uint32_t cThreads) 123 { 124 uint32_t i; 125 RTTestSubF(g_hTest, "critsect deadlock with %u threads", cThreads); 244 static DECLCALLBACK(int) test2Thread(RTTHREAD ThreadSelf, void *pvUser) 245 { 246 uintptr_t i = (uintptr_t)pvUser; 247 RTSEMRW hMine = g_ahSemRWs[i]; 248 RTSEMRW hNext = g_ahSemRWs[(i + 1) % g_cThreads]; 249 int rc; 250 251 if (i & 1) 252 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestWrite(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck); 253 else 254 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck); 255 if (testWaitForSemRWToBeOwned(hNext)) 256 { 257 if (i != g_iDeadlockThread) 258 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS); 259 else 260 { 261 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_RW_WRITE, 1)); 262 if (RT_SUCCESS(rc)) 263 { 264 if (g_cThreads > 1) 265 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_DEADLOCK); 266 else 267 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_ILLEGAL_UPGRADE); 268 } 269 } 270 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 271 if (RT_SUCCESS(rc)) 272 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hNext), VINF_SUCCESS); 273 } 274 if (i & 1) 275 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hMine), VINF_SUCCESS); 276 else 277 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseRead(hMine), VINF_SUCCESS); 278 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 279 return VINF_SUCCESS; 280 } 281 282 283 static void testIt(uint32_t cThreads, uint32_t cPasses, PFNRTTHREAD pfnThread, const char *pszName) 284 { 285 RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses); 286 126 287 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads); 127 288 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads); 128 289 129 290 g_cThreads = cThreads; 130 for (i = 0; i < cThreads; i++) 291 g_iDeadlockThread = cThreads - 1; 292 293 for (uint32_t i = 0; i < cThreads; i++) 294 { 131 295 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS); 132 133 for (i = 0; i < cThreads && g_ahThreads[i]; i++) 134 g_ahThreads[i] = NIL_RTTHREAD; 135 int rc = VINF_SUCCESS; 136 for (i = 0; i < cThreads && RT_SUCCESS(rc); i++) 137 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadCreateF(&g_ahThreads[i], test1Thread, (void *)(uintptr_t)i, 0, 138 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1-%02u", i)); 139 if (RT_SUCCESS(rc)) 140 { 141 int rc2 = VINF_SUCCESS; 142 i = cThreads; 143 while (i-- > 0 && RT_SUCCESS(rc) && RT_SUCCESS(rc2)) 144 { 145 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 30*1000, &rc2)); 146 if (RT_SUCCESS(rc)) 147 g_ahThreads[i] = NIL_RTTHREAD; 148 } 296 RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS); 297 } 298 299 uint32_t cErrors = RTTestErrorCount(g_hTest); 300 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++) 301 { 302 #if 0 /** @todo figure why this ain't working for either of the two tests! */ 303 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads; 304 #endif 305 int rc = testStartThreads(cThreads, pfnThread); 306 if (RT_SUCCESS(rc)) 307 testWaitForThreads(30*1000, true); 149 308 } 150 309 151 310 for (uint32_t i = 0; i < cThreads; i++) 152 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS); 153 for (uint32_t i = 0; i < cThreads; i++) 154 if (g_ahThreads[i] != NIL_RTTHREAD) 155 { 156 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 10*1000, NULL)); 157 g_ahThreads[i] = NIL_RTTHREAD; 158 } 159 } 311 { 312 RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS); 313 RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS); 314 } 315 testWaitForThreads(10*1000, false); 316 } 317 318 319 static void test1(uint32_t cThreads, uint32_t cPasses) 320 { 321 testIt(cThreads, cPasses, test1Thread, "critsect"); 322 } 323 324 325 static void test2(uint32_t cThreads, uint32_t cPasses) 326 { 327 testIt(cThreads, cPasses, test2Thread, "read-write"); 328 } 329 160 330 161 331 static bool testIsLockValidationCompiledIn(void) … … 194 364 RTLockValidatorSetEnabled(true); 195 365 RTLockValidatorSetMayPanic(false); 366 RTLockValidatorSetQuiet(true); 196 367 if (!testIsLockValidationCompiledIn()) 197 368 return RTTestErrorCount(g_hTest) > 0 198 369 ? RTTestSummaryAndDestroy(g_hTest) 199 370 : RTTestSkipAndDestroy(g_hTest, "deadlock detection is not compiled in"); 200 201 test1(2); 202 test1(3); 203 test1(15); 204 test1(30); 371 RTLockValidatorSetQuiet(false); 372 373 /* 374 * Some initial tests with verbose output. 375 */ 376 test1(3, 1); 377 378 test2(1, 1); 379 test2(3, 1); 380 381 /* 382 * More thorough testing without noisy output. 383 */ 384 RTLockValidatorSetQuiet(true); 385 386 test1( 2, 1024); 387 test1( 3, 1024); 388 test1( 7, 896); 389 test1(10, 768); 390 test1(15, 512); 391 test1(30, 384); 392 393 test2( 1, 100); 394 test2( 2, 1024); 395 test2( 3, 1024); 396 test2( 7, 896); 397 test2(10, 768); 398 test2(15, 512); 399 test2(30, 384); 400 205 401 206 402 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.

