VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp

Last change on this file 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 Author Date Id Revision
File size: 30.2 KB
Line 
1/* $Id: tstSupSem.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Support Library Testcase - Ring-3 Semaphore interface.
4 */
5
6/*
7 * Copyright (C) 2009-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 <VBox/sup.h>
42
43#include <VBox/param.h>
44#include <iprt/err.h>
45#include <iprt/initterm.h>
46#include <iprt/message.h>
47#include <iprt/stream.h>
48#include <iprt/test.h>
49#include <iprt/thread.h>
50#include <iprt/process.h>
51#include <iprt/env.h>
52#include <iprt/string.h>
53#include <iprt/time.h>
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59static PSUPDRVSESSION g_pSession;
60static RTTEST g_hTest;
61static uint32_t g_cMillies; /* Used by the interruptible tests. */
62
63
64
65static DECLCALLBACK(int) tstSupSemInterruptibleSRE(RTTHREAD hSelf, void *pvUser)
66{
67 SUPSEMEVENT hEvent = (SUPSEMEVENT)pvUser;
68 RTThreadUserSignal(hSelf);
69 return SUPSemEventWaitNoResume(g_pSession, hEvent, g_cMillies);
70}
71
72
73static DECLCALLBACK(int) tstSupSemInterruptibleMRE(RTTHREAD hSelf, void *pvUser)
74{
75 SUPSEMEVENTMULTI hEventMulti = (SUPSEMEVENTMULTI)pvUser;
76 RTThreadUserSignal(hSelf);
77 return SUPSemEventMultiWaitNoResume(g_pSession, hEventMulti, g_cMillies);
78}
79
80
81int main(int argc, char **argv)
82{
83 bool fSys = true;
84 bool fGip = false;
85#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
86 fGip = true;
87#endif
88
89 /*
90 * Init.
91 */
92 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_TRY_SUPLIB);
93 if (RT_FAILURE(rc))
94 return RTMsgInitFailure(rc);
95
96 if (argc == 2 && !strcmp(argv[1], "child"))
97 {
98 RTThreadSleep(300);
99 return 0;
100 }
101
102 RTTEST hTest;
103 rc = RTTestCreate("tstSupSem", &hTest);
104 if (RT_FAILURE(rc))
105 {
106 RTPrintf("tstSupSem: fatal error: RTTestCreate failed with rc=%Rrc\n", rc);
107 return 1;
108 }
109 g_hTest = hTest;
110
111 PSUPDRVSESSION pSession;
112 rc = SUPR3Init(&pSession);
113 if (RT_FAILURE(rc))
114 {
115 RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc);
116 return RTTestSummaryAndDestroy(hTest);
117 }
118 g_pSession = pSession;
119 RTTestBanner(hTest);
120
121 /*
122 * Basic API checks.
123 */
124 RTTestSub(hTest, "Single Release Event (SRE) API");
125 SUPSEMEVENT hEvent = NIL_SUPSEMEVENT;
126 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
127 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VERR_TIMEOUT);
128 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VERR_TIMEOUT);
129 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VERR_TIMEOUT);
130 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VERR_TIMEOUT);
131 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20), VERR_TIMEOUT);
132 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
133 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VINF_SUCCESS);
134 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
135 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VINF_SUCCESS);
136 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
137 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VINF_SUCCESS);
138 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
139 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VINF_SUCCESS);
140 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
141 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 20), VINF_SUCCESS);
142 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
143 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,1000),VINF_SUCCESS);
144 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
145 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
146 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VINF_SUCCESS);
147 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VERR_TIMEOUT);
148 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VERR_TIMEOUT);
149 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VERR_TIMEOUT);
150 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VERR_TIMEOUT);
151 RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20), VERR_TIMEOUT);
152 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
153 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VERR_INVALID_HANDLE);
154 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, NIL_SUPSEMEVENT), VINF_SUCCESS);
155
156 RTTestSub(hTest, "Multiple Release Event (MRE) API");
157 SUPSEMEVENTMULTI hEventMulti = NIL_SUPSEMEVENT;
158 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS);
159 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VERR_TIMEOUT);
160 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VERR_TIMEOUT);
161 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VERR_TIMEOUT);
162 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VERR_TIMEOUT);
163 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VERR_TIMEOUT);
164 RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS);
165 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS);
166 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS);
167 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS);
168 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VINF_SUCCESS);
169 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VINF_SUCCESS);
170 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VINF_SUCCESS);
171 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VINF_SUCCESS);
172 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000), VINF_SUCCESS);
173 RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS);
174 RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS);
175 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS);
176 RTTESTI_CHECK_RC(SUPSemEventMultiReset(pSession, hEventMulti), VINF_SUCCESS);
177 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VERR_TIMEOUT);
178 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VERR_TIMEOUT);
179 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VERR_TIMEOUT);
180 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VERR_TIMEOUT);
181 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VERR_TIMEOUT);
182 RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS);
183 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS);
184 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VINF_SUCCESS);
185 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VINF_SUCCESS);
186 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VINF_SUCCESS);
187 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 20), VINF_SUCCESS);
188 RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000), VINF_SUCCESS);
189 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED);
190 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VERR_INVALID_HANDLE);
191 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, NIL_SUPSEMEVENTMULTI), VINF_SUCCESS);
192
193#if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS)
194 RTTestSub(hTest, "SRE Interruptibility");
195 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
196 g_cMillies = RT_INDEFINITE_WAIT;
197 RTTHREAD hThread = NIL_RTTHREAD;
198 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS);
199 RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS);
200 RTThreadSleep(120);
201 RTThreadPoke(hThread);
202 int rcThread = VINF_SUCCESS;
203 RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS);
204 RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED);
205 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
206
207 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
208 g_cMillies = 120*1000;
209 hThread = NIL_RTTHREAD;
210 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS);
211 RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS);
212 RTThreadSleep(120);
213 RTThreadPoke(hThread);
214 rcThread = VINF_SUCCESS;
215 RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS);
216 RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED);
217 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
218
219
220 RTTestSub(hTest, "MRE Interruptibility");
221 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS);
222 g_cMillies = RT_INDEFINITE_WAIT;
223 hThread = NIL_RTTHREAD;
224 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntMRE"), VINF_SUCCESS);
225 RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS);
226 RTThreadSleep(120);
227 RTThreadPoke(hThread);
228 rcThread = VINF_SUCCESS;
229 RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS);
230 RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED);
231 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED);
232
233 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS);
234 g_cMillies = 120*1000;
235 hThread = NIL_RTTHREAD;
236 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntMRE"), VINF_SUCCESS);
237 RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS);
238 RTThreadSleep(120);
239 RTThreadPoke(hThread);
240 rcThread = VINF_SUCCESS;
241 RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS);
242 RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED);
243 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED);
244
245 /*
246 * Fork test.
247 * Spawn a thread waiting for an event, then spawn a new child process (of
248 * ourselves) and make sure that this does not alter the intended behaviour
249 * of our event semaphore implementation (see @bugref{5090}).
250 */
251 RTTestSub(hTest, "SRE Process Spawn");
252 hThread = NIL_RTTHREAD;
253 g_cMillies = 120*1000;
254 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
255 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS);
256
257 const char *apszArgs[3] = { argv[0], "child", NULL };
258 RTPROCESS Process = NIL_RTPROCESS;
259 RTThreadSleep(250);
260 RTTESTI_CHECK_RC(RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0, &Process), VINF_SUCCESS);
261
262 RTThreadSleep(250);
263 RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS);
264
265 rcThread = VERR_GENERAL_FAILURE;
266 RTTESTI_CHECK_RC(RTThreadWait(hThread, 120*1000, &rcThread), VINF_SUCCESS);
267 RTTESTI_CHECK_RC(rcThread, VINF_SUCCESS);
268 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
269
270
271 RTTestSub(hTest, "MRE Process Spawn");
272 hThread = NIL_RTTHREAD;
273 g_cMillies = 120*1000;
274 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
275 RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS);
276
277 RTTHREAD hThread2 = NIL_RTTHREAD;
278 RTTESTI_CHECK_RC(RTThreadCreate(&hThread2, tstSupSemInterruptibleMRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS);
279
280 Process = NIL_RTPROCESS;
281 RTThreadSleep(250);
282 RTTESTI_CHECK_RC(RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0, &Process), VINF_SUCCESS);
283
284 RTThreadSleep(250);
285 RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEvent), VINF_SUCCESS);
286
287 rcThread = VERR_GENERAL_FAILURE;
288 RTTESTI_CHECK_RC(RTThreadWait(hThread, 120*1000, &rcThread), VINF_SUCCESS);
289 RTTESTI_CHECK_RC(rcThread, VINF_SUCCESS);
290
291 int rcThread2 = VERR_GENERAL_FAILURE;
292 RTTESTI_CHECK_RC(RTThreadWait(hThread2, 120*1000, &rcThread2), VINF_SUCCESS);
293 RTTESTI_CHECK_RC(rcThread2, VINF_SUCCESS);
294
295 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
296
297#endif /* !OS2 && !WINDOWS */
298
299 {
300
301#define LOOP_COUNT 20
302 static unsigned const s_acMsIntervals[] = { 0, 1, 2, 3, 4, 8, 10, 16, 32 };
303 if (RTTestErrorCount(hTest) == 0)
304 {
305 RTTestSub(hTest, "SRE Timeout Accuracy (ms)");
306 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
307
308 uint32_t cInterrupted = 0;
309 for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
310 {
311 uint64_t cMs = s_acMsIntervals[i];
312 uint64_t cNsMinSys = UINT64_MAX;
313 uint64_t cNsMin = UINT64_MAX;
314 uint64_t cNsTotalSys= 0;
315 uint64_t cNsTotal = 0;
316 unsigned cLoops = 0;
317 while (cLoops < LOOP_COUNT)
318 {
319 uint64_t u64StartSys = RTTimeSystemNanoTS();
320 uint64_t u64Start = RTTimeNanoTS();
321 int rcX = SUPSemEventWaitNoResume(pSession, hEvent, cMs);
322 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
323 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
324
325 if (rcX == VERR_INTERRUPTED)
326 {
327 cInterrupted++;
328 continue; /* retry */
329 }
330 if (rcX != VERR_TIMEOUT)
331 RTTestFailed(hTest, "%Rrc cLoops=%u cMs=%u", rcX, cLoops, cMs);
332
333 if (cNsElapsedSys < cNsMinSys)
334 cNsMinSys = cNsElapsedSys;
335 if (cNsElapsed < cNsMin)
336 cNsMin = cNsElapsed;
337 cNsTotalSys += cNsElapsedSys;
338 cNsTotal += cNsElapsed;
339 cLoops++;
340 }
341 if (fSys)
342 {
343 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs);
344 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs);
345 }
346 if (fGip)
347 {
348 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs);
349 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=gip)", cMs);
350 }
351 }
352
353 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
354 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
355 }
356
357 if (RTTestErrorCount(hTest) == 0)
358 {
359 RTTestSub(hTest, "MRE Timeout Accuracy (ms)");
360 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
361
362 uint32_t cInterrupted = 0;
363 for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
364 {
365 uint64_t cMs = s_acMsIntervals[i];
366 uint64_t cNsMinSys = UINT64_MAX;
367 uint64_t cNsMin = UINT64_MAX;
368 uint64_t cNsTotalSys= 0;
369 uint64_t cNsTotal = 0;
370 unsigned cLoops = 0;
371 while (cLoops < LOOP_COUNT)
372 {
373 uint64_t u64StartSys = RTTimeSystemNanoTS();
374 uint64_t u64Start = RTTimeNanoTS();
375 int rcX = SUPSemEventMultiWaitNoResume(pSession, hEvent, cMs);
376 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
377 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
378
379 if (rcX == VERR_INTERRUPTED)
380 {
381 cInterrupted++;
382 continue; /* retry */
383 }
384 if (rcX != VERR_TIMEOUT)
385 RTTestFailed(hTest, "%Rrc cLoops=%u cMs=%u", rcX, cLoops, cMs);
386
387 if (cNsElapsedSys < cNsMinSys)
388 cNsMinSys = cNsElapsedSys;
389 if (cNsElapsed < cNsMin)
390 cNsMin = cNsElapsed;
391 cNsTotalSys += cNsElapsedSys;
392 cNsTotal += cNsElapsed;
393 cLoops++;
394 }
395 if (fSys)
396 {
397 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs);
398 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs);
399 }
400 if (fGip)
401 {
402 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs);
403 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=gip)", cMs);
404 }
405 }
406
407 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
408 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
409 }
410 }
411
412 {
413 static uint32_t const s_acNsIntervals[] =
414 {
415 0, 1000, 5000, 15000, 30000, 50000, 100000, 250000, 500000, 750000, 900000, 1500000, 2200000
416 };
417
418 if (RTTestErrorCount(hTest) == 0)
419 {
420 RTTestSub(hTest, "SUPSemEventWaitNsRelIntr Accuracy");
421 RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "SRE resolution");
422 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
423
424 uint32_t cInterrupted = 0;
425 for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
426 {
427 uint64_t cNs = s_acNsIntervals[i];
428 uint64_t cNsMinSys = UINT64_MAX;
429 uint64_t cNsMin = UINT64_MAX;
430 uint64_t cNsTotalSys= 0;
431 uint64_t cNsTotal = 0;
432 unsigned cLoops = 0;
433 while (cLoops < LOOP_COUNT)
434 {
435 uint64_t u64StartSys = RTTimeSystemNanoTS();
436 uint64_t u64Start = RTTimeNanoTS();
437 int rcX = SUPSemEventWaitNsRelIntr(pSession, hEvent, cNs);
438 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
439 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
440
441 if (rcX == VERR_INTERRUPTED)
442 {
443 cInterrupted++;
444 continue; /* retry */
445 }
446 if (rcX != VERR_TIMEOUT)
447 RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs);
448
449 if (cNsElapsedSys < cNsMinSys)
450 cNsMinSys = cNsElapsedSys;
451 if (cNsElapsed < cNsMin)
452 cNsMin = cNsElapsed;
453 cNsTotalSys += cNsElapsedSys;
454 cNsTotal += cNsElapsed;
455 cLoops++;
456 }
457 if (fSys)
458 {
459 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs);
460 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
461 }
462 if (fGip)
463 {
464 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs);
465 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs);
466 }
467 }
468
469 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
470 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
471 }
472
473 if (RTTestErrorCount(hTest) == 0)
474 {
475 RTTestSub(hTest, "SUPSemEventMultiWaitNsRelIntr Accuracy");
476 RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
477 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
478
479 uint32_t cInterrupted = 0;
480 for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
481 {
482 uint64_t cNs = s_acNsIntervals[i];
483 uint64_t cNsMinSys = UINT64_MAX;
484 uint64_t cNsMin = UINT64_MAX;
485 uint64_t cNsTotalSys= 0;
486 uint64_t cNsTotal = 0;
487 unsigned cLoops = 0;
488 while (cLoops < LOOP_COUNT)
489 {
490 uint64_t u64StartSys = RTTimeSystemNanoTS();
491 uint64_t u64Start = RTTimeNanoTS();
492 int rcX = SUPSemEventMultiWaitNsRelIntr(pSession, hEvent, cNs);
493 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
494 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
495
496 if (rcX == VERR_INTERRUPTED)
497 {
498 cInterrupted++;
499 continue; /* retry */
500 }
501 if (rcX != VERR_TIMEOUT)
502 RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs);
503
504 if (cNsElapsedSys < cNsMinSys)
505 cNsMinSys = cNsElapsedSys;
506 if (cNsElapsed < cNsMin)
507 cNsMin = cNsElapsed;
508 cNsTotalSys += cNsElapsedSys;
509 cNsTotal += cNsElapsed;
510 cLoops++;
511 }
512 if (fSys)
513 {
514 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs);
515 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
516 }
517 if (fGip)
518 {
519 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs);
520 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs);
521 }
522 }
523
524 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
525 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
526 }
527
528 if (RTTestErrorCount(hTest) == 0)
529 {
530 RTTestSub(hTest, "SUPSemEventWaitNsAbsIntr Accuracy");
531 RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
532 RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
533
534 uint32_t cInterrupted = 0;
535 for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
536 {
537 uint64_t cNs = s_acNsIntervals[i];
538 uint64_t cNsMinSys = UINT64_MAX;
539 uint64_t cNsMin = UINT64_MAX;
540 uint64_t cNsTotalSys= 0;
541 uint64_t cNsTotal = 0;
542 unsigned cLoops = 0;
543 while (cLoops < LOOP_COUNT)
544 {
545 uint64_t u64StartSys = RTTimeSystemNanoTS();
546 uint64_t u64Start = RTTimeNanoTS();
547 uint64_t uAbsDeadline = (fGip ? u64Start : u64StartSys) + cNs;
548 int rcX = SUPSemEventWaitNsAbsIntr(pSession, hEvent, uAbsDeadline);
549 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
550 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
551
552 if (rcX == VERR_INTERRUPTED)
553 {
554 cInterrupted++;
555 continue; /* retry */
556 }
557 if (rcX != VERR_TIMEOUT)
558 RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs);
559
560 if (cNsElapsedSys < cNsMinSys)
561 cNsMinSys = cNsElapsedSys;
562 if (cNsElapsed < cNsMin)
563 cNsMin = cNsElapsed;
564 cNsTotalSys += cNsElapsedSys;
565 cNsTotal += cNsElapsed;
566 cLoops++;
567 }
568 if (fSys)
569 {
570 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs);
571 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
572 }
573 if (fGip)
574 {
575 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs);
576 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs);
577 }
578 }
579
580 RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
581 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
582 }
583
584
585 if (RTTestErrorCount(hTest) == 0)
586 {
587 RTTestSub(hTest, "SUPSemEventMultiWaitNsAbsIntr Accuracy");
588 RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
589 RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
590
591 uint32_t cInterrupted = 0;
592 for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
593 {
594 uint64_t cNs = s_acNsIntervals[i];
595 uint64_t cNsMinSys = UINT64_MAX;
596 uint64_t cNsMin = UINT64_MAX;
597 uint64_t cNsTotalSys= 0;
598 uint64_t cNsTotal = 0;
599 unsigned cLoops = 0;
600 while (cLoops < LOOP_COUNT)
601 {
602 uint64_t u64StartSys = RTTimeSystemNanoTS();
603 uint64_t u64Start = RTTimeNanoTS();
604 uint64_t uAbsDeadline = (fGip ? u64Start : u64StartSys) + cNs;
605 int rcX = SUPSemEventMultiWaitNsAbsIntr(pSession, hEvent, uAbsDeadline);
606 uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
607 uint64_t cNsElapsed = RTTimeNanoTS() - u64Start;
608
609 if (rcX == VERR_INTERRUPTED)
610 {
611 cInterrupted++;
612 continue; /* retry */
613 }
614 if (rcX != VERR_TIMEOUT)
615 RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs);
616
617 if (cNsElapsedSys < cNsMinSys)
618 cNsMinSys = cNsElapsedSys;
619 if (cNsElapsed < cNsMin)
620 cNsMin = cNsElapsed;
621 cNsTotalSys += cNsElapsedSys;
622 cNsTotal += cNsElapsed;
623 cLoops++;
624 }
625 if (fSys)
626 {
627 RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs);
628 RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
629 }
630 if (fGip)
631 {
632 RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs);
633 RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs);
634 }
635 }
636
637 RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
638 RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned");
639 }
640
641 }
642
643
644 /*
645 * Done.
646 */
647 return RTTestSummaryAndDestroy(hTest);
648}
649
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