VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstTimer.cpp@ 32878

Last change on this file since 32878 was 32431, checked in by vboxsync, 14 years ago

scm cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1/* $Id: tstTimer.cpp 32431 2010-09-11 18:02:17Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Timers.
4 */
5
6/*
7 * Copyright (C) 2006-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* 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/stream.h>
35#include <iprt/err.h>
36#include <iprt/string.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;
47static volatile uint64_t gu64Norm;
48
49static uint32_t cFrequency[200];
50
51static DECLCALLBACK(void) TimerCallback(PRTTIMER pTimer, void *pvUser, uint64_t 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 int i = (int)( RT_ELEMENTS(cFrequency)
64 - (u64Delta * (RT_ELEMENTS(cFrequency) / 2) / gu64Norm));
65 if (i >= 0 && i < (int)RT_ELEMENTS(cFrequency))
66 cFrequency[i]++;
67 }
68 gu64Prev = u64Now;
69}
70
71
72int main()
73{
74 /*
75 * Init runtime
76 */
77 unsigned cErrors = 0;
78 int rc = RTR3Init();
79 if (RT_FAILURE(rc))
80 {
81 RTPrintf("tstTimer: RTR3Init() -> %d\n", rc);
82 return 1;
83 }
84
85 /*
86 * Check that the clock is reliable.
87 */
88 RTPrintf("tstTimer: TESTING - RTTimeNanoTS() for 2sec\n");
89 uint64_t uTSMillies = RTTimeMilliTS();
90 uint64_t uTSBegin = RTTimeNanoTS();
91 uint64_t uTSLast = uTSBegin;
92 uint64_t uTSDiff;
93 uint64_t cIterations = 0;
94
95 do
96 {
97 uint64_t uTS = RTTimeNanoTS();
98 if (uTS < uTSLast)
99 {
100 RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. uTS=%RU64 uTSLast=%RU64\n", uTS, uTSLast);
101 cErrors++;
102 }
103 if (++cIterations > (2*1000*1000*1000))
104 {
105 RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. cIterations=%RU64 uTS=%RU64 uTSBegin=%RU64\n", cIterations, uTS, uTSBegin);
106 return 1;
107 }
108 uTSLast = uTS;
109 uTSDiff = uTSLast - uTSBegin;
110 } while (uTSDiff < (2*1000*1000*1000));
111 uTSMillies = RTTimeMilliTS() - uTSMillies;
112 if (uTSMillies >= 2500 || uTSMillies <= 1500)
113 {
114 RTPrintf("tstTimer: FAILURE - uTSMillies=%RI64 uTSBegin=%RU64 uTSLast=%RU64 uTSDiff=%RU64\n",
115 uTSMillies, uTSBegin, uTSLast, uTSDiff);
116 cErrors++;
117 }
118 if (!cErrors)
119 RTPrintf("tstTimer: OK - RTTimeNanoTS()\n");
120
121 /*
122 * Tests.
123 */
124 static struct
125 {
126 unsigned uMicroInterval;
127 unsigned uMilliesWait;
128 unsigned cLower;
129 unsigned cUpper;
130 } aTests[] =
131 {
132 { 32000, 2000, 0, 0 },
133 { 20000, 2000, 0, 0 },
134 { 10000, 2000, 0, 0 },
135 { 8000, 2000, 0, 0 },
136 { 2000, 2000, 0, 0 },
137 { 1000, 2000, 0, 0 },
138 { 500, 5000, 0, 0 },
139 { 200, 5000, 0, 0 },
140 { 100, 5000, 0, 0 }
141 };
142
143 unsigned i = 0;
144 for (i = 0; i < RT_ELEMENTS(aTests); i++)
145 {
146 aTests[i].cLower = (aTests[i].uMilliesWait*1000 - aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval;
147 aTests[i].cUpper = (aTests[i].uMilliesWait*1000 + aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval;
148 gu64Norm = aTests[i].uMicroInterval*1000;
149
150 RTPrintf("\n"
151 "tstTimer: TESTING - %d us interval, %d ms wait, expects %d-%d ticks.\n",
152 aTests[i].uMicroInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
153
154 /*
155 * Start timer which ticks every 10ms.
156 */
157 gcTicks = 0;
158 PRTTIMER pTimer;
159 gu64Max = 0;
160 gu64Min = UINT64_MAX;
161 gu64Prev = 0;
162 RT_ZERO(cFrequency);
163#ifdef RT_OS_WINDOWS
164 if (aTests[i].uMicroInterval < 1000)
165 continue;
166 rc = RTTimerCreate(&pTimer, aTests[i].uMicroInterval / 1000, TimerCallback, NULL);
167#else
168 rc = RTTimerCreateEx(&pTimer, aTests[i].uMicroInterval * (uint64_t)1000, 0, TimerCallback, NULL);
169#endif
170 if (RT_FAILURE(rc))
171 {
172 RTPrintf("tstTimer: FAILURE - RTTimerCreateEx(,%u*1M,,,) -> %Rrc\n", aTests[i].uMicroInterval, rc);
173 cErrors++;
174 continue;
175 }
176
177 /*
178 * Start the timer and active waiting for the requested test period.
179 */
180 uTSBegin = RTTimeNanoTS();
181#ifndef RT_OS_WINDOWS
182 rc = RTTimerStart(pTimer, 0);
183 if (RT_FAILURE(rc))
184 {
185 RTPrintf("tstTimer: FAILURE - RTTimerStart(,0) -> %Rrc\n", aTests[i].uMicroInterval, rc);
186 cErrors++;
187 }
188#endif
189
190 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000)
191 /* nothing */;
192
193 /* destroy the timer */
194 uint64_t uTSEnd = RTTimeNanoTS();
195 uTSDiff = uTSEnd - uTSBegin;
196 rc = RTTimerDestroy(pTimer);
197 if (RT_FAILURE(rc))
198 {
199 RTPrintf("tstTimer: FAILURE - RTTimerDestroy() -> %d gcTicks=%d\n", rc, gcTicks);
200 cErrors++;
201 }
202
203 RTPrintf("tstTimer: uTS=%RI64 (%RU64 - %RU64)\n", uTSDiff, uTSBegin, uTSEnd);
204 unsigned cTicks = gcTicks;
205 RTThreadSleep(aTests[i].uMicroInterval/1000 * 3);
206 if (gcTicks != cTicks)
207 {
208 RTPrintf("tstTimer: FAILURE - RTTimerDestroy() didn't really stop the timer! gcTicks=%d cTicks=%d\n", gcTicks, cTicks);
209 cErrors++;
210 continue;
211 }
212
213 /*
214 * Check the number of ticks.
215 */
216 if (gcTicks < aTests[i].cLower)
217 {
218 RTPrintf("tstTimer: FAILURE - Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
219 cErrors++;
220 }
221 else if (gcTicks > aTests[i].cUpper)
222 {
223 RTPrintf("tstTimer: FAILURE - Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
224 cErrors++;
225 }
226 else
227 RTPrintf("tstTimer: OK - gcTicks=%d", gcTicks);
228 RTPrintf(" min=%RU64 max=%RU64\n", gu64Min, gu64Max);
229
230 for (int j = 0; j < (int)RT_ELEMENTS(cFrequency); j++)
231 {
232 uint32_t len = cFrequency[j] * 70 / gcTicks;
233 uint32_t deviation = j - RT_ELEMENTS(cFrequency) / 2;
234 uint64_t u64FreqPercent = (uint64_t)cFrequency[j] * 10000 / gcTicks;
235 uint64_t u64FreqPercentFrac = u64FreqPercent % 100;
236 u64FreqPercent = u64FreqPercent / 100;
237 RTPrintf("%+4d%c %6u %3llu.%02llu%% ",
238 deviation, deviation == 0 ? ' ' : '%', cFrequency[j],
239 u64FreqPercent, u64FreqPercentFrac);
240 for (unsigned k = 0; k < len; k++)
241 RTPrintf("*");
242 RTPrintf("\n");
243 }
244 }
245
246 /*
247 * Summary.
248 */
249 if (!cErrors)
250 RTPrintf("tstTimer: SUCCESS\n");
251 else
252 RTPrintf("tstTimer: FAILURE %d errors\n", cErrors);
253 return !!cErrors;
254}
255
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