diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 94fbdbde2f2..bd1a0f4df18 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2020-04-06 Kamil Rytarowski + + * nbsd-nat.h (struct thread_info): Add forward declaration. + (nbsd_nat_target::thread_alive): Add. + (nbsd_nat_target::thread_name): Likewise. + (nbsd_nat_target::update_thread_list): Likewise. + (update_thread_list::post_attach): Likewise. + (post_attach::pid_to_str): Likewise. + * nbsd-nat.c: Include "gdbthread.h" and "inferior.h". + (nbsd_thread_lister): Add. + (nbsd_nat_target::thread_alive): Likewise. + (nbsd_nat_target::thread_name): Likewise. + (nbsd_add_threads): Likewise. + (update_thread_list::post_attach): Likewise. + (nbsd_nat_target::update_thread_list): Likewise. + (post_attach::pid_to_str): Likewise. + 2020-04-06 Tom Tromey * ada-valprint.c (print_variant_part): Extract the variant field. diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c index 326bbe3aec3..4423e19428d 100644 --- a/gdb/nbsd-nat.c +++ b/gdb/nbsd-nat.c @@ -20,6 +20,8 @@ #include "defs.h" #include "nbsd-nat.h" +#include "gdbthread.h" +#include "inferior.h" #include #include @@ -39,3 +41,161 @@ nbsd_nat_target::pid_to_exec_file (int pid) return NULL; return buf; } + +/* Generic thread (LWP) lister within a specified process. The callback + parameters is a C++ function that is called for each detected thread. */ + +static bool +nbsd_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; +} + +/* Return true if PTID is still active in the inferior. */ + +bool +nbsd_nat_target::thread_alive (ptid_t ptid) +{ + pid_t pid = ptid.pid (); + int lwp = ptid.lwp (); + + auto fn + = [&lwp] (const struct kinfo_lwp *kl) + { + return kl->l_lid == lwp; + }; + + return nbsd_thread_lister (pid, fn); +} + +/* Return the name assigned to a thread by an application. Returns + the string in a static buffer. */ + +const char * +nbsd_nat_target::thread_name (struct thread_info *thr) +{ + ptid_t ptid = thr->ptid; + pid_t pid = ptid.pid (); + int lwp = ptid.lwp (); + + static char buf[KI_LNAMELEN] = {}; + + auto fn + = [&lwp] (const struct kinfo_lwp *kl) + { + if (kl->l_lid == lwp) + { + xsnprintf (buf, sizeof buf, "%s", kl->l_name); + return true; + } + return false; + }; + + if (nbsd_thread_lister (pid, fn)) + return buf; + else + return NULL; +} + +/* Implement the "post_attach" target_ops method. */ + +static void +nbsd_add_threads (nbsd_nat_target *target, pid_t pid) +{ + auto fn + = [&target, &pid] (const struct kinfo_lwp *kl) + { + ptid_t ptid = ptid_t (pid, kl->l_lid, 0); + if (!in_thread_list (target, ptid)) + { + if (inferior_ptid.lwp () == 0) + thread_change_ptid (target, inferior_ptid, ptid); + else + add_thread (target, ptid); + } + return false; + }; + + nbsd_thread_lister (pid, fn); +} + +/* Implement the "post_attach" target_ops method. */ + +void +nbsd_nat_target::post_attach (int pid) +{ + nbsd_add_threads (this, pid); +} + +/* Implement the "update_thread_list" target_ops method. */ + +void +nbsd_nat_target::update_thread_list () +{ + prune_threads (); + + nbsd_add_threads (this, inferior_ptid.pid ()); +} + +/* Convert PTID to a string. */ + +std::string +nbsd_nat_target::pid_to_str (ptid_t ptid) +{ + int lwp = ptid.lwp (); + + if (lwp != 0) + { + pid_t pid = ptid.pid (); + + return string_printf ("LWP %d of process %d", lwp, pid); + } + + return normal_pid_to_str (ptid); +} diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h index a752fbe572d..3606048cd07 100644 --- a/gdb/nbsd-nat.h +++ b/gdb/nbsd-nat.h @@ -22,11 +22,19 @@ #include "inf-ptrace.h" +struct thread_info; + /* A prototype NetBSD target. */ struct nbsd_nat_target : public inf_ptrace_target { char *pid_to_exec_file (int pid) override; + + bool thread_alive (ptid_t ptid) override; + const char *thread_name (struct thread_info *thr) override; + void post_attach (int pid) override; + void update_thread_list () override; + std::string pid_to_str (ptid_t ptid) override; }; #endif /* nbsd-nat.h */