Changeset 25692 in vbox
- Timestamp:
- Jan 8, 2010 3:59:45 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r25638 r25692 862 862 /** The thread is not a valid signaller of the event. */ 863 863 #define VERR_SEM_LV_NOT_SIGNALLER (-376) 864 /** Internal error in the lock validator or related components. */ 865 #define VERR_SEM_LV_INTERNAL_ERROR (-377) 864 866 /** @} */ 865 867 -
trunk/include/iprt/lockvalidator.h
r25685 r25692 730 730 * user will teach it all it needs to know (false). 731 731 * @param fRecursionOk Whether to allow lock recursion or not. 732 * @param fStrictReleaseOrder Enforce strict lock release order or not. 732 733 * @param cMsMinDeadlock Used to raise the sleep interval at which 733 734 * deadlock detection kicks in. Minimum is 1 ms, … … 741 742 */ 742 743 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, 743 bool fAutodidact, bool fRecursionOk, 744 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, 744 745 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder); 745 746 -
trunk/include/iprt/types.h
r25685 r25692 1497 1497 /** @name Special sub-class values. 1498 1498 * The range 16..UINT32_MAX is available to the user, the range 0..15 is 1499 * reserved for the lock validator. 1499 * reserved for the lock validator. In the user range the locks can only be 1500 * taking in ascending order. 1500 1501 * @{ */ 1501 1502 /** Not allowed to be taken with any other locks in the same class. -
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25690 r25692 140 140 /** Whether to allow recursion. */ 141 141 bool fRecursionOk; 142 /** Reserved. */143 bool f Reserved;142 /** Strict release order. */ 143 bool fStrictReleaseOrder; 144 144 /** Whether this class is in the tree. */ 145 145 bool fInTree; … … 372 372 373 373 /** 374 * Describes the class. 375 * 376 * @param pszPrefix Message prefix. 377 * @param pClass The class to complain about. 378 * @param uSubClass My sub-class. 379 * @param fVerbose Verbose description including relations to other 380 * classes. 381 */ 382 static void rtLockValComplainAboutClass(const char *pszPrefix, RTLOCKVALCLASSINT *pClass, uint32_t uSubClass, bool fVerbose) 383 { 384 385 } 386 387 388 /** 374 389 * Helper for rtLockValComplainAboutLock. 375 390 */ … … 497 512 * @param cMinFrames The minimum number of frames to consider 498 513 * dumping. 499 */ 500 static void rtLockValComplainAboutLockStack(PRTTHREADINT pThread, unsigned cchIndent, uint32_t cMinFrames) 514 * @param pHighightRec Record that should be marked specially in the 515 * dump. 516 */ 517 static void rtLockValComplainAboutLockStack(PRTTHREADINT pThread, unsigned cchIndent, uint32_t cMinFrames, 518 PRTLOCKVALRECUNION pHighightRec) 501 519 { 502 520 if ( VALID_PTR(pThread) … … 515 533 char szPrefix[80]; 516 534 RTStrPrintf(szPrefix, sizeof(szPrefix), "%*s#%02u: ", cchIndent, "", i); 517 rtLockValComplainAboutLock(szPrefix, pCur, "\n");535 rtLockValComplainAboutLock(szPrefix, pCur, pHighightRec != pCur ? "\n" : " (*)\n"); 518 536 switch (pCur->Core.u32Magic) 519 537 { … … 552 570 RTAssertMsg2Weak("%s [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>"); 553 571 rtLockValComplainAboutLock("Lock: ", pRec, "\n"); 554 rtLockValComplainAboutLockStack(pThreadSelf, 0, 1 );572 rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec); 555 573 } 556 574 } … … 804 822 805 823 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, 806 bool fAutodidact, bool fRecursionOk, 824 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, 807 825 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder) 808 826 { … … 826 844 pThis->fAutodidact = fAutodidact; 827 845 pThis->fRecursionOk = fRecursionOk; 828 pThis->f Reserved = false;846 pThis->fStrictReleaseOrder = fStrictReleaseOrder; 829 847 pThis->fInTree = false; 830 848 pThis->cMsMinDeadlock = cMsMinDeadlock; … … 860 878 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_POS_NO_ID(); 861 879 return RTLockValidatorClassCreateEx(phClass, &SrcPos, 862 fAutodidact, true /*fRecursionOk*/, 880 fAutodidact, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/, 863 881 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/); 864 882 } … … 980 998 */ 981 999 int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos, 982 true /*fAutodidact*/, true /*fRecursionOk*/, 1000 true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/, 983 1001 1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/); 984 1002 if (RT_SUCCESS(rc)) … … 1095 1113 * @param fAutodidacticism Whether we're teaching ourselfs (true) or 1096 1114 * somebody is teaching us via the API (false). 1097 */ 1098 static int rtLockValidatorClassAddPriorClass(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass, bool fAutodidacticism) 1115 * @param pSrcPos Where this rule was added (optional). 1116 */ 1117 static int rtLockValidatorClassAddPriorClass(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass, 1118 bool fAutodidacticism, PCRTLOCKVALSRCPOS pSrcPos) 1099 1119 { 1100 1120 if (!RTCritSectIsInitialized(&g_LockValClassTeachCS)) … … 1105 1125 * Check that there are no conflict (no assert since we might race each other). 1106 1126 */ 1107 int rc = VERR_ INTERNAL_ERROR_5;1127 int rc = VERR_SEM_LV_INTERNAL_ERROR; 1108 1128 if (!rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 1109 1129 { … … 1180 1200 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE); 1181 1201 1182 return rtLockValidatorClassAddPriorClass(pClass, pPriorClass, false /*fAutodidacticism*/); 1183 } 1202 return rtLockValidatorClassAddPriorClass(pClass, pPriorClass, false /*fAutodidacticism*/, NULL); 1203 } 1204 1205 1206 /** 1207 * Unlinks all siblings. 1208 * 1209 * This is used during record deletion and assumes no races. 1210 * 1211 * @param pCore One of the siblings. 1212 */ 1213 static void rtLockValidatorUnlinkAllSiblings(PRTLOCKVALRECCORE pCore) 1214 { 1215 /* ASSUMES sibling destruction doesn't involve any races and that all 1216 related records are to be disposed off now. */ 1217 PRTLOCKVALRECUNION pSibling = (PRTLOCKVALRECUNION)pCore; 1218 while (pSibling) 1219 { 1220 PRTLOCKVALRECUNION volatile *ppCoreNext; 1221 switch (pSibling->Core.u32Magic) 1222 { 1223 case RTLOCKVALRECEXCL_MAGIC: 1224 case RTLOCKVALRECEXCL_MAGIC_DEAD: 1225 ppCoreNext = &pSibling->Excl.pSibling; 1226 break; 1227 1228 case RTLOCKVALRECSHRD_MAGIC: 1229 case RTLOCKVALRECSHRD_MAGIC_DEAD: 1230 ppCoreNext = &pSibling->Shared.pSibling; 1231 break; 1232 1233 default: 1234 AssertFailed(); 1235 ppCoreNext = NULL; 1236 break; 1237 } 1238 if (RT_UNLIKELY(ppCoreNext)) 1239 break; 1240 pSibling = (PRTLOCKVALRECUNION)ASMAtomicXchgPtr((void * volatile *)ppCoreNext, NULL); 1241 } 1242 } 1243 1244 1245 RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1, PRTLOCKVALRECCORE pRec2) 1246 { 1247 /* 1248 * Validate input. 1249 */ 1250 PRTLOCKVALRECUNION p1 = (PRTLOCKVALRECUNION)pRec1; 1251 PRTLOCKVALRECUNION p2 = (PRTLOCKVALRECUNION)pRec2; 1252 1253 AssertPtrReturn(p1, VERR_SEM_LV_INVALID_PARAMETER); 1254 AssertReturn( p1->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC 1255 || p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC 1256 , VERR_SEM_LV_INVALID_PARAMETER); 1257 1258 AssertPtrReturn(p2, VERR_SEM_LV_INVALID_PARAMETER); 1259 AssertReturn( p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC 1260 || p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC 1261 , VERR_SEM_LV_INVALID_PARAMETER); 1262 1263 /* 1264 * Link them (circular list). 1265 */ 1266 if ( p1->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC 1267 && p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC) 1268 { 1269 p1->Excl.pSibling = p2; 1270 p2->Shared.pSibling = p1; 1271 } 1272 else if ( p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC 1273 && p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC) 1274 { 1275 p1->Shared.pSibling = p2; 1276 p2->Excl.pSibling = p1; 1277 } 1278 else 1279 AssertFailedReturn(VERR_SEM_LV_INVALID_PARAMETER); /* unsupported mix */ 1280 1281 return VINF_SUCCESS; 1282 } 1283 1284 1285 /** 1286 * Gets the lock name for the given record. 1287 * 1288 * @returns Read-only lock name. 1289 * @param pRec The lock record. 1290 */ 1291 DECL_FORCE_INLINE(const char *) rtLockValidatorRecName(PRTLOCKVALRECUNION pRec) 1292 { 1293 switch (pRec->Core.u32Magic) 1294 { 1295 case RTLOCKVALRECEXCL_MAGIC: 1296 return pRec->Excl.pszName; 1297 case RTLOCKVALRECSHRD_MAGIC: 1298 return pRec->Shared.pszName; 1299 case RTLOCKVALRECSHRDOWN_MAGIC: 1300 return pRec->ShrdOwner.pSharedRec ? pRec->ShrdOwner.pSharedRec->pszName : "orphaned"; 1301 case RTLOCKVALRECNEST_MAGIC: 1302 pRec = rtLockValidatorReadRecUnionPtr(&pRec->Nest.pRec); 1303 if (VALID_PTR(pRec)) 1304 { 1305 switch (pRec->Core.u32Magic) 1306 { 1307 case RTLOCKVALRECEXCL_MAGIC: 1308 return pRec->Excl.pszName; 1309 case RTLOCKVALRECSHRD_MAGIC: 1310 return pRec->Shared.pszName; 1311 case RTLOCKVALRECSHRDOWN_MAGIC: 1312 return pRec->ShrdOwner.pSharedRec ? pRec->ShrdOwner.pSharedRec->pszName : "orphaned"; 1313 default: 1314 return "unknown-nested"; 1315 } 1316 } 1317 return "orphaned-nested"; 1318 default: 1319 return "unknown"; 1320 } 1321 } 1322 1323 1324 /** 1325 * Gets the class for this locking record. 1326 * 1327 * @returns Pointer to the class or NIL_RTLOCKVALCLASS. 1328 * @param pRec The lock validator record. 1329 */ 1330 DECLINLINE(RTLOCKVALCLASSINT *) rtLockValidatorRecGetClass(PRTLOCKVALRECUNION pRec) 1331 { 1332 switch (pRec->Core.u32Magic) 1333 { 1334 case RTLOCKVALRECEXCL_MAGIC: 1335 return pRec->Excl.hClass; 1336 1337 case RTLOCKVALRECSHRD_MAGIC: 1338 return pRec->Shared.hClass; 1339 1340 case RTLOCKVALRECSHRDOWN_MAGIC: 1341 { 1342 PRTLOCKVALRECSHRD pSharedRec = pRec->ShrdOwner.pSharedRec; 1343 if (RT_LIKELY( VALID_PTR(pSharedRec) 1344 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1345 return pSharedRec->hClass; 1346 return NIL_RTLOCKVALCLASS; 1347 } 1348 1349 case RTLOCKVALRECNEST_MAGIC: 1350 { 1351 PRTLOCKVALRECUNION pRealRec = pRec->Nest.pRec; 1352 if (VALID_PTR(pRealRec)) 1353 { 1354 switch (pRealRec->Core.u32Magic) 1355 { 1356 case RTLOCKVALRECEXCL_MAGIC: 1357 return pRealRec->Excl.hClass; 1358 1359 case RTLOCKVALRECSHRDOWN_MAGIC: 1360 { 1361 PRTLOCKVALRECSHRD pSharedRec = pRealRec->ShrdOwner.pSharedRec; 1362 if (RT_LIKELY( VALID_PTR(pSharedRec) 1363 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1364 return pSharedRec->hClass; 1365 break; 1366 } 1367 1368 default: 1369 AssertMsgFailed(("%p %p %#x\n", pRec, pRealRec, pRealRec->Core.u32Magic)); 1370 break; 1371 } 1372 } 1373 return NIL_RTLOCKVALCLASS; 1374 } 1375 1376 default: 1377 AssertMsgFailed(("%#x\n", pRec->Core.u32Magic)); 1378 return NIL_RTLOCKVALCLASS; 1379 } 1380 } 1381 1382 1383 /** 1384 * Gets the class for this locking record and the pointer to the one below it in 1385 * the stack. 1386 * 1387 * @returns Pointer to the class or NIL_RTLOCKVALCLASS. 1388 * @param pRec The lock validator record. 1389 * @param puSubClass Where to return the sub-class. 1390 * @param ppDown Where to return the pointer to the record below. 1391 */ 1392 DECL_FORCE_INLINE(RTLOCKVALCLASSINT *) 1393 rtLockValidatorRecGetClassesAndDown(PRTLOCKVALRECUNION pRec, uint32_t *puSubClass, PRTLOCKVALRECUNION *ppDown) 1394 { 1395 switch (pRec->Core.u32Magic) 1396 { 1397 case RTLOCKVALRECEXCL_MAGIC: 1398 *ppDown = pRec->Excl.pDown; 1399 *puSubClass = pRec->Excl.uSubClass; 1400 return pRec->Excl.hClass; 1401 1402 case RTLOCKVALRECSHRD_MAGIC: 1403 *ppDown = NULL; 1404 *puSubClass = pRec->Shared.uSubClass; 1405 return pRec->Shared.hClass; 1406 1407 case RTLOCKVALRECSHRDOWN_MAGIC: 1408 { 1409 *ppDown = pRec->ShrdOwner.pDown; 1410 1411 PRTLOCKVALRECSHRD pSharedRec = pRec->ShrdOwner.pSharedRec; 1412 if (RT_LIKELY( VALID_PTR(pSharedRec) 1413 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1414 { 1415 *puSubClass = pSharedRec->uSubClass; 1416 return pSharedRec->hClass; 1417 } 1418 *puSubClass = RTLOCKVAL_SUB_CLASS_NONE; 1419 return NIL_RTLOCKVALCLASS; 1420 } 1421 1422 case RTLOCKVALRECNEST_MAGIC: 1423 { 1424 *ppDown = pRec->Nest.pDown; 1425 1426 PRTLOCKVALRECUNION pRealRec = pRec->Nest.pRec; 1427 if (VALID_PTR(pRealRec)) 1428 { 1429 switch (pRealRec->Core.u32Magic) 1430 { 1431 case RTLOCKVALRECEXCL_MAGIC: 1432 *puSubClass = pRealRec->Excl.uSubClass; 1433 return pRealRec->Excl.hClass; 1434 1435 case RTLOCKVALRECSHRDOWN_MAGIC: 1436 { 1437 PRTLOCKVALRECSHRD pSharedRec = pRealRec->ShrdOwner.pSharedRec; 1438 if (RT_LIKELY( VALID_PTR(pSharedRec) 1439 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1440 { 1441 *puSubClass = pSharedRec->uSubClass; 1442 return pSharedRec->hClass; 1443 } 1444 break; 1445 } 1446 1447 default: 1448 AssertMsgFailed(("%p %p %#x\n", pRec, pRealRec, pRealRec->Core.u32Magic)); 1449 break; 1450 } 1451 } 1452 *puSubClass = RTLOCKVAL_SUB_CLASS_NONE; 1453 return NIL_RTLOCKVALCLASS; 1454 } 1455 1456 default: 1457 AssertMsgFailed(("%#x\n", pRec->Core.u32Magic)); 1458 *ppDown = NULL; 1459 *puSubClass = RTLOCKVAL_SUB_CLASS_NONE; 1460 return NIL_RTLOCKVALCLASS; 1461 } 1462 } 1463 1464 1465 /** 1466 * Gets the sub-class for a lock record. 1467 * 1468 * @returns the sub-class. 1469 * @param pRec The lock validator record. 1470 */ 1471 DECLINLINE(uint32_t) rtLockValidatorRecGetSubClass(PRTLOCKVALRECUNION pRec) 1472 { 1473 switch (pRec->Core.u32Magic) 1474 { 1475 case RTLOCKVALRECEXCL_MAGIC: 1476 return pRec->Excl.uSubClass; 1477 1478 case RTLOCKVALRECSHRD_MAGIC: 1479 return pRec->Shared.uSubClass; 1480 1481 case RTLOCKVALRECSHRDOWN_MAGIC: 1482 { 1483 PRTLOCKVALRECSHRD pSharedRec = pRec->ShrdOwner.pSharedRec; 1484 if (RT_LIKELY( VALID_PTR(pSharedRec) 1485 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1486 return pSharedRec->uSubClass; 1487 return RTLOCKVAL_SUB_CLASS_NONE; 1488 } 1489 1490 case RTLOCKVALRECNEST_MAGIC: 1491 { 1492 PRTLOCKVALRECUNION pRealRec = pRec->Nest.pRec; 1493 if (VALID_PTR(pRealRec)) 1494 { 1495 switch (pRealRec->Core.u32Magic) 1496 { 1497 case RTLOCKVALRECEXCL_MAGIC: 1498 return pRec->Excl.uSubClass; 1499 1500 case RTLOCKVALRECSHRDOWN_MAGIC: 1501 { 1502 PRTLOCKVALRECSHRD pSharedRec = pRealRec->ShrdOwner.pSharedRec; 1503 if (RT_LIKELY( VALID_PTR(pSharedRec) 1504 && pSharedRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)) 1505 return pSharedRec->uSubClass; 1506 break; 1507 } 1508 1509 default: 1510 AssertMsgFailed(("%p %p %#x\n", pRec, pRealRec, pRealRec->Core.u32Magic)); 1511 break; 1512 } 1513 } 1514 return RTLOCKVAL_SUB_CLASS_NONE; 1515 } 1516 1517 default: 1518 AssertMsgFailed(("%#x\n", pRec->Core.u32Magic)); 1519 return RTLOCKVAL_SUB_CLASS_NONE; 1520 } 1521 } 1522 1523 1184 1524 1185 1525 … … 1524 1864 1525 1865 1526 static int rtLockValidatorCheckOrderOnRequest(RTLOCKVALCLASS hClass, uint32_t uSubClass, RTTHREAD hThreadSelf, 1527 PRTLOCKVALRECUNION pRec, PCRTLOCKVALSRCPOS pSrcPos) 1528 { 1529 /** @todo Lock Order Validation: request */ 1866 /** 1867 * Helper for rtLockValidatorStackCheckLockingOrder that does the bitching and 1868 * returns VERR_SEM_LV_WRONG_ORDER. 1869 */ 1870 static int rtLockValidatorStackWrongOrder(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, 1871 PRTLOCKVALRECUNION pRec1, PRTLOCKVALRECUNION pRec2, 1872 RTLOCKVALCLASSINT *pClass1, RTLOCKVALCLASSINT *pClass2) 1873 1874 1875 { 1876 rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1); 1877 rtLockValComplainAboutLock("Other lock: ", pRec2, "\n"); 1878 rtLockValComplainAboutClass("My class: ", pClass1, rtLockValidatorRecGetSubClass(pRec1), true /*fVerbose*/); 1879 rtLockValComplainAboutClass("Other class: ", pClass2, rtLockValidatorRecGetSubClass(pRec2), true /*fVerbose*/); 1880 rtLockValComplainAboutLockStack(pThreadSelf, 0, 0, pRec2); 1881 return VERR_SEM_LV_WRONG_ORDER; 1882 } 1883 1884 1885 /** 1886 * Checks if the sub-class order is ok or not. 1887 * 1888 * Used to deal with two locks from the same class. 1889 * 1890 * @returns true if ok, false if not. 1891 * @param uSubClass1 The sub-class of the lock that is being 1892 * considered. 1893 * @param uSubClass2 The sub-class of the lock that is already being 1894 * held. 1895 */ 1896 DECL_FORCE_INLINE(bool) rtLockValidatorIsSubClassOrderOk(uint32_t uSubClass1, uint32_t uSubClass2) 1897 { 1898 if (uSubClass1 > uSubClass2) 1899 { 1900 /* NONE kills ANY. */ 1901 if (uSubClass2 == RTLOCKVAL_SUB_CLASS_NONE) 1902 return false; 1903 return true; 1904 } 1905 1906 /* ANY counters all USER values. (uSubClass1 == NONE only if they are equal) */ 1907 AssertCompile(RTLOCKVAL_SUB_CLASS_ANY > RTLOCKVAL_SUB_CLASS_NONE); 1908 if (uSubClass1 == RTLOCKVAL_SUB_CLASS_ANY) 1909 return true; 1910 return false; 1911 } 1912 1913 1914 /** 1915 * Checks if the class and sub-class lock order is ok. 1916 * 1917 * @returns true if ok, false if not. 1918 * @param pClass1 The class of the lock that is being considered. 1919 * @param uSubClass1 The sub-class that goes with @a pClass1. 1920 * @param pClass2 The class of the lock that is already being 1921 * held. 1922 * @param uSubClass2 The sub-class that goes with @a pClass2. 1923 */ 1924 DECL_FORCE_INLINE(bool) rtLockValidatorIsClassOrderOk(RTLOCKVALCLASSINT *pClass1, uint32_t uSubClass1, 1925 RTLOCKVALCLASSINT *pClass2, uint32_t uSubClass2) 1926 { 1927 if (pClass1 == pClass2) 1928 return rtLockValidatorIsSubClassOrderOk(uSubClass1, uSubClass2); 1929 return rtLockValidatorClassIsPriorClass(pClass1, pClass2); 1930 } 1931 1932 1933 /** 1934 * Checks the locking order, part two. 1935 * 1936 * @returns VINF_SUCCESS, VERR_SEM_LV_WRONG_ORDER or VERR_SEM_LV_INTERNAL_ERROR. 1937 * @param pClass The lock class. 1938 * @param uSubClass The lock sub-class. 1939 * @param pThreadSelf The current thread. 1940 * @param pRec The lock record. 1941 * @param pSrcPos The source position of the locking operation. 1942 */ 1943 static int rtLockValidatorStackCheckLockingOrder2(RTLOCKVALCLASSINT * const pClass, uint32_t const uSubClass, 1944 PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION const pRec, 1945 PCRTLOCKVALSRCPOS const pSrcPos, 1946 RTLOCKVALCLASSINT * const pFirstBadClass, 1947 PRTLOCKVALRECUNION const pFirstBadRec, 1948 PRTLOCKVALRECUNION const pFirstBadDown) 1949 { 1950 /* 1951 * Something went wrong, pCur is pointing to where. 1952 */ 1953 if (rtLockValidatorClassIsPriorClass(pFirstBadClass, pClass)) 1954 return rtLockValidatorStackWrongOrder("Wrong locking order!", pSrcPos, pThreadSelf, 1955 pRec, pFirstBadRec, pClass, pFirstBadClass); 1956 if (!pClass->fAutodidact) 1957 return rtLockValidatorStackWrongOrder("Wrong locking order! (unknown)", pSrcPos, pThreadSelf, 1958 pRec, pFirstBadRec, pClass, pFirstBadClass); 1959 1960 /* 1961 * This class is an autodidact, so we have to check out the rest of the stack 1962 * for direct violations. 1963 */ 1964 uint32_t cNewRules = 1; 1965 PRTLOCKVALRECUNION pCur = pFirstBadDown; 1966 while (pCur) 1967 { 1968 AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR); 1969 1970 uint32_t uPriorSubClass; 1971 PRTLOCKVALRECUNION pDown; 1972 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 1973 if (pPriorClass != NIL_RTLOCKVALCLASS) 1974 { 1975 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR); 1976 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR); 1977 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 1978 { 1979 if ( pClass == pPriorClass 1980 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 1981 return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf, 1982 pRec, pCur, pClass, pPriorClass); 1983 cNewRules++; 1984 } 1985 } 1986 1987 pCur = pDown; 1988 if (!pCur) 1989 return VINF_SUCCESS; 1990 } 1991 1992 if (cNewRules == 1) 1993 { 1994 /* 1995 * Special case the simple operation, hoping that it will be a 1996 * frequent case. 1997 */ 1998 int rc = rtLockValidatorClassAddPriorClass(pClass, pFirstBadClass, true /*fAutodidacticism*/, pSrcPos); 1999 if (rc == VERR_SEM_LV_WRONG_ORDER) 2000 return rtLockValidatorStackWrongOrder("Wrong locking order! (race)", pSrcPos, pThreadSelf, 2001 pRec, pFirstBadRec, pClass, pFirstBadClass); 2002 Assert(RT_SUCCESS(rc) || rc == VERR_NO_MEMORY); 2003 } 2004 else 2005 { 2006 /* 2007 * We may be adding more than one rule, so we have to take the lock 2008 * before starting to add the rules. This means we have to check 2009 * the state after taking it since we might be racing someone adding 2010 * a conflicting rule. 2011 */ 2012 if (!RTCritSectIsInitialized(&g_LockValClassTeachCS)) 2013 rtLockValidatorLazyInit(); 2014 int rcLock = RTCritSectEnter(&g_LockValClassTeachCS); 2015 2016 /* Check */ 2017 pCur = pFirstBadDown; 2018 while (pCur) 2019 { 2020 uint32_t uPriorSubClass; 2021 PRTLOCKVALRECUNION pDown; 2022 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2023 if (pPriorClass != NIL_RTLOCKVALCLASS) 2024 { 2025 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2026 { 2027 if ( pClass == pPriorClass 2028 || rtLockValidatorClassIsPriorClass(pPriorClass, pClass)) 2029 { 2030 if (RT_SUCCESS(rcLock)) 2031 RTCritSectLeave(&g_LockValClassTeachCS); 2032 return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf, 2033 pRec, pCur, pClass, pPriorClass); 2034 } 2035 } 2036 } 2037 2038 pCur = pDown; 2039 } 2040 2041 /* Iterate the stack yet again, adding new rules this time. */ 2042 pCur = pFirstBadDown; 2043 while (pCur) 2044 { 2045 uint32_t uPriorSubClass; 2046 PRTLOCKVALRECUNION pDown; 2047 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2048 if (pPriorClass != NIL_RTLOCKVALCLASS) 2049 { 2050 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)) 2051 { 2052 Assert( pClass != pPriorClass 2053 && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass)); 2054 int rc = rtLockValidatorClassAddPriorClass(pClass, pFirstBadClass, true /*fAutodidacticism*/, pSrcPos); 2055 if (RT_FAILURE(rc)) 2056 { 2057 Assert(rc == VERR_NO_MEMORY); 2058 break; 2059 } 2060 Assert(rtLockValidatorClassIsPriorClass(pPriorClass, pClass)); 2061 } 2062 } 2063 2064 pCur = pDown; 2065 } 2066 2067 if (RT_SUCCESS(rcLock)) 2068 RTCritSectLeave(&g_LockValClassTeachCS); 2069 } 2070 1530 2071 return VINF_SUCCESS; 1531 2072 } 1532 2073 1533 2074 1534 static int rtLockValidatorCheckOrderOnRelease(RTLOCKVALCLASS hClass, uint32_t uSubClass, RTTHREAD hThreadSelf, 1535 PRTLOCKVALRECUNION pRec) 1536 { 1537 /** @todo Lock Order Validation: release, maybe */ 1538 return VINF_SUCCESS; 2075 2076 /** 2077 * Checks the locking order. 2078 * 2079 * @returns VINF_SUCCESS, VERR_SEM_LV_WRONG_ORDER or VERR_SEM_LV_INTERNAL_ERROR. 2080 * @param pClass The lock class. 2081 * @param uSubClass The lock sub-class. 2082 * @param pThreadSelf The current thread. 2083 * @param pRec The lock record. 2084 * @param pSrcPos The source position of the locking operation. 2085 */ 2086 static int rtLockValidatorStackCheckLockingOrder(RTLOCKVALCLASSINT * const pClass, uint32_t const uSubClass, 2087 PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION const pRec, 2088 PCRTLOCKVALSRCPOS pSrcPos) 2089 { 2090 /* 2091 * Some internal paranoia first. 2092 */ 2093 AssertPtr(pClass); 2094 Assert(pClass->u32Magic == RTLOCKVALCLASS_MAGIC); 2095 AssertPtr(pThreadSelf); 2096 Assert(pThreadSelf->u32Magic == RTTHREADINT_MAGIC); 2097 AssertPtr(pRec); 2098 AssertPtrNull(pSrcPos); 2099 2100 /* 2101 * Walk the stack, delegate problems to a worker routine. 2102 */ 2103 PRTLOCKVALRECUNION pCur = pThreadSelf->LockValidator.pStackTop; 2104 if (!pCur) 2105 return VINF_SUCCESS; 2106 2107 for (;;) 2108 { 2109 AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR); 2110 2111 uint32_t uPriorSubClass; 2112 PRTLOCKVALRECUNION pDown; 2113 RTLOCKVALCLASSINT *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown); 2114 if (pPriorClass != NIL_RTLOCKVALCLASS) 2115 { 2116 AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR); 2117 AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR); 2118 if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))) 2119 return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos, 2120 pPriorClass, pCur, pDown); 2121 } 2122 2123 pCur = pDown; 2124 if (!pCur) 2125 return VINF_SUCCESS; 2126 } 2127 } 2128 2129 2130 /** 2131 * Check that the lock record is the topmost one on the stack, complain and fail 2132 * if it isn't. 2133 * 2134 * @returns VINF_SUCCESS, VERR_SEM_LV_WRONG_RELEASE_ORDER or 2135 * VERR_SEM_LV_INVALID_PARAMETER. 2136 * @param pThreadSelf The current thread. 2137 * @param pRec The record. 2138 */ 2139 static int rtLockValidatorStackCheckReleaseOrder(PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec) 2140 { 2141 AssertReturn(pThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER); 2142 Assert(pThreadSelf == RTThreadSelf()); 2143 2144 PRTLOCKVALRECUNION pTop = pThreadSelf->LockValidator.pStackTop; 2145 if (RT_LIKELY( pTop == pRec 2146 || ( pTop 2147 && pTop->Core.u32Magic == RTLOCKVALRECNEST_MAGIC 2148 && pTop->Nest.pRec == pRec))) 2149 return VINF_SUCCESS; 2150 2151 rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec); 2152 rtLockValComplainPanic(); 2153 return VERR_SEM_LV_WRONG_ORDER; 1539 2154 } 1540 2155 … … 1941 2556 char szPrefix[24]; 1942 2557 RTStrPrintf(szPrefix, sizeof(szPrefix), "#%02u: ", i); 1943 PRTLOCKVALREC SHRDOWN pShrdOwner = NULL;2558 PRTLOCKVALRECUNION pShrdOwner = NULL; 1944 2559 if (pStack->a[i].pRec->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC) 1945 pShrdOwner = pStack->a[i].pRec->Shared.papOwners[pStack->a[i].iEntry];2560 pShrdOwner = (PRTLOCKVALRECUNION)pStack->a[i].pRec->Shared.papOwners[pStack->a[i].iEntry]; 1946 2561 if (VALID_PTR(pShrdOwner) && pShrdOwner->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC) 1947 2562 { 1948 rtLockValComplainAboutLock(szPrefix, (PRTLOCKVALRECUNION)pShrdOwner, "\n");1949 rtLockValComplainAboutLockStack(pShrdOwner-> hThread, 5, 2);2563 rtLockValComplainAboutLock(szPrefix, pShrdOwner, "\n"); 2564 rtLockValComplainAboutLockStack(pShrdOwner->ShrdOwner.hThread, 5, 2, pShrdOwner); 1950 2565 } 1951 2566 else 1952 2567 { 1953 2568 rtLockValComplainAboutLock(szPrefix, pStack->a[i].pRec, "\n"); 1954 if (pStack->a[i].pRec->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC) ;1955 rtLockValComplainAboutLockStack(pStack->a[i].pRec->Excl.hThread, 5, 2 );2569 if (pStack->a[i].pRec->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC) 2570 rtLockValComplainAboutLockStack(pStack->a[i].pRec->Excl.hThread, 5, 2, pStack->a[i].pRec); 1956 2571 } 1957 2572 } … … 2004 2619 return VINF_SUCCESS; 2005 2620 #endif 2006 }2007 2008 2009 /**2010 * Unlinks all siblings.2011 *2012 * This is used during record deletion and assumes no races.2013 *2014 * @param pCore One of the siblings.2015 */2016 static void rtLockValidatorUnlinkAllSiblings(PRTLOCKVALRECCORE pCore)2017 {2018 /* ASSUMES sibling destruction doesn't involve any races and that all2019 related records are to be disposed off now. */2020 PRTLOCKVALRECUNION pSibling = (PRTLOCKVALRECUNION)pCore;2021 while (pSibling)2022 {2023 PRTLOCKVALRECUNION volatile *ppCoreNext;2024 switch (pSibling->Core.u32Magic)2025 {2026 case RTLOCKVALRECEXCL_MAGIC:2027 case RTLOCKVALRECEXCL_MAGIC_DEAD:2028 ppCoreNext = &pSibling->Excl.pSibling;2029 break;2030 2031 case RTLOCKVALRECSHRD_MAGIC:2032 case RTLOCKVALRECSHRD_MAGIC_DEAD:2033 ppCoreNext = &pSibling->Shared.pSibling;2034 break;2035 2036 default:2037 AssertFailed();2038 ppCoreNext = NULL;2039 break;2040 }2041 if (RT_UNLIKELY(ppCoreNext))2042 break;2043 pSibling = (PRTLOCKVALRECUNION)ASMAtomicXchgPtr((void * volatile *)ppCoreNext, NULL);2044 }2045 }2046 2047 2048 RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1, PRTLOCKVALRECCORE pRec2)2049 {2050 /*2051 * Validate input.2052 */2053 PRTLOCKVALRECUNION p1 = (PRTLOCKVALRECUNION)pRec1;2054 PRTLOCKVALRECUNION p2 = (PRTLOCKVALRECUNION)pRec2;2055 2056 AssertPtrReturn(p1, VERR_SEM_LV_INVALID_PARAMETER);2057 AssertReturn( p1->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC2058 || p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC2059 , VERR_SEM_LV_INVALID_PARAMETER);2060 2061 AssertPtrReturn(p2, VERR_SEM_LV_INVALID_PARAMETER);2062 AssertReturn( p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC2063 || p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC2064 , VERR_SEM_LV_INVALID_PARAMETER);2065 2066 /*2067 * Link them (circular list).2068 */2069 if ( p1->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC2070 && p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)2071 {2072 p1->Excl.pSibling = p2;2073 p2->Shared.pSibling = p1;2074 }2075 else if ( p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC2076 && p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC)2077 {2078 p1->Shared.pSibling = p2;2079 p2->Excl.pSibling = p1;2080 }2081 else2082 AssertFailedReturn(VERR_SEM_LV_INVALID_PARAMETER); /* unsupported mix */2083 2084 return VINF_SUCCESS;2085 }2086 2087 2088 /**2089 * Gets the lock name for the given record.2090 *2091 * @returns Read-only lock name.2092 * @param pRec The lock record.2093 */2094 DECL_FORCE_INLINE(const char *) rtLockValidatorRecName(PRTLOCKVALRECUNION pRec)2095 {2096 switch (pRec->Core.u32Magic)2097 {2098 case RTLOCKVALRECEXCL_MAGIC:2099 return pRec->Excl.pszName;2100 case RTLOCKVALRECSHRD_MAGIC:2101 return pRec->Shared.pszName;2102 case RTLOCKVALRECSHRDOWN_MAGIC:2103 return pRec->ShrdOwner.pSharedRec ? pRec->ShrdOwner.pSharedRec->pszName : "orphaned";2104 case RTLOCKVALRECNEST_MAGIC:2105 pRec = rtLockValidatorReadRecUnionPtr(&pRec->Nest.pRec);2106 if (VALID_PTR(pRec))2107 {2108 switch (pRec->Core.u32Magic)2109 {2110 case RTLOCKVALRECEXCL_MAGIC:2111 return pRec->Excl.pszName;2112 case RTLOCKVALRECSHRD_MAGIC:2113 return pRec->Shared.pszName;2114 case RTLOCKVALRECSHRDOWN_MAGIC:2115 return pRec->ShrdOwner.pSharedRec ? pRec->ShrdOwner.pSharedRec->pszName : "orphaned";2116 default:2117 return "unknown-nested";2118 }2119 }2120 return "orphaned-nested";2121 default:2122 return "unknown";2123 }2124 2621 } 2125 2622 … … 2205 2702 AssertReturnVoid(hThreadSelf != NIL_RTTHREAD); 2206 2703 } 2704 AssertReturnVoid(hThreadSelf->u32Magic == RTTHREADINT_MAGIC); 2207 2705 Assert(hThreadSelf == RTThreadSelf()); 2208 2706 … … 2257 2755 PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec; 2258 2756 AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 2259 if (pRecU->Excl.fEnabled) 2260 rtLockValidatorRecExclReleaseOwnerUnchecked(pRecU, fFinalRecursion); 2757 if (!pRecU->Excl.fEnabled) 2758 return VINF_SUCCESS; 2759 2760 /* 2761 * Check the release order. 2762 */ 2763 if ( pRecU->Excl.hClass != NIL_RTLOCKVALCLASS 2764 && pRecU->Excl.hClass->fStrictReleaseOrder 2765 && pRecU->Excl.hClass->cMsMinOrder != RT_INDEFINITE_WAIT 2766 ) 2767 { 2768 int rc = rtLockValidatorStackCheckReleaseOrder(pRecU->Excl.hThread, pRecU); 2769 if (RT_FAILURE(rc)) 2770 return rc; 2771 } 2772 2773 /* 2774 * Join paths with RTLockValidatorRecExclReleaseOwnerUnchecked. 2775 */ 2776 rtLockValidatorRecExclReleaseOwnerUnchecked(pRecU, fFinalRecursion); 2261 2777 return VINF_SUCCESS; 2262 2778 } … … 2366 2882 PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec; 2367 2883 AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 2368 if ( 2369 || 2370 || 2371 || 2884 if ( !pRecU->Excl.fEnabled 2885 || pRecU->Excl.hClass == NIL_RTLOCKVALCLASS 2886 || pRecU->Excl.hClass->cMsMinOrder == RT_INDEFINITE_WAIT 2887 || pRecU->Excl.hClass->cMsMinOrder > cMillies) 2372 2888 return VINF_SUCCESS; 2373 2889 2374 return rtLockValidatorCheckOrderOnRequest(pRecU->Excl.hClass, pRecU->Excl.uSubClass, hThreadSelf, pRecU, pSrcPos); 2890 if (hThreadSelf == NIL_RTTHREAD) 2891 { 2892 hThreadSelf = RTThreadSelfAutoAdopt(); 2893 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR); 2894 } 2895 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 2896 Assert(hThreadSelf == RTThreadSelf()); 2897 2898 return rtLockValidatorStackCheckLockingOrder(pRecU->Excl.hClass, pRecU->Excl.uSubClass, hThreadSelf, pRecU, pSrcPos); 2375 2899 } 2376 2900 … … 2568 3092 2569 3093 2570 RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies) 3094 RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, 3095 PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies) 2571 3096 { 2572 3097 PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec; … … 2578 3103 ) 2579 3104 return VINF_SUCCESS; 2580 Assert(hThreadSelf == NIL_RTTHREAD || hThreadSelf == RTThreadSelf()); 2581 2582 return rtLockValidatorCheckOrderOnRequest(pRecU->Shared.hClass, pRecU->Shared.uSubClass, hThreadSelf, pRecU, pSrcPos); 3105 3106 if (hThreadSelf == NIL_RTTHREAD) 3107 { 3108 hThreadSelf = RTThreadSelfAutoAdopt(); 3109 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR); 3110 } 3111 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 3112 Assert(hThreadSelf == RTThreadSelf()); 3113 3114 return rtLockValidatorStackCheckLockingOrder(pRecU->Shared.hClass, pRecU->Shared.uSubClass, hThreadSelf, pRecU, pSrcPos); 2583 3115 } 2584 3116 … … 2988 3520 AssertReturnVoid(hThread != NIL_RTTHREAD); 2989 3521 } 2990 AssertReturnVoid(hThread != NIL_RTTHREAD);2991 3522 AssertReturnVoid(hThread->u32Magic == RTTHREADINT_MAGIC); 2992 3523 … … 3065 3596 { 3066 3597 hThreadSelf = RTThreadSelfAutoAdopt(); 3067 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_IN VALID_PARAMETER);3598 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR); 3068 3599 } 3069 3600 Assert(hThreadSelf == RTThreadSelf()); 3601 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 3070 3602 3071 3603 /* … … 3085 3617 */ 3086 3618 if ( pRec->hClass != NIL_RTLOCKVALCLASS 3087 && pRec->hClass->cMsMinOrder != RT_INDEFINITE_WAIT) 3088 { 3089 int rc = rtLockValidatorCheckOrderOnRelease(pRec->hClass, pRec->uSubClass, 3090 hThreadSelf, (PRTLOCKVALRECUNION)pEntry); 3619 && pRec->hClass->fStrictReleaseOrder 3620 && pRec->hClass->cMsMinOrder != RT_INDEFINITE_WAIT 3621 ) 3622 { 3623 int rc = rtLockValidatorStackCheckReleaseOrder(hThreadSelf, (PRTLOCKVALRECUNION)pEntry); 3091 3624 if (RT_FAILURE(rc)) 3092 3625 return rc; … … 3118 3651 { 3119 3652 hThreadSelf = RTThreadSelfAutoAdopt(); 3120 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_IN VALID_PARAMETER);3653 AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR); 3121 3654 } 3122 3655 Assert(hThreadSelf == RTThreadSelf()); 3656 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 3123 3657 3124 3658 /*
Note:
See TracChangeset
for help on using the changeset viewer.