@@ -143,6 +143,14 @@ static void *thread_top_exec(void *p1)
143143 return NULL ;
144144}
145145
146+ static void * timedjoin_thread (void * p1 )
147+ {
148+ int sleep_duration_ms = POINTER_TO_INT (p1 );
149+
150+ usleep (USEC_PER_MSEC * sleep_duration_ms );
151+ return NULL ;
152+ }
153+
146154static int bounce_test_done (void )
147155{
148156 int i ;
@@ -371,6 +379,69 @@ ZTEST(pthread, test_pthread_termination)
371379 zassert_equal (ret , ESRCH , "cancelled a terminated thread!" );
372380}
373381
382+ ZTEST (pthread , test_pthread_tryjoin )
383+ {
384+ pthread_t th = {0 };
385+ int sleep_duration_ms = 200 ;
386+ void * retval ;
387+
388+ /* Creating a thread that exits after 200ms*/
389+ zassert_ok (pthread_create (& th , NULL , timedjoin_thread , INT_TO_POINTER (sleep_duration_ms )));
390+
391+ /* Attempting to join, when thread is still running, should fail */
392+ usleep (USEC_PER_MSEC * sleep_duration_ms / 2 );
393+ zassert_equal (pthread_tryjoin_np (th , & retval ), EBUSY );
394+
395+ /* Sleep so thread will exit */
396+ usleep (USEC_PER_MSEC * sleep_duration_ms );
397+
398+ /* Attempting to join without blocking should succeed now */
399+ zassert_ok (pthread_tryjoin_np (th , & retval ));
400+ }
401+
402+ ZTEST (pthread , test_pthread_timedjoin )
403+ {
404+ pthread_t th = {0 };
405+ int sleep_duration_ms = 200 ;
406+ void * ret ;
407+ struct timespec not_done ;
408+ struct timespec done ;
409+ struct timespec invalid [] = {
410+ [0 ] = {.tv_sec = -1 },
411+ [1 ] = {.tv_nsec = -1 },
412+ [2 ] = {.tv_nsec = NSEC_PER_SEC },
413+ };
414+
415+ /* setup timespecs when the thread is still running and when it is done */
416+ clock_gettime (CLOCK_MONOTONIC , & not_done );
417+ clock_gettime (CLOCK_MONOTONIC , & done );
418+ not_done .tv_nsec += sleep_duration_ms / 2 * NSEC_PER_MSEC ;
419+ done .tv_nsec += sleep_duration_ms * 1.5 * NSEC_PER_MSEC ;
420+ while (not_done .tv_nsec >= NSEC_PER_SEC ) {
421+ not_done .tv_sec ++ ;
422+ not_done .tv_nsec -= NSEC_PER_SEC ;
423+ }
424+ while (done .tv_nsec >= NSEC_PER_SEC ) {
425+ done .tv_sec ++ ;
426+ done .tv_nsec -= NSEC_PER_SEC ;
427+ }
428+
429+ /* Creating a thread that exits after 200ms*/
430+ zassert_ok (pthread_create (& th , NULL , timedjoin_thread , INT_TO_POINTER (sleep_duration_ms )));
431+
432+ /* pthread_timedjoin-np must return -EINVAL for invalid struct timespecs */
433+ zassert_equal (pthread_timedjoin_np (th , & ret , NULL ), EINVAL );
434+ for (size_t i = 0 ; i < ARRAY_SIZE (invalid ); ++ i ) {
435+ zassert_equal (pthread_timedjoin_np (th , & ret , & invalid [i ]), EINVAL );
436+ }
437+
438+ /* Attempting to join with a timeout, when the thread is still running should fail */
439+ zassert_equal (pthread_timedjoin_np (th , & ret , & not_done ), ETIMEDOUT );
440+
441+ /* Attempting to join with a timeout, when the thread is done, should succeed */
442+ zassert_ok (pthread_timedjoin_np (th , & ret , & done ));
443+ }
444+
374445static void * create_thread1 (void * p1 )
375446{
376447 /* do nothing */
0 commit comments