~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/testcase/tstRTR0Timer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: tstRTR0Timer.cpp 33540 2010-10-28 09:27:05Z vboxsync $ */
 
2
/** @file
 
3
 * IPRT R0 Testcase - Timers.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2009-2010 Oracle Corporation
 
8
 *
 
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
10
 * available from http://www.virtualbox.org. This file is free software;
 
11
 * you can redistribute it and/or modify it under the terms of the GNU
 
12
 * General Public License (GPL) as published by the Free Software
 
13
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
14
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
15
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
16
 *
 
17
 * The contents of this file may alternatively be used under the terms
 
18
 * of the Common Development and Distribution License Version 1.0
 
19
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 
20
 * VirtualBox OSE distribution, in which case the provisions of the
 
21
 * CDDL are applicable instead of those of the GPL.
 
22
 *
 
23
 * You may elect to license modified versions of this file under the
 
24
 * terms and conditions of either the GPL or the CDDL or both.
 
25
 */
 
26
 
 
27
 
 
28
/*******************************************************************************
 
29
*   Header Files                                                               *
 
30
*******************************************************************************/
 
31
#include <iprt/timer.h>
 
32
 
 
33
#include <iprt/asm.h>
 
34
#include <iprt/cpuset.h>
 
35
#include <iprt/err.h>
 
36
#include <iprt/mem.h>
 
37
#include <iprt/mp.h>
 
38
#include <iprt/param.h>
 
39
#include <iprt/string.h>
 
40
#include <iprt/thread.h>
 
41
#include <iprt/time.h>
 
42
#include <VBox/sup.h>
 
43
#include "tstRTR0Timer.h"
 
44
#include "tstRTR0Common.h"
 
45
 
 
46
 
 
47
/*******************************************************************************
 
48
*   Structures and Typedefs                                                    *
 
49
*******************************************************************************/
 
50
typedef struct
 
51
{
 
52
    /** Array of nano second timestamp of the first few shots. */
 
53
    uint64_t volatile   aShotNsTSes[10];
 
54
    /** The number of shots. */
 
55
    uint32_t volatile   cShots;
 
56
    /** The shot at which action is to be taken. */
 
57
    uint32_t            iActionShot;
 
58
    /** The RC of whatever operation performed in the handler. */
 
59
    int volatile        rc;
 
60
    /** Set if it's a periodic test. */
 
61
    bool                fPeriodic;
 
62
    /** Test specific stuff. */
 
63
    union
 
64
    {
 
65
        /** tstRTR0TimerCallbackU32ChangeInterval parameters.  */
 
66
        struct
 
67
        {
 
68
            /** The interval change step. */
 
69
            uint32_t            cNsChangeStep;
 
70
            /** The current timer interval. */
 
71
            uint32_t            cNsCurInterval;
 
72
            /** The minimum interval. */
 
73
            uint32_t            cNsMinInterval;
 
74
            /** The maximum interval. */
 
75
            uint32_t            cNsMaxInterval;
 
76
            /** Direction flag; false = decrement, true = increment. */
 
77
            bool                fDirection;
 
78
            /** The number of steps between each change. */
 
79
            uint8_t             cStepsBetween;
 
80
        } ChgInt;
 
81
        /** tstRTR0TimerCallbackSpecific parameters.  */
 
82
        struct
 
83
        {
 
84
            /** The expected CPU. */
 
85
            RTCPUID             idCpu;
 
86
            /** Set if this failed. */
 
87
            bool                fFailed;
 
88
        } Specific;
 
89
    } u;
 
90
} TSTRTR0TIMERS1;
 
91
typedef TSTRTR0TIMERS1 *PTSTRTR0TIMERS1;
 
92
 
 
93
 
 
94
/**
 
95
 * Per cpu state for an omni timer test.
 
96
 */
 
97
typedef struct TSTRTR0TIMEROMNI1
 
98
{
 
99
    /** When we started receiving timer callbacks on this CPU. */
 
100
    uint64_t            u64Start;
 
101
    /** When we received the last tick on this timer. */
 
102
    uint64_t            u64Last;
 
103
    /** The number of ticks received on this CPU. */
 
104
    uint32_t volatile   cTicks;
 
105
    uint32_t            u32Padding;
 
106
} TSTRTR0TIMEROMNI1;
 
107
typedef TSTRTR0TIMEROMNI1 *PTSTRTR0TIMEROMNI1;
 
108
 
 
109
 
 
110
/**
 
111
 * Callback which increments a 32-bit counter.
 
112
 *
 
113
 * @param   pTimer      The timer.
 
114
 * @param   iTick       The current tick.
 
115
 * @param   pvUser      The user argument.
 
116
 */
 
117
static DECLCALLBACK(void) tstRTR0TimerCallbackOmni(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
118
{
 
119
    PTSTRTR0TIMEROMNI1  paStates = (PTSTRTR0TIMEROMNI1)pvUser;
 
120
    RTCPUID             idCpu    = RTMpCpuId();
 
121
    uint32_t            iCpu     = RTMpCpuIdToSetIndex(idCpu);
 
122
 
 
123
    RTR0TESTR0_CHECK_MSG(iCpu < RTCPUSET_MAX_CPUS, ("iCpu=%d idCpu=%u\n", iCpu, idCpu));
 
124
    if (iCpu < RTCPUSET_MAX_CPUS)
 
125
    {
 
126
        uint32_t iCountedTick = ASMAtomicIncU32(&paStates[iCpu].cTicks);
 
127
        RTR0TESTR0_CHECK_MSG(iCountedTick == iTick,
 
128
                             ("iCountedTick=%u iTick=%u iCpu=%d idCpu=%u\n", iCountedTick, iTick, iCpu, idCpu));
 
129
        paStates[iCpu].u64Last = RTTimeSystemNanoTS();
 
130
        if (!paStates[iCpu].u64Start)
 
131
        {
 
132
            paStates[iCpu].u64Start = paStates[iCpu].u64Last;
 
133
            RTR0TESTR0_CHECK_MSG(iCountedTick == 1, ("iCountedTick=%u iCpu=%d idCpu=%u\n", iCountedTick, iCpu, idCpu));
 
134
        }
 
135
    }
 
136
}
 
137
 
 
138
 
 
139
/**
 
140
 * Callback which increments a 32-bit counter.
 
141
 *
 
142
 * @param   pTimer      The timer.
 
143
 * @param   iTick       The current tick.
 
144
 * @param   pvUser      The user argument.
 
145
 */
 
146
static DECLCALLBACK(void) tstRTR0TimerCallbackSpecific(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
147
{
 
148
    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
 
149
    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
 
150
 
 
151
    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
 
152
        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
 
153
 
 
154
    RTCPUID idCpu = RTMpCpuId();
 
155
    if (pState->u.Specific.idCpu != idCpu)
 
156
        pState->u.Specific.fFailed = true;
 
157
    RTR0TESTR0_CHECK_MSG(pState->u.Specific.idCpu == idCpu, ("idCpu=%u, expected %u\n", idCpu, pState->u.Specific.idCpu));
 
158
 
 
159
    if (pState->fPeriodic)
 
160
        RTR0TESTR0_CHECK_MSG(iShot == iTick, ("iShot=%u iTick=%u\n", iShot, iTick));
 
161
    else
 
162
        RTR0TESTR0_CHECK_MSG(iTick == 1, ("iShot=%u iTick=%u\n", iShot, iTick));
 
163
}
 
164
 
 
165
 
 
166
/**
 
167
 * Callback which changes the interval at each invocation.
 
168
 *
 
169
 * The changes are governed by TSTRTR0TIMERS1::ChangeInterval.  The callback
 
170
 * calls RTTimerStop at iActionShot.
 
171
 *
 
172
 * @param   pTimer      The timer.
 
173
 * @param   iTick       The current tick.
 
174
 * @param   pvUser      The user argument.
 
175
 */
 
176
static DECLCALLBACK(void) tstRTR0TimerCallbackChangeInterval(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
177
{
 
178
    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
 
179
    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots) - 1;
 
180
 
 
181
    if (iShot < RT_ELEMENTS(pState->aShotNsTSes))
 
182
        pState->aShotNsTSes[iShot] = RTTimeSystemNanoTS();
 
183
    if (pState->fPeriodic)
 
184
        RTR0TESTR0_CHECK_MSG(iShot + 1 == iTick, ("iShot=%u iTick=%u\n", iShot, iTick));
 
185
    else
 
186
        RTR0TESTR0_CHECK_MSG(iTick == 1, ("iShot=%u iTick=%u\n", iShot, iTick));
 
187
 
 
188
    if (!(iShot % pState->u.ChgInt.cStepsBetween))
 
189
    {
 
190
        if (pState->u.ChgInt.fDirection)
 
191
        {
 
192
            pState->u.ChgInt.cNsCurInterval += pState->u.ChgInt.cNsChangeStep;
 
193
            if (   pState->u.ChgInt.cNsCurInterval > pState->u.ChgInt.cNsMaxInterval
 
194
                || pState->u.ChgInt.cNsCurInterval < pState->u.ChgInt.cNsMinInterval
 
195
                || !pState->u.ChgInt.cNsCurInterval)
 
196
            {
 
197
                pState->u.ChgInt.cNsCurInterval = pState->u.ChgInt.cNsMaxInterval;
 
198
                pState->u.ChgInt.fDirection = false;
 
199
            }
 
200
        }
 
201
        else
 
202
        {
 
203
            pState->u.ChgInt.cNsCurInterval -= pState->u.ChgInt.cNsChangeStep;
 
204
            if (   pState->u.ChgInt.cNsCurInterval < pState->u.ChgInt.cNsMinInterval
 
205
                || pState->u.ChgInt.cNsCurInterval > pState->u.ChgInt.cNsMaxInterval
 
206
                || pState->u.ChgInt.cNsCurInterval)
 
207
            {
 
208
                pState->u.ChgInt.cNsCurInterval = pState->u.ChgInt.cNsMinInterval;
 
209
                pState->u.ChgInt.fDirection = true;
 
210
            }
 
211
        }
 
212
 
 
213
        RTR0TESTR0_CHECK_RC(RTTimerChangeInterval(pTimer, pState->u.ChgInt.cNsCurInterval), VINF_SUCCESS);
 
214
    }
 
215
 
 
216
    if (iShot == pState->iActionShot)
 
217
        RTR0TESTR0_CHECK_RC(pState->rc = RTTimerStop(pTimer), VINF_SUCCESS);
 
218
}
 
219
 
 
220
 
 
221
/**
 
222
 * Callback which increments destroy the timer when it fires.
 
223
 *
 
224
 * @param   pTimer      The timer.
 
225
 * @param   iTick       The current tick.
 
226
 * @param   pvUser      The user argument.
 
227
 */
 
228
static DECLCALLBACK(void) tstRTR0TimerCallbackDestroyOnce(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
229
{
 
230
    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
 
231
    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
 
232
 
 
233
    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
 
234
        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
 
235
    if (pState->fPeriodic)
 
236
        RTR0TESTR0_CHECK_MSG(iShot == iTick, ("iShot=%u iTick=%u\n", iShot, iTick));
 
237
    else
 
238
        RTR0TESTR0_CHECK_MSG(iTick == 1, ("iShot=%u iTick=%u\n", iShot, iTick));
 
239
 
 
240
    if (iShot == pState->iActionShot + 1)
 
241
        RTR0TESTR0_CHECK_RC(pState->rc = RTTimerDestroy(pTimer), VINF_SUCCESS);
 
242
}
 
243
 
 
244
 
 
245
/**
 
246
 * Callback which increments restarts a timer once.
 
247
 *
 
248
 * @param   pTimer      The timer.
 
249
 * @param   iTick       The current tick.
 
250
 * @param   pvUser      The user argument.
 
251
 */
 
252
static DECLCALLBACK(void) tstRTR0TimerCallbackRestartOnce(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
253
{
 
254
    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
 
255
    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
 
256
 
 
257
    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
 
258
        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
 
259
    if (pState->fPeriodic)
 
260
        RTR0TESTR0_CHECK_MSG(iShot == iTick, ("iShot=%u iTick=%u\n", iShot, iTick));
 
261
    else
 
262
        RTR0TESTR0_CHECK_MSG(iTick == 1, ("iShot=%u iTick=%u\n", iShot, iTick));
 
263
 
 
264
    if (iShot == pState->iActionShot + 1)
 
265
        RTR0TESTR0_CHECK_RC(pState->rc = RTTimerStart(pTimer, 10000000 /* 10ms */), VINF_SUCCESS);
 
266
}
 
267
 
 
268
 
 
269
/**
 
270
 * Callback which increments a 32-bit counter.
 
271
 *
 
272
 * @param   pTimer      The timer.
 
273
 * @param   iTick       The current tick.
 
274
 * @param   pvUser      The user argument.
 
275
 */
 
276
static DECLCALLBACK(void) tstRTR0TimerCallbackU32Counter(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
 
277
{
 
278
    PTSTRTR0TIMERS1 pState = (PTSTRTR0TIMERS1)pvUser;
 
279
    uint32_t        iShot  = ASMAtomicIncU32(&pState->cShots);
 
280
 
 
281
    if (iShot <= RT_ELEMENTS(pState->aShotNsTSes))
 
282
        pState->aShotNsTSes[iShot - 1] = RTTimeSystemNanoTS();
 
283
    if (pState->fPeriodic)
 
284
        RTR0TESTR0_CHECK_MSG(iShot == iTick, ("iShot=%u iTick=%u\n", iShot, iTick));
 
285
    else
 
286
        RTR0TESTR0_CHECK_MSG(iTick == 1, ("iShot=%u iTick=%u\n", iShot, iTick));
 
287
}
 
288
 
 
289
 
 
290
/**
 
291
 * Checks that the interval between two timer shots are within the specified
 
292
 * range.
 
293
 *
 
294
 * @returns 0 if ok, 1 if bad.
 
295
 * @param   iShot               The shot number (for bitching).
 
296
 * @param   uPrevTS             The time stamp of the previous shot (ns).
 
297
 * @param   uThisTS             The timer stamp of this shot (ns).
 
298
 * @param   uMin                The minimum interval (ns).
 
299
 * @param   uMax                The maximum interval (ns).
 
300
 */
 
301
static int tstRTR0TimerCheckShotInterval(uint32_t iShot, uint64_t uPrevTS, uint64_t uThisTS, uint32_t uMin, uint32_t uMax)
 
302
{
 
303
    uint64_t uDelta = uThisTS - uPrevTS;
 
304
    RTR0TESTR0_CHECK_MSG_RET(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin), 1);
 
305
    RTR0TESTR0_CHECK_MSG_RET(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax), 1);
 
306
    return 0;
 
307
}
 
308
 
 
309
 
 
310
/**
 
311
 * Checks that the interval between timer shots are within a certain range.
 
312
 *
 
313
 * @returns Number of violations (i.e. 0 is ok).
 
314
 * @param   pState              The state.
 
315
 * @param   uStartNsTS          The start time stamp (ns).
 
316
 * @param   uMin                The minimum interval (ns).
 
317
 * @param   uMax                The maximum interval (ns).
 
318
 */
 
319
static int tstRTR0TimerCheckShotIntervals(PTSTRTR0TIMERS1 pState, uint64_t uStartNsTS, uint32_t uMin, uint32_t uMax)
 
320
{
 
321
    uint64_t uMaxDelta = 0;
 
322
    uint64_t uMinDelta = UINT64_MAX;
 
323
    uint32_t cBadShots = 0;
 
324
    uint32_t cShots    = pState->cShots;
 
325
    uint64_t uPrevTS   = uStartNsTS;
 
326
    for (uint32_t iShot = 0; iShot < cShots; iShot++)
 
327
    {
 
328
        uint64_t uThisTS = pState->aShotNsTSes[iShot];
 
329
        uint64_t uDelta  = uThisTS - uPrevTS;
 
330
        if (uDelta > uMaxDelta)
 
331
            uMaxDelta = uDelta;
 
332
        if (uDelta < uMinDelta)
 
333
            uMinDelta = uDelta;
 
334
        cBadShots += !(uDelta >= uMin && uDelta <= uMax);
 
335
 
 
336
        RTR0TESTR0_CHECK_MSG(uDelta >= uMin, ("iShot=%u uDelta=%lld uMin=%u\n", iShot, uDelta, uMin));
 
337
        RTR0TESTR0_CHECK_MSG(uDelta <= uMax, ("iShot=%u uDelta=%lld uMax=%u\n", iShot, uDelta, uMax));
 
338
 
 
339
        uPrevTS = uThisTS;
 
340
    }
 
341
 
 
342
    RTR0TestR0Info("uMaxDelta=%llu uMinDelta=%llu\n", uMaxDelta, uMinDelta);
 
343
    return cBadShots;
 
344
}
 
345
 
 
346
 
 
347
/**
 
348
 * Service request callback function.
 
349
 *
 
350
 * @returns VBox status code.
 
351
 * @param   pSession    The caller's session.
 
352
 * @param   u64Arg      64-bit integer argument.
 
353
 * @param   pReqHdr     The request header. Input / Output. Optional.
 
354
 */
 
355
DECLEXPORT(int) TSTRTR0TimerSrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation,
 
356
                                          uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
 
357
{
 
358
    RTR0TESTR0_SRV_REQ_PROLOG_RET(pReqHdr);
 
359
 
 
360
    /*
 
361
     * Common parameter and state variables.
 
362
     */
 
363
    uint32_t const cNsSysHz        = RTTimerGetSystemGranularity();
 
364
    uint32_t const cNsMaxHighResHz = 10000; /** @todo need API for this */
 
365
    TSTRTR0TIMERS1 State;
 
366
    if (   cNsSysHz             < UINT32_C(1000)
 
367
        || cNsSysHz             > UINT32_C(1000000000)
 
368
        || cNsMaxHighResHz      < UINT32_C(1)
 
369
        || cNsMaxHighResHz      > UINT32_C(1000000000))
 
370
    {
 
371
        RTR0TESTR0_CHECK_MSG(cNsSysHz        > UINT32_C(1000) && cNsSysHz     < UINT32_C(1000000000), ("%u", cNsSysHz));
 
372
        RTR0TESTR0_CHECK_MSG(cNsMaxHighResHz > UINT32_C(1) && cNsMaxHighResHz < UINT32_C(1000000000), ("%u", cNsMaxHighResHz));
 
373
        RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr);
 
374
        return VINF_SUCCESS;
 
375
    }
 
376
 
 
377
    /*
 
378
     * The big switch.
 
379
     */
 
380
    switch (uOperation)
 
381
    {
 
382
        RTR0TESTR0_IMPLEMENT_SANITY_CASES();
 
383
        RTR0TESTR0_IMPLEMENT_DEFAULT_CASE(uOperation);
 
384
 
 
385
        case TSTRTR0TIMER_ONE_SHOT_BASIC:
 
386
        case TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES:
 
387
        {
 
388
            /* Create a one-shot timer and take one shot. */
 
389
            PRTTIMER pTimer;
 
390
            uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
391
            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackU32Counter, &State),
 
392
                                      VINF_SUCCESS);
 
393
 
 
394
            do /* break loop */
 
395
            {
 
396
                RT_ZERO(State);
 
397
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
 
398
                for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++)
 
399
                    RTThreadSleep(5);
 
400
                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots));
 
401
 
 
402
                /* check that it is restartable. */
 
403
                RT_ZERO(State);
 
404
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
 
405
                for (uint32_t i = 0; i < 1000 && !ASMAtomicUoReadU32(&State.cShots); i++)
 
406
                    RTThreadSleep(5);
 
407
                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots));
 
408
 
 
409
                /* check that it respects the timeout value and can be cancelled. */
 
410
                RT_ZERO(State);
 
411
                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS);
 
412
                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS);
 
413
                RTThreadSleep(1);
 
414
                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots));
 
415
 
 
416
                /* Check some double starts and stops (shall not assert). */
 
417
                RT_ZERO(State);
 
418
                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 5*UINT64_C(1000000000)), VINF_SUCCESS);
 
419
                RTR0TESTR0_CHECK_RC(RTTimerStart(pTimer, 0), VERR_TIMER_ACTIVE);
 
420
                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VINF_SUCCESS);
 
421
                RTR0TESTR0_CHECK_RC(RTTimerStop(pTimer), VERR_TIMER_SUSPENDED);
 
422
                RTThreadSleep(1);
 
423
                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 0, ("cShots=%u\n", State.cShots));
 
424
            } while (0);
 
425
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
426
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS);
 
427
            break;
 
428
        }
 
429
 
 
430
#if 1 /* might have to disable this for some host... */
 
431
        case TSTRTR0TIMER_ONE_SHOT_RESTART:
 
432
        case TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES:
 
433
        {
 
434
            /* Create a one-shot timer and restart it in the callback handler. */
 
435
            PRTTIMER pTimer;
 
436
            uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
437
            for (uint32_t iTest = 0; iTest < 2; iTest++)
 
438
            {
 
439
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackRestartOnce, &State),
 
440
                                          VINF_SUCCESS);
 
441
 
 
442
                RT_ZERO(State);
 
443
                State.iActionShot = 0;
 
444
                do /* break loop */
 
445
                {
 
446
                    RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, cNsSysHz * iTest), VINF_SUCCESS);
 
447
                    for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 2; i++)
 
448
                        RTThreadSleep(5);
 
449
                    RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 2, ("cShots=%u\n", State.cShots));
 
450
                } while (0);
 
451
                RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
452
            }
 
453
            break;
 
454
        }
 
455
#endif
 
456
 
 
457
#if 1 /* might have to disable this for some host... */
 
458
        case TSTRTR0TIMER_ONE_SHOT_DESTROY:
 
459
        case TSTRTR0TIMER_ONE_SHOT_DESTROY_HIRES:
 
460
        {
 
461
            /* Create a one-shot timer and destroy it in the callback handler. */
 
462
            PRTTIMER pTimer;
 
463
            uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
464
            for (uint32_t iTest = 0; iTest < 2; iTest++)
 
465
            {
 
466
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackDestroyOnce, &State),
 
467
                                          VINF_SUCCESS);
 
468
 
 
469
                RT_ZERO(State);
 
470
                State.rc = VERR_IPE_UNINITIALIZED_STATUS;
 
471
                State.iActionShot = 0;
 
472
                do /* break loop */
 
473
                {
 
474
                    RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, cNsSysHz * iTest), VINF_SUCCESS);
 
475
                    for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 1; i++)
 
476
                        RTThreadSleep(5);
 
477
                    RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicReadU32(&State.cShots) == 1, ("cShots=%u\n", State.cShots));
 
478
                    RTR0TESTR0_CHECK_MSG_BREAK(State.rc == VINF_SUCCESS, ("rc=%Rrc\n", State.rc));
 
479
                } while (0);
 
480
                if (RT_FAILURE(State.rc))
 
481
                    RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
482
            }
 
483
            break;
 
484
        }
 
485
#endif
 
486
 
 
487
        case TSTRTR0TIMER_ONE_SHOT_SPECIFIC:
 
488
        case TSTRTR0TIMER_ONE_SHOT_SPECIFIC_HIRES:
 
489
        {
 
490
            PRTTIMER pTimer = NULL;
 
491
            RTCPUSET OnlineSet;
 
492
            RTMpGetOnlineSet(&OnlineSet);
 
493
            for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
 
494
                if (RTCpuSetIsMemberByIndex(&OnlineSet, iCpu))
 
495
                {
 
496
                    RT_ZERO(State);
 
497
                    State.iActionShot       = 0;
 
498
                    State.rc                = VINF_SUCCESS;
 
499
                    State.u.Specific.idCpu  = RTMpCpuIdFromSetIndex(iCpu);
 
500
 
 
501
                    uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
502
                    fFlags |= RTTIMER_FLAGS_CPU(iCpu);
 
503
                    int rc = RTTimerCreateEx(&pTimer, 0, fFlags, tstRTR0TimerCallbackSpecific, &State);
 
504
                    if (rc == VERR_NOT_SUPPORTED)
 
505
                    {
 
506
                        RTR0TestR0Info("specific timer are not supported, skipping\n");
 
507
                        break;
 
508
                    }
 
509
                    RTR0TESTR0_CHECK_RC_BREAK(rc, VINF_SUCCESS);
 
510
 
 
511
                    for (uint32_t i = 0; i < 5 && !RTR0TestR0HaveErrors(); i++)
 
512
                    {
 
513
                        ASMAtomicWriteU32(&State.cShots, 0);
 
514
                        RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, (i & 2 ? cNsSysHz : cNsSysHz / 2) * (i & 1)), VINF_SUCCESS);
 
515
                        uint64_t cNsElapsed = RTTimeSystemNanoTS();
 
516
                        for (uint32_t j = 0; j < 1000 && ASMAtomicUoReadU32(&State.cShots) < 1; j++)
 
517
                            RTThreadSleep(5);
 
518
                        cNsElapsed = RTTimeSystemNanoTS() - cNsElapsed;
 
519
                        RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicReadU32(&State.cShots) == 1,
 
520
                                                   ("cShots=%u iCpu=%u i=%u iCurCpu=%u cNsElapsed=%'llu\n",
 
521
                                                    State.cShots, iCpu, i, RTMpCpuIdToSetIndex(RTMpCpuId()), cNsElapsed ));
 
522
                        RTR0TESTR0_CHECK_MSG_BREAK(State.rc == VINF_SUCCESS, ("rc=%Rrc\n", State.rc));
 
523
                        RTR0TESTR0_CHECK_MSG_BREAK(!State.u.Specific.fFailed, ("iCpu=%u i=%u\n", iCpu, i));
 
524
                    }
 
525
 
 
526
                    RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
527
                    pTimer = NULL;
 
528
                    if (RTR0TestR0HaveErrors())
 
529
                        break;
 
530
 
 
531
                    RTMpGetOnlineSet(&OnlineSet);
 
532
                }
 
533
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
534
            break;
 
535
        }
 
536
 
 
537
        case TSTRTR0TIMER_PERIODIC_BASIC:
 
538
        case TSTRTR0TIMER_PERIODIC_BASIC_HIRES:
 
539
        {
 
540
            /* Create a periodic timer running at 10 HZ. */
 
541
            uint32_t const  u10HzAsNs    = 100000000;
 
542
            uint32_t const  u10HzAsNsMin = u10HzAsNs - u10HzAsNs / 2;
 
543
            uint32_t const  u10HzAsNsMax = u10HzAsNs + u10HzAsNs / 2;
 
544
            PRTTIMER        pTimer;
 
545
            uint32_t        fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
546
            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, u10HzAsNs, fFlags, tstRTR0TimerCallbackU32Counter, &State),
 
547
                                      VINF_SUCCESS);
 
548
 
 
549
            for (uint32_t iTest = 0; iTest < 2; iTest++)
 
550
            {
 
551
                RT_ZERO(State);
 
552
                State.fPeriodic = true;
 
553
                uint64_t uStartNsTS = RTTimeSystemNanoTS();
 
554
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, u10HzAsNs), VINF_SUCCESS);
 
555
                for (uint32_t i = 0; i < 1000 && ASMAtomicUoReadU32(&State.cShots) < 10; i++)
 
556
                    RTThreadSleep(10);
 
557
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
 
558
                RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicUoReadU32(&State.cShots) == 10, ("cShots=%u\n", State.cShots));
 
559
                if (tstRTR0TimerCheckShotIntervals(&State, uStartNsTS, u10HzAsNsMin, u10HzAsNsMax))
 
560
                    break;
 
561
            }
 
562
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
563
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(NULL), VINF_SUCCESS);
 
564
            break;
 
565
        }
 
566
 
 
567
        case TSTRTR0TIMER_PERIODIC_CSSD_LOOPS:
 
568
        case TSTRTR0TIMER_PERIODIC_CSSD_LOOPS_HIRES:
 
569
        {
 
570
            /* create, start, stop & destroy high res timers a number of times. */
 
571
            uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
572
            for (uint32_t i = 0; i < 40; i++)
 
573
            {
 
574
                PRTTIMER pTimer;
 
575
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, cNsSysHz, fFlags, tstRTR0TimerCallbackU32Counter, &State),
 
576
                                          VINF_SUCCESS);
 
577
                for (uint32_t j = 0; j < 10; j++)
 
578
                {
 
579
                    RT_ZERO(State);
 
580
                    State.fPeriodic = true;
 
581
                    RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, i < 20 ? 0 : cNsSysHz), VINF_SUCCESS);
 
582
                    for (uint32_t k = 0; k < 1000 && ASMAtomicUoReadU32(&State.cShots) < 2; k++)
 
583
                        RTThreadSleep(1);
 
584
                    RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
 
585
                }
 
586
                RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
587
            }
 
588
            break;
 
589
        }
 
590
 
 
591
        case TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL:
 
592
        case TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL_HIRES:
 
593
        {
 
594
            /* Initialize the test parameters, using the u64Arg value for selecting variations.  */
 
595
            RT_ZERO(State);
 
596
            State.cShots        = 0;
 
597
            State.rc            = VERR_IPE_UNINITIALIZED_STATUS;
 
598
            State.iActionShot   = 42;
 
599
            State.fPeriodic     = true;
 
600
            State.u.ChgInt.fDirection     = !!(u64Arg & 1);
 
601
            if (uOperation == TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL_HIRES)
 
602
            {
 
603
                State.u.ChgInt.cNsMaxInterval = RT_MAX(cNsMaxHighResHz * 10, 20000000); /* 10x / 20 ms */
 
604
                State.u.ChgInt.cNsMinInterval = RT_MAX(cNsMaxHighResHz,         10000); /* min / 10 us */
 
605
            }
 
606
            else
 
607
            {
 
608
                State.u.ChgInt.cNsMaxInterval = cNsSysHz * 4;
 
609
                State.u.ChgInt.cNsMinInterval = cNsSysHz;
 
610
            }
 
611
            State.u.ChgInt.cNsChangeStep  = (State.u.ChgInt.cNsMaxInterval - State.u.ChgInt.cNsMinInterval) / 10;
 
612
            State.u.ChgInt.cNsCurInterval = State.u.ChgInt.fDirection
 
613
                                          ? State.u.ChgInt.cNsMaxInterval : State.u.ChgInt.cNsMinInterval;
 
614
            State.u.ChgInt.cStepsBetween  = u64Arg & 4 ? 1 : 3;
 
615
            RTR0TESTR0_CHECK_MSG_BREAK(State.u.ChgInt.cNsMinInterval > 1000, ("%u\n", State.u.ChgInt.cNsMinInterval));
 
616
            RTR0TESTR0_CHECK_MSG_BREAK(State.u.ChgInt.cNsMaxInterval > State.u.ChgInt.cNsMinInterval, ("max=%u min=%u\n", State.u.ChgInt.cNsMaxInterval, State.u.ChgInt.cNsMinInterval));
 
617
 
 
618
            /* create the timer and check if RTTimerChangeInterval is supported. */
 
619
            PRTTIMER pTimer;
 
620
            uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
621
            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, cNsSysHz, fFlags, tstRTR0TimerCallbackChangeInterval, &State),
 
622
                                      VINF_SUCCESS);
 
623
            int rc = RTTimerChangeInterval(pTimer, State.u.ChgInt.cNsMinInterval);
 
624
            if (rc == VERR_NOT_SUPPORTED)
 
625
            {
 
626
                RTR0TestR0Info("RTTimerChangeInterval not supported, skipped");
 
627
                RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
628
                break;
 
629
            }
 
630
 
 
631
            /* do the test. */
 
632
            RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, u64Arg & 2 ? State.u.ChgInt.cNsCurInterval : 0), VINF_SUCCESS);
 
633
            for (uint32_t k = 0;
 
634
                    k < 1000
 
635
                 && ASMAtomicReadU32(&State.cShots) <= State.iActionShot
 
636
                 && State.rc == VERR_IPE_UNINITIALIZED_STATUS;
 
637
                 k++)
 
638
                RTThreadSleep(10);
 
639
 
 
640
            rc = RTTimerStop(pTimer);
 
641
            RTR0TESTR0_CHECK_MSG_BREAK(rc == VERR_TIMER_SUSPENDED || rc == VINF_SUCCESS, ("rc = %Rrc (RTTimerStop)\n", rc));
 
642
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
643
            break;
 
644
        }
 
645
 
 
646
        case TSTRTR0TIMER_PERIODIC_SPECIFIC:
 
647
        case TSTRTR0TIMER_PERIODIC_SPECIFIC_HIRES:
 
648
        {
 
649
            PRTTIMER pTimer = NULL;
 
650
            RTCPUSET OnlineSet;
 
651
            RTMpGetOnlineSet(&OnlineSet);
 
652
            for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
 
653
                if (RTCpuSetIsMemberByIndex(&OnlineSet, iCpu))
 
654
                {
 
655
                    RT_ZERO(State);
 
656
                    State.iActionShot       = 0;
 
657
                    State.rc                = VINF_SUCCESS;
 
658
                    State.fPeriodic         = true;
 
659
                    State.u.Specific.idCpu  = RTMpCpuIdFromSetIndex(iCpu);
 
660
 
 
661
                    uint32_t fFlags = TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0;
 
662
                    fFlags |= RTTIMER_FLAGS_CPU(iCpu);
 
663
                    int rc = RTTimerCreateEx(&pTimer, cNsSysHz, fFlags, tstRTR0TimerCallbackSpecific, &State);
 
664
                    if (rc == VERR_NOT_SUPPORTED)
 
665
                    {
 
666
                        RTR0TestR0Info("specific timer are not supported, skipping\n");
 
667
                        break;
 
668
                    }
 
669
                    RTR0TESTR0_CHECK_RC_BREAK(rc, VINF_SUCCESS);
 
670
 
 
671
                    for (uint32_t i = 0; i < 3 && !RTR0TestR0HaveErrors(); i++)
 
672
                    {
 
673
                        ASMAtomicWriteU32(&State.cShots, 0);
 
674
                        RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, (i & 2 ? cNsSysHz : cNsSysHz / 2) * (i & 1)), VINF_SUCCESS);
 
675
                        uint64_t cNsElapsed = RTTimeSystemNanoTS();
 
676
                        for (uint32_t j = 0; j < 1000 && ASMAtomicUoReadU32(&State.cShots) < 8; j++)
 
677
                            RTThreadSleep(5);
 
678
                        cNsElapsed = RTTimeSystemNanoTS() - cNsElapsed;
 
679
                        RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
 
680
                        RTR0TESTR0_CHECK_MSG_BREAK(ASMAtomicReadU32(&State.cShots) > 5,
 
681
                                                   ("cShots=%u iCpu=%u i=%u iCurCpu=%u cNsElapsed=%'llu\n",
 
682
                                                    State.cShots, iCpu, i, RTMpCpuIdToSetIndex(RTMpCpuId()), cNsElapsed));
 
683
                        RTR0TESTR0_CHECK_MSG_BREAK(State.rc == VINF_SUCCESS, ("rc=%Rrc\n", State.rc));
 
684
                        RTR0TESTR0_CHECK_MSG_BREAK(!State.u.Specific.fFailed, ("iCpu=%u i=%u\n", iCpu, i));
 
685
                    }
 
686
 
 
687
                    RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
688
                    pTimer = NULL;
 
689
                    if (RTR0TestR0HaveErrors())
 
690
                        break;
 
691
 
 
692
                    RTMpGetOnlineSet(&OnlineSet);
 
693
                }
 
694
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
695
            break;
 
696
        }
 
697
 
 
698
        case TSTRTR0TIMER_PERIODIC_OMNI:
 
699
        case TSTRTR0TIMER_PERIODIC_OMNI_HIRES:
 
700
        {
 
701
            /* Create a periodic timer running at max host frequency, but no more than 1000 Hz. */
 
702
            uint32_t        cNsInterval = cNsSysHz;
 
703
            while (cNsInterval < UINT32_C(1000000))
 
704
                cNsInterval *= 2;
 
705
            PTSTRTR0TIMEROMNI1 paStates = (PTSTRTR0TIMEROMNI1)RTMemAllocZ(sizeof(paStates[0]) * RTCPUSET_MAX_CPUS);
 
706
            RTR0TESTR0_CHECK_MSG_BREAK(paStates, ("%d\n", RTCPUSET_MAX_CPUS));
 
707
 
 
708
            PRTTIMER        pTimer;
 
709
            uint32_t        fFlags = (TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0)
 
710
                                   | RTTIMER_FLAGS_CPU_ALL;
 
711
            RTR0TESTR0_CHECK_RC_BREAK(RTTimerCreateEx(&pTimer, cNsInterval, fFlags, tstRTR0TimerCallbackOmni, paStates),
 
712
                                      VINF_SUCCESS);
 
713
 
 
714
            for (uint32_t iTest = 0; iTest < 3 && !RTR0TestR0HaveErrors(); iTest++)
 
715
            {
 
716
                /* reset the state */
 
717
                for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
 
718
                {
 
719
                    paStates[iCpu].u64Start = 0;
 
720
                    paStates[iCpu].u64Last  = 0;
 
721
                    ASMAtomicWriteU32(&paStates[iCpu].cTicks, 0);
 
722
                }
 
723
 
 
724
                /* run it for 1 second. */
 
725
                RTCPUSET OnlineSet;
 
726
                uint64_t uStartNsTS = RTTimeSystemNanoTS();
 
727
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
 
728
                RTMpGetOnlineSet(&OnlineSet);
 
729
 
 
730
                for (uint32_t i = 0; i < 5000 && RTTimeSystemNanoTS() - uStartNsTS <= UINT32_C(1000000000); i++)
 
731
                    RTThreadSleep(2);
 
732
 
 
733
                RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
 
734
                uint64_t    cNsElapsedX = RTTimeNanoTS() - uStartNsTS;
 
735
 
 
736
                /* Do a min/max on the start and stop times and calculate the test period. */
 
737
                uint64_t    u64MinStart = UINT64_MAX;
 
738
                uint64_t    u64MaxStop  = 0;
 
739
                for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
 
740
                {
 
741
                    if (paStates[iCpu].u64Start)
 
742
                    {
 
743
                        if (paStates[iCpu].u64Start < u64MinStart)
 
744
                            u64MinStart = paStates[iCpu].u64Start;
 
745
                        if (paStates[iCpu].u64Last  > u64MaxStop)
 
746
                            u64MaxStop  = paStates[iCpu].u64Last;
 
747
                    }
 
748
                }
 
749
                RTR0TESTR0_CHECK_MSG(u64MinStart < u64MaxStop, ("%llu, %llu", u64MinStart, u64MaxStop));
 
750
                uint64_t cNsElapsed = u64MaxStop - u64MinStart;
 
751
                RTR0TESTR0_CHECK_MSG(cNsElapsed <= cNsElapsedX + 100000, ("%llu, %llu", cNsElapsed, cNsElapsedX)); /* the fudge factor is time drift */
 
752
                uint32_t cAvgTicks  = cNsElapsed / cNsInterval + 1;
 
753
 
 
754
                /* Check tick counts. ASSUMES no cpu on- or offlining.
 
755
                   This only catches really bad stuff. */
 
756
                uint32_t cMinTicks = cAvgTicks - cAvgTicks / 10;
 
757
                uint32_t cMaxTicks = cAvgTicks + cAvgTicks / 10 + 1;
 
758
                for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
 
759
                    if (paStates[iCpu].cTicks)
 
760
                    {
 
761
                        RTR0TESTR0_CHECK_MSG(RTCpuSetIsMemberByIndex(&OnlineSet, iCpu), ("%d\n", iCpu));
 
762
                        RTR0TESTR0_CHECK_MSG(paStates[iCpu].cTicks <= cMaxTicks && paStates[iCpu].cTicks >= cMinTicks,
 
763
                                             ("min=%u, ticks=%u, avg=%u max=%u, iCpu=%u, interval=%'u, elapsed=%'llu/%'llu\n",
 
764
                                              cMinTicks, paStates[iCpu].cTicks, cAvgTicks, cMaxTicks, iCpu,
 
765
                                              cNsInterval, cNsElapsed, cNsElapsedX));
 
766
                    }
 
767
                    else
 
768
                        RTR0TESTR0_CHECK_MSG(!RTCpuSetIsMemberByIndex(&OnlineSet, iCpu), ("%d\n", iCpu));
 
769
            }
 
770
 
 
771
            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
 
772
            RTMemFree(paStates);
 
773
            break;
 
774
        }
 
775
    }
 
776
 
 
777
    RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr);
 
778
    /* The error indicator is the '!' in the message buffer. */
 
779
    return VINF_SUCCESS;
 
780
}
 
781