Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177549640
D60838.1794689105.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None
D60838.1794689105.diff
View Options
diff --git a/include/pthread_np.h b/include/pthread_np.h
--- 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 @@
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/libc/include/libc_private.h b/lib/libc/include/libc_private.h
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -390,4 +390,6 @@
void __libc_uexterr_set(int eerror, int category, const char *mmsg,
uint64ptr_t pp1, uint64ptr_t pp2, int line);
+extern int __libsys_errno;
+
#endif /* _LIBC_PRIVATE_H_ */
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -345,5 +345,7 @@
FBSD_1.9 {
pthread_cond_clockwait;
+ pthread_query_np;
+ pthread_query_all_np;
pthread_tryjoin_np;
};
diff --git a/lib/libthr/sys/thr_error.c b/lib/libthr/sys/thr_error.c
--- a/lib/libthr/sys/thr_error.c
+++ b/lib/libthr/sys/thr_error.c
@@ -39,8 +39,6 @@
#include "libc_private.h"
#include "thr_private.h"
-extern int __libsys_errno;
-
__weak_reference(__error_threaded, __error);
int *
__error_threaded(void)
diff --git a/lib/libthr/thread/Makefile.inc b/lib/libthr/thread/Makefile.inc
--- a/lib/libthr/thread/Makefile.inc
+++ b/lib/libthr/thread/Makefile.inc
@@ -37,6 +37,7 @@
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_exit.c b/lib/libthr/thread/thr_exit.c
--- a/lib/libthr/thread/thr_exit.c
+++ b/lib/libthr/thread/thr_exit.c
@@ -278,8 +278,10 @@
{
struct pthread *curthread = _get_curthread();
+ THR_LOCK(curthread);
free(curthread->name);
curthread->name = NULL;
+ THR_UNLOCK(curthread);
/* Check if there is thread specific data: */
if (curthread->specific != NULL) {
diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c
--- a/lib/libthr/thread/thr_list.c
+++ b/lib/libthr/thread/thr_list.c
@@ -203,6 +203,10 @@
_tcb_dtor(thread->tcb);
}
thread->tcb = NULL;
+ if (thread->name != NULL) {
+ free(thread->name);
+ thread->name = NULL;
+ }
if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) {
thr_destroy(curthread, thread);
atomic_add_int(&total_threads, -1);
diff --git a/lib/libthr/thread/thr_query.c b/lib/libthr/thread/thr_query.c
new file mode 100644
--- /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);
+}
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -39,8 +39,6 @@
#include "rtld_lock.h"
#include "thr_private.h"
-extern int __libsys_errno;
-
static int _thr_rtld_clr_flag(int);
static void *_thr_rtld_lock_create(void);
static void _thr_rtld_lock_destroy(void *);
diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile
--- a/share/man/man3/Makefile
+++ b/share/man/man3/Makefile
@@ -447,6 +447,7 @@
pthread_mutex_unlock.3 \
pthread_np.3 \
pthread_once.3 \
+ pthread_query_np.3 \
pthread_resume_all_np.3 \
pthread_resume_np.3 \
pthread_rwlockattr_destroy.3 \
@@ -543,5 +544,6 @@
PTHREAD_MLINKS+=pthread_join.3 pthread_peekjoin_np.3 \
pthread_join.3 pthread_timedjoin_np.3 \
pthread_join.3 pthread_tryjoin_np.3
+PTHREAD_MLINKS+=pthread_query_np.3 pthread_query_all_np.3
.include <bsd.prog.mk>
diff --git a/share/man/man3/pthread_query_np.3 b/share/man/man3/pthread_query_np.3
new file mode 100644
--- /dev/null
+++ b/share/man/man3/pthread_query_np.3
@@ -0,0 +1,228 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright 2026 The FreeBSD Foundation
+.\"
+.\" This documentation was written by
+.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.Dd October 19, 2026
+.Dt PTHREAD_QUERY_NP 3
+.Os
+.Sh NAME
+.Nm pthread_query_all_np ,
+.Nm pthread_query_np
+.Nd query thread information
+.Sh LIBRARY
+.Lb libpthread
+.Sh SYNOPSIS
+.In pthread.h
+.In pthread_np.h
+.Ft int
+.Fo pthread_query_np
+.Fa "pthread_t thread"
+.Fa "struct pthread_info_np *info"
+.Fa "size_t bufsz"
+.Fc
+.Ft int
+.Fo pthread_query_all_np
+.Fa "struct pthread_info_np *info"
+.Fa "size_t *bufsz"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn pthread_query_np
+function returns the
+.Fx
+threading library implementation-specific information about
+the thread specified by the
+.Fa thread
+argument.
+The
+.Fa info
+argument must point to a
+.Vt struct pthread_info_np
+structure, which is filled with the following information
+if the corresponding thread is found:
+.Bd -literal
+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];
+};
+.Ed
+.Pp
+The meaning of the structure fields is the following:
+.Bl -tag -width pthread_info_size
+.It Va pthread_info_size
+The size of the structure.
+If new fields are added in the future, it is guaranteed they will be
+added at the end of the
+.Vt pthread_info_np
+structure.
+.It Va thread
+The thread identifier, as defined by the threading library.
+.It Va lwpid
+The thread identifier, as defined by the kernel.
+See
+.Xr pthread_getthreadid_np 3 .
+.It Va state
+The state of the thread.
+Can be one of the following values:
+.Bl -tag -width PTHREAD_STATE_SUSPENDED_NP
+.It Dv PTHREAD_STATE_RUNNING_NP
+Thread is runnable.
+.It Dv PTHREAD_STATE_SUSPENDED_NP
+Thread was suspended, see
+.Xr pthread_suspend_np 3 .
+.It Dv PTHREAD_STATE_DEAD_NP
+Thread has exited but was not yet reclaimed by
+.Xr pthread_join 3 .
+.El
+.It Va flags
+Additional information about the reported thread is provided
+by the following flags:
+.Bl -tag -width PTHREAD_INFO_DETACHED_NP
+.It Dv PTHREAD_INFO_DETACHED_NP
+Set if the thread is detached, see
+.Xr pthread_attr_setdetachstate 3
+and
+.Xr pthread_detach 3 .
+.It Dv PTHREAD_INFO_INITIAL_NP
+Set if the thread was the first thread in the process,
+that is it was executing the
+.Fn main
+function in the process.
+.El
+.It Va cancel_state
+Provides information about the thread cancellability state,
+as flags.
+The following flags are defined:
+.Bl -tag -width PTHREAD_INFO_CANCEL_AT_POINT_NP
+.It Dv PTHREAD_INFO_CANCEL_ENABLED_NP
+Cancellation is enabled, see
+.Xr pthread_setcancelstate 3 .
+.It Dv PTHREAD_INFO_CANCEL_ASYNC_NP
+Thread cancellation is asynchronous, see
+.Xr pthread_setcanceltype 3 .
+.It Dv PTHREAD_INFO_CANCEL_PENDING_NP
+The cancel event is pending, see
+.Xr pthread_cancel 3 .
+.It Dv PTHREAD_INFO_CANCEL_AT_POINT_NP
+The thread is executing at a cancellation point.
+.It Dv PTHREAD_INFO_CANCEL_IN_PROG_NP
+The cancellation is in progress.
+In particular, the stack unwinding might happen.
+.El
+.It Va errno_location
+The address of the thread-private instance of the
+.Xr errno 3
+variable.
+.It Va tcb
+The address of the architecture-specific thread control block.
+The
+.In machine/tls.h
+header provides the definition of
+.Vt struct tcb .
+.It Va exterr
+The location of the thread-private instance of the
+.Vt struct uexterror ,
+used by the kernel to pass extended information about errors
+from system calls.
+See
+.Xr exterror 9 .
+.It Va name
+Name of the thread, as set by
+.Xr pthread_setname_np 3 .
+.El
+.Pp
+The
+.Fa bufsz
+argument must specify the size of the passed structure.
+At most
+.Fa bufsz
+bytes are copied to it.
+The
+.Va pthread_info_size
+member reports the size of the buffer needed for
+the full structure,
+if the library has updated its definition.
+The system guarantees that the layout of existing members
+never changes.
+.Pp
+The
+.Fn pthread_query_all_np
+function returns the information about all threads in the calling
+process.
+The buffer pointed to by the
+.Fa info
+argument must have the size in bytes as provided by the value
+pointed to by the
+.Fa bufsz
+argument.
+To iterate over the buffer, increment the pointer to the previous
+.Vt pthread_info_np
+structure by its
+.Va pthread_info_size
+member.
+The
+.Fa bufsz
+location is always updated with the size of the buffer required
+to report all threads.
+.Sh RETURN VALUES
+If successful, the described functions return zero.
+Otherwise an error number is returned to indicate the error or
+special condition.
+.Sh ERRORS
+The
+.Fn pthread_query_np
+and
+.Fn pthread_query_all_np
+functions will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The threading library was not yet initialized.
+.El
+.Pp
+The
+.Fn pthread_query_np
+function also fails if:
+.Bl -tag -width Er
+.It Bq Er ESRCH
+The passed
+.Fa thread
+argument does not designate a valid thread.
+.El
+.Pp
+The
+.Fn pthread_query_all_np
+function also fails if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+The value pointed to by the
+.Fa bufsz
+argument is too small.
+The value is updated with the required size of the buffer.
+.El
+.Sh SEE ALSO
+.Xr pthread 3 ,
+.Xr pthread_create 3 ,
+.Xr pthread_np 3
+.Sh STANDARDS
+The
+.Fn pthread_query_np
+and
+.Fn pthread_query_all_np
+functions are an
+.Fx
+extension.
+.Sh HISTORY
+The described functions first appeared in
+.Fx 16.0 .
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 14, 8:45 PM (16 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41731969
Default Alt Text
D60838.1794689105.diff (13 KB)
Attached To
Mode
D60838: libthr: pthread_query_np(3) and pthread_query_all_np(3)
Attached
Detach File
Event Timeline