VirtualBox

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

Last change on this file since 90918 was 89762, checked in by vboxsync, 3 years ago

Runtime/r3/win/timer-win.cpp: Implement RTTimerCreateEx, RTTimerStart and RTTimerStop as well as removing code paths unused for a very long time

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