VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTTimerLR.cpp@ 97728

Last change on this file since 97728 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.8 KB
Line 
1/* $Id: tstRTTimerLR.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Low Resolution Timers.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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
43#include <iprt/errcore.h>
44#include <iprt/message.h>
45#include <iprt/stream.h>
46#include <iprt/test.h>
47#include <iprt/thread.h>
48#include <iprt/time.h>
49
50
51/*********************************************************************************************************************************
52* Global Variables *
53*********************************************************************************************************************************/
54static volatile unsigned gcTicks;
55static volatile uint64_t gu64Min;
56static volatile uint64_t gu64Max;
57static volatile uint64_t gu64Prev;
58
59
60static DECLCALLBACK(void) TimerLRCallback(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick)
61{
62 RT_NOREF_PV(hTimerLR); RT_NOREF_PV(pvUser); RT_NOREF_PV(iTick);
63
64 gcTicks++;
65
66 const uint64_t u64Now = RTTimeNanoTS();
67 if (gu64Prev)
68 {
69 const uint64_t u64Delta = u64Now - gu64Prev;
70 if (u64Delta < gu64Min)
71 gu64Min = u64Delta;
72 if (u64Delta > gu64Max)
73 gu64Max = u64Delta;
74 }
75 gu64Prev = u64Now;
76}
77
78
79int main()
80{
81 /*
82 * Init runtime
83 */
84 RTTEST hTest;
85 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTTimerLR", &hTest);
86 if (rcExit != RTEXITCODE_SUCCESS)
87 return rcExit;
88
89 /*
90 * Check that the clock is reliable.
91 */
92 RTTestSub(hTest, "RTTimeNanoTS() for 2sec");
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 RTTestFailed(hTest, "RTTimeNanoTS() is unreliable. uTS=%RU64 uTSLast=%RU64", uTS, uTSLast);
104 if (++cIterations > 2*1000*1000*1000)
105 {
106 RTTestFailed(hTest, "RTTimeNanoTS() is unreliable. cIterations=%RU64 uTS=%RU64 uTSBegin=%RU64",
107 cIterations, uTS, uTSBegin);
108 return RTTestSummaryAndDestroy(hTest);
109 }
110 uTSLast = uTS;
111 uTSDiff = uTSLast - uTSBegin;
112 } while (uTSDiff < (2*1000*1000*1000));
113 uTSMillies = RTTimeMilliTS() - uTSMillies;
114 if (uTSMillies >= 2500 || uTSMillies <= 1500)
115 RTTestFailed(hTest, "uTSMillies=%RI64 uTSBegin=%RU64 uTSLast=%RU64 uTSDiff=%RU64",
116 uTSMillies, uTSBegin, uTSLast, uTSDiff);
117
118 /*
119 * Tests.
120 */
121 static struct
122 {
123 unsigned uMilliesInterval;
124 unsigned uMilliesWait;
125 unsigned cLower;
126 unsigned cUpper;
127 } aTests[] =
128 {
129 { 1000, 2500, 3, 3 }, /* (keep in mind the immediate first tick) */
130 { 250, 2000, 6, 10 },
131 { 100, 2000, 17, 23 },
132 };
133
134 int rc;
135 unsigned i = 0;
136 for (i = 0; i < RT_ELEMENTS(aTests); i++)
137 {
138 //aTests[i].cLower = (aTests[i].uMilliesWait - aTests[i].uMilliesWait / 10) / aTests[i].uMilliesInterval;
139 //aTests[i].cUpper = (aTests[i].uMilliesWait + aTests[i].uMilliesWait / 10) / aTests[i].uMilliesInterval;
140
141 RTTestSubF(hTest, "%d ms interval, %d ms wait, expects %d-%d ticks",
142 aTests[i].uMilliesInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
143
144 /*
145 * Start timer which ticks every 10ms.
146 */
147 gcTicks = 0;
148 RTTIMERLR hTimerLR;
149 gu64Max = 0;
150 gu64Min = UINT64_MAX;
151 gu64Prev = 0;
152 rc = RTTimerLRCreateEx(&hTimerLR, aTests[i].uMilliesInterval * (uint64_t)1000000, 0, TimerLRCallback, NULL);
153 if (RT_FAILURE(rc))
154 {
155 RTTestFailed(hTest, "RTTimerLRCreateEX(,%u*1M,,,) -> %Rrc", aTests[i].uMilliesInterval, rc);
156 continue;
157 }
158
159 /*
160 * Start the timer an actively wait for it for the period requested.
161 */
162 uTSBegin = RTTimeNanoTS();
163 rc = RTTimerLRStart(hTimerLR, 0);
164 if (RT_FAILURE(rc))
165 RTTestFailed(hTest, "RTTimerLRStart() -> %Rrc", rc);
166
167 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000)
168 RTThreadSleep(1);
169
170 /* don't stop it, destroy it because there are potential races in destroying an active timer. */
171 rc = RTTimerLRDestroy(hTimerLR);
172 if (RT_FAILURE(rc))
173 RTTestFailed(hTest, "RTTimerLRDestroy() -> %Rrc gcTicks=%d", rc, gcTicks);
174
175 uint64_t uTSEnd = RTTimeNanoTS();
176 uTSDiff = uTSEnd - uTSBegin;
177 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "uTS=%'RI64 (%'RU64 - %'RU64) gcTicks=%u min=%'RU64 max=%'RU64\n",
178 uTSDiff, uTSBegin, uTSEnd, gcTicks, gu64Min, gu64Max);
179
180 /* Check that it really stopped. */
181 unsigned cTicks = gcTicks;
182 RTThreadSleep(aTests[i].uMilliesInterval * 2);
183 if (gcTicks != cTicks)
184 {
185 RTTestFailed(hTest, "RTTimerLRDestroy() didn't really stop the timer! gcTicks=%d cTicks=%d", gcTicks, cTicks);
186 continue;
187 }
188
189 /*
190 * Check the number of ticks.
191 */
192 if (gcTicks < aTests[i].cLower)
193 RTTestFailed(hTest, "Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
194 else if (gcTicks > aTests[i].cUpper)
195 RTTestFailed(hTest, "Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
196 }
197
198 /*
199 * Test changing the interval dynamically
200 */
201 RTTestSub(hTest, "RTTimerLRChangeInterval");
202 do
203 {
204 RTTIMERLR hTimerLR;
205 rc = RTTimerLRCreateEx(&hTimerLR, aTests[0].uMilliesInterval * (uint64_t)1000000, 0, TimerLRCallback, NULL);
206 if (RT_FAILURE(rc))
207 {
208 RTTestFailed(hTest, "RTTimerLRCreateEX(,%u*1M,,,) -> %Rrc", aTests[0].uMilliesInterval, rc);
209 break;
210 }
211
212 for (i = 0; i < RT_ELEMENTS(aTests); i++)
213 {
214 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d ms interval, %d ms wait, expects %d-%d ticks.\n",
215 aTests[i].uMilliesInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper);
216
217 gcTicks = 0;
218 gu64Max = 0;
219 gu64Min = UINT64_MAX;
220 gu64Prev = 0;
221
222 /*
223 * Start the timer an actively wait for it for the period requested.
224 */
225 uTSBegin = RTTimeNanoTS();
226 if (i == 0)
227 {
228 rc = RTTimerLRStart(hTimerLR, 0);
229 if (RT_FAILURE(rc))
230 RTTestFailed(hTest, "RTTimerLRStart() -> %Rrc", rc);
231 }
232 else
233 {
234 rc = RTTimerLRChangeInterval(hTimerLR, aTests[i].uMilliesInterval * RT_NS_1MS_64);
235 if (RT_FAILURE(rc))
236 RTTestFailed(hTest, "RTTimerLRChangeInterval() -> %d gcTicks=%d", rc, gcTicks);
237 }
238
239 while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * RT_NS_1MS_64)
240 RTThreadSleep(1);
241
242 uint64_t uTSEnd = RTTimeNanoTS();
243 uTSDiff = uTSEnd - uTSBegin;
244 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "uTS=%'RI64 (%'RU64 - %'RU64) gcTicks=%u min=%'RU64 max=%'RU64\n",
245 uTSDiff, uTSBegin, uTSEnd, gcTicks, gu64Min, gu64Max);
246
247 /*
248 * Check the number of ticks.
249 */
250 if (gcTicks < aTests[i].cLower)
251 RTTestFailed(hTest, "Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
252 else if (gcTicks > aTests[i].cUpper)
253 RTTestFailed(hTest, "Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower);
254 }
255
256 /* don't stop it, destroy it because there are potential races in destroying an active timer. */
257 rc = RTTimerLRDestroy(hTimerLR);
258 if (RT_FAILURE(rc))
259 RTTestFailed(hTest, "RTTimerLRDestroy() -> %d gcTicks=%d", rc, gcTicks);
260 } while (0);
261
262 /*
263 * Test multiple timers running at once.
264 */
265 /** @todo multiple LR timer testcase. */
266
267 /*
268 * Summary.
269 */
270 return RTTestSummaryAndDestroy(hTest);
271}
272
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