VirtualBox

Changeset 25626 in vbox


Ignore:
Timestamp:
Jan 3, 2010 3:24:13 PM (15 years ago)
Author:
vboxsync
Message:

tstRTLockValidator: Added a simple mutex deadlock to the testcase.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp

    r25623 r25626  
    5757static RTCRITSECT           g_aCritSects[32];
    5858static RTSEMRW              g_ahSemRWs[32];
     59static RTSEMMUTEX           g_ahSemMtxes[32];
    5960
    6061/** When to stop testing. */
     
    103104        if (RTSemRWGetReadCount(hSemRW) > 0)
    104105            return true;
     106        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
     107        iLoop++;
     108    }
     109    return true;
     110}
     111
     112
     113/**
     114 * Spin until someone else has taken ownership of the mutex semaphore.
     115 *
     116 * @returns true on success, false on abort.
     117 * @param   hSemMutex   The mutex sempahore.
     118 */
     119static bool testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex)
     120{
     121    unsigned iLoop = 0;
     122    while (!RTSemMutexIsOwned(hSemMutex))
     123    {
    105124        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
    106125        iLoop++;
     
    169188                    case RTTHREADSTATE_RW_WRITE:
    170189                    case RTTHREADSTATE_RW_READ:     pvLock = g_ahSemRWs[j]; break;
     190                    case RTTHREADSTATE_MUTEX:       pvLock = g_ahSemMtxes[j]; break;
    171191                    default: break;
    172192                }
     
    228248
    229249
     250static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)
     251{
     252    if (cSecs)
     253        RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);
     254    else
     255        RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
     256
     257    RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
     258    RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads);
     259
     260    g_cThreads = cThreads;
     261
     262    for (uint32_t i = 0; i < cThreads; i++)
     263    {
     264        RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
     265        RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS);
     266        RTTEST_CHECK_RC_RETV(g_hTest, RTSemMutexCreate(&g_ahSemMtxes[i]), VINF_SUCCESS);
     267    }
     268
     269    uint32_t cLoops     = 0;
     270    uint32_t cDeadlocks = 0;
     271    uint32_t cErrors    = RTTestErrorCount(g_hTest);
     272    for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
     273    {
     274        g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
     275        g_cLoops          = 0;
     276        g_cDeadlocks      = 0;
     277        g_NanoTSStop      = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
     278
     279        int rc = testStartThreads(cThreads, pfnThread);
     280        if (RT_SUCCESS(rc))
     281            testWaitForThreads(30*1000 + cSecs*1000, true);
     282
     283        RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
     284        cLoops += g_cLoops;
     285        RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
     286        cDeadlocks += g_cDeadlocks;
     287    }
     288
     289    for (uint32_t i = 0; i < cThreads; i++)
     290    {
     291        RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
     292        RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS);
     293        RTTEST_CHECK_RC(g_hTest, RTSemMutexDestroy(g_ahSemMtxes[i]), VINF_SUCCESS);
     294    }
     295    testWaitForThreads(10*1000, false);
     296
     297    if (cSecs)
     298        RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
     299                     cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
     300}
     301
     302
    230303static DECLCALLBACK(int) test1Thread(RTTHREAD ThreadSelf, void *pvUser)
    231304{
     
    256329    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS);
    257330    return VINF_SUCCESS;
     331}
     332
     333
     334static void test1(uint32_t cThreads, uint32_t cPasses)
     335{
     336    testIt(cThreads, cPasses, 0, test1Thread, "critsect");
    258337}
    259338
     
    303382    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    304383    return VINF_SUCCESS;
     384}
     385
     386
     387static void test2(uint32_t cThreads, uint32_t cPasses)
     388{
     389    testIt(cThreads, cPasses, 0, test2Thread, "read-write");
    305390}
    306391
     
    344429    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    345430    return VINF_SUCCESS;
     431}
     432
     433
     434static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
     435{
     436    testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
    346437}
    347438
     
    397488
    398489
    399 static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)
    400 {
    401     if (cSecs)
    402         RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);
    403     else
    404         RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
    405 
    406     RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
    407     RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads);
    408 
    409     g_cThreads = cThreads;
    410 
    411     for (uint32_t i = 0; i < cThreads; i++)
    412     {
    413         RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
    414         RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS);
    415     }
    416 
    417     uint32_t cLoops     = 0;
    418     uint32_t cDeadlocks = 0;
    419     uint32_t cErrors    = RTTestErrorCount(g_hTest);
    420     for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
    421     {
    422         g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
    423         g_cLoops          = 0;
    424         g_cDeadlocks      = 0;
    425         g_NanoTSStop      = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
    426 
    427         int rc = testStartThreads(cThreads, pfnThread);
     490static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
     491{
     492    testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
     493}
     494
     495
     496static DECLCALLBACK(int) test5Thread(RTTHREAD ThreadSelf, void *pvUser)
     497{
     498    uintptr_t       i     = (uintptr_t)pvUser;
     499    RTSEMMUTEX      hMine = g_ahSemMtxes[i];
     500    RTSEMMUTEX      hNext = g_ahSemMtxes[(i + 1) % g_cThreads];
     501
     502    RTTEST_CHECK_RC_RET(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
     503    if (i & 1)
     504        RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS);
     505    if (testWaitForSemMutexToBeOwned(hNext))
     506    {
     507        int rc;
     508        if (i != g_iDeadlockThread)
     509            RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
     510        else
     511        {
     512            RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_MUTEX, 1));
     513            if (RT_SUCCESS(rc))
     514                RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_DEADLOCK);
     515        }
     516        RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    428517        if (RT_SUCCESS(rc))
    429             testWaitForThreads(30*1000 + cSecs*1000, true);
    430 
    431         RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
    432         cLoops += g_cLoops;
    433         RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
    434         cDeadlocks += g_cDeadlocks;
    435     }
    436 
    437     for (uint32_t i = 0; i < cThreads; i++)
    438     {
    439         RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
    440         RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS);
    441     }
    442     testWaitForThreads(10*1000, false);
    443 
    444     if (cSecs)
    445         RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
    446                      cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
    447 }
    448 
    449 
    450 static void test1(uint32_t cThreads, uint32_t cPasses)
    451 {
    452     testIt(cThreads, cPasses, 0, test1Thread, "critsect");
    453 }
    454 
    455 
    456 static void test2(uint32_t cThreads, uint32_t cPasses)
    457 {
    458     testIt(cThreads, cPasses, 0, test2Thread, "read-write");
    459 }
    460 
    461 
    462 static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
    463 {
    464     testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
    465 }
    466 
    467 
    468 static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
    469 {
    470     testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
     518            RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRelease(hNext), VINF_SUCCESS);
     519    }
     520    if (i & 1)
     521        RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(hMine), VINF_SUCCESS);
     522    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(hMine), VINF_SUCCESS);
     523    return VINF_SUCCESS;
     524}
     525
     526
     527static void test5(uint32_t cThreads, uint32_t cPasses)
     528{
     529    testIt(cThreads, cPasses, 0, test5Thread, "mutex");
    471530}
    472531
     
    518577     * Some initial tests with verbose output.
    519578     */
     579#if 0
    520580    test1(3, 1);
    521581    test2(1, 1);
    522582    test2(3, 1);
     583#endif
     584    test5(3, 1);
    523585
    524586    /*
     
    526588     */
    527589    RTLockValidatorSetQuiet(true);
    528 
     590#if 0
    529591    test1( 2, 256);                     /* 256 * 4ms = 1s (approx); 4ms == fudge factor */
    530592    test1( 3, 256);
     
    549611    test4(10,  1, 10);
    550612    test4(30,  1, 10);
     613#endif
     614
     615    test5( 2, 256);
     616    test5( 3, 256);
     617    test5( 7, 256);
     618    test5(10, 256);
     619    test5(15, 256);
     620    test5(30, 256);
    551621
    552622    return RTTestSummaryAndDestroy(g_hTest);
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