git: 588bd8bb6c13 - main - libthr: pthread_query_np(3) and pthread_query_all_np(3)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 13:52:36 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=588bd8bb6c1331dad1bbe1cf222db970f6476c44
commit 588bd8bb6c1331dad1bbe1cf222db970f6476c44
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-10-18 09:46:56 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-10-30 13:51:03 +0000
libthr: pthread_query_np(3) and pthread_query_all_np(3)
Reviewed by: aokblast, markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D60838
---
include/pthread_np.h | 30 +++++++++++
lib/libthr/pthread.map | 2 +
lib/libthr/thread/Makefile.inc | 1 +
lib/libthr/thread/thr_query.c | 116 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
diff --git a/include/pthread_np.h b/include/pthread_np.h
index 04c64a748b72..dc38abb9b729 100644
--- a/include/pthread_np.h
+++ b/include/pthread_np.h
@@ -34,6 +34,34 @@
#include <sys/param.h>
#include <sys/cpuset.h>
+enum pthread_state_np {
+ PTHREAD_STATE_RUNNING_NP = 100,
+ PTHREAD_STATE_SUSPENDED_NP,
+ PTHREAD_STATE_DEAD_NP,
+};
+
+#define PTHREAD_INFO_DETACHED_NP 0x0001
+#define PTHREAD_INFO_INITIAL_NP 0x0002
+
+#define PTHREAD_INFO_CANCEL_ENABLED_NP 0x0001
+#define PTHREAD_INFO_CANCEL_ASYNC_NP 0x0002
+#define PTHREAD_INFO_CANCEL_PENDING_NP 0x0004
+#define PTHREAD_INFO_CANCEL_AT_POINT_NP 0x0008
+#define PTHREAD_INFO_CANCEL_IN_PROG_NP 0x0010
+
+struct pthread_info_np {
+ size_t pthread_info_size;
+ pthread_t thread;
+ long lwpid;
+ enum pthread_state_np state;
+ int flags;
+ int cancel_state;
+ int *errno_location;
+ struct tcb *tcb;
+ struct uexterror *exterr;
+ char name[128];
+};
+
/*
* Non-POSIX thread function prototype definitions:
*/
@@ -57,6 +85,8 @@ int pthread_mutex_isowned_np(pthread_mutex_t *mutex);
void pthread_resume_all_np(void);
int pthread_resume_np(pthread_t);
int pthread_peekjoin_np(pthread_t, void **);
+int pthread_query_np(pthread_t, struct pthread_info_np *, size_t);
+int pthread_query_all_np(struct pthread_info_np *, size_t *);
void pthread_set_name_np(pthread_t, const char *);
int pthread_setaffinity_np(pthread_t, size_t, const cpuset_t *);
void pthread_signals_block_np(void);
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
index 4fe5f2c28331..80a07d472a0e 100644
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -345,5 +345,7 @@ FBSD_1.8 {
FBSD_1.9 {
pthread_cond_clockwait;
+ pthread_query_np;
+ pthread_query_all_np;
pthread_tryjoin_np;
};
diff --git a/lib/libthr/thread/Makefile.inc b/lib/libthr/thread/Makefile.inc
index c7442284bd51..1910fcada64c 100644
--- a/lib/libthr/thread/Makefile.inc
+++ b/lib/libthr/thread/Makefile.inc
@@ -37,6 +37,7 @@ SRCS+= \
thr_printf.c \
thr_pshared.c \
thr_pspinlock.c \
+ thr_query.c \
thr_resume_np.c \
thr_rtld.c \
thr_rwlock.c \
diff --git a/lib/libthr/thread/thr_query.c b/lib/libthr/thread/thr_query.c
new file mode 100644
index 000000000000..bc9104fd848f
--- /dev/null
+++ b/lib/libthr/thread/thr_query.c
@@ -0,0 +1,116 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <string.h>
+#include <pthread.h>
+#include <pthread_np.h>
+
+#include "libc_private.h"
+#include "thr_private.h"
+
+static void
+pthread_getinfo(struct pthread *curthread, struct pthread *thread, bool locked,
+ struct pthread_info_np *info)
+{
+ if (!locked)
+ THR_THREAD_LOCK(curthread, thread);
+ info->pthread_info_size = sizeof(*info);
+ info->thread = thread;
+ info->lwpid = thread->tid;
+ if (thread->state == PS_DEAD)
+ info->state = PTHREAD_STATE_DEAD_NP;
+ else if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
+ info->state = PTHREAD_STATE_SUSPENDED_NP;
+ else
+ info->state = PTHREAD_STATE_RUNNING_NP;
+ info->flags = 0;
+ if ((thread->flags & THR_FLAGS_DETACHED) != 0)
+ info->flags |= PTHREAD_INFO_DETACHED_NP;
+ if (thread == _thr_initial)
+ info->flags |= PTHREAD_INFO_INITIAL_NP;
+ info->cancel_state = 0;
+ if (thread->cancel_enable)
+ info->cancel_state |= PTHREAD_INFO_CANCEL_ENABLED_NP;
+ if (thread->cancel_async)
+ info->cancel_state |= PTHREAD_INFO_CANCEL_ASYNC_NP;
+ if (thread->cancel_point)
+ info->cancel_state |= PTHREAD_INFO_CANCEL_AT_POINT_NP;
+ if (thread->cancel_pending)
+ info->cancel_state |= PTHREAD_INFO_CANCEL_PENDING_NP;
+ if (thread->cancelling)
+ info->cancel_state |= PTHREAD_INFO_CANCEL_IN_PROG_NP;
+ info->errno_location = thread == _thr_initial ? &__libsys_errno :
+ &thread->error;
+ info->tcb = thread->tcb;
+ if (thread->name != NULL)
+ strlcpy(info->name, thread->name, sizeof(info->name));
+ else
+ info->name[0] = '\0';
+ info->exterr = &thread->uexterr;
+ THR_THREAD_UNLOCK(curthread, thread);
+}
+
+int
+pthread_query_np(pthread_t thread, struct pthread_info_np *info, size_t bufsz)
+{
+ struct pthread *curthread;
+ struct pthread_info_np pi;
+ int ret;
+
+ if (_thr_initial == NULL)
+ return (EAGAIN);
+
+ curthread = _get_curthread();
+ if (thread != curthread) {
+ ret = _thr_find_thread(curthread, thread, 1);
+ if (ret != 0)
+ return (ret);
+ }
+ pthread_getinfo(curthread, thread, thread != curthread, &pi);
+ memcpy(info, &pi, MIN(sizeof(pi), bufsz));
+ return (0);
+}
+
+int
+pthread_query_all_np(struct pthread_info_np *info, size_t *bufsz)
+{
+ struct pthread *curthread, *thr;
+ size_t cnt, i;
+ int res;
+
+ if (_thr_initial == NULL) {
+ /* Exactly one thread exists. */
+ *bufsz = sizeof(*info);
+ return (EAGAIN);
+ }
+
+ curthread = _get_curthread();
+ res = 0;
+ i = 0;
+ cnt = *bufsz / sizeof(*info);
+ THREAD_LIST_RDLOCK(curthread);
+ TAILQ_FOREACH(thr, &_thread_list, tle) {
+ if (i + 1 > cnt)
+ res = ENOMEM;
+ /*
+ * Continue the loop even after the buffer is filled,
+ * to report required buffer size.
+ */
+ if (res == 0)
+ pthread_getinfo(curthread, thr, false, &info[i]);
+ i++;
+ }
+ THREAD_LIST_UNLOCK(curthread);
+
+ *bufsz = i * sizeof(*info);
+ return (res);
+}