From 08a66f5f3063dae0e79b71683e35f5123799db84 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 28 Jun 2024 22:15:23 +0200 Subject: [PATCH] cond tests: Avoid theoretically possible failure. * tests/test-cnd.c (cnd_wait_routine, cnd_timedwait_routine): Report to the main thread if this thread comes too late. (test_cnd_wait, test_cnd_timedwait): Return a 'skipped' value. (main): Print SKIP instead of OK if the essence of the test was skipped. * tests/test-cond.c (cond_routine, timedcond_routine): Report to the main thread if this thread comes too late. (test_cond, test_timedcond): Return a 'skipped' value. (main): Print SKIP instead of OK if the essence of the test was skipped. * tests/test-pthread-cond.c (pthread_cond_wait_routine, pthread_cond_timedwait_routine): Report to the main thread if this thread comes too late. (test_pthread_cond_wait, test_pthread_cond_timedwait): Return a 'skipped' value. (main): Print SKIP instead of OK if the essence of the test was skipped. --- ChangeLog | 16 ++++++++++ tests/test-cnd.c | 61 ++++++++++++++++++++++++++++---------- tests/test-cond.c | 60 +++++++++++++++++++++++++++---------- tests/test-pthread-cond.c | 62 +++++++++++++++++++++++++++++---------- 4 files changed, 154 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75f9d19a43..cb730bb006 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2024-06-28 Bruno Haible + cond tests: Avoid theoretically possible failure. + * tests/test-cnd.c (cnd_wait_routine, cnd_timedwait_routine): Report to + the main thread if this thread comes too late. + (test_cnd_wait, test_cnd_timedwait): Return a 'skipped' value. + (main): Print SKIP instead of OK if the essence of the test was skipped. + * tests/test-cond.c (cond_routine, timedcond_routine): Report to the + main thread if this thread comes too late. + (test_cond, test_timedcond): Return a 'skipped' value. + (main): Print SKIP instead of OK if the essence of the test was skipped. + * tests/test-pthread-cond.c (pthread_cond_wait_routine, + pthread_cond_timedwait_routine): Report to the main thread if this + thread comes too late. + (test_pthread_cond_wait, test_pthread_cond_timedwait): Return a + 'skipped' value. + (main): Print SKIP instead of OK if the essence of the test was skipped. + cond tests: Improve multithread-safety. * tests/test-cnd.c (cond_value, cond_timed_out): Mark as volatile. * tests/test-cond.c (cond_value, cond_timed_out): Likewise. diff --git a/tests/test-cnd.c b/tests/test-cnd.c index 730c879c49..b8906a15c0 100644 --- a/tests/test-cnd.c +++ b/tests/test-cnd.c @@ -70,9 +70,19 @@ static int cnd_wait_routine (void *arg) { ASSERT (mtx_lock (&lockcond) == thrd_success); - while (!cond_value) + if (cond_value) { - ASSERT (cnd_wait (&condtest, &lockcond) == thrd_success); + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else + { + do + { + ASSERT (cnd_wait (&condtest, &lockcond) == thrd_success); + } + while (!cond_value); } ASSERT (mtx_unlock (&lockcond) == thrd_success); @@ -81,16 +91,17 @@ cnd_wait_routine (void *arg) return 0; } -static void +static int test_cnd_wait () { + int skipped = 0; thrd_t thread; int ret; cond_value = 0; /* Create a separate thread. */ - ASSERT (thrd_create (&thread, cnd_wait_routine, NULL) == thrd_success); + ASSERT (thrd_create (&thread, cnd_wait_routine, &skipped) == thrd_success); /* Sleep for 2 seconds. */ { @@ -118,6 +129,8 @@ test_cnd_wait () if (cond_value != 2) abort (); + + return skipped; } @@ -148,28 +161,40 @@ cnd_timedwait_routine (void *arg) struct timespec ts; ASSERT (mtx_lock (&lockcond) == thrd_success); - while (!cond_value) + if (cond_value) + { + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else { - get_ts (&ts); - ret = cnd_timedwait (&condtest, &lockcond, &ts); - if (ret == thrd_timedout) - cond_timed_out = 1; + do + { + get_ts (&ts); + ret = cnd_timedwait (&condtest, &lockcond, &ts); + if (ret == thrd_timedout) + cond_timed_out = 1; + } + while (!cond_value); } ASSERT (mtx_unlock (&lockcond) == thrd_success); return 0; } -static void +static int test_cnd_timedwait (void) { + int skipped = 0; thrd_t thread; int ret; cond_value = cond_timed_out = 0; /* Create a separate thread. */ - ASSERT (thrd_create (&thread, cnd_timedwait_routine, NULL) == thrd_success); + ASSERT (thrd_create (&thread, cnd_timedwait_routine, &skipped) + == thrd_success); /* Sleep for 2 seconds. */ { @@ -197,6 +222,8 @@ test_cnd_timedwait (void) if (!cond_timed_out) abort (); + + return skipped; } @@ -216,13 +243,17 @@ main () #if DO_TEST_COND printf ("Starting test_cnd_wait ..."); fflush (stdout); - test_cnd_wait (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_cnd_wait (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif #if DO_TEST_TIMEDCOND printf ("Starting test_cnd_timedwait ..."); fflush (stdout); - test_cnd_timedwait (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_cnd_timedwait (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif return test_exit_status; diff --git a/tests/test-cond.c b/tests/test-cond.c index 80d696a5d8..712220aaac 100644 --- a/tests/test-cond.c +++ b/tests/test-cond.c @@ -70,9 +70,19 @@ static void * cond_routine (void *arg) { gl_lock_lock (lockcond); - while (!cond_value) + if (cond_value) { - gl_cond_wait (condtest, lockcond); + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else + { + do + { + gl_cond_wait (condtest, lockcond); + } + while (!cond_value); } gl_lock_unlock (lockcond); @@ -81,15 +91,16 @@ cond_routine (void *arg) return NULL; } -static void +static int test_cond () { + int skipped = 0; gl_thread_t thread; cond_value = 0; /* Create a separate thread. */ - thread = gl_thread_create (cond_routine, NULL); + thread = gl_thread_create (cond_routine, &skipped); /* Sleep for 2 seconds. */ { @@ -113,6 +124,8 @@ test_cond () if (cond_value != 2) abort (); + + return skipped; } @@ -143,27 +156,38 @@ timedcond_routine (void *arg) struct timespec ts; gl_lock_lock (lockcond); - while (!cond_value) + if (cond_value) + { + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else { - get_ts (&ts); - ret = glthread_cond_timedwait (&condtest, &lockcond, &ts); - if (ret == ETIMEDOUT) - cond_timed_out = 1; + do + { + get_ts (&ts); + ret = glthread_cond_timedwait (&condtest, &lockcond, &ts); + if (ret == ETIMEDOUT) + cond_timed_out = 1; + } + while (!cond_value); } gl_lock_unlock (lockcond); return NULL; } -static void +static int test_timedcond (void) { + int skipped = 0; gl_thread_t thread; cond_value = cond_timed_out = 0; /* Create a separate thread. */ - thread = gl_thread_create (timedcond_routine, NULL); + thread = gl_thread_create (timedcond_routine, &skipped); /* Sleep for 2 seconds. */ { @@ -187,6 +211,8 @@ test_timedcond (void) if (!cond_timed_out) abort (); + + return skipped; } @@ -195,13 +221,17 @@ main () { #if DO_TEST_COND printf ("Starting test_cond ..."); fflush (stdout); - test_cond (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_cond (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif #if DO_TEST_TIMEDCOND printf ("Starting test_timedcond ..."); fflush (stdout); - test_timedcond (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_timedcond (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif return 0; diff --git a/tests/test-pthread-cond.c b/tests/test-pthread-cond.c index 98c291c24c..3854ee2745 100644 --- a/tests/test-pthread-cond.c +++ b/tests/test-pthread-cond.c @@ -75,9 +75,19 @@ static void * pthread_cond_wait_routine (void *arg) { ASSERT (pthread_mutex_lock (&lockcond) == 0); - while (!cond_value) + if (cond_value) { - ASSERT (pthread_cond_wait (&condtest, &lockcond) == 0); + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else + { + do + { + ASSERT (pthread_cond_wait (&condtest, &lockcond) == 0); + } + while (!cond_value); } ASSERT (pthread_mutex_unlock (&lockcond) == 0); @@ -86,16 +96,18 @@ pthread_cond_wait_routine (void *arg) return NULL; } -static void +static int test_pthread_cond_wait () { + int skipped = 0; pthread_t thread; int ret; cond_value = 0; /* Create a separate thread. */ - ASSERT (pthread_create (&thread, NULL, pthread_cond_wait_routine, NULL) == 0); + ASSERT (pthread_create (&thread, NULL, pthread_cond_wait_routine, &skipped) + == 0); /* Sleep for 2 seconds. */ { @@ -123,6 +135,8 @@ test_pthread_cond_wait () if (cond_value != 2) abort (); + + return skipped; } @@ -153,28 +167,40 @@ pthread_cond_timedwait_routine (void *arg) struct timespec ts; ASSERT (pthread_mutex_lock (&lockcond) == 0); - while (!cond_value) + if (cond_value) + { + /* The main thread already slept, and nevertheless this thread comes + too late. */ + *(int *)arg = 1; + } + else { - get_ts (&ts); - ret = pthread_cond_timedwait (&condtest, &lockcond, &ts); - if (ret == ETIMEDOUT) - cond_timed_out = 1; + do + { + get_ts (&ts); + ret = pthread_cond_timedwait (&condtest, &lockcond, &ts); + if (ret == ETIMEDOUT) + cond_timed_out = 1; + } + while (!cond_value); } ASSERT (pthread_mutex_unlock (&lockcond) == 0); return NULL; } -static void +static int test_pthread_cond_timedwait (void) { + int skipped = 0; pthread_t thread; int ret; cond_value = cond_timed_out = 0; /* Create a separate thread. */ - ASSERT (pthread_create (&thread, NULL, pthread_cond_timedwait_routine, NULL) + ASSERT (pthread_create (&thread, NULL, + pthread_cond_timedwait_routine, &skipped) == 0); /* Sleep for 2 seconds. */ @@ -203,6 +229,8 @@ test_pthread_cond_timedwait (void) if (!cond_timed_out) abort (); + + return skipped; } @@ -230,13 +258,17 @@ main () #if DO_TEST_COND printf ("Starting test_pthread_cond_wait ..."); fflush (stdout); - test_pthread_cond_wait (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_pthread_cond_wait (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif #if DO_TEST_TIMEDCOND printf ("Starting test_pthread_cond_timedwait ..."); fflush (stdout); - test_pthread_cond_timedwait (); - printf (" OK\n"); fflush (stdout); + { + int skipped = test_pthread_cond_timedwait (); + printf (skipped ? " SKIP\n" : " OK\n"); fflush (stdout); + } #endif return test_exit_status; -- 2.39.5