VirtualBox

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

Last change on this file since 98715 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 17.5 KB
Line 
1/* $Id: tstRTSemEvent.cpp 98103 2023-01-17 14:15:46Z 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("Three 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 /* Signal once, hopefully waking up thread1: */
188 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
189 RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS);
190
191 /* Signal once more, hopefully waking up thread2: */
192 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
193 RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS);
194
195 RTTESTI_CHECK_RC(RTSemEventDestroy(hSem), VINF_SUCCESS);
196}
197
198
199/*********************************************************************************************************************************
200* Basic tests *
201*********************************************************************************************************************************/
202
203/**
204 * Just do a number of short waits and calculate min, max and average.
205 */
206static void resolution(void)
207{
208 RTTestISub("Timeout resolution");
209
210 RTSEMEVENT hSem;
211 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
212
213 uint64_t cNsMin = UINT64_MAX;
214 uint64_t cNsMax = 0;
215 uint64_t cNsTotal = 0;
216 uint32_t cLoops;
217 for (cLoops = 0; cLoops < 256; cLoops++)
218 {
219 uint64_t const nsStart = RTTimeNanoTS();
220 int rc = RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS, RT_NS_1US);
221 uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
222 RTTESTI_CHECK_RC(rc, VERR_TIMEOUT);
223 cNsTotal += cNsElapsed;
224 if (cNsElapsed < cNsMin)
225 cNsMin = cNsElapsed;
226 if (cNsElapsed > cNsMax)
227 cNsMax = cNsElapsed;
228 }
229
230 RTTestIValue("min", cNsMin, RTTESTUNIT_NS);
231 RTTestIValue("max", cNsMax, RTTESTUNIT_NS);
232 RTTestIValue("average", cNsTotal / cLoops, RTTESTUNIT_NS);
233 RTTestIValue("RTSemEventGetResolution", RTSemEventGetResolution(), RTTESTUNIT_NS);
234
235 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
236}
237
238
239
240static void testBasicsWaitTimeout(RTSEMEVENT hSem, unsigned i)
241{
242 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VERR_TIMEOUT);
243#if 0
244 RTTESTI_CHECK_RC_RETV(RTSemEventWaitNoResume(hSem, 0), VERR_TIMEOUT);
245#else
246 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
247 0), VERR_TIMEOUT);
248 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
249 RTTimeSystemNanoTS() + 1000*i), VERR_TIMEOUT);
250 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
251 RTTimeNanoTS() + 1000*i), VERR_TIMEOUT);
252 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
253 0), VERR_TIMEOUT);
254#endif
255}
256
257
258static void testBasics(void)
259{
260 RTTestISub("Basics");
261
262 RTSEMEVENT hSem;
263 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
264
265 /* The semaphore is created in a non-signalled state. */
266 testBasicsWaitTimeout(hSem, 0);
267 testBasicsWaitTimeout(hSem, 1);
268 if (RTTestIErrorCount())
269 return;
270
271 /* When signalling the semaphore, only the next waiter call shall
272 success, all subsequent ones should timeout as above. */
273 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
274 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VINF_SUCCESS);
275 testBasicsWaitTimeout(hSem, 0);
276 if (RTTestIErrorCount())
277 return;
278
279 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
280 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 2), VINF_SUCCESS);
281 testBasicsWaitTimeout(hSem, 2);
282
283 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
284 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
285 testBasicsWaitTimeout(hSem, 1);
286
287 if (RTTestIErrorCount())
288 return;
289
290 /* Now do all the event wait ex variations: */
291 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
292 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
293 0),
294 VINF_SUCCESS);
295 testBasicsWaitTimeout(hSem, 1);
296
297 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
298 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
299 testBasicsWaitTimeout(hSem, 1);
300
301 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
302 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
303 testBasicsWaitTimeout(hSem, 1);
304
305 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
306 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
307 RTTimeSystemNanoTS() + RT_NS_1US), VINF_SUCCESS);
308 testBasicsWaitTimeout(hSem, 1);
309
310 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
311 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
312 RTTimeNanoTS() + RT_NS_1US), VINF_SUCCESS);
313 testBasicsWaitTimeout(hSem, 0);
314
315 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
316 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
317 RTTimeNanoTS() + RT_NS_1HOUR), VINF_SUCCESS);
318 testBasicsWaitTimeout(hSem, 0);
319
320 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
321 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
322 0), VINF_SUCCESS);
323 testBasicsWaitTimeout(hSem, 1);
324
325 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
326 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
327 _1G), 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_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
332 UINT64_MAX), VINF_SUCCESS);
333
334 testBasicsWaitTimeout(hSem, 10);
335
336 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
337 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
338 RTTimeSystemMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
339 testBasicsWaitTimeout(hSem, 1);
340
341 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
342 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
343 RTTimeMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
344 testBasicsWaitTimeout(hSem, 1);
345
346 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
347 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
348 0), VINF_SUCCESS);
349 testBasicsWaitTimeout(hSem, 0);
350
351 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
352 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
353 _1M), VINF_SUCCESS);
354 testBasicsWaitTimeout(hSem, 1);
355
356 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
357 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
358 UINT64_MAX), VINF_SUCCESS);
359 testBasicsWaitTimeout(hSem, 1);
360
361 /* Destroy it. */
362 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
363 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(NIL_RTSEMEVENT), VINF_SUCCESS);
364
365 /* Whether it is signalled or not used shouldn't matter. */
366 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
367 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
368 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
369
370 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
371 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
372
373 RTTestISubDone();
374}
375
376
377int main(int argc, char **argv)
378{
379 RT_NOREF_PV(argc); RT_NOREF_PV(argv);
380
381 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTSemEvent", &g_hTest);
382 if (rcExit != RTEXITCODE_SUCCESS)
383 return rcExit;
384
385 testBasics();
386 if (!RTTestErrorCount(g_hTest))
387 {
388 test1();
389 resolution();
390 }
391 if (!RTTestErrorCount(g_hTest))
392 {
393 bench1("Benchmark: Ping Pong, spin", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
394 0);
395 bench1("Benchmark: Ping Pong, indefinite", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE,
396 0);
397 bench1("Benchmark: Ping Pong, absolute", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
398 RTTimeSystemNanoTS() + RT_NS_1HOUR);
399 bench1("Benchmark: Ping Pong, relative", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
400 RT_NS_1HOUR);
401 bench1("Benchmark: Ping Pong, relative, resume", RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
402 RT_NS_1HOUR);
403 }
404
405 return RTTestSummaryAndDestroy(g_hTest);
406}
407
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