VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTSemEvent.cpp@ 103075

Last change on this file since 103075 was 99704, checked in by vboxsync, 20 months ago

Runtime/testcase/tstRTSemEvent: test1() queues up two threads behind a
condition variable and then sends a signal to the condition variable and
verifies that the first thread queued was awakened. This fails on
Solaris since the order in which multiple threads blocked on a condition
variable are awakened is unspecified in the default scheduling class
(SCHED_OTHER). Fixed by simplifying the test for Solaris systems to
simply send two signals and then check that both of the waiting threads
have been awakened.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.0 KB
Line 
1/* $Id: tstRTSemEvent.cpp 99704 2023-05-09 17:01:36Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Multiple Release Event Semaphores.
4 */
5
6/*
7 * Copyright (C) 2009-2023 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/semaphore.h>
42
43#include <iprt/asm.h>
44#include <iprt/assert.h>
45#include <iprt/errcore.h>
46#include <iprt/rand.h>
47#include <iprt/stream.h>
48#include <iprt/string.h>
49#include <iprt/test.h>
50#include <iprt/thread.h>
51#include <iprt/time.h>
52
53
54/*********************************************************************************************************************************
55* Global Variables *
56*********************************************************************************************************************************/
57/** The test handle. */
58static RTTEST g_hTest;
59/** Use to stop test loops. */
60static volatile bool g_fStop = false;
61
62
63
64/*********************************************************************************************************************************
65* Benchmark #1: Two thread pinging each other on two event sempahores. *
66*********************************************************************************************************************************/
67/** Pair of event semphores for the first benchmark test. */
68static RTSEMEVENT g_ahEvtBench1[2];
69static uint64_t g_uTimeoutBench1;
70static uint64_t g_fWaitBench1;
71static uint64_t volatile g_cBench1Iterations;
72
73
74static DECLCALLBACK(int) bench1Thread(RTTHREAD hThreadSelf, void *pvUser)
75{
76 uintptr_t const idxThread = (uintptr_t)pvUser;
77 RT_NOREF(hThreadSelf);
78
79 uint64_t cIterations = 0;
80 for (;; cIterations++)
81 {
82 int rc = RTSemEventWaitEx(g_ahEvtBench1[idxThread], g_fWaitBench1, g_uTimeoutBench1);
83 if (RT_SUCCESS(rc))
84 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS);
85 else if ( rc == VERR_TIMEOUT
86 && g_uTimeoutBench1 == 0
87 && (g_fWaitBench1 & RTSEMWAIT_FLAGS_RELATIVE) )
88 { /* likely */ }
89 else
90 RTTestFailed(g_hTest, "rc=%Rrc g_fWaitBench1=%#x g_uTimeoutBench1=%#RX64 (now=%#RX64)",
91 rc, g_fWaitBench1, g_uTimeoutBench1, RTTimeSystemNanoTS());
92 if (g_fStop)
93 {
94 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS);
95 break;
96 }
97 }
98
99 if (idxThread == 0)
100 g_cBench1Iterations = cIterations;
101 return VINF_SUCCESS;
102}
103
104
105static void bench1(const char *pszTest, uint32_t fFlags, uint64_t uTimeout)
106{
107 RTTestISub(pszTest);
108
109 /*
110 * Create the two threads and make the wait on one another's sempahore.
111 */
112 g_fStop = false;
113 g_uTimeoutBench1 = uTimeout;
114 g_fWaitBench1 = fFlags;
115
116 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[0]), VINF_SUCCESS);
117 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[1]), VINF_SUCCESS);
118
119 RTTHREAD hThread1;
120 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, bench1Thread, (void *)0, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t1"), VINF_SUCCESS);
121 RTTHREAD hThread2;
122 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, bench1Thread, (void *)1, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t2"), VINF_SUCCESS);
123 RTThreadSleep(256);
124
125 /*
126 * Kick off the first thread and wait for 5 seconds before stopping them
127 * and seeing how many iterations they managed to perform.
128 */
129 uint64_t const nsStart = RTTimeNanoTS();
130 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS);
131 RTThreadSleep(RT_MS_5SEC);
132
133 ASMAtomicWriteBool(&g_fStop, true);
134 uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
135
136 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS); /* paranoia */
137 RTTESTI_CHECK_RC(RTThreadWait(hThread1, RT_MS_5SEC, NULL), VINF_SUCCESS);
138 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[1]), VINF_SUCCESS);
139 RTTESTI_CHECK_RC(RTThreadWait(hThread2, RT_MS_5SEC, NULL), VINF_SUCCESS);
140
141 RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[0]), VINF_SUCCESS);
142 RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[1]), VINF_SUCCESS);
143
144 /*
145 * Report the result.
146 */
147 uint64_t cIterations = g_cBench1Iterations;
148 RTTestValue(g_hTest, "Throughput", cIterations * RT_NS_1SEC / cNsElapsed, RTTESTUNIT_OCCURRENCES_PER_SEC);
149 RTTestValue(g_hTest, "Roundtrip", cNsElapsed / RT_MAX(cIterations, 1), RTTESTUNIT_NS_PER_OCCURRENCE);
150}
151
152
153/*********************************************************************************************************************************
154* Test #1: Simple setup checking wakup order of two waiting thread. *
155*********************************************************************************************************************************/
156
157static DECLCALLBACK(int) test1Thread(RTTHREAD hThreadSelf, void *pvUser)
158{
159 RTSEMEVENT hSem = *(PRTSEMEVENT)pvUser;
160 RTTEST_CHECK_RC(g_hTest, RTThreadUserSignal(hThreadSelf), VINF_SUCCESS);
161 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
162 return VINF_SUCCESS;
163}
164
165
166static void test1(void)
167{
168 RTTestISub("Two threads");
169
170 /*
171 * Create the threads and let them block on the event semaphore one
172 * after the other.
173 */
174 RTSEMEVENT hSem;
175 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
176
177 RTTHREAD hThread1;
178 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t1"), VINF_SUCCESS);
179 RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread1, RT_MS_30SEC), VINF_SUCCESS);
180 RTThreadSleep(256);
181
182 RTTHREAD hThread2;
183 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t2"), VINF_SUCCESS);
184 RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread2, RT_MS_30SEC), VINF_SUCCESS);
185 RTThreadSleep(256);
186
187#if defined(RT_OS_SOLARIS)
188 /*
189 * The Single UNIX Specification v2 states: "If more than one thread is blocked on a
190 * condition variable, the scheduling policy determines the order in which threads
191 * are unblocked." On Solaris, the default scheduling policy, SCHED_OTHER, does not
192 * specify the order in which multiple threads blocked on a condition variable are
193 * awakened. Thus we can't guarantee which thread will wake up when the condition
194 * variable is signalled so instead of verifying the order of thread wakeup we
195 * simply verify that two signals wake both threads.
196 */
197 /* Signal twice to wake up both threads */
198 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
199 RTThreadSleep(256);
200 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
201
202 RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS);
203 RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS);
204#else
205 /*
206 * The Linux sched(7) man page states: "SCHED_OTHER is the standard Linux
207 * time-sharing scheduler ... the thread chosen to run is based on a dynamic
208 * priority that ... is based on the nice value and is increased for each time
209 * quantum the thread is ready to run, but denied to run by the scheduler." This
210 * means that in practice the thread blocked longest on the condition variable will
211 * be awakened first and thus we can verify the ordering below. FreeBSD and macOS
212 * don't seem to document their implementations for this scenario but empirically
213 * they behave similar to Linux.
214 */
215 /* Signal once, hopefully waking up thread1: */
216 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
217 RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS);
218
219 /* Signal once more, hopefully waking up thread2: */
220 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
221 RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS);
222#endif
223
224 RTTESTI_CHECK_RC(RTSemEventDestroy(hSem), VINF_SUCCESS);
225}
226
227
228/*********************************************************************************************************************************
229* Basic tests *
230*********************************************************************************************************************************/
231
232/**
233 * Just do a number of short waits and calculate min, max and average.
234 */
235static void resolution(void)
236{
237 RTTestISub("Timeout resolution");
238
239 RTSEMEVENT hSem;
240 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
241
242 uint64_t cNsMin = UINT64_MAX;
243 uint64_t cNsMax = 0;
244 uint64_t cNsTotal = 0;
245 uint32_t cLoops;
246 for (cLoops = 0; cLoops < 256; cLoops++)
247 {
248 uint64_t const nsStart = RTTimeNanoTS();
249 int rc = RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS, RT_NS_1US);
250 uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
251 RTTESTI_CHECK_RC(rc, VERR_TIMEOUT);
252 cNsTotal += cNsElapsed;
253 if (cNsElapsed < cNsMin)
254 cNsMin = cNsElapsed;
255 if (cNsElapsed > cNsMax)
256 cNsMax = cNsElapsed;
257 }
258
259 RTTestIValue("min", cNsMin, RTTESTUNIT_NS);
260 RTTestIValue("max", cNsMax, RTTESTUNIT_NS);
261 RTTestIValue("average", cNsTotal / cLoops, RTTESTUNIT_NS);
262 RTTestIValue("RTSemEventGetResolution", RTSemEventGetResolution(), RTTESTUNIT_NS);
263
264 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
265}
266
267
268
269static void testBasicsWaitTimeout(RTSEMEVENT hSem, unsigned i)
270{
271 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VERR_TIMEOUT);
272#if 0
273 RTTESTI_CHECK_RC_RETV(RTSemEventWaitNoResume(hSem, 0), VERR_TIMEOUT);
274#else
275 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
276 0), VERR_TIMEOUT);
277 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
278 RTTimeSystemNanoTS() + 1000*i), VERR_TIMEOUT);
279 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
280 RTTimeNanoTS() + 1000*i), VERR_TIMEOUT);
281 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
282 0), VERR_TIMEOUT);
283#endif
284}
285
286
287static void testBasics(void)
288{
289 RTTestISub("Basics");
290
291 RTSEMEVENT hSem;
292 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
293
294 /* The semaphore is created in a non-signalled state. */
295 testBasicsWaitTimeout(hSem, 0);
296 testBasicsWaitTimeout(hSem, 1);
297 if (RTTestIErrorCount())
298 return;
299
300 /* When signalling the semaphore, only the next waiter call shall
301 success, all subsequent ones should timeout as above. */
302 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
303 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VINF_SUCCESS);
304 testBasicsWaitTimeout(hSem, 0);
305 if (RTTestIErrorCount())
306 return;
307
308 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
309 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 2), VINF_SUCCESS);
310 testBasicsWaitTimeout(hSem, 2);
311
312 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
313 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
314 testBasicsWaitTimeout(hSem, 1);
315
316 if (RTTestIErrorCount())
317 return;
318
319 /* Now do all the event wait ex variations: */
320 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
321 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
322 0),
323 VINF_SUCCESS);
324 testBasicsWaitTimeout(hSem, 1);
325
326 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
327 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
328 testBasicsWaitTimeout(hSem, 1);
329
330 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
331 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
332 testBasicsWaitTimeout(hSem, 1);
333
334 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
335 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
336 RTTimeSystemNanoTS() + RT_NS_1US), VINF_SUCCESS);
337 testBasicsWaitTimeout(hSem, 1);
338
339 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
340 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
341 RTTimeNanoTS() + RT_NS_1US), VINF_SUCCESS);
342 testBasicsWaitTimeout(hSem, 0);
343
344 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
345 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
346 RTTimeNanoTS() + RT_NS_1HOUR), VINF_SUCCESS);
347 testBasicsWaitTimeout(hSem, 0);
348
349 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
350 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
351 0), VINF_SUCCESS);
352 testBasicsWaitTimeout(hSem, 1);
353
354 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
355 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
356 _1G), VINF_SUCCESS);
357 testBasicsWaitTimeout(hSem, 1);
358
359 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
360 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
361 UINT64_MAX), VINF_SUCCESS);
362
363 testBasicsWaitTimeout(hSem, 10);
364
365 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
366 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
367 RTTimeSystemMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
368 testBasicsWaitTimeout(hSem, 1);
369
370 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
371 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
372 RTTimeMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
373 testBasicsWaitTimeout(hSem, 1);
374
375 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
376 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
377 0), VINF_SUCCESS);
378 testBasicsWaitTimeout(hSem, 0);
379
380 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
381 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
382 _1M), VINF_SUCCESS);
383 testBasicsWaitTimeout(hSem, 1);
384
385 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
386 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
387 UINT64_MAX), VINF_SUCCESS);
388 testBasicsWaitTimeout(hSem, 1);
389
390 /* Destroy it. */
391 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
392 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(NIL_RTSEMEVENT), VINF_SUCCESS);
393
394 /* Whether it is signalled or not used shouldn't matter. */
395 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
396 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
397 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
398
399 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
400 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
401
402 RTTestISubDone();
403}
404
405
406int main(int argc, char **argv)
407{
408 RT_NOREF_PV(argc); RT_NOREF_PV(argv);
409
410 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTSemEvent", &g_hTest);
411 if (rcExit != RTEXITCODE_SUCCESS)
412 return rcExit;
413
414 testBasics();
415 if (!RTTestErrorCount(g_hTest))
416 {
417 test1();
418 resolution();
419 }
420 if (!RTTestErrorCount(g_hTest))
421 {
422 bench1("Benchmark: Ping Pong, spin", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
423 0);
424 bench1("Benchmark: Ping Pong, indefinite", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE,
425 0);
426 bench1("Benchmark: Ping Pong, absolute", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
427 RTTimeSystemNanoTS() + RT_NS_1HOUR);
428 bench1("Benchmark: Ping Pong, relative", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
429 RT_NS_1HOUR);
430 bench1("Benchmark: Ping Pong, relative, resume", RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
431 RT_NS_1HOUR);
432 }
433
434 return RTTestSummaryAndDestroy(g_hTest);
435}
436
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