Page MenuHomeFreeBSD

D60838.1794689105.diff
No OneTemporary

Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None

D60838.1794689105.diff

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

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)

Event Timeline