The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=afa70a8496e90fa751418be8d1b55e3d559a281a
commit afa70a8496e90fa751418be8d1b55e3d559a281a Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-01-18 12:26:46 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-01-19 16:49:57 +0000 libthr: add pthread_tryjoin_np() Similar to the same glibc function. Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54766 --- include/pthread_np.h | 1 + lib/libthr/pthread.map | 4 ++++ lib/libthr/thread/thr_join.c | 55 +++++++++++++++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/include/pthread_np.h b/include/pthread_np.h index a9e738540db4..04c64a748b72 100644 --- a/include/pthread_np.h +++ b/include/pthread_np.h @@ -65,6 +65,7 @@ int pthread_single_np(void); void pthread_suspend_all_np(void); int pthread_suspend_np(pthread_t); int pthread_timedjoin_np(pthread_t, void **, const struct timespec *); +int pthread_tryjoin_np(pthread_t, void **); __END_DECLS #endif diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 3a5353a32dc3..ad0c28de98c1 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -342,3 +342,7 @@ FBSD_1.8 { pthread_signals_unblock_np; pthread_sigqueue; }; + +FBSD_1.9 { + pthread_tryjoin_np; +}; diff --git a/lib/libthr/thread/thr_join.c b/lib/libthr/thread/thr_join.c index 56b316ec0f51..33eb18638169 100644 --- a/lib/libthr/thread/thr_join.c +++ b/lib/libthr/thread/thr_join.c @@ -34,14 +34,17 @@ #include "thr_private.h" int _pthread_peekjoin_np(pthread_t pthread, void **thread_return); +int _pthread_tryjoin_np(pthread_t pthread, void **thread_return); int _pthread_timedjoin_np(pthread_t pthread, void **thread_return, const struct timespec *abstime); -static int join_common(pthread_t, void **, const struct timespec *, bool peek); +static int join_common(pthread_t, void **, const struct timespec *, bool peek, + bool try); __weak_reference(_thr_join, pthread_join); __weak_reference(_thr_join, _pthread_join); __weak_reference(_pthread_timedjoin_np, pthread_timedjoin_np); __weak_reference(_pthread_peekjoin_np, pthread_peekjoin_np); +__weak_reference(_pthread_tryjoin_np, pthread_tryjoin_np); static void backout_join(struct pthread *pthread, struct pthread *curthread) @@ -63,7 +66,7 @@ backout_join_pop(void *arg) int _thr_join(pthread_t pthread, void **thread_return) { - return (join_common(pthread, thread_return, NULL, false)); + return (join_common(pthread, thread_return, NULL, false, false)); } int @@ -74,13 +77,34 @@ _pthread_timedjoin_np(pthread_t pthread, void **thread_return, abstime->tv_nsec >= 1000000000) return (EINVAL); - return (join_common(pthread, thread_return, abstime, false)); + return (join_common(pthread, thread_return, abstime, false, false)); } int _pthread_peekjoin_np(pthread_t pthread, void **thread_return) { - return (join_common(pthread, thread_return, NULL, true)); + return (join_common(pthread, thread_return, NULL, true, false)); +} + +int +_pthread_tryjoin_np(pthread_t pthread, void **thread_return) +{ + return (join_common(pthread, thread_return, NULL, false, true)); +} + +static void +join_common_joined(struct pthread *pthread, struct pthread *curthread, + void **thread_return) +{ + void *tmp; + + tmp = pthread->ret; + pthread->flags |= THR_FLAGS_DETACHED; + pthread->joiner = NULL; + _thr_try_gc(curthread, pthread); /* thread lock released */ + + if (thread_return != NULL) + *thread_return = tmp; } /* @@ -89,11 +113,10 @@ _pthread_peekjoin_np(pthread_t pthread, void **thread_return) */ static int join_common(pthread_t pthread, void **thread_return, - const struct timespec *abstime, bool peek) + const struct timespec *abstime, bool peek, bool try) { struct pthread *curthread = _get_curthread(); struct timespec ts, ts2, *tsp; - void *tmp; long tid; int ret; @@ -127,12 +150,22 @@ join_common(pthread_t pthread, void **thread_return, return (ret); } + /* Only try to join. */ + if (try) { + if (pthread->tid != TID_TERMINATED) { + THR_THREAD_UNLOCK(curthread, pthread); + return (EBUSY); + } + join_common_joined(pthread, curthread, thread_return); + return (0); + } + /* Set the running thread to be the joiner: */ pthread->joiner = curthread; THR_THREAD_UNLOCK(curthread, pthread); - THR_CLEANUP_PUSH(curthread, backout_join, pthread); + THR_CLEANUP_PUSH(curthread, backout_join_pop, pthread); _thr_cancel_enter(curthread); tid = pthread->tid; @@ -160,14 +193,8 @@ join_common(pthread_t pthread, void **thread_return, backout_join(pthread, curthread); } else { ret = 0; - tmp = pthread->ret; THR_THREAD_LOCK(curthread, pthread); - pthread->flags |= THR_FLAGS_DETACHED; - pthread->joiner = NULL; - _thr_try_gc(curthread, pthread); /* thread lock released */ - - if (thread_return != NULL) - *thread_return = tmp; + join_common_joined(pthread, curthread, thread_return); } return (ret); }
