VirtualBox

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

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