VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTTimerLR.cpp@ 93632

Last change on this file since 93632 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.4 KB
Line 
1/* $Id: tstRTTimerLR.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Low Resolution Timers.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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/errcore.h>
34#include <iprt/message.h>
35#include <iprt/stream.h>
36#include <iprt/test.h>
37#include <iprt/thread.h>
38#include <iprt/time.h>
39
40
41/*********************************************************************************************************************************
42* Global Variables *
43*********************************************************************************************************************************/
44static volatile unsigned gcTicks;
45static volatile uint64_t gu64Min;
46static volatile uint64_t gu64Max;
47static volatile uint64_t gu64Prev;
48
49
50static DECLCALLBACK(void) TimerLRCallback(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick)
51{
52 RT_NOREF_PV(hTimerLR); RT_NOREF_PV(pvUser); RT_NOREF_PV(iTick);
53
54 gcTicks++;
55
56 const uint64_t u64Now = RTTimeNanoTS();
57 if (gu64Prev)
58 {
59 const uint64_t u64Delta = u64Now - gu64Prev;
60 if (u64Delta < gu64Min)
61 gu64Min = u64Delta;
62 if (u64Delta > gu64Max)
63 gu64Max = u64Delta;
64 }
65 gu64Prev = u64Now;
66}
67
68
69int main()
70{
71 /*
72 * Init runtime
73 */
74 RTTEST hTest;
75 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTTimerLR", &hTest);
76 if (rcExit != RTEXITCODE_SUCCESS)
77 return rcExit;
78
79 /*
80 * Check that the clock is reliable.
81 */
82 RTTestSub(hTest, "RTTimeNanoTS() for 2sec");
83 uint64_t uTSMillies = RTTimeMilliTS();
84 uint64_t uTSBegin = RTTimeNanoTS();
85 uint64_t uTSLast = uTSBegin;
86 uint64_t uTSDiff;
87 uint64_t cIterations = 0;
88
89 do
90 {
91 uint64_t uTS = RTTimeNanoTS();
92 if (uTS < uTSLast)
93 RTTestFailed(hTest, "RTTimeNanoTS() is unreliable. uTS=%RU64 uTSLast=%RU64", uTS, uTSLast);
94 if (++cIterations > 2*1000*1000*1000)
95 {
96 RTTestFailed(hTest, "RTTimeNanoTS() is unreliable. cIterations=%RU64 uTS=%RU64 uTSBegin=%RU64",
97 cIterations, uTS, uTSBegin);
98 return RTTestSummaryAndDestroy(hTest);
99 }
100 uTSLast = uTS;
101 uTSDiff = uTSLast - uTSBegin;
102 } while (uTSDiff < (2*1000*1000*1000));
103 uTSMillies = RTTimeMilliTS() - uTSMillies;
104 if (uTSMillies >= 2500 || uTSMillies <= 1500)
105 RTTestFailed(hTest, "uTSMillies=%RI64 uTSBegin=%RU64 uTSLast=%RU64 uTSDiff=%RU64",
106 uTSMillies, uTSBegin, uTSLast, uTSDiff);
107
108 /*
109 * Tests.
110 */
111 static struct
112 {
113 unsigned uMilliesInterval;
114 unsigned uMilliesWait;
115 unsigned cLower;
116 unsigned cUpper;
117 } aTests[] =
118 {
119 { 1000, 2500, 3, 3 }, /* (keep in mind the immediate first tick) */
120 { 250, 2000, 6, 10 },
121 { 100, 2000, 17, 23 },
122 };
123
124 int rc;
125 unsigned i = 0;
126 for (i = 0; i < RT_ELEMENTS(aTests); i++)
127 {
128 //aTests[i].cLower = (aTests[i].uMilliesWait - aTests[i].uMilliesWait / 10) / aTests[i].uMilliesInterval;
129 //aTests[i].cUpper = (aTests[i].uMilliesWait + aTests[i].uMilliesWait / 10) / aTests[i].uMilliesInterval;
130
131 RTTestSubF(hTest, "%d ms interval, %d ms wait, expects %d-%d ticks",
132 aTests[i].uMilliesInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
133
134 /*
135 * Start timer which ticks every 10ms.
136 */
137 gcTicks = 0;
138 RTTIMERLR hTimerLR;
139 gu64Max = 0;
140 gu64Min = UINT64_MAX;
141 gu64Prev = 0;
142 rc = RTTimerLRCreateEx(&hTimerLR, aTests[i].uMilliesInterval * (uint64_t)1000000, 0, TimerLRCallback, NULL);
143 if (RT_FAILURE(rc))
144 {
145 RTTestFailed(hTest, "RTTimerLRCreateEX(,%u*1M,,,) -> %Rrc", aTests[i].uMilliesInterval, rc);
146 continue;
147 }
148
149 /*
150 * Start the timer an actively wait for it for the period requested.
151 */
152 uTSBegin = RTTimeNanoTS();
153 rc = RTTimerLRStart(hTimerLR, 0);
154 if (RT_FAILURE(rc))
155 RTTestFailed(hTest, "RTTimerLRStart() -> %Rrc", rc);
156
157 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000)
158 RTThreadSleep(1);
159
160 /* don't stop it, destroy it because there are potential races in destroying an active timer. */
161 rc = RTTimerLRDestroy(hTimerLR);
162 if (RT_FAILURE(rc))
163 RTTestFailed(hTest, "RTTimerLRDestroy() -> %Rrc gcTicks=%d", rc, gcTicks);
164
165 uint64_t uTSEnd = RTTimeNanoTS();
166 uTSDiff = uTSEnd - uTSBegin;
167 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "uTS=%'RI64 (%'RU64 - %'RU64) gcTicks=%u min=%'RU64 max=%'RU64\n",
168 uTSDiff, uTSBegin, uTSEnd, gcTicks, gu64Min, gu64Max);
169
170 /* Check that it really stopped. */
171 unsigned cTicks = gcTicks;
172 RTThreadSleep(aTests[i].uMilliesInterval * 2);
173 if (gcTicks != cTicks)
174 {
175 RTTestFailed(hTest, "RTTimerLRDestroy() didn't really stop the timer! gcTicks=%d cTicks=%d", gcTicks, cTicks);
176 continue;
177 }
178
179 /*
180 * Check the number of ticks.
181 */
182 if (gcTicks < aTests[i].cLower)
183 RTTestFailed(hTest, "Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
184 else if (gcTicks > aTests[i].cUpper)
185 RTTestFailed(hTest, "Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
186 }
187
188 /*
189 * Test changing the interval dynamically
190 */
191 RTTestSub(hTest, "RTTimerLRChangeInterval");
192 do
193 {
194 RTTIMERLR hTimerLR;
195 rc = RTTimerLRCreateEx(&hTimerLR, aTests[0].uMilliesInterval * (uint64_t)1000000, 0, TimerLRCallback, NULL);
196 if (RT_FAILURE(rc))
197 {
198 RTTestFailed(hTest, "RTTimerLRCreateEX(,%u*1M,,,) -> %Rrc", aTests[0].uMilliesInterval, rc);
199 break;
200 }
201
202 for (i = 0; i < RT_ELEMENTS(aTests); i++)
203 {
204 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d ms interval, %d ms wait, expects %d-%d ticks.\n",
205 aTests[i].uMilliesInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
206
207 gcTicks = 0;
208 gu64Max = 0;
209 gu64Min = UINT64_MAX;
210 gu64Prev = 0;
211
212 /*
213 * Start the timer an actively wait for it for the period requested.
214 */
215 uTSBegin = RTTimeNanoTS();
216 if (i == 0)
217 {
218 rc = RTTimerLRStart(hTimerLR, 0);
219 if (RT_FAILURE(rc))
220 RTTestFailed(hTest, "RTTimerLRStart() -> %Rrc", rc);
221 }
222 else
223 {
224 rc = RTTimerLRChangeInterval(hTimerLR, aTests[i].uMilliesInterval * RT_NS_1MS_64);
225 if (RT_FAILURE(rc))
226 RTTestFailed(hTest, "RTTimerLRChangeInterval() -> %d gcTicks=%d", rc, gcTicks);
227 }
228
229 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * RT_NS_1MS_64)
230 RTThreadSleep(1);
231
232 uint64_t uTSEnd = RTTimeNanoTS();
233 uTSDiff = uTSEnd - uTSBegin;
234 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "uTS=%'RI64 (%'RU64 - %'RU64) gcTicks=%u min=%'RU64 max=%'RU64\n",
235 uTSDiff, uTSBegin, uTSEnd, gcTicks, gu64Min, gu64Max);
236
237 /*
238 * Check the number of ticks.
239 */
240 if (gcTicks < aTests[i].cLower)
241 RTTestFailed(hTest, "Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
242 else if (gcTicks > aTests[i].cUpper)
243 RTTestFailed(hTest, "Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
244 }
245
246 /* don't stop it, destroy it because there are potential races in destroying an active timer. */
247 rc = RTTimerLRDestroy(hTimerLR);
248 if (RT_FAILURE(rc))
249 RTTestFailed(hTest, "RTTimerLRDestroy() -> %d gcTicks=%d", rc, gcTicks);
250 } while (0);
251
252 /*
253 * Test multiple timers running at once.
254 */
255 /** @todo multiple LR timer testcase. */
256
257 /*
258 * Summary.
259 */
260 return RTTestSummaryAndDestroy(hTest);
261}
262
Note: See TracBrowser for help on using the repository browser.

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