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
This commit is contained in:
Konstantin Belousov committed 2026-10-30 15:51:03 +02:00
1 parent 49e0c6270c
commit 588bd8bb6c
4 files changed
+149

No files matched your search

+30
View File
@@ -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);
+2
View File
@@ -345,5 +345,7 @@ FBSD_1.8 {
FBSD_1.9 {
pthread_cond_clockwait;
pthread_query_np;
pthread_query_all_np;
pthread_tryjoin_np;
};
+1
View File
@@ -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 \
+116
View File
@@ -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);
}