From c489f8c6e61e0b60a4108e10be3681885b253864 Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Wed, 2 Sep 2020 19:13:19 +0200 Subject: [PATCH] Add gdb/nat common functions for listing threads Add netbsd_nat::netbsd_thread_lister a generic thread lister, used internally in netbsd-nat.c, copied from gdb/nbsd-nat.c. Add public extern functions for listing threads: * netbsd_nat::thread_alive * netbsd_nat::thread_name * netbsd_nat::for_each_thread gdb/ChangeLog: * netbsd-nat.h: Include "gdbsupport/function-view.h". * (netbsd_nat::thread_alive, netbsd_nat::thread_name) (netbsd_nat::for_each_thread): Add. * netbsd-nat.c: Include "gdbsupport/common-defs.h" and "gdbsupport/common-debug.h". * (netbsd_nat::netbsd_thread_lister) (netbsd_nat::thread_alive, netbsd_nat::thread_name) (netbsd_nat::for_each_thread): Add. --- gdb/ChangeLog | 11 ++++ gdb/nat/netbsd-nat.c | 125 +++++++++++++++++++++++++++++++++++++++++++ gdb/nat/netbsd-nat.h | 20 +++++++ 3 files changed, 156 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2b8a0ac9e3a..21f30e4b297 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2020-09-10 Kamil Rytarowski + + * netbsd-nat.h: Include "gdbsupport/function-view.h". + * (netbsd_nat::thread_alive, netbsd_nat::thread_name) + (netbsd_nat::for_each_thread): Add. + * netbsd-nat.c: Include "gdbsupport/common-defs.h" and + "gdbsupport/common-debug.h". + * (netbsd_nat::netbsd_thread_lister) + (netbsd_nat::thread_alive, netbsd_nat::thread_name) + (netbsd_nat::for_each_thread): Add. + 2020-09-10 Kamil Rytarowski * netbsd-nat.h: Include . diff --git a/gdb/nat/netbsd-nat.c b/gdb/nat/netbsd-nat.c index a63ac04a39c..3f8b8b8eeab 100644 --- a/gdb/nat/netbsd-nat.c +++ b/gdb/nat/netbsd-nat.c @@ -17,11 +17,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include "gdbsupport/common-defs.h" #include "nat/netbsd-nat.h" +#include "gdbsupport/common-debug.h" #include #include +#include + +#include "gdbsupport/function-view.h" + namespace netbsd_nat { @@ -38,4 +44,123 @@ pid_to_exec_file (pid_t pid) return buf; } +/* Generic thread (LWP) lister within a specified PID. The CALLBACK + parameters is a C++ function that is called for each detected thread. + When the CALLBACK function returns true, the iteration is interrupted. + + This function assumes internally that the queried process is stopped + and the number of threads does not change between two sysctl () calls. */ + +static bool +netbsd_thread_lister (const pid_t pid, + gdb::function_view + callback) +{ + int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0}; + size_t size; + + if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) + perror_with_name (("sysctl")); + + mib[4] = size / sizeof (size_t); + + gdb::unique_xmalloc_ptr kl + ((struct kinfo_lwp *) xcalloc (size, 1)); + + if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1 + || size == 0) + perror_with_name (("sysctl")); + + for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++) + { + struct kinfo_lwp *l = &kl[i]; + + /* Return true if the specified thread is alive. */ + auto lwp_alive + = [] (struct kinfo_lwp *lwp) + { + switch (lwp->l_stat) + { + case LSSLEEP: + case LSRUN: + case LSONPROC: + case LSSTOP: + case LSSUSPENDED: + return true; + default: + return false; + } + }; + + /* Ignore embryonic or demised threads. */ + if (!lwp_alive (l)) + continue; + + if (callback (l)) + return true; + } + + return false; +} + +/* See netbsd-nat.h. */ + +bool +thread_alive (ptid_t ptid) +{ + pid_t pid = ptid.pid (); + lwpid_t lwp = ptid.lwp (); + + auto fn + = [=] (const struct kinfo_lwp *kl) + { + return kl->l_lid == lwp; + }; + + return netbsd_thread_lister (pid, fn); +} + +/* See netbsd-nat.h. */ + +const char * +thread_name (ptid_t ptid) +{ + pid_t pid = ptid.pid (); + lwpid_t lwp = ptid.lwp (); + + static char buf[KI_LNAMELEN] = {}; + + auto fn + = [=] (const struct kinfo_lwp *kl) + { + if (kl->l_lid == lwp) + { + xsnprintf (buf, sizeof buf, "%s", kl->l_name); + return true; + } + return false; + }; + + if (netbsd_thread_lister (pid, fn)) + return buf; + else + return NULL; +} + +/* See netbsd-nat.h. */ + +void +for_each_thread (pid_t pid, gdb::function_view callback) +{ + auto fn + = [=, &callback] (const struct kinfo_lwp *kl) + { + ptid_t ptid = ptid_t (pid, kl->l_lid, 0); + callback (ptid); + return false; + }; + + netbsd_thread_lister (pid, fn); +} + } diff --git a/gdb/nat/netbsd-nat.h b/gdb/nat/netbsd-nat.h index d11fadd247c..3f2650f5cad 100644 --- a/gdb/nat/netbsd-nat.h +++ b/gdb/nat/netbsd-nat.h @@ -20,6 +20,8 @@ #ifndef NAT_NETBSD_NAT_H #define NAT_NETBSD_NAT_H +#include "gdbsupport/function-view.h" + #include namespace netbsd_nat @@ -30,6 +32,24 @@ namespace netbsd_nat extern const char *pid_to_exec_file (pid_t pid); +/* Return true if PTID is still active in the inferior. */ + +extern bool thread_alive (ptid_t ptid); + +/* Return the name assigned to a thread by an application. Returns + the string in a static buffer. + + This function assumes internally that the queried process is stopped. */ + +extern const char *thread_name (ptid_t ptid); + +/* A generic thread lister within a specific PID. The CALLBACK parameter + is a C++ function that is called for each detected thread. + + This function assumes internally that the queried process is stopped. */ + +extern void for_each_thread (pid_t pid, + gdb::function_view callback); } #endif -- 2.30.2