VirtualBox

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

Last change on this file since 106061 was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.8 KB
Line 
1/* $Id: tstTimer.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Timers.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/timer.h>
42#include <iprt/time.h>
43#include <iprt/thread.h>
44#include <iprt/initterm.h>
45#include <iprt/message.h>
46#include <iprt/stream.h>
47#include <iprt/errcore.h>
48#include <iprt/string.h>
49
50
51
52/*********************************************************************************************************************************
53* Global Variables *
54*********************************************************************************************************************************/
55static volatile unsigned gcTicks;
56static volatile uint64_t gu64Min;
57static volatile uint64_t gu64Max;
58static volatile uint64_t gu64Prev;
59static volatile uint64_t gu64Norm;
60
61static uint32_t cFrequency[200];
62
63static DECLCALLBACK(void) TimerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
64{
65 RT_NOREF_PV(pTimer); RT_NOREF_PV(pvUser); RT_NOREF_PV(iTick);
66
67 gcTicks++;
68
69 if (iTick != gcTicks)
70 RTPrintf("tstTimer: FAILURE - iTick=%llu expected %u\n", iTick, gcTicks);
71
72 const uint64_t u64Now = RTTimeNanoTS();
73 if (gu64Prev)
74 {
75 const uint64_t u64Delta = u64Now - gu64Prev;
76 if (u64Delta < gu64Min)
77 gu64Min = u64Delta;
78 if (u64Delta > gu64Max)
79 gu64Max = u64Delta;
80 int i = (int)( RT_ELEMENTS(cFrequency)
81 - (u64Delta * (RT_ELEMENTS(cFrequency) / 2) / gu64Norm));
82 if (i >= 0 && i < (int)RT_ELEMENTS(cFrequency))
83 cFrequency[i]++;
84 }
85 gu64Prev = u64Now;
86}
87
88
89int main()
90{
91 /*
92 * Init runtime
93 */
94 unsigned cErrors = 0;
95 int rc = RTR3InitExeNoArguments(0);
96 if (RT_FAILURE(rc))
97 return RTMsgInitFailure(rc);
98
99 /*
100 * Check that the clock is reliable.
101 */
102 RTPrintf("tstTimer: TESTING - RTTimeNanoTS() for 2sec\n");
103 uint64_t uTSMillies = RTTimeMilliTS();
104 uint64_t uTSBegin = RTTimeNanoTS();
105 uint64_t uTSLast = uTSBegin;
106 uint64_t uTSDiff;
107 uint64_t cIterations = 0;
108
109 do
110 {
111 uint64_t uTS = RTTimeNanoTS();
112 if (uTS < uTSLast)
113 {
114 RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. uTS=%RU64 uTSLast=%RU64\n", uTS, uTSLast);
115 cErrors++;
116 }
117 if (++cIterations > (2*1000*1000*1000))
118 {
119 RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. cIterations=%RU64 uTS=%RU64 uTSBegin=%RU64\n", cIterations, uTS, uTSBegin);
120 return 1;
121 }
122 uTSLast = uTS;
123 uTSDiff = uTSLast - uTSBegin;
124 } while (uTSDiff < (2*1000*1000*1000));
125 uTSMillies = RTTimeMilliTS() - uTSMillies;
126 if (uTSMillies >= 2500 || uTSMillies <= 1500)
127 {
128 RTPrintf("tstTimer: FAILURE - uTSMillies=%RI64 uTSBegin=%RU64 uTSLast=%RU64 uTSDiff=%RU64\n",
129 uTSMillies, uTSBegin, uTSLast, uTSDiff);
130 cErrors++;
131 }
132 if (!cErrors)
133 RTPrintf("tstTimer: OK - RTTimeNanoTS()\n");
134
135 /*
136 * Tests.
137 */
138 static struct
139 {
140 unsigned uMicroInterval;
141 unsigned uMilliesWait;
142 unsigned cLower;
143 unsigned cUpper;
144 } aTests[] =
145 {
146 { 32000, 2000, 0, 0 },
147 { 20000, 2000, 0, 0 },
148 { 10000, 2000, 0, 0 },
149 { 8000, 2000, 0, 0 },
150 { 2000, 2000, 0, 0 },
151 { 1000, 2000, 0, 0 },
152 { 500, 5000, 0, 0 },
153 { 200, 5000, 0, 0 },
154 { 100, 5000, 0, 0 }
155 };
156
157 unsigned i = 0;
158 for (i = 0; i < RT_ELEMENTS(aTests); i++)
159 {
160 aTests[i].cLower = (aTests[i].uMilliesWait*1000 - aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval;
161 aTests[i].cUpper = (aTests[i].uMilliesWait*1000 + aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval;
162 gu64Norm = aTests[i].uMicroInterval*1000;
163
164 RTPrintf("\n"
165 "tstTimer: TESTING - %d us interval, %d ms wait, expects %d-%d ticks.\n",
166 aTests[i].uMicroInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
167
168 /*
169 * Start timer which ticks every 10ms.
170 */
171 gcTicks = 0;
172 PRTTIMER pTimer;
173 gu64Max = 0;
174 gu64Min = UINT64_MAX;
175 gu64Prev = 0;
176 RT_ZERO(cFrequency);
177 rc = RTTimerCreateEx(&pTimer, aTests[i].uMicroInterval * (uint64_t)1000, 0, TimerCallback, NULL);
178 if (RT_FAILURE(rc))
179 {
180 RTPrintf("tstTimer: FAILURE - RTTimerCreateEx(,%u*1M,,,) -> %Rrc\n", aTests[i].uMicroInterval, rc);
181 cErrors++;
182 continue;
183 }
184
185 /*
186 * Start the timer and active waiting for the requested test period.
187 */
188 uTSBegin = RTTimeNanoTS();
189 rc = RTTimerStart(pTimer, 0);
190 if (RT_FAILURE(rc))
191 {
192 RTPrintf("tstTimer: FAILURE - RTTimerStart(,0) -> %Rrc\n", rc);
193 cErrors++;
194 }
195
196 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000)
197 /* nothing */;
198
199 /* destroy the timer */
200 uint64_t uTSEnd = RTTimeNanoTS();
201 uTSDiff = uTSEnd - uTSBegin;
202 rc = RTTimerDestroy(pTimer);
203 if (RT_FAILURE(rc))
204 {
205 RTPrintf("tstTimer: FAILURE - RTTimerDestroy() -> %d gcTicks=%d\n", rc, gcTicks);
206 cErrors++;
207 }
208
209 RTPrintf("tstTimer: uTS=%RI64 (%RU64 - %RU64)\n", uTSDiff, uTSBegin, uTSEnd);
210 unsigned cTicks = gcTicks;
211 RTThreadSleep(aTests[i].uMicroInterval/1000 * 3);
212 if (gcTicks != cTicks)
213 {
214 RTPrintf("tstTimer: FAILURE - RTTimerDestroy() didn't really stop the timer! gcTicks=%d cTicks=%d\n", gcTicks, cTicks);
215 cErrors++;
216 continue;
217 }
218
219 /*
220 * Check the number of ticks.
221 */
222 if (gcTicks < aTests[i].cLower)
223 {
224 RTPrintf("tstTimer: FAILURE - Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
225 cErrors++;
226 }
227 else if (gcTicks > aTests[i].cUpper)
228 {
229 RTPrintf("tstTimer: FAILURE - Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
230 cErrors++;
231 }
232 else
233 RTPrintf("tstTimer: OK - gcTicks=%d", gcTicks);
234 RTPrintf(" min=%RU64 max=%RU64\n", gu64Min, gu64Max);
235
236 for (int j = 0; j < (int)RT_ELEMENTS(cFrequency); j++)
237 {
238 uint32_t len = cFrequency[j] * 70 / gcTicks;
239 uint32_t deviation = j - RT_ELEMENTS(cFrequency) / 2;
240 uint64_t u64FreqPercent = (uint64_t)cFrequency[j] * 10000 / gcTicks;
241 uint64_t u64FreqPercentFrac = u64FreqPercent % 100;
242 u64FreqPercent = u64FreqPercent / 100;
243 RTPrintf("%+4d%c %6u %3llu.%02llu%% ",
244 deviation, deviation == 0 ? ' ' : '%', cFrequency[j],
245 u64FreqPercent, u64FreqPercentFrac);
246 for (unsigned k = 0; k < len; k++)
247 RTPrintf("*");
248 RTPrintf("\n");
249 }
250 }
251
252 /*
253 * Summary.
254 */
255 if (!cErrors)
256 RTPrintf("tstTimer: SUCCESS\n");
257 else
258 RTPrintf("tstTimer: FAILURE %d errors\n", cErrors);
259 return !!cErrors;
260}
261
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