VirtualBox

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

Last change on this file since 52320 was 48935, checked in by vboxsync, 11 years ago

Runtime: Whitespace and svn:keyword cleanups by scm.

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