VirtualBox

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

Last change on this file since 58269 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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