Changeset 25689 in vbox for trunk/src/VBox/Runtime/common/misc
- Timestamp:
- Jan 8, 2010 10:36:43 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25685 r25689 241 241 * Internal Functions * 242 242 *******************************************************************************/ 243 static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass); 243 static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass); 244 static uint32_t rtLockValidatorStackDepth(PRTTHREADINT pThread); 244 245 245 246 … … 342 343 * @param ... Format arguments. 343 344 */ 344 static void rtLockVal idatorComplain(RT_SRC_POS_DECL, const char *pszWhat, ...)345 static void rtLockValComplain(RT_SRC_POS_DECL, const char *pszWhat, ...) 345 346 { 346 347 if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet)) … … 364 365 * @param pszSuffix Message suffix. 365 366 */ 366 static void rtLockVal idatorComplainAboutLock(const char *pszPrefix, PRTLOCKVALRECUNION pRec, const char *pszSuffix)367 static void rtLockValComplainAboutLock(const char *pszPrefix, PRTLOCKVALRECUNION pRec, const char *pszSuffix) 367 368 { 368 369 if ( VALID_PTR(pRec) … … 413 414 414 415 /** 416 * Dump the lock stack. 417 * 418 * @param pThread The thread which lock stack we're gonna dump. 419 * @param cchIndent The indentation in chars. 420 * @param cMinFrames The minimum number of frames to consider 421 * dumping. 422 */ 423 static void rtLockValComplainAboutLockStack(PRTTHREADINT pThread, unsigned cchIndent, uint32_t cMinFrames) 424 { 425 if ( VALID_PTR(pThread) 426 && !ASMAtomicUoReadBool(&g_fLockValidatorQuiet) 427 && pThread->u32Magic == RTTHREADINT_MAGIC 428 ) 429 { 430 uint32_t cEntries = rtLockValidatorStackDepth(pThread); 431 if (cEntries >= cMinFrames) 432 { 433 RTAssertMsg2AddWeak("%*s---- start of lock stack - %u entr%s ----\n", cchIndent, "", cEntries, 434 cEntries == 1 ? "y" : "ies"); 435 PRTLOCKVALRECUNION pCur = rtLockValidatorReadRecUnionPtr(&pThread->LockValidator.pStackTop); 436 for (uint32_t i = 0; pCur; i++) 437 { 438 char szPrefix[80]; 439 RTStrPrintf(szPrefix, sizeof(szPrefix), "%*s#%02u: ", cchIndent, "", i); 440 rtLockValComplainAboutLock(szPrefix, pCur, "\n"); 441 switch (pCur->Core.u32Magic) 442 { 443 case RTLOCKVALRECEXCL_MAGIC: pCur = rtLockValidatorReadRecUnionPtr(&pCur->Excl.pDown); break; 444 case RTLOCKVALRECSHRDOWN_MAGIC: pCur = rtLockValidatorReadRecUnionPtr(&pCur->ShrdOwner.pDown); break; 445 default: 446 RTAssertMsg2AddWeak("%*s<bad stack frame>\n", cchIndent, ""); 447 pCur = NULL; 448 break; 449 } 450 } 451 RTAssertMsg2AddWeak("%*s---- end of lock stack ----\n", cchIndent, ""); 452 } 453 } 454 } 455 456 457 /** 415 458 * Launch the initial complaint. 416 459 * … … 420 463 * @param pRec The main lock involved. Can be NULL. 421 464 */ 422 static void rtLockVal idatorComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec)465 static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 423 466 { 424 467 if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet)) … … 430 473 else 431 474 RTAssertMsg2Weak("%s [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>"); 432 rtLockValidatorComplainAboutLock("Lock: ", pRec, "\n"); 475 rtLockValComplainAboutLock("Lock: ", pRec, "\n"); 476 rtLockValComplainAboutLockStack(pThreadSelf, 0, 1); 433 477 } 434 478 } … … 441 485 * @param ... Format arguments. 442 486 */ 443 static void rtLockVal idatorComplainMore(const char *pszFormat, ...)487 static void rtLockValComplainMore(const char *pszFormat, ...) 444 488 { 445 489 if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet)) … … 456 500 * Raise a panic if enabled. 457 501 */ 458 static void rtLockVal idatorComplainPanic(void)502 static void rtLockValComplainPanic(void) 459 503 { 460 504 if (ASMAtomicUoReadBool(&g_fLockValidatorMayPanic)) … … 645 689 Assert(pPerThread->cReadLocks == 0); 646 690 Assert(pPerThread->fInValidator == false); 691 Assert(pPerThread->pStackTop == NULL); 647 692 } 648 693 … … 1029 1074 1030 1075 1031 static void rtLockValidatorStackPush(PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec, PCRTLOCKVALSRCPOS pSrcPos) 1076 /** 1077 * Calculates the depth of a lock stack. 1078 * 1079 * @returns Number of stack frames. 1080 * @param pThread The thread. 1081 */ 1082 static uint32_t rtLockValidatorStackDepth(PRTTHREADINT pThread) 1083 { 1084 uint32_t cEntries = 0; 1085 PRTLOCKVALRECUNION pCur = rtLockValidatorReadRecUnionPtr(&pThread->LockValidator.pStackTop); 1086 while (pCur) 1087 { 1088 switch (pCur->Core.u32Magic) 1089 { 1090 case RTLOCKVALRECEXCL_MAGIC: 1091 pCur = rtLockValidatorReadRecUnionPtr(&pCur->Excl.pDown); 1092 break; 1093 1094 case RTLOCKVALRECSHRDOWN_MAGIC: 1095 pCur = rtLockValidatorReadRecUnionPtr(&pCur->ShrdOwner.pDown); 1096 break; 1097 1098 default: 1099 AssertMsgFailedReturn(("%#x\n", pCur->Core.u32Magic), cEntries); 1100 } 1101 cEntries++; 1102 } 1103 return cEntries; 1104 } 1105 1106 1107 /** 1108 * Checks if the stack contains @a pRec. 1109 * 1110 * @returns true / false. 1111 * @param pThreadSelf The curren thread. 1112 * @param pRec The lock record. 1113 */ 1114 static bool rtLockValidatorStackContainsRec(PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 1115 { 1116 PRTLOCKVALRECUNION pCur = pThreadSelf->LockValidator.pStackTop; 1117 while (pCur) 1118 { 1119 switch (pCur->Core.u32Magic) 1120 { 1121 case RTLOCKVALRECEXCL_MAGIC: 1122 Assert(pRec->Excl.cRecursion >= 1); 1123 if (pCur->Excl.pDown == pRec) 1124 return true; 1125 pCur = pCur->Excl.pDown; 1126 break; 1127 1128 case RTLOCKVALRECSHRDOWN_MAGIC: 1129 Assert(pCur->ShrdOwner.cRecursion >= 1); 1130 if (pCur->ShrdOwner.pDown == pRec) 1131 return true; 1132 pCur = pCur->ShrdOwner.pDown; 1133 break; 1134 1135 default: 1136 AssertMsgFailedReturn(("%#x\n", pCur->Core.u32Magic), false); 1137 } 1138 } 1139 return false; 1140 } 1141 1142 1143 /** 1144 * Pushes a lock onto the stack. 1145 * 1146 * @param pThreadSelf The current thread. 1147 * @param pRec The lock record. 1148 */ 1149 static void rtLockValidatorStackPush(PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 1032 1150 { 1033 1151 Assert(pThreadSelf == RTThreadSelf()); 1034 1035 } 1036 1037 1152 Assert(!rtLockValidatorStackContainsRec(pThreadSelf, pRec)); 1153 1154 switch (pRec->Core.u32Magic) 1155 { 1156 case RTLOCKVALRECEXCL_MAGIC: 1157 Assert(pRec->Excl.cRecursion == 1); 1158 Assert(pRec->Excl.pDown == NULL); 1159 pRec->Excl.pDown = pThreadSelf->LockValidator.pStackTop; 1160 break; 1161 1162 case RTLOCKVALRECSHRDOWN_MAGIC: 1163 Assert(pRec->ShrdOwner.cRecursion == 1); 1164 Assert(pRec->ShrdOwner.pDown == NULL); 1165 pRec->ShrdOwner.pDown = pThreadSelf->LockValidator.pStackTop; 1166 break; 1167 1168 case RTLOCKVALRECSHRD_MAGIC: 1169 default: 1170 AssertMsgFailedReturnVoid(("%#x\n", pRec->Core.u32Magic)); 1171 } 1172 pThreadSelf->LockValidator.pStackTop = pRec; 1173 } 1174 1175 1176 /** 1177 * Pops a lock off the stack. 1178 * 1179 * @param pThreadSelf The current thread. 1180 * @param pRec The lock. 1181 */ 1038 1182 static void rtLockValidatorStackPop(PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 1039 1183 { 1040 1184 Assert(pThreadSelf == RTThreadSelf()); 1041 1185 1186 PRTLOCKVALRECUNION pDown; 1187 switch (pRec->Core.u32Magic) 1188 { 1189 case RTLOCKVALRECEXCL_MAGIC: 1190 Assert(pRec->Excl.cRecursion == 0); 1191 pDown = pRec->Excl.pDown; 1192 pRec->Excl.pDown = NULL; 1193 break; 1194 1195 case RTLOCKVALRECSHRDOWN_MAGIC: 1196 Assert(pRec->ShrdOwner.cRecursion == 0); 1197 pDown = pRec->ShrdOwner.pDown; 1198 pRec->ShrdOwner.pDown = NULL; 1199 break; 1200 1201 default: 1202 AssertMsgFailedReturnVoid(("%#x\n", pRec->Core.u32Magic)); 1203 } 1204 if (pThreadSelf->LockValidator.pStackTop == pRec) 1205 pThreadSelf->LockValidator.pStackTop = pDown; 1206 else 1207 { 1208 /* find the record on top of ours */ 1209 PRTLOCKVALRECUNION pAbove = pThreadSelf->LockValidator.pStackTop; 1210 while (pAbove) 1211 { 1212 switch (pAbove->Core.u32Magic) 1213 { 1214 case RTLOCKVALRECEXCL_MAGIC: 1215 Assert(pRec->Excl.cRecursion >= 1); 1216 if (pAbove->Excl.pDown == pRec) 1217 { 1218 pAbove->Excl.pDown = pDown; 1219 return; 1220 } 1221 pAbove = pAbove->Excl.pDown; 1222 break; 1223 1224 case RTLOCKVALRECSHRDOWN_MAGIC: 1225 Assert(pAbove->ShrdOwner.cRecursion >= 1); 1226 if (pAbove->ShrdOwner.pDown == pRec) 1227 { 1228 pAbove->ShrdOwner.pDown = pDown; 1229 return; 1230 } 1231 pAbove = pAbove->ShrdOwner.pDown; 1232 break; 1233 1234 default: 1235 AssertMsgFailedReturnVoid(("%#x\n", pAbove->Core.u32Magic)); 1236 } 1237 } 1238 AssertMsgFailed(("%p %p\n", pRec, pThreadSelf)); 1239 } 1042 1240 } 1043 1241 … … 1046 1244 { 1047 1245 Assert(pThreadSelf == RTThreadSelf()); 1048 /** @todo insert a recursion record onto the stack. Keep a reasonally big pool1246 /** @todo insert a recursion record onto the stack. Keep a reasonally big pool 1049 1247 * of them associated with each thread. */ 1248 switch (pRec->Core.u32Magic) 1249 { 1250 case RTLOCKVALRECEXCL_MAGIC: 1251 Assert(pRec->Excl.cRecursion > 1); 1252 break; 1253 1254 case RTLOCKVALRECSHRDOWN_MAGIC: 1255 Assert(pRec->ShrdOwner.cRecursion > 1); 1256 break; 1257 1258 default: 1259 AssertMsgFailedReturnVoid(("%#x\n", pRec->Core.u32Magic)); 1260 } 1050 1261 } 1051 1262 … … 1054 1265 { 1055 1266 Assert(pThreadSelf == RTThreadSelf()); 1056 1267 switch (pRec->Core.u32Magic) 1268 { 1269 case RTLOCKVALRECEXCL_MAGIC: 1270 Assert(pRec->Excl.cRecursion >= 1); 1271 break; 1272 1273 case RTLOCKVALRECSHRDOWN_MAGIC: 1274 Assert(pRec->ShrdOwner.cRecursion >= 1); 1275 break; 1276 1277 default: 1278 AssertMsgFailedReturnVoid(("%#x\n", pRec->Core.u32Magic)); 1279 } 1057 1280 } 1058 1281 … … 1175 1398 { 1176 1399 s_fComplained = true; 1177 rtLockVal idatorComplain(RT_SRC_POS, "lock validator stack is too small! (%zu entries)\n", RT_ELEMENTS(pStack->a));1400 rtLockValComplain(RT_SRC_POS, "lock validator stack is too small! (%zu entries)\n", RT_ELEMENTS(pStack->a)); 1178 1401 } 1179 1402 return VINF_SUCCESS; … … 1469 1692 default: AssertFailed(); pszWhat = "!unexpected rc!"; break; 1470 1693 } 1471 rtLockVal idatorComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL);1472 rtLockVal idatorComplainMore("---- start of deadlock chain - %u entries ----\n", pStack->c);1694 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL); 1695 rtLockValComplainMore("---- start of deadlock chain - %u entries ----\n", pStack->c); 1473 1696 for (uint32_t i = 0; i < pStack->c; i++) 1474 1697 { … … 1479 1702 pShrdOwner = pStack->a[i].pRec->Shared.papOwners[pStack->a[i].iEntry]; 1480 1703 if (VALID_PTR(pShrdOwner) && pShrdOwner->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC) 1481 rtLockVal idatorComplainAboutLock(szPrefix, (PRTLOCKVALRECUNION)pShrdOwner, "\n");1704 rtLockValComplainAboutLock(szPrefix, (PRTLOCKVALRECUNION)pShrdOwner, "\n"); 1482 1705 else 1483 rtLockVal idatorComplainAboutLock(szPrefix, pStack->a[i].pRec, "\n");1484 } 1485 rtLockVal idatorComplainMore("---- end of deadlock chain ----\n");1486 } 1487 1488 rtLockVal idatorComplainPanic();1706 rtLockValComplainAboutLock(szPrefix, pStack->a[i].pRec, "\n"); 1707 } 1708 rtLockValComplainMore("---- end of deadlock chain ----\n"); 1709 } 1710 1711 rtLockValComplainPanic(); 1489 1712 } 1490 1713 … … 1610 1833 1611 1834 return VINF_SUCCESS; 1835 } 1836 1837 1838 /** 1839 * Gets the lock name for the given record. 1840 * 1841 * @returns Read-only lock name. 1842 * @param pRec The lock record. 1843 */ 1844 DECL_FORCE_INLINE(const char *) rtLockValidatorRecName(PRTLOCKVALRECUNION pRec) 1845 { 1846 switch (pRec->Core.u32Magic) 1847 { 1848 case RTLOCKVALRECEXCL_MAGIC: 1849 return pRec->Excl.pszName; 1850 case RTLOCKVALRECSHRD_MAGIC: 1851 return pRec->Shared.pszName; 1852 case RTLOCKVALRECSHRDOWN_MAGIC: 1853 return pRec->ShrdOwner.pSharedRec ? pRec->ShrdOwner.pSharedRec->pszName : "orphaned"; 1854 default: 1855 return "unknown"; 1856 } 1612 1857 } 1613 1858 … … 1711 1956 ASMAtomicWriteHandle(&pRecU->Excl.hThread, hThreadSelf); 1712 1957 1713 rtLockValidatorStackPush(hThreadSelf, pRecU , pSrcPos);1958 rtLockValidatorStackPush(hThreadSelf, pRecU); 1714 1959 } 1715 1960 } … … 1730 1975 if (c == 0) 1731 1976 { 1732 rtLockValidatorStackPop Recursion(pThread, pRec);1977 rtLockValidatorStackPop(pThread, pRec); 1733 1978 ASMAtomicWriteHandle(&pRec->Excl.hThread, NIL_RTTHREAD); 1734 1979 } … … 1772 2017 && !pRecU->Excl.hClass->fRecursionOk) 1773 2018 { 1774 rtLockVal idatorComplainFirst("Recursion not allowed by the class",2019 rtLockValComplainFirst("Recursion not allowed by the class", 1775 2020 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec); 1776 rtLockVal idatorComplainPanic();2021 rtLockValComplainPanic(); 1777 2022 return VERR_SEM_LV_NESTED; 1778 2023 } … … 1780 2025 Assert(pRecU->Excl.cRecursion < _1M); 1781 2026 pRecU->Excl.cRecursion++; 1782 rtLockValidatorStackPush (pRecU->Excl.hThread, pRecU, pSrcPos);2027 rtLockValidatorStackPushRecursion(pRecU->Excl.hThread, pRecU, pSrcPos); 1783 2028 return VINF_SUCCESS; 1784 2029 } … … 1794 2039 AssertReturn(pRecU->Excl.cRecursion > 1, VERR_SEM_LV_INVALID_PARAMETER); 1795 2040 1796 rtLockValidatorStackPop(pRecU->Excl.hThread, pRecU);1797 2041 pRecU->Excl.cRecursion--; 2042 rtLockValidatorStackPopRecursion(pRecU->Excl.hThread, pRecU); 1798 2043 return VINF_SUCCESS; 1799 2044 } … … 1816 2061 && !pRecU->Excl.hClass->fRecursionOk) 1817 2062 { 1818 rtLockVal idatorComplainFirst("Mixed recursion not allowed by the class",2063 rtLockValComplainFirst("Mixed recursion not allowed by the class", 1819 2064 pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec); 1820 rtLockVal idatorComplainPanic();2065 rtLockValComplainPanic(); 1821 2066 return VERR_SEM_LV_NESTED; 1822 2067 } … … 1843 2088 AssertReturn(pRecU->Excl.cRecursion > 1, VERR_SEM_LV_INVALID_PARAMETER); 1844 2089 2090 pRecU->Excl.cRecursion--; 1845 2091 rtLockValidatorStackPopRecursion(pRecU->Excl.hThread, pRecU); 1846 pRecU->Excl.cRecursion--;1847 2092 return VINF_SUCCESS; 1848 2093 } … … 1915 2160 && !pRecU->Excl.hClass->fRecursionOk)) 1916 2161 { 1917 rtLockVal idatorComplainFirst("Recursion not allowed", pSrcPos, pThreadSelf, pRecU);1918 rtLockVal idatorComplainPanic();2162 rtLockValComplainFirst("Recursion not allowed", pSrcPos, pThreadSelf, pRecU); 2163 rtLockValComplainPanic(); 1919 2164 rc = VERR_SEM_LV_NESTED; 1920 2165 } … … 2124 2369 ) 2125 2370 { 2126 rtLockVal idatorComplainFirst("Recursion not allowed", pSrcPos, pThreadSelf, pRecU);2127 rtLockVal idatorComplainPanic();2371 rtLockValComplainFirst("Recursion not allowed", pSrcPos, pThreadSelf, pRecU); 2372 rtLockValComplainPanic(); 2128 2373 rc = VERR_SEM_LV_NESTED; 2129 2374 } … … 2504 2749 { 2505 2750 if (!pRec->fSignaller) 2506 rtLockValidatorStackPush(hThread, pEntry , pSrcPos);2751 rtLockValidatorStackPush(hThread, pEntry); 2507 2752 } 2508 2753 else … … 2527 2772 PRTLOCKVALRECUNION pEntry = rtLockValidatorRecSharedFindOwner(pRec, hThread, &iEntry); 2528 2773 AssertReturnVoid(pEntry); 2529 if (pEntry->ShrdOwner.cRecursion > 1) 2530 { 2531 Assert(!pRec->fSignaller); 2532 rtLockValidatorStackPopRecursion(hThread, pEntry); 2533 pEntry->ShrdOwner.cRecursion--; 2534 } 2535 else 2774 AssertReturnVoid(pEntry->ShrdOwner.cRecursion > 0); 2775 2776 uint32_t c = --pEntry->ShrdOwner.cRecursion; 2777 if (c == 0) 2536 2778 { 2537 2779 if (!pRec->fSignaller) 2538 2780 rtLockValidatorStackPop(hThread, (PRTLOCKVALRECUNION)pEntry); 2539 2781 rtLockValidatorRecSharedRemoveAndFreeOwner(pRec, &pEntry->ShrdOwner, iEntry); 2782 } 2783 else 2784 { 2785 Assert(!pRec->fSignaller); 2786 rtLockValidatorStackPopRecursion(hThread, pEntry); 2540 2787 } 2541 2788 } … … 2562 2809 if (RT_UNLIKELY(!pEntry)) 2563 2810 { 2564 rtLockVal idatorComplainFirst("Not owner (shared)", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);2565 rtLockVal idatorComplainPanic();2811 rtLockValComplainFirst("Not owner (shared)", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec); 2812 rtLockValComplainPanic(); 2566 2813 return VERR_SEM_LV_NOT_OWNER; 2567 2814 } … … 2583 2830 */ 2584 2831 Assert(pEntry->ShrdOwner.cRecursion > 0); 2585 if (pEntry->ShrdOwner.cRecursion > 1) 2586 { 2587 rtLockValidatorStackPopRecursion(hThreadSelf, pEntry); 2588 pEntry->ShrdOwner.cRecursion--; 2589 } 2590 else 2832 uint32_t c = --pEntry->ShrdOwner.cRecursion; 2833 if (c == 0) 2591 2834 { 2592 2835 rtLockValidatorStackPop(hThreadSelf, pEntry); 2593 2836 rtLockValidatorRecSharedRemoveAndFreeOwner(pRec, &pEntry->ShrdOwner, iEntry); 2594 2837 } 2838 else 2839 rtLockValidatorStackPopRecursion(hThreadSelf, pEntry); 2595 2840 2596 2841 return VINF_SUCCESS; … … 2617 2862 if (RT_UNLIKELY(!pEntry)) 2618 2863 { 2619 rtLockVal idatorComplainFirst("Invalid signaller", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);2620 rtLockVal idatorComplainPanic();2864 rtLockValComplainFirst("Invalid signaller", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec); 2865 rtLockValComplainPanic(); 2621 2866 return VERR_SEM_LV_NOT_SIGNALLER; 2622 2867 }
Note:
See TracChangeset
for help on using the changeset viewer.