Changeset 25467 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Dec 17, 2009 3:16:55 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25436 r25467 181 181 RTDECL(int) RTLockValidatorCheckOrder(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL) 182 182 { 183 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_ INVALID_MAGIC);183 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 184 184 185 185 /* … … 196 196 197 197 198 RTDECL(int) RTLockValidatorCheckReleaseOrder(PRTLOCKVALIDATORREC pRec) 199 { 200 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 201 AssertReturn(pRec->hThread != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER); 202 203 return VINF_SUCCESS; 204 } 205 206 207 RTDECL(int) RTLockValidatorRecordRecursion(PRTLOCKVALIDATORREC pRec, RTHCUINTPTR uId, RT_SRC_POS_DECL) 208 { 209 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 210 AssertReturn(pRec->hThread != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER); 211 212 Assert(pRec->cRecursion < _1M); 213 pRec->cRecursion++; 214 215 return VINF_SUCCESS; 216 } 217 218 219 RTDECL(void) RTLockValidatorRecordUnwind(PRTLOCKVALIDATORREC pRec) 220 { 221 AssertReturnVoid(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC); 222 AssertReturnVoid(pRec->hThread != NIL_RTTHREAD); 223 AssertReturnVoid(pRec->cRecursion > 0); 224 225 pRec->cRecursion--; 226 } 227 228 198 229 RTDECL(RTTHREAD) RTLockValidatorSetOwner(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL) 199 230 { … … 201 232 202 233 if (hThread == NIL_RTTHREAD) 234 { 203 235 hThread = RTThreadSelfAutoAdopt(); 236 AssertReturn(hThread != NIL_RTTHREAD, hThread); 237 } 238 239 ASMAtomicIncS32(&hThread->LockValidator.cWriteLocks); 240 204 241 if (pRec->hThread == hThread) 205 242 pRec->cRecursion++; … … 232 269 { 233 270 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, NIL_RTTHREAD); 234 RTTHREAD hThread = pRec->hThread; 235 AssertReturn(hThread != NIL_RTTHREAD, hThread); 236 AssertReturn(pRec->hThread == hThread, hThread); 271 RTTHREADINT *pThread = pRec->hThread; 272 AssertReturn(pThread != NIL_RTTHREAD, pThread); 273 274 ASMAtomicDecS32(&pThread->LockValidator.cWriteLocks); 237 275 238 276 if (ASMAtomicDecU32(&pRec->cRecursion) == 0) … … 249 287 } 250 288 251 return hThread;289 return pThread; 252 290 } 253 291 … … 421 459 422 460 423 /** 424 * Change the thread state to blocking and do deadlock detection. 425 * 426 * @param pRec The validator record we're blocing on. 427 * @param hThread The current thread. Shall not be NIL_RTTHREAD! 428 * @param enmState The sleep state. 429 * @param pvBlock Pointer to a RTLOCKVALIDATORREC structure. 430 * @param fRecursiveOk Whether it's ok to recurse. 431 * @param uId Where we are blocking. 432 * @param RT_SRC_POS_DECL Where we are blocking. 433 */ 434 RTDECL(void) RTLockValidatorCheckBlocking(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, 435 RTTHREADSTATE enmState, bool fRecursiveOk, 436 RTHCUINTPTR uId, RT_SRC_POS_DECL) 461 RTDECL(int) RTLockValidatorCheckBlocking(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, 462 RTTHREADSTATE enmState, bool fRecursiveOk, 463 RTHCUINTPTR uId, RT_SRC_POS_DECL) 437 464 { 438 465 /* 439 466 * Fend off wild life. 440 467 */ 441 AssertReturn Void(RTTHREAD_IS_SLEEPING(enmState));442 AssertPtrReturn Void(pRec);443 AssertReturn Void(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC);468 AssertReturn(RTTHREAD_IS_SLEEPING(enmState), VERR_SEM_LV_INVALID_PARAMETER); 469 AssertPtrReturn(pRec, VERR_SEM_LV_INVALID_PARAMETER); 470 AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 444 471 PRTTHREADINT pThread = hThread; 445 AssertPtrReturn Void(pThread);446 AssertReturn Void(pThread->u32Magic == RTTHREADINT_MAGIC);472 AssertPtrReturn(pThread, VERR_SEM_LV_INVALID_PARAMETER); 473 AssertReturn(pThread->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 447 474 RTTHREADSTATE enmThreadState = rtThreadGetState(pThread); 448 AssertReturnVoid( enmThreadState == RTTHREADSTATE_RUNNING 449 || enmThreadState == RTTHREADSTATE_TERMINATED /* rtThreadRemove uses locks too */); 475 AssertReturn( enmThreadState == RTTHREADSTATE_RUNNING 476 || enmThreadState == RTTHREADSTATE_TERMINATED /* rtThreadRemove uses locks too */ 477 || enmThreadState == RTTHREADSTATE_INITIALIZING /* rtThreadInsert uses locks too */ 478 , VERR_SEM_LV_INVALID_PARAMETER); 450 479 451 480 /* … … 468 497 * isn't any other place to check for this. semmutex-win.cpp for instance. 469 498 */ 470 if ( !fRecursiveOk 471 || pRec->hThread != pThread) 472 { 473 /* 474 * Do deadlock detection. 475 * 476 * Since we're missing proper serialization, we don't declare it a 477 * deadlock until we've got three runs with the same list length. 478 * While this isn't perfect, it should avoid out the most obvious 479 * races on SMP boxes. 480 */ 481 rtLockValidatorSerializeDetectionEnter(); 482 483 PRTTHREADINT pCur; 484 unsigned cPrevLength = ~0U; 485 unsigned cEqualRuns = 0; 486 unsigned iParanoia = 256; 487 do 499 if (pRec->hThread == pThread) 500 { 501 if (fRecursiveOk) 502 return VINF_SUCCESS; 503 AssertMsgFailed(("%p (%s)\n", pRec->hLock, pRec->pszName)); 504 return VERR_SEM_LV_NESTED; 505 } 506 507 /* 508 * Do deadlock detection. 509 * 510 * Since we're missing proper serialization, we don't declare it a 511 * deadlock until we've got three runs with the same list length. 512 * While this isn't perfect, it should avoid out the most obvious 513 * races on SMP boxes. 514 */ 515 rtLockValidatorSerializeDetectionEnter(); 516 517 PRTTHREADINT pCur; 518 unsigned cPrevLength = ~0U; 519 unsigned cEqualRuns = 0; 520 unsigned iParanoia = 256; 521 do 522 { 523 unsigned cLength = 0; 524 pCur = pThread; 525 for (;;) 488 526 { 489 unsigned cLength = 0; 490 pCur = pThread; 527 /* 528 * Get the next thread. 529 */ 530 PRTTHREADINT pNext = NULL; 491 531 for (;;) 492 532 { 493 /* 494 * Get the next thread. 495 */ 496 PRTTHREADINT pNext = NULL; 497 for (;;) 533 RTTHREADSTATE enmCurState = rtThreadGetState(pCur); 534 switch (enmCurState) 498 535 { 499 RTTHREADSTATE enmCurState = rtThreadGetState(pCur); 500 switch (enmCurState) 536 case RTTHREADSTATE_CRITSECT: 537 case RTTHREADSTATE_EVENT: 538 case RTTHREADSTATE_EVENT_MULTI: 539 case RTTHREADSTATE_FAST_MUTEX: 540 case RTTHREADSTATE_MUTEX: 541 case RTTHREADSTATE_RW_READ: 542 case RTTHREADSTATE_RW_WRITE: 543 case RTTHREADSTATE_SPIN_MUTEX: 501 544 { 502 case RTTHREADSTATE_CRITSECT: 503 case RTTHREADSTATE_EVENT: 504 case RTTHREADSTATE_EVENT_MULTI: 505 case RTTHREADSTATE_FAST_MUTEX: 506 case RTTHREADSTATE_MUTEX: 507 case RTTHREADSTATE_RW_READ: 508 case RTTHREADSTATE_RW_WRITE: 509 case RTTHREADSTATE_SPIN_MUTEX: 510 { 511 PRTLOCKVALIDATORREC pCurRec = pCur->LockValidator.pRec; 512 if ( rtThreadGetState(pCur) != enmCurState 513 || !VALID_PTR(pCurRec) 514 || pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC) 515 continue; 516 pNext = pCurRec->hThread; 517 if ( rtThreadGetState(pCur) != enmCurState 518 || pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC 519 || pCurRec->hThread != pNext) 520 continue; 521 break; 522 } 523 524 default: 525 pNext = NULL; 526 break; 545 PRTLOCKVALIDATORREC pCurRec = pCur->LockValidator.pRec; 546 if ( rtThreadGetState(pCur) != enmCurState 547 || !VALID_PTR(pCurRec) 548 || pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC) 549 continue; 550 pNext = pCurRec->hThread; 551 if ( rtThreadGetState(pCur) != enmCurState 552 || pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC 553 || pCurRec->hThread != pNext) 554 continue; 555 break; 527 556 } 528 break; 557 558 default: 559 pNext = NULL; 560 break; 529 561 } 530 531 /* 532 * If we arrive at the end of the list we're good. 533 */ 534 pCur = pNext; 535 if (!pCur) 536 { 537 rtLockValidatorSerializeDetectionLeave(); 538 return; 539 } 540 541 /* 542 * If we've got back to the blocking thread id we've 543 * got a deadlock. 544 */ 545 if (pCur == pThread) 546 break; 547 548 /* 549 * If we've got a chain of more than 256 items, there is some 550 * kind of cycle in the list, which means that there is already 551 * a deadlock somewhere. 552 */ 553 if (cLength >= 256) 554 break; 555 556 cLength++; 562 break; 557 563 } 558 564 559 /* compare with previous list run. */ 560 if (cLength != cPrevLength) 565 /* 566 * If we arrive at the end of the list we're good. 567 */ 568 pCur = pNext; 569 if (!pCur) 561 570 { 562 cPrevLength = cLength;563 cEqualRuns = 0;571 rtLockValidatorSerializeDetectionLeave(); 572 return VINF_SUCCESS; 564 573 } 565 else 566 cEqualRuns++; 567 } while (cEqualRuns < 3 && --iParanoia > 0); 568 569 /* 570 * Ok, if we ever get here, it's most likely a genuine deadlock. 571 */ 572 rtLockValidatorComplainAboutDeadlock(pRec, pThread, enmState, pCur, uId, RT_SRC_POS_ARGS); 573 574 rtLockValidatorSerializeDetectionLeave(); 575 } 574 575 /* 576 * If we've got back to the blocking thread id we've 577 * got a deadlock. 578 */ 579 if (pCur == pThread) 580 break; 581 582 /* 583 * If we've got a chain of more than 256 items, there is some 584 * kind of cycle in the list, which means that there is already 585 * a deadlock somewhere. 586 */ 587 if (cLength >= 256) 588 break; 589 590 cLength++; 591 } 592 593 /* compare with previous list run. */ 594 if (cLength != cPrevLength) 595 { 596 cPrevLength = cLength; 597 cEqualRuns = 0; 598 } 599 else 600 cEqualRuns++; 601 } while (cEqualRuns < 3 && --iParanoia > 0); 602 603 /* 604 * Ok, if we ever get here, it's most likely a genuine deadlock. 605 */ 606 rtLockValidatorComplainAboutDeadlock(pRec, pThread, enmState, pCur, uId, RT_SRC_POS_ARGS); 607 608 rtLockValidatorSerializeDetectionLeave(); 609 610 return VERR_SEM_LV_DEADLOCK; 576 611 } 577 612 RT_EXPORT_SYMBOL(RTThreadBlocking);
Note:
See TracChangeset
for help on using the changeset viewer.