Changeset 25703 in vbox
- Timestamp:
- Jan 10, 2010 4:49:14 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56438
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/lockvalidator.h
r25700 r25703 822 822 * Releases a reference to a lock validator class. 823 823 * 824 * @returns New reference count; UINT32_MAX if the handle is invalid. 824 * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX 825 * if the handle is invalid. 825 826 * @param hClass Handle to the class. 826 827 */ … … 840 841 841 842 /** 843 * Enables or disables the strict release order enforcing. 844 * 845 * @returns IPRT status. 846 * @param hClass Handle to the class to change. 847 * @param fEnable Enable it (true) or disable it (false). 848 */ 849 RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled); 850 851 /** 842 852 * Enables / disables the lock validator for new locks. 843 853 * … … 867 877 * @returns True if it is quiet, false if noisy. 868 878 */ 869 RTDECL(bool) RTLockValidator AreQuiet(void);879 RTDECL(bool) RTLockValidatorIsQuiet(void); 870 880 871 881 /** -
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25701 r25703 62 62 /** Hashes the class handle (pointer) into an apPriorLocksHash index. */ 63 63 #define RTLOCKVALCLASS_HASH(hClass) \ 64 ( ( uintptr_t)(hClass) \64 ( ((uintptr_t)(hClass) >> 6 ) \ 65 65 % ( RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \ 66 66 / sizeof(PRTLOCKVALCLASSREF)) ) … … 202 202 RTLOCKVALCLASSREFCHUNK PriorLocks; 203 203 /** Hash table containing frequently encountered prior locks. */ 204 PRTLOCKVALCLASSREF apPriorLocksHash[11]; 204 PRTLOCKVALCLASSREF apPriorLocksHash[17]; 205 /** Class name. (Allocated after the end of the block as usual.) */ 206 char const *pszName; 207 /** Where this class was created. 208 * This is mainly used for finding automatically created lock classes. 209 * @remarks The strings are stored after this structure so we won't crash 210 * if the class lives longer than the module (dll/so/dylib) that 211 * spawned it. */ 212 RTLOCKVALSRCPOS CreatePos; 205 213 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 206 214 /** Hash hits. */ … … 209 217 uint32_t volatile cHashMisses; 210 218 #endif 211 /** Where this class was created.212 * This is mainly used for finding automatically created lock classes.213 * @remarks The strings are stored after this structure so we won't crash214 * if the class lives longer than the module (dll/so/dylib) that215 * spawned it. */216 RTLOCKVALSRCPOS CreatePos;217 /** Class name. (Allocated after the end of the block as usual.) */218 char const *pszName;219 219 } RTLOCKVALCLASSINT; 220 220 AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32); … … 251 251 #endif 252 252 /** Serializing class tree insert and lookups. */ 253 static RTSEMRW g_hLockValClassTreeRWLock 253 static RTSEMRW g_hLockValClassTreeRWLock= NIL_RTSEMRW; 254 254 /** Class tree. */ 255 static PAVLLU32NODECORE g_LockValClassTree = NULL;255 static PAVLLU32NODECORE g_LockValClassTree = NULL; 256 256 /** Critical section serializing the teaching new rules to the classes. */ 257 257 static RTCRITSECT g_LockValClassTeachCS; … … 1006 1006 for (unsigned i = 0; i < RT_ELEMENTS(pThis->apPriorLocksHash); i++) 1007 1007 pThis->apPriorLocksHash[i] = NULL; 1008 char *pszDst = (char *)(pThis + 1); 1009 pThis->pszName = (char *)memcpy(pszDst, szName, cbName); 1010 pszDst += cbName; 1008 1011 rtLockValidatorSrcPosCopy(&pThis->CreatePos, pSrcPos); 1009 char *pszDst = (char *)(pThis + 1);1010 1012 pThis->CreatePos.pszFile = pSrcPos->pszFile ? (char *)memcpy(pszDst, pSrcPos->pszFile, cbFile) : NULL; 1011 1013 pszDst += cbFile; 1012 1014 pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL; 1013 pszDst += cbFunction;1014 1015 Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key); 1015 pThis->pszName = (char *)memcpy(pszDst, szName, cbName); 1016 #ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS 1017 pThis->cHashHits = 0; 1018 pThis->cHashMisses = 0; 1019 #endif 1016 1020 1017 1021 *phClass = pThis; … … 1084 1088 static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass) 1085 1089 { 1086 AssertReturnVoid( pClass->fInTree);1090 AssertReturnVoid(!pClass->fInTree); 1087 1091 ASMAtomicWriteU32(&pClass->u32Magic, RTLOCKVALCLASS_MAGIC_DEAD); 1088 1092 … … 1104 1108 if (pChunk != &pClass->PriorLocks) 1105 1109 RTMemFree(pChunk); 1106 p Next = pChunk;1110 pChunk = pNext; 1107 1111 } 1108 1112 … … 1122 1126 { 1123 1127 if (rtLockValidatorSrcPosCompare(&pClass->CreatePos, pSrcPos) == 0) 1124 {1125 rtLockValidatorClassRetain(pClass);1126 1128 break; 1127 }1128 1129 pClass = (RTLOCKVALCLASSINT *)pClass->Core.pList; 1129 1130 } … … 1179 1180 { 1180 1181 RTLOCKVALCLASSINT *pClass = hClass; 1182 if (pClass == NIL_RTLOCKVALCLASS) 1183 return 0; 1181 1184 AssertPtrReturn(pClass, UINT32_MAX); 1182 1185 AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, UINT32_MAX); … … 1349 1352 1350 1353 return rtLockValidatorClassAddPriorClass(pClass, pPriorClass, false /*fAutodidacticism*/, NULL); 1354 } 1355 1356 1357 RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled) 1358 { 1359 RTLOCKVALCLASSINT *pClass = hClass; 1360 AssertPtrReturn(pClass, VERR_INVALID_HANDLE); 1361 AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE); 1362 1363 ASMAtomicWriteBool(&pClass->fStrictReleaseOrder, fEnabled); 1364 return VINF_SUCCESS; 1351 1365 } 1352 1366 … … 2076 2090 * Something went wrong, pCur is pointing to where. 2077 2091 */ 2078 if (rtLockValidatorClassIsPriorClass(pFirstBadClass, pClass)) 2092 if ( pClass == pFirstBadClass 2093 || rtLockValidatorClassIsPriorClass(pFirstBadClass, pClass)) 2079 2094 return rtLockValidatorStackWrongOrder("Wrong locking order!", pSrcPos, pThreadSelf, 2080 2095 pRec, pFirstBadRec, pClass, pFirstBadClass); … … 2285 2300 || ( pTop 2286 2301 && pTop->Core.u32Magic == RTLOCKVALRECNEST_MAGIC 2287 && pTop->Nest.pRec == pRec) ))2302 && pTop->Nest.pRec == pRec) )) 2288 2303 return VINF_SUCCESS; 2304 2305 #ifdef RTLOCKVAL_WITH_RECURSION_RECORDS 2306 /* Look for a recursion record so the right frame is dumped and marked. */ 2307 while (pTop) 2308 { 2309 if (pTop->Core.u32Magic == RTLOCKVALRECNEST_MAGIC) 2310 { 2311 if (pTop->Nest.pRec == pRec) 2312 { 2313 pRec = pTop; 2314 break; 2315 } 2316 pTop = pTop->Nest.pDown; 2317 } 2318 else if (pTop->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC) 2319 pTop = pTop->Excl.pDown; 2320 else if (pTop->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC) 2321 pTop = pTop->ShrdOwner.pDown; 2322 else 2323 break; 2324 } 2325 #endif 2289 2326 2290 2327 rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec, true); 2291 2328 rtLockValComplainPanic(); 2292 return VERR_SEM_LV_WRONG_ ORDER;2329 return VERR_SEM_LV_WRONG_RELEASE_ORDER; 2293 2330 } 2294 2331 … … 2810 2847 ASMAtomicWriteU32(&pRec->Core.u32Magic, RTLOCKVALRECEXCL_MAGIC_DEAD); 2811 2848 ASMAtomicWriteHandle(&pRec->hThread, NIL_RTTHREAD); 2812 ASMAtomicWriteHandle(&pRec->hClass, NIL_RTLOCKVALCLASS); 2849 RTLOCKVALCLASS hClass; 2850 ASMAtomicXchgHandle(&pRec->hClass, NIL_RTLOCKVALCLASS, &hClass); 2813 2851 if (pRec->pSibling) 2814 2852 rtLockValidatorUnlinkAllSiblings(&pRec->Core); 2815 2853 rtLockValidatorSerializeDestructLeave(); 2854 if (hClass != NIL_RTLOCKVALCLASS) 2855 RTLockValidatorClassRelease(hClass); 2816 2856 } 2817 2857 … … 3019 3059 PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies) 3020 3060 { 3061 /* 3062 * Validate and adjust input. Quit early if order validation is disabled. 3063 */ 3021 3064 PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec; 3022 3065 AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); … … 3034 3077 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 3035 3078 Assert(hThreadSelf == RTThreadSelf()); 3079 3080 /* 3081 * Detect recursion as it isn't subject to order restrictions. 3082 */ 3083 if (pRec->hThread == hThreadSelf) 3084 return VINF_SUCCESS; 3036 3085 3037 3086 return rtLockValidatorStackCheckLockingOrder(pRecU->Excl.hClass, pRecU->Excl.uSubClass, hThreadSelf, pRecU, pSrcPos); … … 3234 3283 PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies) 3235 3284 { 3285 /* 3286 * Validate and adjust input. Quit early if order validation is disabled. 3287 */ 3236 3288 PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec; 3237 3289 AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); … … 3250 3302 AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 3251 3303 Assert(hThreadSelf == RTThreadSelf()); 3304 3305 /* 3306 * Detect recursion as it isn't subject to order restrictions. 3307 */ 3308 PRTLOCKVALRECUNION pEntry = rtLockValidatorRecSharedFindOwner(&pRecU->Shared, hThreadSelf, NULL); 3309 if (pEntry) 3310 return VINF_SUCCESS; 3252 3311 3253 3312 return rtLockValidatorStackCheckLockingOrder(pRecU->Shared.hClass, pRecU->Shared.uSubClass, hThreadSelf, pRecU, pSrcPos); … … 3960 4019 3961 4020 3962 RTDECL(bool) RTLockValidator AreQuiet(void)4021 RTDECL(bool) RTLockValidatorIsQuiet(void) 3963 4022 { 3964 4023 return ASMAtomicUoReadBool(&g_fLockValidatorQuiet); 3965 4024 } 3966 RT_EXPORT_SYMBOL(RTLockValidator AreQuiet);4025 RT_EXPORT_SYMBOL(RTLockValidatorIsQuiet); 3967 4026 3968 4027 -
trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
r25694 r25703 768 768 static void testLo1(void) 769 769 { 770 RTTestSub(g_hTest, "locking order, automatic"); 771 772 /* init, each critsect has its own class now. */ 770 RTTestSub(g_hTest, "locking order basics"); 771 772 /* Initialize the critsections, the first 4 has their own classes, the rest 773 use the same class and relies on the sub-class mechanism for ordering. */ 773 774 for (unsigned i = 0; i < RT_ELEMENTS(g_ahClasses); i++) 774 775 { 775 RTTEST_CHECK_RC_RETV(g_hTest, RTLockValidatorClassCreate(&g_ahClasses[i], true /*fAutodidact*/, RT_SRC_POS), VINF_SUCCESS); 776 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectLO"), VINF_SUCCESS); 777 RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 3); 778 RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 2); 776 if (i <= 3) 777 { 778 RTTEST_CHECK_RC_RETV(g_hTest, RTLockValidatorClassCreate(&g_ahClasses[i], true /*fAutodidact*/, RT_SRC_POS), VINF_SUCCESS); 779 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectLO-Auto"), VINF_SUCCESS); 780 RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 3); 781 RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 2); 782 } 783 else 784 { 785 g_ahClasses[i] = RTLockValidatorClassForSrcPos(RT_SRC_POS); 786 RTTEST_CHECK_RETV(g_hTest, g_ahClasses[i] != NIL_RTLOCKVALCLASS); 787 RTTEST_CHECK_RETV(g_hTest, i == 4 || g_ahClasses[i] == g_ahClasses[i - 1]); 788 if (i == 4) 789 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectLO-None"), VINF_SUCCESS); 790 else if (i == 5) 791 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_ANY, "RTCritSectLO-Any"), VINF_SUCCESS); 792 else 793 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_USER + i, "RTCritSectLO-User"), VINF_SUCCESS); 794 795 RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 1 + (i - 4 + 1) * 2); /* released in cleanup. */ 796 } 779 797 } 780 798 … … 807 825 808 826 /* Check that recursion isn't subject to order checks. */ 809 827 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS); 828 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS); 829 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS); 830 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS); 831 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS); 832 if (RT_SUCCESS(rc)) 833 { 834 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS); 835 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS); 836 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS); 837 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS); 838 839 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS); 840 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS); 841 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS); 842 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS); 843 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS); 844 } 845 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS); 846 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS); 847 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS); 848 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS); 810 849 811 850 /* Enable strict release order for class 2 and check that violations 812 851 are caught. */ 813 852 RTTEST_CHECK_RC(g_hTest, RTLockValidatorClassEnforceStrictReleaseOrder(g_ahClasses[2], true), VINF_SUCCESS); 853 854 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS); 855 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS); 856 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS); 857 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS); 858 859 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER); 860 if (RT_FAILURE(rc)) 861 { 862 /* applies to recursions as well */ 863 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS); 864 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS); 865 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER); 866 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS); 867 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS); 868 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER); 869 } 870 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS); 871 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS); 872 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS); 873 if (RT_FAILURE(rc)) 874 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS); 875 876 /* Test that sub-class order works (4 = NONE, 5 = ANY, 6+ = USER). */ 877 uint32_t cErrorsBefore = RTTestErrorCount(g_hTest); 878 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[7]), VINF_SUCCESS); 879 880 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[4]), VERR_SEM_LV_WRONG_ORDER); 881 if (RT_SUCCESS(rc)) 882 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[4]), VINF_SUCCESS); 883 884 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS); 885 if (RT_SUCCESS(rc)) 886 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS); 887 888 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[8]), VINF_SUCCESS); 889 if (RT_SUCCESS(rc)) 890 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[8]), VINF_SUCCESS); 891 892 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[6]), VERR_SEM_LV_WRONG_ORDER); 893 if (RT_SUCCESS(rc)) 894 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[6]), VINF_SUCCESS); 895 896 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[7]), VINF_SUCCESS); 897 if (RT_SUCCESS(rc)) 898 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[7]), VINF_SUCCESS); 899 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[7]), VINF_SUCCESS); 900 901 /* Check that NONE trumps both ANY and USER. */ 902 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[4]), VINF_SUCCESS); 903 904 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[5]), VERR_SEM_LV_WRONG_ORDER); 905 if (RT_SUCCESS(rc)) 906 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS); 907 908 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[6]), VERR_SEM_LV_WRONG_ORDER); 909 if (RT_SUCCESS(rc)) 910 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[6]), VINF_SUCCESS); 911 912 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[4]), VINF_SUCCESS); 913 914 /* Take all the locks using sub-classes. */ 915 if (cErrorsBefore == RTTestErrorCount(g_hTest)) 916 { 917 bool fSavedQuiet = RTLockValidatorSetQuiet(true); 918 for (uint32_t i = 6; i < RT_ELEMENTS(g_aCritSects); i++) 919 { 920 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[i]), VINF_SUCCESS); 921 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[4]), VERR_SEM_LV_WRONG_ORDER); 922 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS); 923 } 924 for (uint32_t i = 6; i < RT_ELEMENTS(g_aCritSects); i++) 925 { 926 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[i]), VINF_SUCCESS); 927 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS); 928 } 929 RTLockValidatorSetQuiet(fSavedQuiet); 930 } 931 932 /* Work up some hash statistics and trigger a violation to show them. */ 933 for (uint32_t i = 0; i < 10240; i++) 934 { 935 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS); 936 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS); 937 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS); 938 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS); 939 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS); 940 941 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS); 942 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS); 943 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS); 944 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS); 945 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS); 946 } 947 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS); 948 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VERR_SEM_LV_WRONG_ORDER); 949 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS); 814 950 815 951 /* clean up */ 816 952 for (unsigned i = 0; i < RT_ELEMENTS(g_ahClasses); i++) 817 953 { 818 RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 1); 954 if (i <= 3) 955 RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 1); 956 else 957 { 958 uint32_t cExpect = 1 + (RT_ELEMENTS(g_ahClasses) - i) * 2 - 1; 959 RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == cExpect); 960 } 819 961 g_ahClasses[i] = NIL_RTLOCKVALCLASS; 820 962 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
Note:
See TracChangeset
for help on using the changeset viewer.