summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2023-05-09 17:01:36 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2023-05-09 17:01:36 +0000
commit6a8a935afa1ddac57a55c69e819416f2454bfa73 (patch)
treea639b7ccf0ee9ca885cc89cdd0ff9d1d3df1fdb1
parent0df60991e041246f2ac63b0c1ea89056ab039bc3 (diff)
downloadVirtualBox-svn-6a8a935afa1ddac57a55c69e819416f2454bfa73.tar.gz
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. git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@99704 cfe28804-0f27-0410-a406-dd0f0b0b656f
-rw-r--r--src/VBox/Runtime/testcase/tstRTSemEvent.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/VBox/Runtime/testcase/tstRTSemEvent.cpp b/src/VBox/Runtime/testcase/tstRTSemEvent.cpp
index 569325f4d9f..63f7cd5f2aa 100644
--- a/src/VBox/Runtime/testcase/tstRTSemEvent.cpp
+++ b/src/VBox/Runtime/testcase/tstRTSemEvent.cpp
@@ -165,7 +165,7 @@ static DECLCALLBACK(int) test1Thread(RTTHREAD hThreadSelf, void *pvUser)
static void test1(void)
{
- RTTestISub("Three threads");
+ RTTestISub("Two threads");
/*
* Create the threads and let them block on the event semaphore one
@@ -184,6 +184,34 @@ static void test1(void)
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);
@@ -191,6 +219,7 @@ static void test1(void)
/* 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);
}