VirtualBox

Changeset 25648 in vbox


Ignore:
Timestamp:
Jan 5, 2010 2:32:58 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56363
Message:

iprt: Instrumented semeventmulti-linux.cpp and hacked more on the validator and the testcase.

Location:
trunk/src/VBox/Runtime
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp

    r25645 r25648  
    12331233    rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
    12341234    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
     1235    pThreadSelf->LockValidator.enmRecState = enmSleepState;
    12351236    rtThreadSetState(pThreadSelf, enmSleepState);
    12361237
     
    12601261        ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping);
    12611262    else
     1263    {
    12621264        rtThreadSetState(pThreadSelf, enmThreadState);
     1265        rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL);
     1266    }
    12631267    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false);
    12641268    return rc;
     
    14341438    rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
    14351439    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
     1440    pThreadSelf->LockValidator.enmRecState = enmSleepState;
    14361441    rtThreadSetState(pThreadSelf, enmSleepState);
    14371442
     
    14611466        ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping);
    14621467    else
     1468    {
    14631469        rtThreadSetState(pThreadSelf, enmThreadState);
     1470        rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL);
     1471    }
    14641472    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false);
    14651473    return rc;
  • trunk/src/VBox/Runtime/common/misc/thread.cpp

    r25645 r25648  
    13341334        Assert(pThread == RTThreadSelf());
    13351335        ASMAtomicWriteBool(&pThread->fReallySleeping, false);
    1336         if (rtThreadGetState(pThread) == enmCurState)
     1336
     1337        RTTHREADSTATE enmActualState = rtThreadGetState(pThread);
     1338        if (enmActualState == enmCurState)
     1339        {
    13371340            rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
     1341            if (   pThread->LockValidator.pRec
     1342                && pThread->LockValidator.enmRecState == enmCurState)
     1343                ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
     1344        }
     1345        /* This is a bit ugly... :-/ */
     1346        else if (   (   enmActualState == RTTHREADSTATE_TERMINATED
     1347                     || enmActualState == RTTHREADSTATE_INITIALIZING)
     1348                 && pThread->LockValidator.pRec)
     1349            ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
     1350        Assert(   pThread->LockValidator.pRec == NULL
     1351               || RTTHREAD_IS_SLEEPING(enmActualState));
    13381352    }
    13391353}
  • trunk/src/VBox/Runtime/include/internal/lockvalidator.h

    r25638 r25648  
    5959    /** Where we are blocking. */
    6060    RTLOCKVALSRCPOS                 SrcPos;
    61     /** What we're blocking on. */
     61    /** What we're blocking on.
     62     * The lock validator sets this, RTThreadUnblock clears it. */
    6263    PRTLOCKVALRECUNION volatile     pRec;
     64    /** The state in which pRec that goes with pRec.
     65     * RTThreadUnblocking uses this to figure out when to clear pRec. */
     66    RTTHREADSTATE volatile          enmRecState;
     67    /** The thread is running inside the lock validator. */
     68    bool volatile                   fInValidator;
     69    /** Reserved for alignment purposes. */
     70    bool                            afReserved[3];
    6371    /** Number of registered write locks, mutexes and critsects that this thread owns. */
    6472    int32_t volatile                cWriteLocks;
    6573    /** Number of registered read locks that this thread owns, nesting included. */
    6674    int32_t volatile                cReadLocks;
    67     /** The thread is running inside the lock validator. */
    68     bool volatile                   fInValidator;
    69     /** Reserved for alignment purposes. */
    70     bool                            afReserved[3];
    7175    /** Bitmap indicating which entires are free (set) and allocated (clear). */
    7276    uint32_t volatile               bmFreeShrdOwners;
     77    /** Reserved for alignment purposes. */
     78    uint32_t                        u32Reserved;
    7379    /** Statically allocated shared owner records */
    7480    RTLOCKVALRECSHRDOWN             aShrdOwners[32];
  • trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp

    r25640 r25648  
    5252*******************************************************************************/
    5353#include <iprt/semaphore.h>
     54#include "internal/iprt.h"
     55
    5456#include <iprt/assert.h>
    55 #include <iprt/alloc.h>
    5657#include <iprt/asm.h>
    5758#include <iprt/err.h>
     59#include <iprt/lockvalidator.h>
     60#include <iprt/mem.h>
    5861#include <iprt/time.h>
    5962#include "internal/magics.h"
     63#include "internal/strict.h"
     64
    6065
    6166#include <errno.h>
     
    8287{
    8388    /** Magic value. */
    84     intptr_t volatile   iMagic;
     89    uint32_t volatile   u32Magic;
    8590    /** The futex state variable.
    8691     * -1 means signaled.
     
    8994     */
    9095    int32_t volatile    iState;
     96#ifdef RTSEMEVENTMULTI_STRICT
     97    /** Signallers. */
     98    RTLOCKVALRECSHRD    Signallers;
     99    /** Indicates that lock validation should be performed. */
     100    bool volatile       fEverHadSignallers;
     101#endif
    91102};
    92103
     
    116127    if (pThis)
    117128    {
    118         pThis->iMagic = RTSEMEVENTMULTI_MAGIC;
    119         pThis->iState = 0;
     129        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
     130        pThis->iState   = 0;
     131#ifdef RTSEMEVENTMULTI_STRICT
     132        RTLockValidatorRecSharedInit(&pThis->Signallers,
     133                                     NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY,
     134                                     "RTSemEventMulti", pThis, true /*fSignaller*/);
     135        pThis->fEverHadSignallers = false;
     136#endif
    120137        *pEventMultiSem = pThis;
    121138        return VINF_SUCCESS;
     
    131148     */
    132149    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    133     AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
     150    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
    134151                 VERR_INVALID_HANDLE);
    135152
     
    137154     * Invalidate the semaphore and wake up anyone waiting on it.
    138155     */
    139     ASMAtomicWriteSize(&pThis->iMagic, RTSEMEVENTMULTI_MAGIC + 1);
     156    ASMAtomicWriteSize(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1);
    140157    if (ASMAtomicXchgS32(&pThis->iState, -1) == 1)
    141158    {
     
    147164     * Free the semaphore memory and be gone.
    148165     */
     166#ifdef RTSEMEVENTMULTI_STRICT
     167    RTLockValidatorRecSharedDelete(&pThis->Signallers);
     168#endif
    149169    RTMemFree(pThis);
    150170    return VINF_SUCCESS;
     
    158178     */
    159179    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    160     AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
     180    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
    161181                 VERR_INVALID_HANDLE);
     182
     183#ifdef RTSEMEVENTMULTI_STRICT
     184    if (pThis->fEverHadSignallers)
     185    {
     186        int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
     187        if (RT_FAILURE(rc9))
     188            return rc9;
     189    }
     190#endif
     191
     192
    162193    /*
    163194     * Signal it.
     
    181212     */
    182213    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    183     AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
     214    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
    184215                 VERR_INVALID_HANDLE);
    185216#ifdef RT_STRICT
     
    198229static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume)
    199230{
     231    PCRTLOCKVALSRCPOS pSrcPos = NULL;
     232
    200233    /*
    201234     * Validate input.
    202235     */
    203236    struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
    204     AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
     237    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
    205238                 VERR_INVALID_HANDLE);
    206239
     
    221254    if (cMillies != RT_INDEFINITE_WAIT)
    222255    {
     256        /* If the timeout is zero, then we're done. */
    223257        if (!cMillies)
    224258            return VERR_TIMEOUT;
     
    232266     * The wait loop.
    233267     */
     268#ifdef RTSEMEVENTMULTI_STRICT
     269    RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
     270#else
     271    RTTHREAD hThreadSelf = RTThreadSelf();
     272#endif
    234273    for (unsigned i = 0;; i++)
    235274    {
     
    252291                ts.tv_nsec = i64Diff % 1000000000;
    253292            }
     293#ifdef RTSEMEVENTMULTI_STRICT
     294            if (pThis->fEverHadSignallers)
     295            {
     296                int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
     297                                                                RTTHREADSTATE_EVENT_MULTI, true);
     298                if (RT_FAILURE(rc9))
     299                    return rc9;
     300            }
     301#endif
     302            RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
    254303            long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 1, pTimeout, NULL, 0);
    255             if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENTMULTI_MAGIC))
     304            RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
     305            if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
    256306                return VERR_SEM_DESTROYED;
    257307            if (rc == 0)
     
    263313            if (rc == -ETIMEDOUT)
    264314            {
    265 /** @something is broken here. shows up every now and again in the ata code. Should try to run the timeout against RTTimeMilliTS to check that it's doing the right thing... */
     315/** @todo something is broken here. shows up every now and again in the ata
     316 *        code. Should try to run the timeout against RTTimeMilliTS to
     317 *        check that it's doing the right thing... */
    266318                Assert(pTimeout);
    267319                return VERR_TIMEOUT;
     
    303355RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
    304356{
    305     /** @todo implement RTSemEventMultiSetSignaller on OS/2 */
     357#ifdef RTSEMEVENTMULTI_STRICT
     358    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
     359    AssertPtrReturnVoid(pThis);
     360    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     361
     362    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
     363    RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
     364#endif
    306365}
    307366
     
    309368RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
    310369{
     370#ifdef RTSEMEVENTMULTI_STRICT
     371    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
     372    AssertPtrReturnVoid(pThis);
     373    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     374
     375    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
     376    RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
     377#endif
    311378}
    312379
     
    314381RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
    315382{
     383#ifdef RTSEMEVENTMULTI_STRICT
     384    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
     385    AssertPtrReturnVoid(pThis);
     386    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     387
     388    RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
     389#endif
    316390}
    317391
  • trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp

    r25640 r25648  
    124124                        RTLockValidatorRecSharedInit(&pThis->Signallers,
    125125                                                     NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY,
    126                                                      "RTSemEvent", pThis, true /*fSignaller*/);
     126                                                     "RTSemEventMulti", pThis, true /*fSignaller*/);
    127127                        pThis->fEverHadSignallers = false;
    128128#endif
  • trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp

    r25640 r25648  
    4545
    4646/*******************************************************************************
     47*   Defined Constants And Macros                                               *
     48*******************************************************************************/
     49#define SECS_SIMPLE_TEST    1
     50#define SECS_RACE_TEST      3
     51#define TEST_SMALL_TIMEOUT  (  10*1000)
     52#define TEST_LARGE_TIMEOUT  (  60*1000)
     53#define TEST_DEBUG_TIMEOUT  (3600*1000)
     54
     55
     56/*******************************************************************************
    4757*   Global Variables                                                           *
    4858*******************************************************************************/
     
    5262bool volatile               g_fDoNotSpin = false;
    5363
     64/** Set when the main thread wishes to terminate the test. */
     65bool volatile               g_fShutdown = false;
     66/** The number of threads. */
    5467static uint32_t             g_cThreads;
    5568static uint32_t             g_iDeadlockThread;
     
    6376/** Multiple release event semaphore that is signalled by the main thread after
    6477 * it has started all the threads. */
    65 static RTSEMEVENTMULTI      g_hThreadStarteEvt;
    66 
     78static RTSEMEVENTMULTI      g_hThreadsStartedEvt;
     79
     80/** The number of threads that have called testThreadBlocking */
     81static uint32_t volatile    g_cThreadsBlocking;
     82/** Multiple release event semaphore that is signalled by the last thread to
     83 * call testThreadBlocking.  testWaitForAllOtherThreadsToSleep waits on this. */
     84static RTSEMEVENTMULTI      g_hThreadsBlockingEvt;
    6785
    6886/** When to stop testing. */
     
    7593
    7694/**
    77  * Spin until someone else has taken ownership of the critical section.
     95 * Spin until the callback stops returning VERR_TRY_AGAIN.
    7896 *
    79  * @returns true on success, false on abort.
    80  * @param   pCritSect   The critical section.
     97 * @returns Callback result. VERR_TIMEOUT if too much time elapses.
     98 * @param   pfnCallback     Callback for checking the state.
     99 * @param   pvWhat          Callback parameter.
    81100 */
    82 static bool testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
     101static int testWaitForSomethingToBeOwned(int (*pfnCallback)(void *), void *pvWhat)
    83102{
    84103    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    85     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
    86 
    87     unsigned iLoop = 0;
    88     while (!RTCritSectIsOwned(pCritSect))
    89     {
    90         if (!RTCritSectIsInitialized(pCritSect))
    91             return false;
    92         RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
    93         iLoop++;
    94     }
    95     return true;
     104    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsStartedEvt, TEST_SMALL_TIMEOUT));
     105
     106    uint64_t u64StartMS = RTTimeMilliTS();
     107    for (unsigned iLoop = 0; ; iLoop++)
     108    {
     109        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     110
     111        int rc = pfnCallback(pvWhat);
     112        if (rc != VERR_TRY_AGAIN/* && !g_fDoNotSpin*/)
     113        {
     114            RTTEST_CHECK_RC_OK(g_hTest, rc);
     115            return rc;
     116        }
     117
     118        uint64_t cMsElapsed = RTTimeMilliTS() - u64StartMS;
     119        if (!g_fDoNotSpin)
     120            RTTEST_CHECK_RET(g_hTest, cMsElapsed <= TEST_SMALL_TIMEOUT, VERR_TIMEOUT);
     121
     122        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     123        RTThreadSleep(/*g_fDoNotSpin ? TEST_DEBUG_TIMEOUT :*/ iLoop > 256 ? 1 : 0);
     124    }
     125}
     126
     127
     128static int testCheckIfCritSectIsOwned(void *pvWhat)
     129{
     130    PRTCRITSECT pCritSect = (PRTCRITSECT)pvWhat;
     131    if (!RTCritSectIsInitialized(pCritSect))
     132        return VERR_SEM_DESTROYED;
     133    if (RTCritSectIsOwned(pCritSect))
     134        return VINF_SUCCESS;
     135    return VERR_TRY_AGAIN;
     136}
     137
     138
     139static int testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
     140{
     141    return testWaitForSomethingToBeOwned(testCheckIfCritSectIsOwned, pCritSect);
     142}
     143
     144
     145static int testCheckIfSemRWIsOwned(void *pvWhat)
     146{
     147    RTSEMRW hSemRW = (RTSEMRW)pvWhat;
     148    if (RTSemRWGetWriteRecursion(hSemRW) > 0)
     149        return VINF_SUCCESS;
     150    if (RTSemRWGetReadCount(hSemRW) > 0)
     151        return VINF_SUCCESS;
     152    return VERR_TRY_AGAIN;
     153}
     154
     155static int testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
     156{
     157    return testWaitForSomethingToBeOwned(testCheckIfSemRWIsOwned, hSemRW);
     158}
     159
     160
     161static int testCheckIfSemMutexIsOwned(void *pvWhat)
     162{
     163    RTSEMMUTEX hSemRW = (RTSEMMUTEX)pvWhat;
     164    if (RTSemMutexIsOwned(hSemRW))
     165        return VINF_SUCCESS;
     166    return VERR_TRY_AGAIN;
     167}
     168
     169static int testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex)
     170{
     171    return testWaitForSomethingToBeOwned(testCheckIfSemMutexIsOwned, hSemMutex);
    96172}
    97173
    98174
    99175/**
    100  * Spin until someone else has taken ownership (any kind) of the read-write
    101  * semaphore.
    102  *
    103  * @returns true on success, false on abort.
    104  * @param   hSemRW      The read-write semaphore.
     176 * For reducing spin in testWaitForAllOtherThreadsToSleep.
    105177 */
    106 static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
    107 {
    108     RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    109     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
    110 
    111     unsigned iLoop = 0;
    112     for (;;)
    113     {
    114         if (RTSemRWGetWriteRecursion(hSemRW) > 0)
    115             return true;
    116         if (RTSemRWGetReadCount(hSemRW) > 0)
    117             return true;
    118         RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
    119         iLoop++;
    120     }
    121     return true;
    122 }
    123 
    124 
    125 /**
    126  * Spin until someone else has taken ownership of the mutex semaphore.
    127  *
    128  * @returns true on success, false on abort.
    129  * @param   hSemMutex   The mutex sempahore.
    130  */
    131 static bool testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex)
    132 {
    133     RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    134     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
    135 
    136     unsigned iLoop = 0;
    137     while (!RTSemMutexIsOwned(hSemMutex))
    138     {
    139         RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
    140         iLoop++;
    141     }
    142     return true;
     178static void testThreadBlocking(void)
     179{
     180    if (ASMAtomicIncU32(&g_cThreadsBlocking) == g_cThreads)
     181        RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt));
    143182}
    144183
     
    155194static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn)
    156195{
     196    testThreadBlocking();
    157197    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    158     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
     198    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsBlockingEvt, TEST_SMALL_TIMEOUT));
    159199
    160200    RTTHREAD hThreadSelf = RTThreadSelf();
     
    207247                             && enmState != RTTHREADSTATE_INITIALIZING)
    208248                        return VERR_INTERNAL_ERROR;
    209                     RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop + iLoop > 256 ? 1 : 0);
     249                    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     250                    RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop + iLoop > 256 ? 1 : 0);
     251                    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
    210252                    cWaitedOn++;
    211253                }
    212254            }
     255            RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
    213256        }
    214257
    215258        if (!cMissing && !cWaitedOn)
    216259            break;
    217         RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop > 256 ? 1 : 0);
     260        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     261        RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop > 256 ? 1 : 0);
     262        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
    218263    }
    219264
    220265    RTThreadSleep(0);                   /* fudge factor */
     266    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
    221267    return VINF_SUCCESS;
    222268}
     
    232278static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread)
    233279{
    234     RTSemEventMultiReset(g_hThreadStarteEvt);
     280    RTSemEventMultiReset(g_hThreadsStartedEvt);
    235281
    236282    for (uint32_t i = 0; i < RT_ELEMENTS(g_ahThreads); i++)
     
    247293    }
    248294
    249     RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThreadStarteEvt), rcCheck);
     295    RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), rcCheck);
    250296    return rc;
    251297}
     
    276322
    277323
    278 static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)
     324static void testIt(uint32_t cThreads, uint32_t cSecs, bool fLoops, PFNRTTHREAD pfnThread, const char *pszName)
    279325{
    280326    /*
    281327     * Init test.
    282328     */
    283     if (cSecs)
    284         RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);
     329    if (cSecs > 0)
     330        RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs);
    285331    else
    286         RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
     332        RTTestSubF(g_hTest, "%s, %u threads, single pass", pszName, cThreads);
    287333
    288334    RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
     
    290336
    291337    g_cThreads = cThreads;
     338    g_fShutdown = false;
    292339
    293340    for (uint32_t i = 0; i < cThreads; i++)
     
    299346    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventCreate(&g_hSemEvt), VINF_SUCCESS);
    300347    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hSemEvtMulti), VINF_SUCCESS);
    301     RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadStarteEvt), VINF_SUCCESS);
     348    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsStartedEvt), VINF_SUCCESS);
     349    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsBlockingEvt), VINF_SUCCESS);
    302350
    303351    /*
    304352     * The test loop.
    305353     */
     354    uint32_t cPasses    = 0;
    306355    uint32_t cLoops     = 0;
    307356    uint32_t cDeadlocks = 0;
    308357    uint32_t cErrors    = RTTestErrorCount(g_hTest);
    309     for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
    310     {
    311         g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
    312         g_cLoops          = 0;
    313         g_cDeadlocks      = 0;
    314         g_NanoTSStop      = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
     358    uint64_t uStartNS   = RTTimeNanoTS();
     359    g_NanoTSStop        = uStartNS + cSecs * UINT64_C(1000000000);
     360    do
     361    {
     362        g_iDeadlockThread  = (cThreads - 1 + cPasses) % cThreads;
     363        g_cLoops           = 0;
     364        g_cDeadlocks       = 0;
     365        g_cThreadsBlocking = 0;
     366        RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hThreadsBlockingEvt), VINF_SUCCESS);
    315367
    316368        int rc = testStartThreads(cThreads, pfnThread);
    317369        if (RT_SUCCESS(rc))
    318             testWaitForThreads(30*1000 + cSecs*1000, true);
    319 
    320         RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
     370        {
     371            testWaitForThreads(TEST_LARGE_TIMEOUT + cSecs*1000, true);
     372            if (g_fDoNotSpin && RTTestErrorCount(g_hTest) != cErrors)
     373                testWaitForThreads(TEST_DEBUG_TIMEOUT, true);
     374        }
     375
     376        RTTEST_CHECK(g_hTest, !fLoops || g_cLoops > 0);
    321377        cLoops += g_cLoops;
    322         RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
     378        RTTEST_CHECK(g_hTest, !fLoops || g_cDeadlocks > 0);
    323379        cDeadlocks += g_cDeadlocks;
    324     }
     380        cPasses++;
     381    } while (   RTTestErrorCount(g_hTest) == cErrors
     382             && !fLoops
     383             && RTTimeNanoTS() < g_NanoTSStop);
    325384
    326385    /*
    327386     * Cleanup.
    328387     */
     388    ASMAtomicWriteBool(&g_fShutdown, true);
     389    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt), VINF_SUCCESS);
     390    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), VINF_SUCCESS);
     391    RTThreadSleep(RTTestErrorCount(g_hTest) == cErrors ? 0 : 50);
     392
    329393    for (uint32_t i = 0; i < cThreads; i++)
    330394    {
     
    335399    RTTEST_CHECK_RC(g_hTest, RTSemEventDestroy(g_hSemEvt), VINF_SUCCESS);
    336400    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hSemEvtMulti), VINF_SUCCESS);
    337     RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadStarteEvt), VINF_SUCCESS);
    338 
    339     testWaitForThreads(10*1000, false);
     401    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsStartedEvt), VINF_SUCCESS);
     402    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsBlockingEvt), VINF_SUCCESS);
     403
     404    testWaitForThreads(TEST_SMALL_TIMEOUT, false);
    340405
    341406    /*
     
    343408     */
    344409    if (cSecs)
    345         RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
    346                      cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
     410    {
     411        if (fLoops)
     412            RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
     413                         cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
     414        else
     415            RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cPasses=%u\n", cPasses);
     416    }
    347417}
    348418
     
    357427    if (i & 1)
    358428        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
    359     if (testWaitForCritSectToBeOwned(pNext))
     429    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
    360430    {
    361431        int rc;
    362432        if (i != g_iDeadlockThread)
     433        {
     434            testThreadBlocking();
    363435            RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
     436        }
    364437        else
    365438        {
     
    379452
    380453
    381 static void test1(uint32_t cThreads, uint32_t cPasses)
    382 {
    383     testIt(cThreads, cPasses, 0, test1Thread, "critsect");
     454static void test1(uint32_t cThreads, uint32_t cSecs)
     455{
     456    testIt(cThreads, cSecs, false, test1Thread, "critsect");
    384457}
    385458
     
    400473    else
    401474        RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
    402     if (testWaitForSemRWToBeOwned(hNext))
     475    if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext)))
    403476    {
    404477        if (i != g_iDeadlockThread)
     478        {
     479            testThreadBlocking();
    405480            RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
     481        }
    406482        else
    407483        {
     
    432508
    433509
    434 static void test2(uint32_t cThreads, uint32_t cPasses)
    435 {
    436     testIt(cThreads, cPasses, 0, test2Thread, "read-write");
     510static void test2(uint32_t cThreads, uint32_t cSecs)
     511{
     512    testIt(cThreads, cSecs, false, test2Thread, "read-write");
    437513}
    438514
     
    449525    else
    450526        RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
    451     if (testWaitForSemRWToBeOwned(hNext))
     527    if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext)))
    452528    {
    453529        do
    454530        {
    455             rc = RTSemRWRequestWrite(hNext, 60*1000);
     531            rc = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT);
    456532            if (rc != VINF_SUCCESS && rc != VERR_SEM_LV_DEADLOCK && rc != VERR_SEM_LV_ILLEGAL_UPGRADE)
    457533            {
     
    479555
    480556
    481 static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
    482 {
    483     testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
     557static void test3(uint32_t cThreads, uint32_t cSecs)
     558{
     559    testIt(cThreads, cSecs, true, test3Thread, "read-write race");
    484560}
    485561
     
    493569    do
    494570    {
    495         int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, 60*1000); /* ugly ;-) */
     571        int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, TEST_SMALL_TIMEOUT); /* ugly ;-) */
    496572        RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    497573        if (rc1 != VINF_SUCCESS && rc1 != VERR_SEM_LV_DEADLOCK && rc1 != VERR_SEM_LV_ILLEGAL_UPGRADE)
     
    504580            for (unsigned iInner = 0; iInner < 4; iInner++)
    505581            {
    506                 int rc2 = RTSemRWRequestWrite(hNext, 60*1000);
     582                int rc2 = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT);
    507583                if (rc2 != VINF_SUCCESS && rc2 != VERR_SEM_LV_DEADLOCK && rc2 != VERR_SEM_LV_ILLEGAL_UPGRADE)
    508584                {
     
    535611
    536612
    537 static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
    538 {
    539     testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
     613static void test4(uint32_t cThreads, uint32_t cSecs)
     614{
     615    testIt(cThreads, cSecs, true, test4Thread, "read-write race v2");
    540616}
    541617
     
    550626    if (i & 1)
    551627        RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS);
    552     if (testWaitForSemMutexToBeOwned(hNext))
     628    if (RT_SUCCESS(testWaitForSemMutexToBeOwned(hNext)))
    553629    {
    554630        int rc;
    555631        if (i != g_iDeadlockThread)
     632        {
     633            testThreadBlocking();
    556634            RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
     635        }
    557636        else
    558637        {
     
    572651
    573652
    574 static void test5(uint32_t cThreads, uint32_t cPasses)
    575 {
    576     testIt(cThreads, cPasses, 0, test5Thread, "mutex");
     653static void test5(uint32_t cThreads, uint32_t cSecs)
     654{
     655    testIt(cThreads, cSecs, false, test5Thread, "mutex");
    577656}
    578657
     
    587666    if (i & 1)
    588667        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
    589     if (testWaitForCritSectToBeOwned(pNext))
     668    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
    590669    {
    591670        int rc;
    592671        if (i != g_iDeadlockThread)
    593672        {
     673            testThreadBlocking();
    594674            RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
    595675            RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
     
    606686                    RTSemEventAddSignaller(g_hSemEvt, g_ahThreads[iThread]);
    607687                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    608                 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VERR_SEM_LV_DEADLOCK);
     688                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK);
    609689                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    610690                RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_hSemEvt), VINF_SUCCESS);
    611691                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    612                 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VINF_SUCCESS);
     692                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VINF_SUCCESS);
    613693                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    614694                RTSemEventSetSignaller(g_hSemEvt, NIL_RTTHREAD);
     
    624704
    625705
    626 static void test6(uint32_t cThreads, uint32_t cPasses)
    627 {
    628     testIt(cThreads, cPasses, 0, test6Thread, "event");
     706static void test6(uint32_t cThreads, uint32_t cSecs)
     707{
     708    testIt(cThreads, cSecs, false, test6Thread, "event");
    629709}
    630710
     
    639719    if (i & 1)
    640720        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
    641     if (testWaitForCritSectToBeOwned(pNext))
     721    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
    642722    {
    643723        int rc;
    644724        if (i != g_iDeadlockThread)
    645725        {
     726            testThreadBlocking();
    646727            RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
    647728            RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
     
    659740                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    660741                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hSemEvtMulti), VINF_SUCCESS);
    661                 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VERR_SEM_LV_DEADLOCK);
     742                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK);
    662743                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    663744                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hSemEvtMulti), VINF_SUCCESS);
    664745                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    665                 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VINF_SUCCESS);
     746                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VINF_SUCCESS);
    666747                RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
    667748                RTSemEventMultiSetSignaller(g_hSemEvtMulti, NIL_RTTHREAD);
     
    677758
    678759
    679 static void test7(uint32_t cThreads, uint32_t cPasses)
    680 {
    681     testIt(cThreads, cPasses, 0, test7Thread, "event multi");
    682 }
     760static void test7(uint32_t cThreads, uint32_t cSecs)
     761{
     762    testIt(cThreads, cSecs, false, test7Thread, "event multi");
     763}
     764
    683765
    684766static bool testIsLockValidationCompiledIn(void)
     
    756838
    757839    /*
    758      * Some initial tests with verbose output.
     840     * Some initial tests with verbose output (all single pass).
    759841     */
    760 #if 1
    761     test1(3, 1);
    762     test2(1, 1);
    763     test2(3, 1);
    764     test5(3, 1);
    765     test6(3, 1);
    766 #endif
    767     test7(3, 1);
     842    test1(3, 0);
     843    test2(1, 0);
     844    test2(3, 0);
     845    test5(3, 0);
     846    test6(3, 0);
     847    test7(3, 0);
    768848
    769849    /*
    770      * More thorough testing without noisy output.
     850     * If successful, perform more thorough testing without noisy output.
    771851     */
    772     RTLockValidatorSetQuiet(true);
    773 #if 1
    774     test1( 2, 256);                     /* 256 * 4ms = 1s (approx); 4ms == fudge factor */
    775     test1( 3, 256);
    776     test1( 7, 256);
    777     test1(10, 256);
    778     test1(15, 256);
    779     test1(30, 256);
    780 
    781     test2( 1, 256);
    782     test2( 2, 256);
    783     test2( 3, 256);
    784     test2( 7, 256);
    785     test2(10, 256);
    786     test2(15, 256);
    787     test2(30, 256);
    788 
    789     test3( 2,  1,  2);
    790     test3(10,  1,  2);
    791 
    792     test4( 2,  1,  2);
    793     test4( 6,  1,  2);
    794     test4(10,  1, 10);
    795     test4(30,  1, 10);
    796 
    797     test5( 2, 256);
    798     test5( 3, 256);
    799     test5( 7, 256);
    800     test5(10, 256);
    801     test5(15, 256);
    802     test5(30, 256);
    803 
    804     test6( 2, 256);
    805     test6( 3, 256);
    806     test6( 7, 256);
    807     test6(10, 256);
    808     test6(15, 256);
    809     test6(30, 256);
    810 #endif
    811 
    812 #if 1
    813     test7( 2, 256);
    814     test7( 3, 256);
    815     test7( 7, 256);
    816     test7(10, 256);
    817     test7(15, 256);
    818     test7(30, 256);
    819 #endif
     852    if (RTTestErrorCount(g_hTest) == 0)
     853    {
     854        RTLockValidatorSetQuiet(true);
     855
     856        test1( 2, SECS_SIMPLE_TEST);
     857        test1( 3, SECS_SIMPLE_TEST);
     858        test1( 7, SECS_SIMPLE_TEST);
     859        test1(10, SECS_SIMPLE_TEST);
     860        test1(15, SECS_SIMPLE_TEST);
     861        test1(30, SECS_SIMPLE_TEST);
     862
     863        test2( 1, SECS_SIMPLE_TEST);
     864        test2( 2, SECS_SIMPLE_TEST);
     865        test2( 3, SECS_SIMPLE_TEST);
     866        test2( 7, SECS_SIMPLE_TEST);
     867        test2(10, SECS_SIMPLE_TEST);
     868        test2(15, SECS_SIMPLE_TEST);
     869        test2(30, SECS_SIMPLE_TEST);
     870
     871        test3( 2, SECS_SIMPLE_TEST);
     872        test3(10, SECS_SIMPLE_TEST);
     873
     874        test4( 2, SECS_RACE_TEST);
     875        test4( 6, SECS_RACE_TEST);
     876        test4(10, SECS_RACE_TEST);
     877        test4(30, SECS_RACE_TEST);
     878
     879        test5( 2, SECS_RACE_TEST);
     880        test5( 3, SECS_RACE_TEST);
     881        test5( 7, SECS_RACE_TEST);
     882        test5(10, SECS_RACE_TEST);
     883        test5(15, SECS_RACE_TEST);
     884        test5(30, SECS_RACE_TEST);
     885
     886        test6( 2, SECS_SIMPLE_TEST);
     887        test6( 3, SECS_SIMPLE_TEST);
     888        test6( 7, SECS_SIMPLE_TEST);
     889        test6(10, SECS_SIMPLE_TEST);
     890        test6(15, SECS_SIMPLE_TEST);
     891        test6(30, SECS_SIMPLE_TEST);
     892
     893        test7( 2, SECS_SIMPLE_TEST);
     894        test7( 3, SECS_SIMPLE_TEST);
     895        test7( 7, SECS_SIMPLE_TEST);
     896        test7(10, SECS_SIMPLE_TEST);
     897        test7(15, SECS_SIMPLE_TEST);
     898        test7(30, SECS_SIMPLE_TEST);
     899    }
    820900
    821901    return RTTestSummaryAndDestroy(g_hTest);
Note: See TracChangeset for help on using the changeset viewer.

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