Changeset 25700 in vbox for trunk/src/VBox
- Timestamp:
- Jan 9, 2010 9:34:21 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25694 r25700 47 47 #include "internal/magics.h" 48 48 #include "internal/thread.h" 49 50 /******************************************************************************* 51 * Defined Constants And Macros * 52 *******************************************************************************/ 53 /** Macro that asserts that a pointer is aligned correctly. 54 * Only used when fighting bugs. */ 55 #if 1 56 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \ 57 AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p))); 58 #else 59 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) do { } while (0) 60 #endif 61 62 /** Hashes the class handle (pointer) into an apPriorLocksHash index. */ 63 #define RTLOCKVALCLASS_HASH(hClass) \ 64 ( (uintptr_t)(hClass) \ 65 % ( RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \ 66 / sizeof(PRTLOCKVALCLASSREF)) ) 67 68 /** The max value for RTLOCKVALCLASSINT::cRefs. */ 69 #define RTLOCKVALCLASS_MAX_REFS UINT32_C(0xffff0000) 70 /** The max value for RTLOCKVALCLASSREF::cLookups. */ 71 #define RTLOCKVALCLASSREF_MAX_LOOKUPS UINT32_C(0xfffe0000) 72 /** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will 73 * be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */ 74 #define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX UINT32_C(0xffff0000) 75 76 77 /** @def RTLOCKVAL_WITH_RECURSION_RECORDS 78 * Enable recursion records. */ 79 #if defined(IN_RING3) || defined(DOXYGEN_RUNNING) 80 # define RTLOCKVAL_WITH_RECURSION_RECORDS 1 81 #endif 82 83 /** @def RTLOCKVAL_WITH_VERBOSE_DUMPS 84 * Enables some extra verbosity in the lock dumping. */ 85 #if defined(DOXYGEN_RUNNING) 86 # define RTLOCKVAL_WITH_VERBOSE_DUMPS 87 #endif 88 89 /** @def RTLOCKVAL_WITH_CLASS_HASH_STATS 90 * Enables collection prior class hash lookup statistics, dumping them when 91 * complaining about the class. */ 92 #if defined(DEBUG/*_bird*/) || defined(DOXYGEN_RUNNING) 93 # define RTLOCKVAL_WITH_CLASS_HASH_STATS 94 #endif 49 95 50 96 … … 157 203 /** Hash table containing frequently encountered prior locks. */ 158 204 PRTLOCKVALCLASSREF apPriorLocksHash[11]; 159 #define RTLOCKVALCLASS_HASH_STATS 160 #ifdef RTLOCKVALCLASS_HASH_STATS 205 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 161 206 /** Hash hits. */ 162 207 uint32_t volatile cHashHits; … … 170 215 * spawned it. */ 171 216 RTLOCKVALSRCPOS CreatePos; 217 /** Class name. (Allocated after the end of the block as usual.) */ 218 char const *pszName; 172 219 } RTLOCKVALCLASSINT; 173 220 AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32); 174 221 AssertCompileMemberOffset(RTLOCKVALCLASSINT, PriorLocks, 64); 175 176 177 /*******************************************************************************178 * Defined Constants And Macros *179 *******************************************************************************/180 /** Macro that asserts that a pointer is aligned correctly.181 * Only used when fighting bugs. */182 #if 1183 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \184 AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));185 #else186 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) do { } while (0)187 #endif188 189 /** Hashes the class handle (pointer) into an apPriorLocksHash index. */190 #define RTLOCKVALCLASS_HASH(hClass) \191 ( (uintptr_t)(hClass) \192 % ( RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \193 / sizeof(PRTLOCKVALCLASSREF)) )194 195 /** The max value for RTLOCKVALCLASSINT::cRefs. */196 #define RTLOCKVALCLASS_MAX_REFS UINT32_C(0xffff0000)197 /** The max value for RTLOCKVALCLASSREF::cLookups. */198 #define RTLOCKVALCLASSREF_MAX_LOOKUPS UINT32_C(0xfffe0000)199 /** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will200 * be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */201 #define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX UINT32_C(0xffff0000)202 203 204 /** @def RTLOCKVAL_WITH_RECURSION_RECORDS205 * Enable recursion records. */206 #if defined(IN_RING3) || defined(DOXYGEN_RUNNING)207 # define RTLOCKVAL_WITH_RECURSION_RECORDS 1208 #endif209 210 /** @def RTLOCKVAL_WITH_VERBOSE_DUMPS211 * Enables some extra verbosity in the lock dumping. */212 #if defined(DOXYGEN_RUNNING)213 # define RTLOCKVAL_WITH_VERBOSE_DUMPS214 #endif215 222 216 223 … … 382 389 static void rtLockValComplainAboutClass(const char *pszPrefix, RTLOCKVALCLASSINT *pClass, uint32_t uSubClass, bool fVerbose) 383 390 { 384 if ( VALID_PTR(pClass) 385 && pClass->u32Magic == RTLOCKVALCLASS_MAGIC) 386 { 387 391 if (ASMAtomicUoReadBool(&g_fLockValidatorQuiet)) 392 return; 393 394 /* Stringify the sub-class. */ 395 const char *pszSubClass; 396 char szSubClass[32]; 397 if (uSubClass < RTLOCKVAL_SUB_CLASS_USER) 398 switch (uSubClass) 399 { 400 case RTLOCKVAL_SUB_CLASS_NONE: pszSubClass = "none"; break; 401 case RTLOCKVAL_SUB_CLASS_ANY: pszSubClass = "any"; break; 402 default: 403 RTStrPrintf(szSubClass, sizeof(szSubClass), "invl-%u", uSubClass); 404 pszSubClass = szSubClass; 405 break; 406 } 407 else 408 { 409 RTStrPrintf(szSubClass, sizeof(szSubClass), "%u", uSubClass); 410 pszSubClass = szSubClass; 411 } 412 413 /* Validate the class pointer. */ 414 if (!VALID_PTR(pClass)) 415 { 416 RTAssertMsg2AddWeak("%sbad class=%p sub-class=%s\n", pszPrefix, pClass, pszSubClass); 417 return; 418 } 419 if (pClass->u32Magic != RTLOCKVALCLASS_MAGIC) 420 { 421 RTAssertMsg2AddWeak("%sbad class=%p magic=%#x sub-class=%s\n", pszPrefix, pClass, pClass->u32Magic, pszSubClass); 422 return; 423 } 424 425 /* OK, dump the class info. */ 426 RTAssertMsg2AddWeak("%sclass=%p %s created={%Rbn(%u) %Rfn %p} sub-class=%s\n", pszPrefix, 427 pClass, 428 pClass->pszName, 429 pClass->CreatePos.pszFile, 430 pClass->CreatePos.uLine, 431 pClass->CreatePos.pszFunction, 432 pClass->CreatePos.uId, 433 pszSubClass); 434 if (fVerbose) 435 { 436 uint32_t i = 0; 437 uint32_t cPrinted = 0; 438 for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext) 439 for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++, i++) 440 { 441 RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass; 442 if (pCurClass != NIL_RTLOCKVALCLASS) 443 { 444 RTAssertMsg2AddWeak("%s%s #%02u: %s, %s, %u lookup%s\n", pszPrefix, 445 cPrinted == 0 446 ? "Prior:" 447 : " ", 448 i, 449 pCurClass->pszName, 450 pChunk->aRefs[j].fAutodidacticism 451 ? "autodidactic" 452 : "manually ", 453 pChunk->aRefs[j].cLookups, 454 pChunk->aRefs[j].cLookups != 1 ? "s" : ""); 455 cPrinted++; 456 } 457 } 458 if (!cPrinted) 459 RTAssertMsg2AddWeak("%sPrior: none\n", pszPrefix); 460 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 461 RTAssertMsg2AddWeak("%sHash Stats: %u hits, %u misses\n", pszPrefix, pClass->cHashHits, pClass->cHashMisses); 462 #endif 463 } 464 else 465 { 466 uint32_t cPrinted = 0; 467 for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext) 468 for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++) 469 { 470 RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass; 471 if (pCurClass != NIL_RTLOCKVALCLASS) 472 { 473 if ((cPrinted % 10) == 0) 474 RTAssertMsg2AddWeak("%sPrior classes: %s%s", pszPrefix, pCurClass->pszName, 475 pChunk->aRefs[j].fAutodidacticism ? "*" : ""); 476 else if ((cPrinted % 10) != 9) 477 RTAssertMsg2AddWeak(", %s%s", pCurClass->pszName, 478 pChunk->aRefs[j].fAutodidacticism ? "*" : ""); 479 else 480 RTAssertMsg2AddWeak(", %s%s\n", pCurClass->pszName, 481 pChunk->aRefs[j].fAutodidacticism ? "*" : ""); 482 cPrinted++; 483 } 484 } 485 if (!cPrinted) 486 RTAssertMsg2AddWeak("%sPrior classes: none\n", pszPrefix); 487 else if ((cPrinted % 10) != 0) 488 RTAssertMsg2AddWeak("\n"); 388 489 } 389 490 } … … 562 663 * @param pThreadSelf The calling thread. 563 664 * @param pRec The main lock involved. Can be NULL. 564 */ 565 static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 665 * @param fDumpStack Whether to dump the lock stack (true) or not 666 * (false). 667 */ 668 static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, 669 PRTLOCKVALRECUNION pRec, bool fDumpStack) 566 670 { 567 671 if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet)) … … 574 678 RTAssertMsg2Weak("%s [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>"); 575 679 rtLockValComplainAboutLock("Lock: ", pRec, "\n"); 576 rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec); 680 if (fDumpStack) 681 rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec); 577 682 } 578 683 } … … 807 912 rtLockValComplainFirst("Thread terminating owning locks!", NULL, 808 913 RT_FROM_MEMBER(pPerThread, RTTHREADINT, LockValidator), 809 pPerThread->pStackTop );914 pPerThread->pStackTop, true); 810 915 rtLockValComplainPanic(); 811 916 } … … 824 929 } 825 930 826 827 931 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, 828 932 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, 829 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder) 933 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder, 934 const char *pszNameFmt, ...) 935 { 936 va_list va; 937 va_start(va, pszNameFmt); 938 int rc = RTLockValidatorClassCreateExV(phClass, pSrcPos, fAutodidact, fRecursionOk, fStrictReleaseOrder, 939 cMsMinDeadlock, cMsMinOrder, pszNameFmt, va); 940 va_end(va); 941 return rc; 942 } 943 944 945 RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, 946 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, 947 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder, 948 const char *pszNameFmt, va_list va) 830 949 { 831 950 Assert(cMsMinDeadlock >= 1); … … 833 952 AssertPtr(pSrcPos); 834 953 954 /* 955 * Format the name and calc its length. 956 */ 957 size_t cbName; 958 char szName[32]; 959 if (pszNameFmt && *pszNameFmt) 960 cbName = RTStrPrintfV(szName, sizeof(szName), pszNameFmt, va) + 1; 961 else 962 { 963 static uint32_t volatile s_cAnonymous = 0; 964 uint32_t i = ASMAtomicIncU32(&s_cAnonymous); 965 cbName = RTStrPrintf(szName, sizeof(szName), "anon-%u", i - 1) + 1; 966 } 967 968 /* 969 * Figure out the file and function name lengths and allocate memory for 970 * it all. 971 */ 835 972 size_t const cbFile = pSrcPos->pszFile ? strlen(pSrcPos->pszFile) + 1 : 0; 836 973 size_t const cbFunction = pSrcPos->pszFile ? strlen(pSrcPos->pszFunction) + 1 : 0; 837 RTLOCKVALCLASSINT *pThis = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction );974 RTLOCKVALCLASSINT *pThis = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction + cbName); 838 975 if (!pThis) 839 976 return VERR_NO_MEMORY; 840 977 978 /* 979 * Initialize the class data. 980 */ 841 981 pThis->Core.Key = rtLockValidatorSrcPosHash(pSrcPos); 842 982 pThis->Core.uchHeight = 0; … … 871 1011 pszDst += cbFile; 872 1012 pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL; 1013 pszDst += cbFunction; 873 1014 Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key); 1015 pThis->pszName = (char *)memcpy(pszDst, szName, cbName); 874 1016 875 1017 *phClass = pThis; … … 883 1025 return RTLockValidatorClassCreateEx(phClass, &SrcPos, 884 1026 fAutodidact, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/, 885 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/); 1027 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/, 1028 NULL /*pszName*/); 886 1029 } 887 1030 … … 1003 1146 int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos, 1004 1147 true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/, 1005 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/); 1148 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/, 1149 NULL /*pszName*/); 1006 1150 if (RT_SUCCESS(rc)) 1007 1151 { … … 1069 1213 ASMAtomicWritePtr((void * volatile *)ppHashEntry, &pChunk->aRefs[i]); 1070 1214 1071 #ifdef RTLOCKVAL CLASS_HASH_STATS1215 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 1072 1216 ASMAtomicIncU32(&pClass->cHashMisses); 1073 1217 #endif … … 1099 1243 if (RT_UNLIKELY(cLookups >= RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX)) 1100 1244 ASMAtomicWriteU32(&pRef->cLookups, RTLOCKVALCLASSREF_MAX_LOOKUPS); 1101 #ifdef RTLOCKVAL CLASS_HASH_STATS1245 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 1102 1246 ASMAtomicIncU32(&pClass->cHashHits); 1103 1247 #endif … … 1581 1725 { 1582 1726 case RTLOCKVALRECEXCL_MAGIC: 1583 Assert(p Rec->Excl.cRecursion >= 1);1727 Assert(pCur->Excl.cRecursion >= 1); 1584 1728 pCur = pCur->Excl.pDown; 1585 1729 break; … … 1667 1811 else 1668 1812 { 1669 /* Find the record above ours. */ 1670 PRTLOCKVALRECUNION pAbove = pThreadSelf->LockValidator.pStackTop; 1671 while (pAbove) 1672 { 1673 switch (pAbove->Core.u32Magic) 1813 /* Find the pointer to our record and unlink ourselves. */ 1814 PRTLOCKVALRECUNION pCur = pThreadSelf->LockValidator.pStackTop; 1815 while (pCur) 1816 { 1817 PRTLOCKVALRECUNION volatile *ppDown; 1818 switch (pCur->Core.u32Magic) 1674 1819 { 1675 1820 case RTLOCKVALRECEXCL_MAGIC: 1676 Assert(pRec->Excl.cRecursion >= 1); 1677 if (pAbove->Excl.pDown == pRec) 1678 { 1679 rtLockValidatorWriteRecUnionPtr(&pAbove->Excl.pDown, pDown); 1680 return; 1681 } 1682 pAbove = pAbove->Excl.pDown; 1821 Assert(pCur->Excl.cRecursion >= 1); 1822 ppDown = &pCur->Excl.pDown; 1683 1823 break; 1684 1824 1685 1825 case RTLOCKVALRECSHRDOWN_MAGIC: 1686 Assert(pAbove->ShrdOwner.cRecursion >= 1); 1687 if (pAbove->ShrdOwner.pDown == pRec) 1688 { 1689 rtLockValidatorWriteRecUnionPtr(&pAbove->ShrdOwner.pDown, pDown); 1690 return; 1691 } 1692 pAbove = pAbove->ShrdOwner.pDown; 1826 Assert(pCur->ShrdOwner.cRecursion >= 1); 1827 ppDown = &pCur->ShrdOwner.pDown; 1693 1828 break; 1694 1829 1695 1830 case RTLOCKVALRECNEST_MAGIC: 1696 Assert(pAbove->Nest.cRecursion >= 1); 1697 if (pAbove->Nest.pDown == pRec) 1698 { 1699 rtLockValidatorWriteRecUnionPtr(&pAbove->Nest.pDown, pDown); 1700 return; 1701 } 1702 pAbove = pAbove->Nest.pDown; 1831 Assert(pCur->Nest.cRecursion >= 1); 1832 ppDown = &pCur->Nest.pDown; 1703 1833 break; 1704 1834 1705 1835 default: 1706 AssertMsgFailedReturnVoid(("%#x\n", pAbove->Core.u32Magic)); 1836 AssertMsgFailedReturnVoid(("%#x\n", pCur->Core.u32Magic)); 1837 } 1838 pCur = *ppDown; 1839 if (pCur == pRec) 1840 { 1841 rtLockValidatorWriteRecUnionPtr(ppDown, pDown); 1842 return; 1707 1843 } 1708 1844 } … … 1810 1946 { 1811 1947 /* Find the record above ours. */ 1812 PRTLOCKVALRECUNION pAbove = NULL; 1813 while (pNest) 1814 { 1948 PRTLOCKVALRECUNION volatile *ppDown = NULL; 1949 for (;;) 1950 { 1951 AssertMsgReturnVoid(pNest, ("%p %p\n", pRec, pThreadSelf)); 1815 1952 switch (pNest->Core.u32Magic) 1816 1953 { 1817 1954 case RTLOCKVALRECEXCL_MAGIC: 1818 p Above = pNest;1819 pNest = pNest->Excl.pDown;1820 break;1955 ppDown = &pNest->Excl.pDown; 1956 pNest = *ppDown; 1957 continue; 1821 1958 case RTLOCKVALRECSHRDOWN_MAGIC: 1822 p Above = pNest;1823 pNest = pNest->ShrdOwner.pDown;1824 break;1959 ppDown = &pNest->ShrdOwner.pDown; 1960 pNest = *ppDown; 1961 continue; 1825 1962 case RTLOCKVALRECNEST_MAGIC: 1826 1963 if (pNest->Nest.pRec == pRec) 1827 {1828 pNest = pNest;1829 1964 break; 1830 } 1831 pAbove = pNest; 1832 pNest = pNest->Nest.pDown; 1833 break; 1965 ppDown = &pNest->Nest.pDown; 1966 pNest = *ppDown; 1967 continue; 1834 1968 default: 1835 1969 AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic)); 1836 1970 } 1837 } 1838 AssertMsg(pNest, ("%p %p\n", pRec, pThreadSelf)); 1839 AssertMsg(pAbove, ("%p %p\n", pRec, pThreadSelf)); 1971 break; /* ugly */ 1972 } 1840 1973 Assert(pNest->Nest.cRecursion == cRecursion + 1); 1841 switch (pAbove->Core.u32Magic) 1842 { 1843 case RTLOCKVALRECEXCL_MAGIC: 1844 rtLockValidatorWriteRecUnionPtr(&pNest->Excl.pDown, pNest->Nest.pDown); 1845 break; 1846 case RTLOCKVALRECSHRDOWN_MAGIC: 1847 rtLockValidatorWriteRecUnionPtr(&pNest->ShrdOwner.pDown, pNest->Nest.pDown); 1848 break; 1849 case RTLOCKVALRECNEST_MAGIC: 1850 rtLockValidatorWriteRecUnionPtr(&pNest->Nest.pDown, pNest->Nest.pDown); 1851 break; 1852 default: 1853 AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic)); 1854 } 1974 rtLockValidatorWriteRecUnionPtr(ppDown, pNest->Nest.pDown); 1855 1975 } 1856 1976 … … 1878 1998 1879 1999 { 1880 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1 );2000 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1, false); 1881 2001 rtLockValComplainAboutLock("Other lock: ", pRec2, "\n"); 1882 2002 rtLockValComplainAboutClass("My class: ", pClass1, rtLockValidatorRecGetSubClass(pRec1), true /*fVerbose*/); 1883 2003 rtLockValComplainAboutClass("Other class: ", pClass2, rtLockValidatorRecGetSubClass(pRec2), true /*fVerbose*/); 1884 2004 rtLockValComplainAboutLockStack(pThreadSelf, 0, 0, pRec2); 2005 rtLockValComplainPanic(); 1885 2006 return VERR_SEM_LV_WRONG_ORDER; 1886 2007 } … … 1972 2093 AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR); 1973 2094 1974 uint32_t uPriorSubClass;1975 PRTLOCKVALRECUNIONpDown;1976 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);1977 if (pPriorClass != NIL_RTLOCKVALCLASS)1978 {1979 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);1980 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);1981 if ( !rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))2095 if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC) 2096 pCur = pCur->Nest.pDown; 2097 else 2098 { 2099 PRTLOCKVALRECUNION pDown; 2100 uint32_t uPriorSubClass; 2101 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2102 if (pPriorClass != NIL_RTLOCKVALCLASS) 1982 2103 { 1983 if ( pClass == pPriorClass 1984 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 1985 return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf, 1986 pRec, pCur, pClass, pPriorClass); 1987 cNewRules++; 2104 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR); 2105 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR); 2106 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2107 { 2108 if ( pClass == pPriorClass 2109 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 2110 return rtLockValidatorStackWrongOrder("Wrong locking order! (more than one)", pSrcPos, pThreadSelf, 2111 pRec, pCur, pClass, pPriorClass); 2112 cNewRules++; 2113 } 1988 2114 } 1989 } 1990 1991 pCur = pDown; 1992 if (!pCur) 1993 return VINF_SUCCESS; 2115 pCur = pDown; 2116 } 1994 2117 } 1995 2118 … … 2019 2142 2020 2143 /* Check */ 2021 pCur = pFirstBad Down;2144 pCur = pFirstBadRec; 2022 2145 while (pCur) 2023 2146 { 2024 uint32_t uPriorSubClass; 2025 PRTLOCKVALRECUNION pDown; 2026 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2027 if (pPriorClass != NIL_RTLOCKVALCLASS) 2147 if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC) 2148 pCur = pCur->Nest.pDown; 2149 else 2028 2150 { 2029 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2151 uint32_t uPriorSubClass; 2152 PRTLOCKVALRECUNION pDown; 2153 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2154 if (pPriorClass != NIL_RTLOCKVALCLASS) 2030 2155 { 2031 if ( pClass == pPriorClass 2032 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 2156 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2033 2157 { 2034 if (RT_SUCCESS(rcLock)) 2035 RTCritSectLeave(&g_LockValClassTeachCS); 2036 return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf, 2037 pRec, pCur, pClass, pPriorClass); 2158 if ( pClass == pPriorClass 2159 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 2160 { 2161 if (RT_SUCCESS(rcLock)) 2162 RTCritSectLeave(&g_LockValClassTeachCS); 2163 return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf, 2164 pRec, pCur, pClass, pPriorClass); 2165 } 2038 2166 } 2039 2167 } 2168 pCur = pDown; 2040 2169 } 2041 2042 pCur = pDown;2043 2170 } 2044 2171 2045 2172 /* Iterate the stack yet again, adding new rules this time. */ 2046 pCur = pFirstBad Down;2173 pCur = pFirstBadRec; 2047 2174 while (pCur) 2048 2175 { 2049 uint32_t uPriorSubClass; 2050 PRTLOCKVALRECUNION pDown; 2051 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2052 if (pPriorClass != NIL_RTLOCKVALCLASS) 2176 if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC) 2177 pCur = pCur->Nest.pDown; 2178 else 2053 2179 { 2054 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2180 uint32_t uPriorSubClass; 2181 PRTLOCKVALRECUNION pDown; 2182 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2183 if (pPriorClass != NIL_RTLOCKVALCLASS) 2055 2184 { 2056 Assert( pClass != pPriorClass 2057 && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass)); 2058 int rc = rtLockValidatorClassAddPriorClass(pClass, pFirstBadClass, true /*fAutodidacticism*/, pSrcPos); 2059 if (RT_FAILURE(rc)) 2185 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2060 2186 { 2061 Assert(rc == VERR_NO_MEMORY); 2062 break; 2187 Assert( pClass != pPriorClass 2188 && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass)); 2189 int rc = rtLockValidatorClassAddPriorClass(pClass, pPriorClass, true /*fAutodidacticism*/, pSrcPos); 2190 if (RT_FAILURE(rc)) 2191 { 2192 Assert(rc == VERR_NO_MEMORY); 2193 break; 2194 } 2195 Assert(rtLockValidatorClassIsPriorClass(pClass, pPriorClass)); 2063 2196 } 2064 Assert(rtLockValidatorClassIsPriorClass(pPriorClass, pClass));2065 2197 } 2198 pCur = pDown; 2066 2199 } 2067 2068 pCur = pDown;2069 2200 } 2070 2201 … … 2113 2244 AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR); 2114 2245 2115 uint32_t uPriorSubClass; 2116 PRTLOCKVALRECUNION pDown; 2117 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2118 if (pPriorClass != NIL_RTLOCKVALCLASS) 2119 { 2120 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR); 2121 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR); 2122 if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))) 2123 return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos, 2124 pPriorClass, pCur, pDown); 2125 } 2126 2127 pCur = pDown; 2246 if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC) 2247 pCur = pCur->Nest.pDown; 2248 else 2249 { 2250 uint32_t uPriorSubClass; 2251 PRTLOCKVALRECUNION pDown; 2252 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2253 if (pPriorClass != NIL_RTLOCKVALCLASS) 2254 { 2255 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR); 2256 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR); 2257 if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))) 2258 return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos, 2259 pPriorClass, pCur, pDown); 2260 } 2261 pCur = pDown; 2262 } 2128 2263 if (!pCur) 2129 2264 return VINF_SUCCESS; … … 2153 2288 return VINF_SUCCESS; 2154 2289 2155 rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec );2290 rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec, true); 2156 2291 rtLockValComplainPanic(); 2157 2292 return VERR_SEM_LV_WRONG_ORDER; … … 2554 2689 default: AssertFailed(); pszWhat = "!unexpected rc!"; break; 2555 2690 } 2556 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL );2691 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL, true); 2557 2692 rtLockValComplainMore("---- start of deadlock chain - %u entries ----\n", pStack->c); 2558 2693 for (uint32_t i = 0; i < pStack->c; i++) … … 2805 2940 { 2806 2941 rtLockValComplainFirst("Recursion not allowed by the class!", 2807 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec );2942 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true); 2808 2943 rtLockValComplainPanic(); 2809 2944 return VERR_SEM_LV_NESTED; … … 2849 2984 { 2850 2985 rtLockValComplainFirst("Mixed recursion not allowed by the class!", 2851 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec );2986 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true); 2852 2987 rtLockValComplainPanic(); 2853 2988 return VERR_SEM_LV_NESTED; … … 2955 3090 && !pRecU->Excl.hClass->fRecursionOk)) 2956 3091 { 2957 rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU );3092 rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true); 2958 3093 rtLockValComplainPanic(); 2959 3094 rc = VERR_SEM_LV_NESTED; … … 3172 3307 ) 3173 3308 { 3174 rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU );3309 rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true); 3175 3310 rtLockValComplainPanic(); 3176 3311 rc = VERR_SEM_LV_NESTED; … … 3612 3747 if (RT_UNLIKELY(!pEntry)) 3613 3748 { 3614 rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec );3749 rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true); 3615 3750 rtLockValComplainPanic(); 3616 3751 return VERR_SEM_LV_NOT_OWNER; … … 3667 3802 if (RT_UNLIKELY(!pEntry)) 3668 3803 { 3669 rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec );3804 rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true); 3670 3805 rtLockValComplainPanic(); 3671 3806 return VERR_SEM_LV_NOT_SIGNALLER;
Note:
See TracChangeset
for help on using the changeset viewer.