VirtualBox

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

Last change on this file since 62477 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

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