VirtualBox

Changeset 25692 in vbox


Ignore:
Timestamp:
Jan 8, 2010 3:59:45 PM (15 years ago)
Author:
vboxsync
Message:

iprt/lockvalidator: Implemented order validatation and the autodidactic class code.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/err.h

    r25638 r25692  
    862862/** The thread is not a valid signaller of the event. */
    863863#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)
    864866/** @} */
    865867
  • trunk/include/iprt/lockvalidator.h

    r25685 r25692  
    730730 *                              user will teach it all it needs to know (false).
    731731 * @param   fRecursionOk        Whether to allow lock recursion or not.
     732 * @param   fStrictReleaseOrder Enforce strict lock release order or not.
    732733 * @param   cMsMinDeadlock      Used to raise the sleep interval at which
    733734 *                              deadlock detection kicks in.  Minimum is 1 ms,
     
    741742 */
    742743RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
    743                                          bool fAutodidact, bool fRecursionOk,
     744                                         bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
    744745                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder);
    745746
  • trunk/include/iprt/types.h

    r25685 r25692  
    14971497/** @name   Special sub-class values.
    14981498 * 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.
    15001501 * @{ */
    15011502/** Not allowed to be taken with any other locks in the same class.
  • trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp

    r25690 r25692  
    140140    /** Whether to allow recursion. */
    141141    bool                    fRecursionOk;
    142     /** Reserved. */
    143     bool                    fReserved;
     142    /** Strict release order. */
     143    bool                    fStrictReleaseOrder;
    144144    /** Whether this class is in the tree. */
    145145    bool                    fInTree;
     
    372372
    373373/**
     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 */
     382static void rtLockValComplainAboutClass(const char *pszPrefix, RTLOCKVALCLASSINT *pClass, uint32_t uSubClass, bool fVerbose)
     383{
     384
     385}
     386
     387
     388/**
    374389 * Helper for rtLockValComplainAboutLock.
    375390 */
     
    497512 * @param   cMinFrames          The minimum number of frames to consider
    498513 *                              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 */
     517static void rtLockValComplainAboutLockStack(PRTTHREADINT pThread, unsigned cchIndent, uint32_t cMinFrames,
     518                                            PRTLOCKVALRECUNION pHighightRec)
    501519{
    502520    if (    VALID_PTR(pThread)
     
    515533                char szPrefix[80];
    516534                RTStrPrintf(szPrefix, sizeof(szPrefix), "%*s#%02u: ", cchIndent, "", i);
    517                 rtLockValComplainAboutLock(szPrefix, pCur, "\n");
     535                rtLockValComplainAboutLock(szPrefix, pCur, pHighightRec != pCur ? "\n" : " (*)\n");
    518536                switch (pCur->Core.u32Magic)
    519537                {
     
    552570            RTAssertMsg2Weak("%s  [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>");
    553571        rtLockValComplainAboutLock("Lock: ", pRec, "\n");
    554         rtLockValComplainAboutLockStack(pThreadSelf, 0, 1);
     572        rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec);
    555573    }
    556574}
     
    804822
    805823RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
    806                                          bool fAutodidact, bool fRecursionOk,
     824                                         bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
    807825                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder)
    808826{
     
    826844    pThis->fAutodidact          = fAutodidact;
    827845    pThis->fRecursionOk         = fRecursionOk;
    828     pThis->fReserved            = false;
     846    pThis->fStrictReleaseOrder  = fStrictReleaseOrder;
    829847    pThis->fInTree              = false;
    830848    pThis->cMsMinDeadlock       = cMsMinDeadlock;
     
    860878    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_POS_NO_ID();
    861879    return RTLockValidatorClassCreateEx(phClass, &SrcPos,
    862                                         fAutodidact, true /*fRecursionOk*/,
     880                                        fAutodidact, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
    863881                                        1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
    864882}
     
    980998         */
    981999        int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos,
    982                                               true /*fAutodidact*/, true /*fRecursionOk*/,
     1000                                              true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
    9831001                                              1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
    9841002        if (RT_SUCCESS(rc))
     
    10951113 * @param   fAutodidacticism    Whether we're teaching ourselfs (true) or
    10961114 *                              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 */
     1117static int rtLockValidatorClassAddPriorClass(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass,
     1118                                             bool fAutodidacticism, PCRTLOCKVALSRCPOS pSrcPos)
    10991119{
    11001120    if (!RTCritSectIsInitialized(&g_LockValClassTeachCS))
     
    11051125     * Check that there are no conflict (no assert since we might race each other).
    11061126     */
    1107     int rc = VERR_INTERNAL_ERROR_5;
     1127    int rc = VERR_SEM_LV_INTERNAL_ERROR;
    11081128    if (!rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
    11091129    {
     
    11801200    AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE);
    11811201
    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 */
     1213static 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
     1245RTDECL(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 */
     1291DECL_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 */
     1330DECLINLINE(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 */
     1392DECL_FORCE_INLINE(RTLOCKVALCLASSINT *)
     1393rtLockValidatorRecGetClassesAndDown(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 */
     1471DECLINLINE(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
    11841524
    11851525
     
    15241864
    15251865
    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 */
     1870static 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 */
     1896DECL_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 */
     1924DECL_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 */
     1943static 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
    15302071    return VINF_SUCCESS;
    15312072}
    15322073
    15332074
    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 */
     2086static 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 */
     2139static 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;
    15392154}
    15402155
     
    19412556            char szPrefix[24];
    19422557            RTStrPrintf(szPrefix, sizeof(szPrefix), "#%02u: ", i);
    1943             PRTLOCKVALRECSHRDOWN pShrdOwner = NULL;
     2558            PRTLOCKVALRECUNION pShrdOwner = NULL;
    19442559            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];
    19462561            if (VALID_PTR(pShrdOwner) && pShrdOwner->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC)
    19472562            {
    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);
    19502565            }
    19512566            else
    19522567            {
    19532568                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);
    19562571            }
    19572572        }
     
    20042619    return VINF_SUCCESS;
    20052620#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 all
    2019        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_MAGIC
    2058                  || p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC
    2059                  , VERR_SEM_LV_INVALID_PARAMETER);
    2060 
    2061     AssertPtrReturn(p2, VERR_SEM_LV_INVALID_PARAMETER);
    2062     AssertReturn(   p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC
    2063                  || p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC
    2064                  , VERR_SEM_LV_INVALID_PARAMETER);
    2065 
    2066     /*
    2067      * Link them (circular list).
    2068      */
    2069     if (    p1->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC
    2070         &&  p2->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC)
    2071     {
    2072         p1->Excl.pSibling   = p2;
    2073         p2->Shared.pSibling = p1;
    2074     }
    2075     else if (   p1->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC
    2076              && p2->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC)
    2077     {
    2078         p1->Shared.pSibling = p2;
    2079         p2->Excl.pSibling   = p1;
    2080     }
    2081     else
    2082         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     }
    21242621}
    21252622
     
    22052702        AssertReturnVoid(hThreadSelf != NIL_RTTHREAD);
    22062703    }
     2704    AssertReturnVoid(hThreadSelf->u32Magic == RTTHREADINT_MAGIC);
    22072705    Assert(hThreadSelf == RTThreadSelf());
    22082706
     
    22572755    PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec;
    22582756    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);
    22612777    return VINF_SUCCESS;
    22622778}
     
    23662882    PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec;
    23672883    AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    2368     if (    !pRecU->Excl.fEnabled
    2369         ||  pRecU->Excl.hClass == NIL_RTLOCKVALCLASS
    2370         ||  pRecU->Excl.hClass->cMsMinOrder == RT_INDEFINITE_WAIT
    2371         ||  pRecU->Excl.hClass->cMsMinOrder > cMillies)
     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)
    23722888        return VINF_SUCCESS;
    23732889
    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);
    23752899}
    23762900
     
    25683092
    25693093
    2570 RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies)
     3094RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
     3095                                               PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies)
    25713096{
    25723097    PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec;
     
    25783103        )
    25793104        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);
    25833115}
    25843116
     
    29883520        AssertReturnVoid(hThread != NIL_RTTHREAD);
    29893521    }
    2990     AssertReturnVoid(hThread != NIL_RTTHREAD);
    29913522    AssertReturnVoid(hThread->u32Magic == RTTHREADINT_MAGIC);
    29923523
     
    30653596    {
    30663597        hThreadSelf = RTThreadSelfAutoAdopt();
    3067         AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER);
     3598        AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR);
    30683599    }
    30693600    Assert(hThreadSelf == RTThreadSelf());
     3601    AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    30703602
    30713603    /*
     
    30853617     */
    30863618    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);
    30913624        if (RT_FAILURE(rc))
    30923625            return rc;
     
    31183651    {
    31193652        hThreadSelf = RTThreadSelfAutoAdopt();
    3120         AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER);
     3653        AssertReturn(hThreadSelf != NIL_RTTHREAD, VERR_SEM_LV_INTERNAL_ERROR);
    31213654    }
    31223655    Assert(hThreadSelf == RTThreadSelf());
     3656    AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    31233657
    31243658    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette