VirtualBox

Ignore:
Timestamp:
Sep 20, 2010 4:17:03 PM (14 years ago)
Author:
vboxsync
Message:

IPRT: linux kernel timer changes, testcase. hrtimers are not working reliably yet.

File:
1 edited

Legend:

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

    r32611 r32648  
    2828*   Header Files                                                               *
    2929*******************************************************************************/
    30 #include <iprt/mem.h>
    31 
     30#include <iprt/timer.h>
     31
     32#include <iprt/asm.h>
    3233#include <iprt/err.h>
    3334#include <iprt/param.h>
     35#include <iprt/string.h>
     36#include <iprt/thread.h>
    3437#include <iprt/time.h>
    35 #include <iprt/string.h>
    3638#include <VBox/sup.h>
    3739#include "tstRTR0Timer.h"
    38 
     40#include "tstRTR0Common.h"
     41
     42/*******************************************************************************
     43*   Structures and Typedefs                                                    *
     44*******************************************************************************/
     45typedef struct
     46{
     47    /** Array of nano second timestamp of the first few shots. */
     48    uint64_t volatile   aShotNsTSes[10];
     49    /** The number of shots. */
     50    uint32_t volatile   cShots;
     51} TSTRTR0TIMERS1;
     52typedef TSTRTR0TIMERS1 *PTSTRTR0TIMERS1;
     53
     54
     55/**
     56 * Callback which increments restarts a timer once.
     57 *
     58 * @param   pTimer      The timer.
     59 * @param   iTick       The current tick.
     60 * @param   pvUser      The user argument.
     61 */
     62static DECLCALLBACK(void) tstRTR0TimerCallbackRestartOnce(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     63{
     64    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
     65    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
     66
     67    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
     68        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
     69
     70    if (iShot == 1)
     71        RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 10000000 /* 10ms */), VINF_SUCCESS);
     72}
     73
     74
     75/**
     76 * Callback which increments a 32-bit counter.
     77 *
     78 * @param   pTimer      The timer.
     79 * @param   iTick       The current tick.
     80 * @param   pvUser      The user argument.
     81 */
     82static DECLCALLBACK(void) tstRTR0TimerCallbackU32Counter(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     83{
     84    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
     85    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
     86
     87    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
     88        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
     89}
     90
     91
     92/**
     93 * Checks that the interval between two timer shots are within the specified
     94 * range.
     95 *
     96 * @returns 0 if ok, 1 if bad.
     97 * @param   iShot               The shot number (for bitching).
     98 * @param   uPrevTS             The time stamp of the previous shot (ns).
     99 * @param   uThisTS             The timer stamp of this shot (ns).
     100 * @param   uMin                The minimum interval (ns).
     101 * @param   uMax                The maximum interval (ns).
     102 */
     103static int tstRTR0TimerCheckShotInterval(uint32_t iShot, uint64_t uPrevTS, uint64_t uThisTS, uint32_t uMin, uint32_t uMax)
     104{
     105    uint64_t uDelta = uThisTS - uPrevTS;
     106    RTR0TESTR0_CHECK_MSG_RET(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin), 1);
     107    RTR0TESTR0_CHECK_MSG_RET(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax), 1);
     108    return 0;
     109}
     110
     111
     112/**
     113 * Checks that the interval between timer shots are within a certain range.
     114 *
     115 * @returns Number of violations (i.e. 0 is ok).
     116 * @param   pState              The state.
     117 * @param   uStartNsTS          The start time stamp (ns).
     118 * @param   uMin                The minimum interval (ns).
     119 * @param   uMax                The maximum interval (ns).
     120 */
     121static int tstRTR0TimerCheckShotIntervals(PTSTRTR0TIMERS1 pState, uint64_t uStartNsTS, uint32_t uMin, uint32_t uMax)
     122{
     123    uint64_t uMaxDelta = 0;
     124    uint64_t uMinDelta = UINT64_MAX;
     125    uint32_t cBadShots = 0;
     126    uint32_t cShots    = pState->cShots;
     127    uint64_t uPrevTS   = uStartNsTS;
     128    for (uint32_t iShot = 0; iShot < cShots; iShot++)
     129    {
     130        uint64_t uThisTS = pState->aShotNsTSes[iShot];
     131        uint64_t uDelta  = uThisTS - uPrevTS;
     132        if (uDelta > uMaxDelta)
     133            uMaxDelta = uDelta;
     134        if (uDelta < uMinDelta)
     135            uMinDelta = uDelta;
     136        cBadShots += !(uDelta >= uMin && uDelta <= uMax);
     137
     138        RTR0TESTR0_CHECK_MSG(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin));
     139        RTR0TESTR0_CHECK_MSG(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax));
     140
     141        uPrevTS = uThisTS;
     142    }
     143
     144    RTR0TestR0Info("uMaxDelta=%llu uMinDelta=%llu\n", uMaxDelta, uMinDelta);
     145    return cBadShots;
     146}
    39147
    40148
     
    50158                                          uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
    51159{
    52     if (!VALID_PTR(pReqHdr))
    53         return VERR_INVALID_PARAMETER;
    54     char   *pszErr = (char *)(pReqHdr + 1);
    55     size_t  cchErr = pReqHdr->cbReq - sizeof(*pReqHdr);
    56     if (cchErr < 32 || cchErr >= 0x10000)
    57         return VERR_INVALID_PARAMETER;
    58     *pszErr = '\0';
    59 
     160    RTR0TESTR0_SRV_REQ_PROLOG_RET(pReqHdr);
    60161    if (u64Arg)
    61162        return VERR_INVALID_PARAMETER;
     
    64165     * The big switch.
    65166     */
     167    TSTRTR0TIMERS1 State;
    66168    switch (uOperation)
    67169    {
    68         case TSTRTR0TIMER_SANITY_OK:
    69             break;
    70 
    71         case TSTRTR0TIMER_SANITY_FAILURE:
    72             RTStrPrintf(pszErr, cchErr, "!42failure42%1024s", "");
    73             break;
    74 
    75 #if 0
    76         case TSTRTR0TIMER_BASIC:
     170        RTR0TESTR0_IMPLEMENT_SANITY_CASES();
     171        RTR0TESTR0_IMPLEMENT_DEFAULT_CASE(uOperation);
     172
     173        case TSTRTR0TIMER_ONE_SHOT_BASIC:
     174        case TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES:
    77175        {
    78             int rc = RTR0MemUserCopyFrom(pbKrnlBuf, R3Ptr, PAGE_SIZE);
    79             if (rc == VINF_SUCCESS)
     176            /* Create a one-shot timer and take one shot. */
     177            PRTTIMER        pTimer;
     178            uint32_t        fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0;
     179            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackU32Counter, &State),
     180                                      VINF_SUCCESS);
     181
     182            do /* break loop */
    80183            {
    81                 rc = RTR0MemUserCopyTo(R3Ptr, pbKrnlBuf, PAGE_SIZE);
    82                 if (rc == VINF_SUCCESS)
    83                 {
    84                     if (RTR0MemUserIsValidAddr(R3Ptr))
    85                     {
    86                         if (RTR0MemKernelIsValidAddr(pbKrnlBuf))
    87                         {
    88                             if (RTR0MemAreKrnlAndUsrDifferent())
    89                             {
    90                                 RTStrPrintf(pszErr, cchErr, "RTR0MemAreKrnlAndUsrDifferent returns true");
    91                                 if (!RTR0MemUserIsValidAddr((uintptr_t)pbKrnlBuf))
    92                                 {
    93                                     if (!RTR0MemKernelIsValidAddr((void *)R3Ptr))
    94                                     {
    95                                         /* done */
    96                                     }
    97                                     else
    98                                         RTStrPrintf(pszErr, cchErr, "! #5 - RTR0MemKernelIsValidAddr -> true, expected false");
    99                                 }
    100                                 else
    101                                     RTStrPrintf(pszErr, cchErr, "! #5 - RTR0MemUserIsValidAddr -> true, expected false");
    102                             }
    103                             else
    104                                 RTStrPrintf(pszErr, cchErr, "RTR0MemAreKrnlAndUsrDifferent returns false");
    105                         }
    106                         else
    107                             RTStrPrintf(pszErr, cchErr, "! #4 - RTR0MemKernelIsValidAddr -> false, expected true");
    108                     }
    109                     else
    110                         RTStrPrintf(pszErr, cchErr, "! #3 - RTR0MemUserIsValidAddr -> false, expected true");
    111                 }
    112                 else
    113                     RTStrPrintf(pszErr, cchErr, "! #2 - RTR0MemUserCopyTo -> %Rrc expected %Rrc", rc, VINF_SUCCESS);
    114             }
    115             else
    116                 RTStrPrintf(pszErr, cchErr, "! #1 - RTR0MemUserCopyFrom -> %Rrc expected %Rrc", rc, VINF_SUCCESS);
     184                RT_ZERO(State);
     185                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
     186                for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++)
     187                    RTThreadSleep(5);
     188                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots));
     189
     190                /* check that it is restartable. */
     191                RT_ZERO(State);
     192                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
     193                for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++)
     194                    RTThreadSleep(5);
     195                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots));
     196
     197                /* check that it respects the timeout value and can be cancelled. */
     198                RT_ZERO(State);
     199                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS);
     200                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS);
     201                RTThreadSleep(1);
     202                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots));
     203
     204                /* Check some double starts and stops (shall not assert). */
     205                RT_ZERO(State);
     206                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS);
     207                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 0), VERR_TIMER_ACTIVE);
     208                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS);
     209                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VERR_TIMER_SUSPENDED);
     210                RTThreadSleep(1);
     211                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots));
     212            } while (0);
     213            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
     214            RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS);
    117215            break;
    118216        }
    119217
    120         case TSTRTR0TIMER_GOOD:
     218#if 1 /* might have to disable this for some host... */
     219        case TSTRTR0TIMER_ONE_SHOT_RESTART:
     220        case TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES:
    121221        {
    122             for (unsigned off = 0; off < 16 && !*pszErr; off++)
    123                 for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++)
    124                     TEST_OFF_SIZE(off, cb, VINF_SUCCESS);
    125             break;
    126         }
    127 
    128         case TSTRTR0TIMER_BAD:
    129         {
    130             for (unsigned off = 0; off < 16 && !*pszErr; off++)
    131                 for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++)
    132                     TEST_OFF_SIZE(off, cb, cb > 0 ? VERR_ACCESS_DENIED : VINF_SUCCESS);
    133             break;
    134         }
    135 
    136         case TSTRTR0TIMER_INVALID_ADDRESS:
    137         {
    138             if (    !RTR0MemUserIsValidAddr(R3Ptr)
    139                 &&  RTR0MemKernelIsValidAddr((void *)R3Ptr))
     222            /* Create a one-shot timer and restart it in the callback handler. */
     223            PRTTIMER            pTimer;
     224            uint32_t            fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0;
     225            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackRestartOnce, &State),
     226                                      VINF_SUCCESS);
     227
     228            do /* break loop */
    140229            {
    141                 for (unsigned off = 0; off < 16 && !*pszErr; off++)
    142                     for (unsigned cb = 0; cb < PAGE_SIZE - 16; cb++)
    143                         TEST_OFF_SIZE(off, cb, cb > 0 ? VERR_ACCESS_DENIED : VINF_SUCCESS); /* ... */
    144             }
    145             else
    146                 RTStrPrintf(pszErr, cchErr, "RTR0MemUserIsValidAddr returns true");
     230                RT_ZERO(State);
     231                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
     232                for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 2; i++)
     233                    RTThreadSleep(5);
     234                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 2, ("cShots=%u\n", State.cShots));
     235            } while (0);
     236            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
    147237            break;
    148238        }
    149239#endif
    150240
    151         default:
    152             RTStrPrintf(pszErr, cchErr, "!Unknown test #%d", uOperation);
     241        case TSTRTR0TIMER_PERIODIC_BASIC:
     242        case TSTRTR0TIMER_PERIODIC_BASIC_HIRES:
     243        {
     244            /* Create a periodic timer running at 10 HZ. */
     245            uint32_t const  u10HzAsNs    = 100000000;
     246            uint32_t const  u10HzAsNsMin = u10HzAsNs - u10HzAsNs / 2;
     247            uint32_t const  u10HzAsNsMax = u10HzAsNs + u10HzAsNs / 2;
     248            PRTTIMER        pTimer;
     249            uint32_t        fFlags = uOperation != TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES ? RTTIMER_FLAGS_HIGH_RES : 0;
     250            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, u10HzAsNs, fFlags, tstRTR0TimerCallbackU32Counter, &State),
     251                                      VINF_SUCCESS);
     252
     253            for (uint32_t iTest = 0; iTest < 2; iTest++)
     254            {
     255                RT_ZERO(State);
     256                uint64_t uStartNsTS = RTTimeSystemNanoTS();
     257                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, u10HzAsNs), VINF_SUCCESS);
     258                for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 10; i++)
     259                    RTThreadSleep(10);
     260                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
     261                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 10, ("cShots=%u\n", State.cShots));
     262                if (tstRTR0TimerCheckShotIntervals(&State, uStartNsTS, u10HzAsNsMin, u10HzAsNsMax))
     263                    break;
     264            }
     265            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
     266            RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS);
    153267            break;
     268        }
    154269    }
    155270
     271    RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr);
    156272    /* The error indicator is the '!' in the message buffer. */
    157273    return VINF_SUCCESS;
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