From b0baeee03e575ff380a57370399b8c02cbf1198b Mon Sep 17 00:00:00 2001 From: Cla Galliard Date: Sat, 1 Jun 2024 17:44:41 +0200 Subject: [PATCH] tests/posix: Add test for pthread_timed_join and pthread_try_join Test for the non-standard but useful pthread_timed_join- and pthread_try_join-functions. Signed-off-by: Cla Galliard --- tests/posix/common/src/pthread.c | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/posix/common/src/pthread.c b/tests/posix/common/src/pthread.c index 4fea9ed60ca..8b99f15b883 100644 --- a/tests/posix/common/src/pthread.c +++ b/tests/posix/common/src/pthread.c @@ -143,6 +143,14 @@ static void *thread_top_exec(void *p1) return NULL; } +static void *timedjoin_thread(void *p1) +{ + int sleep_duration_ms = POINTER_TO_INT(p1); + + usleep(USEC_PER_MSEC * sleep_duration_ms); + return NULL; +} + static int bounce_test_done(void) { int i; @@ -371,6 +379,69 @@ ZTEST(pthread, test_pthread_termination) zassert_equal(ret, ESRCH, "cancelled a terminated thread!"); } +ZTEST(pthread, test_pthread_tryjoin) +{ + pthread_t th = {0}; + int sleep_duration_ms = 200; + void *retval; + + /* Creating a thread that exits after 200ms*/ + zassert_ok(pthread_create(&th, NULL, timedjoin_thread, INT_TO_POINTER(sleep_duration_ms))); + + /* Attempting to join, when thread is still running, should fail */ + usleep(USEC_PER_MSEC * sleep_duration_ms / 2); + zassert_equal(pthread_tryjoin_np(th, &retval), EBUSY); + + /* Sleep so thread will exit */ + usleep(USEC_PER_MSEC * sleep_duration_ms); + + /* Attempting to join without blocking should succeed now */ + zassert_ok(pthread_tryjoin_np(th, &retval)); +} + +ZTEST(pthread, test_pthread_timedjoin) +{ + pthread_t th = {0}; + int sleep_duration_ms = 200; + void *ret; + struct timespec not_done; + struct timespec done; + struct timespec invalid[] = { + [0] = {.tv_sec = -1}, + [1] = {.tv_nsec = -1}, + [2] = {.tv_nsec = NSEC_PER_SEC}, + }; + + /* setup timespecs when the thread is still running and when it is done */ + clock_gettime(CLOCK_MONOTONIC, ¬_done); + clock_gettime(CLOCK_MONOTONIC, &done); + not_done.tv_nsec += sleep_duration_ms / 2 * NSEC_PER_MSEC; + done.tv_nsec += sleep_duration_ms * 1.5 * NSEC_PER_MSEC; + while (not_done.tv_nsec >= NSEC_PER_SEC) { + not_done.tv_sec++; + not_done.tv_nsec -= NSEC_PER_SEC; + } + while (done.tv_nsec >= NSEC_PER_SEC) { + done.tv_sec++; + done.tv_nsec -= NSEC_PER_SEC; + } + + /* Creating a thread that exits after 200ms*/ + zassert_ok(pthread_create(&th, NULL, timedjoin_thread, INT_TO_POINTER(sleep_duration_ms))); + + /* pthread_timedjoin-np must return -EINVAL for invalid struct timespecs */ + zassert_equal(pthread_timedjoin_np(th, &ret, NULL), EINVAL); + for (size_t i = 0; i < ARRAY_SIZE(invalid); ++i) { + zassert_equal(pthread_timedjoin_np(th, &ret, &invalid[i]), EINVAL); + } + + /* Attempting to join with a timeout, when the thread is still running should fail */ + zassert_equal(pthread_timedjoin_np(th, &ret, ¬_done), ETIMEDOUT); + + /* Attempting to join with a timeout, when the thread is done, should succeed */ + zassert_ok(pthread_timedjoin_np(th, &ret, &done)); +} + static void *create_thread1(void *p1) { /* do nothing */