VirtualBox

Changeset 24352 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 4, 2009 6:49:05 PM (15 years ago)
Author:
vboxsync
Message:

Runtime/testcase: simple event semaphore testcase, including timeout case

Location:
trunk/src/VBox/Runtime/testcase
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r23960 r24352  
    9090        tstRTS3 \
    9191        tstSems \
     92        tstSemEvent \
    9293        tstSemPingPong \
    9394        tstRTStrCache \
     
    356357tstSemMutex_SOURCES = tstSemMutex.cpp
    357358
     359tstSemEvent_SOURCES = tstSemEvent.cpp
     360
    358361tstSemRW_SOURCES = tstSemRW.cpp
    359362
  • trunk/src/VBox/Runtime/testcase/tstSemEvent.cpp

    r24286 r24352  
    11/* $Id$ */
    22/** @file
    3  * IPRT Testcase - Reader/Writer Semaphore Test.
     3 * IPRT Testcase - Event Semaphore Test.
    44 */
    55
     
    4646*   Global Variables                                                           *
    4747*******************************************************************************/
    48 static RTSEMRW              g_hSemRW = NIL_RTSEMRW;
    49 static bool volatile        g_fTerminate;
    50 static bool                 g_fYield;
    51 static bool                 g_fQuiet;
    52 static unsigned             g_uWritePercent;
    53 static uint32_t volatile    g_cbConcurrentWrite;
    54 static uint32_t volatile    g_cbConcurrentRead;
     48static RTSEMEVENTMULTI      g_hSemEM = NIL_RTSEMEVENTMULTI;
    5549static uint32_t volatile    g_cErrors;
    5650
     
    6054    ASMAtomicIncU32(&g_cErrors);
    6155
    62     RTPrintf("tstSemRW: FAILURE - ");
     56    RTPrintf("tstSemEvent: FAILURE - ");
    6357    va_list va;
    6458    va_start(va, pszFormat);
     
    7266int ThreadTest1(RTTHREAD ThreadSelf, void *pvUser)
    7367{
    74     // Use randomization to get a little more variation of the sync pattern
    75     unsigned c100 = RTRandU32Ex(0, 99);
    76     uint64_t *pu64 = (uint64_t *)pvUser;
    77     bool fWrite;
    78     for (;;)
     68    int rc;
     69    rc = RTSemEventMultiWait(g_hSemEM, 1000);
     70    if (rc != VERR_TIMEOUT)
    7971    {
    80         int rc;
    81         unsigned readrec = RTRandU32Ex(0, 3);
    82         unsigned writerec = RTRandU32Ex(0, 3);
    83         /* Don't overdo recursion testing. */
    84         if (readrec > 1)
    85             readrec--;
    86         if (writerec > 1)
    87             writerec--;
     72        PrintError("Thread 1: unexpected result of first RTSemEventMultiWait %Rrc\n", rc);
     73        return VINF_SUCCESS;
     74    }
    8875
    89         fWrite = (c100 < g_uWritePercent);
    90         if (fWrite)
    91         {
    92             for (unsigned i = 0; i <= writerec; i++)
    93             {
    94                 rc = RTSemRWRequestWriteNoResume(g_hSemRW, RT_INDEFINITE_WAIT);
    95                 if (RT_FAILURE(rc))
    96                 {
    97                     PrintError("%x: RTSemRWRequestWriteNoResume failed with %Rrc\n", rc);
    98                     break;
    99                 }
    100             }
    101             if (RT_FAILURE(rc))
    102                 break;
    103             if (ASMAtomicIncU32(&g_cbConcurrentWrite) != 1)
    104             {
    105                 PrintError("g_cbConcurrentWrite=%d after request!\n", g_cbConcurrentWrite);
    106                 break;
    107             }
    108             if (g_cbConcurrentRead != 0)
    109             {
    110                 PrintError("g_cbConcurrentRead=%d after request!\n", g_cbConcurrentRead);
    111                 break;
    112             }
    113         }
    114         else
    115         {
    116             rc = RTSemRWRequestReadNoResume(g_hSemRW, RT_INDEFINITE_WAIT);
    117             if (RT_FAILURE(rc))
    118             {
    119                 PrintError("%x: RTSemRWRequestReadNoResume failed with %Rrc\n", rc);
    120                 break;
    121             }
    122             ASMAtomicIncU32(&g_cbConcurrentRead);
    123             if (g_cbConcurrentWrite != 0)
    124             {
    125                 PrintError("g_cbConcurrentWrite=%d after request!\n", g_cbConcurrentWrite);
    126                 break;
    127             }
    128         }
    129         for (unsigned i = 0; i < readrec; i++)
    130         {
    131             rc = RTSemRWRequestReadNoResume(g_hSemRW, RT_INDEFINITE_WAIT);
    132             if (RT_FAILURE(rc))
    133             {
    134                 PrintError("%x: RTSemRWRequestReadNoResume failed with %Rrc\n", rc);
    135                 break;
    136             }
    137         }
    138         if (RT_FAILURE(rc))
    139             break;
     76    rc = RTSemEventMultiWait(g_hSemEM, 1000);
     77    if (RT_FAILURE(rc))
     78    {
     79        PrintError("Thread 1: unexpected result of second RTSemEventMultiWait %Rrc\n", rc);
     80        return VINF_SUCCESS;
     81    }
    14082
    141         /*
    142          * Check for fairness: The values of the threads should not differ too much
    143          */
    144         (*pu64)++;
    145 
    146         /*
    147          * Check for correctness: Give other threads a chance. If the implementation is
    148          * correct, no other thread will be able to enter this lock now.
    149          */
    150         if (g_fYield)
    151             RTThreadYield();
    152 
    153         for (unsigned i = 0; i < readrec; i++)
    154         {
    155             rc = RTSemRWReleaseRead(g_hSemRW);
    156             if (RT_FAILURE(rc))
    157             {
    158                 PrintError("%x: RTSemRWReleaseRead failed with %Rrc\n", rc);
    159                 break;
    160             }
    161         }
    162         if (RT_FAILURE(rc))
    163             break;
    164 
    165         if (fWrite)
    166         {
    167             if (ASMAtomicDecU32(&g_cbConcurrentWrite) != 0)
    168             {
    169                 PrintError("g_cbConcurrentWrite=%d before release!\n", g_cbConcurrentWrite);
    170                 break;
    171             }
    172             if (g_cbConcurrentRead != 0)
    173             {
    174                 PrintError("g_cbConcurrentRead=%d before release!\n", g_cbConcurrentRead);
    175                 break;
    176             }
    177             for (unsigned i = 0; i <= writerec; i++)
    178             {
    179                 rc = RTSemRWReleaseWrite(g_hSemRW);
    180                 if (RT_FAILURE(rc))
    181                 {
    182                     PrintError("%x: RTSemRWReleaseWrite failed with %Rrc\n", rc);
    183                     break;
    184                 }
    185             }
    186         }
    187         else
    188         {
    189             if (g_cbConcurrentWrite != 0)
    190             {
    191                 PrintError("g_cbConcurrentWrite=%d before release!\n", g_cbConcurrentWrite);
    192                 break;
    193             }
    194             ASMAtomicDecU32(&g_cbConcurrentRead);
    195             rc = RTSemRWReleaseRead(g_hSemRW);
    196             if (RT_FAILURE(rc))
    197             {
    198                 PrintError("%x: RTSemRWReleaseRead failed with %Rrc\n", rc);
    199                 break;
    200             }
    201         }
    202 
    203         if (g_fTerminate)
    204             break;
    205 
    206         c100++;
    207         c100 %= 100;
    208     }
    209     if (!g_fQuiet)
    210         RTPrintf("tstSemRW: Thread %08x exited with %lld\n", ThreadSelf, *pu64);
     83    RTPrintf("tstSemEvent: Thread 1 normal exit...\n");
    21184    return VINF_SUCCESS;
    21285}
    21386
    21487
    215 static int Test1(unsigned cThreads, unsigned cSeconds, unsigned uWritePercent, bool fYield, bool fQuiet)
     88int ThreadTest2(RTTHREAD ThreadSelf, void *pvUser)
    21689{
    21790    int rc;
    218     unsigned i;
    219     uint64_t g_au64[32];
    220     RTTHREAD aThreads[RT_ELEMENTS(g_au64)];
    221     AssertRelease(cThreads <= RT_ELEMENTS(g_au64));
     91    rc = RTSemEventMultiWait(g_hSemEM, RT_INDEFINITE_WAIT);
     92    if (RT_FAILURE(rc))
     93    {
     94        PrintError("Thread 2: unexpected result of RTSemEventMultiWait %Rrc\n", rc);
     95        return VINF_SUCCESS;
     96    }
     97
     98    RTPrintf("tstSemEvent: Thread 2 normal exit...\n");
     99    return VINF_SUCCESS;
     100}
     101
     102
     103static int Test1()
     104{
     105    int rc;
     106    RTTHREAD Thread1, Thread2;
     107
     108    rc = RTSemEventMultiCreate(&g_hSemEM);
     109    if (RT_FAILURE(rc))
     110        return PrintError("RTSemEventMultiCreate failed (rc=%Rrc)\n", rc);
    222111
    223112    /*
    224      * Init globals.
     113     * Create the threads and let them block on the event multi semaphore.
    225114     */
    226     g_fYield = fYield;
    227     g_fQuiet = fQuiet;
    228     g_fTerminate = false;
    229     g_uWritePercent = uWritePercent;
    230     g_cbConcurrentWrite = 0;
    231     g_cbConcurrentRead = 0;
     115    rc = RTSemEventMultiReset(g_hSemEM);
     116    if (RT_FAILURE(rc))
     117        return PrintError("RTSemEventMultiReset failed (rc=%Rrc)\n", rc);
    232118
    233     rc = RTSemRWCreate(&g_hSemRW);
     119    rc = RTThreadCreate(&Thread2, ThreadTest2, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test2");
    234120    if (RT_FAILURE(rc))
    235         return PrintError("RTSemRWCreate failed (rc=%Rrc)\n", rc);
     121        return PrintError("RTThreadCreate failed for thread 2 (rc=%Rrc)\n", rc);
     122    RTThreadSleep(100);
    236123
    237     /*
    238      * Create the threads and let them block on the semrw.
    239      */
    240     rc = RTSemRWRequestWrite(g_hSemRW, RT_INDEFINITE_WAIT);
     124    rc = RTThreadCreate(&Thread1, ThreadTest1, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1");
    241125    if (RT_FAILURE(rc))
    242         return PrintError("RTSemRWRequestWrite failed (rc=%Rrc)\n", rc);
     126        return PrintError("RTThreadCreate failed for thread 1 (rc=%Rrc)\n", rc);
    243127
    244     for (i = 0; i < cThreads; i++)
    245     {
    246         g_au64[i] = 0;
    247         rc = RTThreadCreate(&aThreads[i], ThreadTest1, &g_au64[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test");
    248         if (RT_FAILURE(rc))
    249             return PrintError("RTThreadCreate failed for thread %u (rc=%Rrc)\n", i, rc);
    250     }
     128    /* Force first thread (which has a timeout of 1 second) to timeout in the
     129     * first wait, and the second wait will succeed. */
     130    RTThreadSleep(1500);
     131    rc = RTSemEventMultiSignal(g_hSemEM);
     132    if (RT_FAILURE(rc))
     133        PrintError("RTSemEventMultiSignal failed (rc=%Rrc)\n", rc);
    251134
    252     if (!fQuiet)
    253         RTPrintf("tstSemRW: %zu Threads created. Racing them for %u seconds (%s) ...\n",
    254                  cThreads, cSeconds, g_fYield ? "yielding" : "no yielding");
     135    rc = RTThreadWait(Thread1, 1000, NULL);
     136    if (RT_FAILURE(rc))
     137        PrintError("RTThreadWait failed for thread 1 (rc=%Rrc)\n", rc);
    255138
    256     uint64_t u64StartTS = RTTimeNanoTS();
    257     rc = RTSemRWReleaseWrite(g_hSemRW);
     139    rc = RTThreadWait(Thread2, 1000, NULL);
    258140    if (RT_FAILURE(rc))
    259         PrintError("RTSemRWReleaseWrite failed (rc=%Rrc)\n", rc);
    260     RTThreadSleep(cSeconds * 1000);
    261     ASMAtomicXchgBool(&g_fTerminate, true);
    262     uint64_t ElapsedNS = RTTimeNanoTS() - u64StartTS;
     141        PrintError("RTThreadWait failed for thread 2 (rc=%Rrc)\n", rc);
    263142
    264     for (i = 0; i < cThreads; i++)
    265     {
    266         rc = RTThreadWait(aThreads[i], 5000, NULL);
    267         if (RT_FAILURE(rc))
    268             PrintError("RTThreadWait failed for thread %u (rc=%Rrc)\n", i, rc);
    269     }
    270 
    271     if (g_cbConcurrentWrite != 0)
    272         PrintError("g_cbConcurrentWrite=%d at end of test!\n", g_cbConcurrentWrite);
    273     if (g_cbConcurrentRead != 0)
    274         PrintError("g_cbConcurrentRead=%d at end of test!\n", g_cbConcurrentRead);
    275 
    276     rc = RTSemRWDestroy(g_hSemRW);
     143    rc = RTSemEventMultiDestroy(g_hSemEM);
    277144    if (RT_FAILURE(rc))
    278         PrintError("RTSemRWDestroy failed - %Rrc\n", rc);
    279     g_hSemRW = NIL_RTSEMRW;
     145        PrintError("RTSemEventMultiDestroy failed - %Rrc\n", rc);
     146    g_hSemEM = NIL_RTSEMEVENTMULTI;
    280147    if (g_cErrors)
    281148        RTThreadSleep(100);
    282 
    283     /*
    284      * Collect and display the results.
    285      */
    286     uint64_t Total = g_au64[0];
    287     for (i = 1; i < cThreads; i++)
    288         Total += g_au64[i];
    289 
    290     uint64_t Normal = Total / cThreads;
    291     uint64_t MaxDeviation = 0;
    292     for (i = 0; i < cThreads; i++)
    293     {
    294         uint64_t Delta = RT_ABS((int64_t)(g_au64[i] - Normal));
    295         if (Delta > Normal / 2)
    296             RTPrintf("tstSemRW: Warning! Thread %d deviates by more than 50%% - %llu (it) vs. %llu (avg)\n",
    297                      i, g_au64[i], Normal);
    298         if (Delta > MaxDeviation)
    299             MaxDeviation = Delta;
    300 
    301     }
    302 
    303     RTPrintf("tstSemRW: Threads: %u  Total: %llu  Per Sec: %llu  Avg: %llu ns  Max dev: %llu%%\n",
    304              cThreads,
    305              Total,
    306              Total / cSeconds,
    307              ElapsedNS / Total,
    308              MaxDeviation * 100 / Normal
    309              );
    310149    return 0;
    311150}
     
    317156    if (RT_FAILURE(rc))
    318157    {
    319         RTPrintf("tstSemRW: RTR3Init failed (rc=%Rrc)\n", rc);
     158        RTPrintf("tstSemEvent: RTR3Init failed (rc=%Rrc)\n", rc);
    320159        return 1;
    321160    }
    322     RTPrintf("tstSemRW: TESTING...\n");
    323 
    324     if (argc == 1)
    325     {
    326         /*    threads, seconds, writePercent,  yield,  quiet */
    327         Test1(      1,       1,            0,   true,  false);
    328         Test1(      1,       1,            1,   true,  false);
    329         Test1(      1,       1,            5,   true,  false);
    330         Test1(      2,       1,            3,   true,  false);
    331         Test1(     10,       1,            5,   true,  false);
    332         Test1(     10,      10,           10,  false,  false);
    333 
    334         RTPrintf("tstSemRW: benchmarking...\n");
    335         for (unsigned cThreads = 1; cThreads < 32; cThreads++)
    336             Test1(cThreads,  2,            1,  false,   true);
    337 
    338         /** @todo add a testcase where some stuff times out. */
    339     }
    340     else
    341     {
    342         /*    threads, seconds, writePercent,  yield,  quiet */
    343         RTPrintf("tstSemRW: benchmarking...\n");
    344         Test1(      1,       3,            1,  false,   true);
    345         Test1(      1,       3,            1,  false,   true);
    346         Test1(      1,       3,            1,  false,   true);
    347         Test1(      2,       3,            1,  false,   true);
    348         Test1(      2,       3,            1,  false,   true);
    349         Test1(      2,       3,            1,  false,   true);
    350         Test1(      3,       3,            1,  false,   true);
    351         Test1(      3,       3,            1,  false,   true);
    352         Test1(      3,       3,            1,  false,   true);
    353     }
     161    RTPrintf("tstSemEvent: TESTING...\n");
     162    Test1();
    354163
    355164    if (!g_cErrors)
    356         RTPrintf("tstSemRW: SUCCESS\n");
     165        RTPrintf("tstSemEvent: SUCCESS\n");
    357166    else
    358         RTPrintf("tstSemRW: FAILURE - %u errors\n", g_cErrors);
     167        RTPrintf("tstSemEvent: FAILURE - %u errors\n", g_cErrors);
    359168    return g_cErrors != 0;
    360169}
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