From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Runtime/testcase/tstRTSemEvent.cpp | 436 ++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 src/VBox/Runtime/testcase/tstRTSemEvent.cpp (limited to 'src/VBox/Runtime/testcase/tstRTSemEvent.cpp') diff --git a/src/VBox/Runtime/testcase/tstRTSemEvent.cpp b/src/VBox/Runtime/testcase/tstRTSemEvent.cpp new file mode 100644 index 00000000..d8ff3a9d --- /dev/null +++ b/src/VBox/Runtime/testcase/tstRTSemEvent.cpp @@ -0,0 +1,436 @@ +/* $Id: tstRTSemEvent.cpp $ */ +/** @file + * IPRT Testcase - Multiple Release Event Semaphores. + */ + +/* + * Copyright (C) 2009-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** The test handle. */ +static RTTEST g_hTest; +/** Use to stop test loops. */ +static volatile bool g_fStop = false; + + + +/********************************************************************************************************************************* +* Benchmark #1: Two thread pinging each other on two event sempahores. * +*********************************************************************************************************************************/ +/** Pair of event semphores for the first benchmark test. */ +static RTSEMEVENT g_ahEvtBench1[2]; +static uint64_t g_uTimeoutBench1; +static uint64_t g_fWaitBench1; +static uint64_t volatile g_cBench1Iterations; + + +static DECLCALLBACK(int) bench1Thread(RTTHREAD hThreadSelf, void *pvUser) +{ + uintptr_t const idxThread = (uintptr_t)pvUser; + RT_NOREF(hThreadSelf); + + uint64_t cIterations = 0; + for (;; cIterations++) + { + int rc = RTSemEventWaitEx(g_ahEvtBench1[idxThread], g_fWaitBench1, g_uTimeoutBench1); + if (RT_SUCCESS(rc)) + RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS); + else if ( rc == VERR_TIMEOUT + && g_uTimeoutBench1 == 0 + && (g_fWaitBench1 & RTSEMWAIT_FLAGS_RELATIVE) ) + { /* likely */ } + else + RTTestFailed(g_hTest, "rc=%Rrc g_fWaitBench1=%#x g_uTimeoutBench1=%#RX64 (now=%#RX64)", + rc, g_fWaitBench1, g_uTimeoutBench1, RTTimeSystemNanoTS()); + if (g_fStop) + { + RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS); + break; + } + } + + if (idxThread == 0) + g_cBench1Iterations = cIterations; + return VINF_SUCCESS; +} + + +static void bench1(const char *pszTest, uint32_t fFlags, uint64_t uTimeout) +{ + RTTestISub(pszTest); + + /* + * Create the two threads and make the wait on one another's sempahore. + */ + g_fStop = false; + g_uTimeoutBench1 = uTimeout; + g_fWaitBench1 = fFlags; + + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[0]), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[1]), VINF_SUCCESS); + + RTTHREAD hThread1; + RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, bench1Thread, (void *)0, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t1"), VINF_SUCCESS); + RTTHREAD hThread2; + RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, bench1Thread, (void *)1, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t2"), VINF_SUCCESS); + RTThreadSleep(256); + + /* + * Kick off the first thread and wait for 5 seconds before stopping them + * and seeing how many iterations they managed to perform. + */ + uint64_t const nsStart = RTTimeNanoTS(); + RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS); + RTThreadSleep(RT_MS_5SEC); + + ASMAtomicWriteBool(&g_fStop, true); + uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart; + + RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS); /* paranoia */ + RTTESTI_CHECK_RC(RTThreadWait(hThread1, RT_MS_5SEC, NULL), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[1]), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTThreadWait(hThread2, RT_MS_5SEC, NULL), VINF_SUCCESS); + + RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[0]), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[1]), VINF_SUCCESS); + + /* + * Report the result. + */ + uint64_t cIterations = g_cBench1Iterations; + RTTestValue(g_hTest, "Throughput", cIterations * RT_NS_1SEC / cNsElapsed, RTTESTUNIT_OCCURRENCES_PER_SEC); + RTTestValue(g_hTest, "Roundtrip", cNsElapsed / RT_MAX(cIterations, 1), RTTESTUNIT_NS_PER_OCCURRENCE); +} + + +/********************************************************************************************************************************* +* Test #1: Simple setup checking wakup order of two waiting thread. * +*********************************************************************************************************************************/ + +static DECLCALLBACK(int) test1Thread(RTTHREAD hThreadSelf, void *pvUser) +{ + RTSEMEVENT hSem = *(PRTSEMEVENT)pvUser; + RTTEST_CHECK_RC(g_hTest, RTThreadUserSignal(hThreadSelf), VINF_SUCCESS); + RTTEST_CHECK_RC(g_hTest, RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS); + return VINF_SUCCESS; +} + + +static void test1(void) +{ + RTTestISub("Two threads"); + + /* + * Create the threads and let them block on the event semaphore one + * after the other. + */ + RTSEMEVENT hSem; + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS); + + RTTHREAD hThread1; + RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t1"), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread1, RT_MS_30SEC), VINF_SUCCESS); + RTThreadSleep(256); + + RTTHREAD hThread2; + RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t2"), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread2, RT_MS_30SEC), VINF_SUCCESS); + RTThreadSleep(256); + +#if defined(RT_OS_SOLARIS) + /* + * The Single UNIX Specification v2 states: "If more than one thread is blocked on a + * condition variable, the scheduling policy determines the order in which threads + * are unblocked." On Solaris, the default scheduling policy, SCHED_OTHER, does not + * specify the order in which multiple threads blocked on a condition variable are + * awakened. Thus we can't guarantee which thread will wake up when the condition + * variable is signalled so instead of verifying the order of thread wakeup we + * simply verify that two signals wake both threads. + */ + /* Signal twice to wake up both threads */ + RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS); + RTThreadSleep(256); + RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS); + + RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS); +#else + /* + * The Linux sched(7) man page states: "SCHED_OTHER is the standard Linux + * time-sharing scheduler ... the thread chosen to run is based on a dynamic + * priority that ... is based on the nice value and is increased for each time + * quantum the thread is ready to run, but denied to run by the scheduler." This + * means that in practice the thread blocked longest on the condition variable will + * be awakened first and thus we can verify the ordering below. FreeBSD and macOS + * don't seem to document their implementations for this scenario but empirically + * they behave similar to Linux. + */ + /* Signal once, hopefully waking up thread1: */ + RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS); + + /* Signal once more, hopefully waking up thread2: */ + RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS); +#endif + + RTTESTI_CHECK_RC(RTSemEventDestroy(hSem), VINF_SUCCESS); +} + + +/********************************************************************************************************************************* +* Basic tests * +*********************************************************************************************************************************/ + +/** + * Just do a number of short waits and calculate min, max and average. + */ +static void resolution(void) +{ + RTTestISub("Timeout resolution"); + + RTSEMEVENT hSem; + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS); + + uint64_t cNsMin = UINT64_MAX; + uint64_t cNsMax = 0; + uint64_t cNsTotal = 0; + uint32_t cLoops; + for (cLoops = 0; cLoops < 256; cLoops++) + { + uint64_t const nsStart = RTTimeNanoTS(); + int rc = RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS, RT_NS_1US); + uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart; + RTTESTI_CHECK_RC(rc, VERR_TIMEOUT); + cNsTotal += cNsElapsed; + if (cNsElapsed < cNsMin) + cNsMin = cNsElapsed; + if (cNsElapsed > cNsMax) + cNsMax = cNsElapsed; + } + + RTTestIValue("min", cNsMin, RTTESTUNIT_NS); + RTTestIValue("max", cNsMax, RTTESTUNIT_NS); + RTTestIValue("average", cNsTotal / cLoops, RTTESTUNIT_NS); + RTTestIValue("RTSemEventGetResolution", RTSemEventGetResolution(), RTTESTUNIT_NS); + + RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS); +} + + + +static void testBasicsWaitTimeout(RTSEMEVENT hSem, unsigned i) +{ + RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VERR_TIMEOUT); +#if 0 + RTTESTI_CHECK_RC_RETV(RTSemEventWaitNoResume(hSem, 0), VERR_TIMEOUT); +#else + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE, + 0), VERR_TIMEOUT); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeSystemNanoTS() + 1000*i), VERR_TIMEOUT); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeNanoTS() + 1000*i), VERR_TIMEOUT); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE, + 0), VERR_TIMEOUT); +#endif +} + + +static void testBasics(void) +{ + RTTestISub("Basics"); + + RTSEMEVENT hSem; + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS); + + /* The semaphore is created in a non-signalled state. */ + testBasicsWaitTimeout(hSem, 0); + testBasicsWaitTimeout(hSem, 1); + if (RTTestIErrorCount()) + return; + + /* When signalling the semaphore, only the next waiter call shall + success, all subsequent ones should timeout as above. */ + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 0); + if (RTTestIErrorCount()) + return; + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 2), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 2); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + if (RTTestIErrorCount()) + return; + + /* Now do all the event wait ex variations: */ + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE, + 0), + VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeSystemNanoTS() + RT_NS_1US), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeNanoTS() + RT_NS_1US), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 0); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeNanoTS() + RT_NS_1HOUR), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 0); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + 0), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + _1G), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + UINT64_MAX), VINF_SUCCESS); + + testBasicsWaitTimeout(hSem, 10); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeSystemMilliTS() + RT_MS_1SEC), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeMilliTS() + RT_MS_1SEC), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE, + 0), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 0); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE, + _1M), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE, + UINT64_MAX), VINF_SUCCESS); + testBasicsWaitTimeout(hSem, 1); + + /* Destroy it. */ + RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(NIL_RTSEMEVENT), VINF_SUCCESS); + + /* Whether it is signalled or not used shouldn't matter. */ + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS); + + RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS); + RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS); + + RTTestISubDone(); +} + + +int main(int argc, char **argv) +{ + RT_NOREF_PV(argc); RT_NOREF_PV(argv); + + RTEXITCODE rcExit = RTTestInitAndCreate("tstRTSemEvent", &g_hTest); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + testBasics(); + if (!RTTestErrorCount(g_hTest)) + { + test1(); + resolution(); + } + if (!RTTestErrorCount(g_hTest)) + { + bench1("Benchmark: Ping Pong, spin", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE, + 0); + bench1("Benchmark: Ping Pong, indefinite", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, + 0); + bench1("Benchmark: Ping Pong, absolute", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE, + RTTimeSystemNanoTS() + RT_NS_1HOUR); + bench1("Benchmark: Ping Pong, relative", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE, + RT_NS_1HOUR); + bench1("Benchmark: Ping Pong, relative, resume", RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE, + RT_NS_1HOUR); + } + + return RTTestSummaryAndDestroy(g_hTest); +} + -- cgit v1.2.3