VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstTimerLR.cpp@ 79325

Last change on this file since 79325 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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