[PATCH] Implement basic threading support in the NetBSD target

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Implement basic threading support in the NetBSD target

Kamil Rytarowski
Use sysctl(3) as the portable interface to prompt NetBSD threads on
all supported NetBSD versions. In future newer versions could switch
to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
and newer.

Implement as part of nbsd_nat_target:
 - thread_name()         - read descriptive thread name
 - thread_alive()        - check whether a thread is alive
 - post_attach()         - updates the list of threads after attach
 - update_thread_list()  - updates the list of threads
 - pid_to_str()          - translates ptid to a descriptive string

There are two local static functions:
 - nbsd_thread_lister()  - generic LWP lister for a specified pid
 - nbsd_add_threads()    - utility to update the list of threads

Now, GDB on NetBSD can attach to a multithreaded process, spawn
a multithreaded process, list threads, print their LWP+PID numbers
and descriptive thread names.

gdb/ChangeLog:

       * 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.
---
 gdb/ChangeLog  |  17 ++++++
 gdb/nbsd-nat.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/nbsd-nat.h |   8 +++
 3 files changed, 186 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1ee58a541cb..f31a7cf236c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2020-03-25  Kamil Rytarowski  <[hidden email]>
+
+ * 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-03-25  Tom Tromey  <[hidden email]>

  * compile/compile-object-load.c (get_out_value_type): Mention
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index 326bbe3aec3..556e146ab23 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 <sys/types.h>
 #include <sys/ptrace.h>
@@ -39,3 +41,162 @@ 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 void
+nbsd_thread_lister (const pid_t pid,
+    std::function<bool (const struct kinfo_lwp *)> 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<struct kinfo_lwp> kl
+    ((struct kinfo_lwp *) xcalloc (size, 1));
+  if (kl == NULL)
+    perror_with_name (("calloc"));
+
+  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.get ()[i];
+
+      /* Return true if the specified thread is alive.  */
+      auto lwp_alive =
+ [&l]()
+ {
+  switch (kl->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))
+ break;
+    }
+}
+
+/* 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 ();
+  bool found = false;
+
+  auto fn =
+    [&lwp, &found] (const struct kinfo_lwp *kl)
+    {
+      if (kl->l_lid == lwp)
+ {
+  found = true;
+  return true;
+ }
+      return false;
+    };
+
+  nbsd_thread_lister (pid, fn);
+
+  return found;
+}
+
+/* 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;
+    };
+
+  nbsd_thread_lister (pid, fn);
+
+  return buf;
+}
+
+/* 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);
+      fprintf_unfiltered (gdb_stdlog, "NLWP: pid=%d lwp=%d\n", pid, kl->l_lid);
+      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)
+{
+  pid_t pid = ptid.pid ();
+  int lwp = ptid.lwp ();
+
+  return string_printf ("LWP %d of process %d", lwp, pid);
+}
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 */
--
2.25.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v2] Implement basic threading support in the NetBSD target

Kamil Rytarowski
Use sysctl(3) as the portable interface to prompt NetBSD threads on
all supported NetBSD versions. In future newer versions could switch
to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
and newer.

Implement as part of nbsd_nat_target:
 - thread_name()         - read descriptive thread name
 - thread_alive()        - check whether a thread is alive
 - post_attach()         - updates the list of threads after attach
 - update_thread_list()  - updates the list of threads
 - pid_to_str()          - translates ptid to a descriptive string

There are two local static functions:
 - nbsd_thread_lister()  - generic LWP lister for a specified pid
 - nbsd_add_threads()    - utility to update the list of threads

Now, GDB on NetBSD can attach to a multithreaded process, spawn
a multithreaded process, list threads, print their LWP+PID numbers
and descriptive thread names.

gdb/ChangeLog:

       * 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.
---
 gdb/ChangeLog  |  17 +++++
 gdb/nbsd-nat.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/nbsd-nat.h |   8 +++
 3 files changed, 191 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1ee58a541cb..f31a7cf236c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2020-03-25  Kamil Rytarowski  <[hidden email]>
+
+ * 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-03-25  Tom Tromey  <[hidden email]>

  * compile/compile-object-load.c (get_out_value_type): Mention
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index 326bbe3aec3..945699ccfbe 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 <sys/types.h>
 #include <sys/ptrace.h>
@@ -39,3 +41,167 @@ 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 void
+nbsd_thread_lister (const pid_t pid,
+    std::function<bool (const struct kinfo_lwp *)> 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<struct kinfo_lwp> kl
+    ((struct kinfo_lwp *) xcalloc (size, 1));
+  if (kl == NULL)
+    perror_with_name (("calloc"));
+
+  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.get ()[i];
+
+      /* Return true if the specified thread is alive.  */
+      auto lwp_alive =
+ [&l]()
+ {
+  switch (l->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 ())
+ continue;
+
+      if (callback (l))
+ break;
+    }
+}
+
+/* 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 ();
+  bool found = false;
+
+  auto fn =
+    [&lwp, &found] (const struct kinfo_lwp *kl)
+    {
+      if (kl->l_lid == lwp)
+ {
+  found = true;
+  return true;
+ }
+      return false;
+    };
+
+  nbsd_thread_lister (pid, fn);
+
+  return found;
+}
+
+/* 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;
+    };
+
+  nbsd_thread_lister (pid, fn);
+
+  return buf;
+}
+
+/* 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 */
--
2.25.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2] Implement basic threading support in the NetBSD target

Kamil Rytarowski
Ping?

On 26.03.2020 04:16, Kamil Rytarowski wrote:

> Use sysctl(3) as the portable interface to prompt NetBSD threads on
> all supported NetBSD versions. In future newer versions could switch
> to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
> and newer.
>
> Implement as part of nbsd_nat_target:
>  - thread_name()         - read descriptive thread name
>  - thread_alive()        - check whether a thread is alive
>  - post_attach()         - updates the list of threads after attach
>  - update_thread_list()  - updates the list of threads
>  - pid_to_str()          - translates ptid to a descriptive string
>
> There are two local static functions:
>  - nbsd_thread_lister()  - generic LWP lister for a specified pid
>  - nbsd_add_threads()    - utility to update the list of threads
>
> Now, GDB on NetBSD can attach to a multithreaded process, spawn
> a multithreaded process, list threads, print their LWP+PID numbers
> and descriptive thread names.
>
> gdb/ChangeLog:
>
>        * 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.
> ---
>  gdb/ChangeLog  |  17 +++++
>  gdb/nbsd-nat.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/nbsd-nat.h |   8 +++
>  3 files changed, 191 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 1ee58a541cb..f31a7cf236c 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,20 @@
> +2020-03-25  Kamil Rytarowski  <[hidden email]>
> +
> + * 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-03-25  Tom Tromey  <[hidden email]>
>
>   * compile/compile-object-load.c (get_out_value_type): Mention
> diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
> index 326bbe3aec3..945699ccfbe 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 <sys/types.h>
>  #include <sys/ptrace.h>
> @@ -39,3 +41,167 @@ 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 void
> +nbsd_thread_lister (const pid_t pid,
> +    std::function<bool (const struct kinfo_lwp *)> 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<struct kinfo_lwp> kl
> +    ((struct kinfo_lwp *) xcalloc (size, 1));
> +  if (kl == NULL)
> +    perror_with_name (("calloc"));
> +
> +  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.get ()[i];
> +
> +      /* Return true if the specified thread is alive.  */
> +      auto lwp_alive =
> + [&l]()
> + {
> +  switch (l->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 ())
> + continue;
> +
> +      if (callback (l))
> + break;
> +    }
> +}
> +
> +/* 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 ();
> +  bool found = false;
> +
> +  auto fn =
> +    [&lwp, &found] (const struct kinfo_lwp *kl)
> +    {
> +      if (kl->l_lid == lwp)
> + {
> +  found = true;
> +  return true;
> + }
> +      return false;
> +    };
> +
> +  nbsd_thread_lister (pid, fn);
> +
> +  return found;
> +}
> +
> +/* 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;
> +    };
> +
> +  nbsd_thread_lister (pid, fn);
> +
> +  return buf;
> +}
> +
> +/* 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 */
> --
> 2.25.0
>

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Implement basic threading support in the NetBSD target

Tom Tromey-2
In reply to this post by Kamil Rytarowski
>>>>> "Kamil" == Kamil Rytarowski <[hidden email]> writes:

Kamil> Use sysctl(3) as the portable interface to prompt NetBSD threads on
Kamil> all supported NetBSD versions. In future newer versions could switch
Kamil> to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
Kamil> and newer.

Thank you for the patch.

Kamil> +static void
Kamil> +nbsd_thread_lister (const pid_t pid,
Kamil> +    std::function<bool (const struct kinfo_lwp *)> callback)

Perhaps a const reference here would be better.
Or maybe gdb::function_view, I'm not sure.

Kamil> +      /* Return true if the specified thread is alive.  */
Kamil> +      auto lwp_alive =
Kamil> + [&l]()
Kamil> + {
Kamil> +  switch (kl->l_stat)
Kamil> +    {
Kamil> +    case LSSLEEP:
Kamil> +    case LSRUN:
Kamil> +    case LSONPROC:
Kamil> +    case LSSTOP:
Kamil> +    case LSSUSPENDED:
Kamil> +      return true;
Kamil> +    default:
Kamil> +      return false;
Kamil> +    }
Kamil> + };
Kamil> +
Kamil> +      /* Ignore embryonic or demised threads.  */
Kamil> +      if (!lwp_alive (l))
Kamil> + continue;

I don't think a lambda is needed here.

Kamil> +bool
Kamil> +nbsd_nat_target::thread_alive (ptid_t ptid)
Kamil> +{
Kamil> +  pid_t pid = ptid.pid ();
Kamil> +  int lwp = ptid.lwp ();
Kamil> +  bool found = false;
Kamil> +
Kamil> +  auto fn =
Kamil> +    [&lwp, &found] (const struct kinfo_lwp *kl)
Kamil> +    {
Kamil> +      if (kl->l_lid == lwp)
Kamil> + {
Kamil> +  found = true;
Kamil> +  return true;
Kamil> + }
Kamil> +      return false;
Kamil> +    };
Kamil> +
Kamil> +  nbsd_thread_lister (pid, fn);
Kamil> +
Kamil> +  return found;

A classic pattern in gdb is to have one of these iteration functions
(here, nbsd_thread_lister) return bool and have it return true if any
callback returns true, and false otherwise.

That would eliminate this "found" variable.

Kamil> +const char *
Kamil> +nbsd_nat_target::thread_name (struct thread_info *thr)
Kamil> +{
Kamil> +  static char buf[KI_LNAMELEN] = {};
...
Kamil> +  return buf;

This should return NULL if no name was found.
The above bool return would make this easy as well.

Kamil> +      fprintf_unfiltered (gdb_stdlog, "NLWP: pid=%d lwp=%d\n", pid, kl->l_lid);

This line should be removed.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2] Implement basic threading support in the NetBSD target

Tom Tromey-2
In reply to this post by Kamil Rytarowski
>>>>> "Kamil" == Kamil Rytarowski <[hidden email]> writes:

Kamil> +  auto fn =
Kamil> +    [&lwp, &found] (const struct kinfo_lwp *kl)

Also, in the gdb style, "=" is an operator and goes after the line
break.  There were a few instances of this.

Tom
Reply | Threaded
Open this post in threaded view
|

[PATCH v3] Implement basic threading support in the NetBSD target

Kamil Rytarowski
In reply to this post by Kamil Rytarowski
Use sysctl(3) as the portable interface to prompt NetBSD threads on
all supported NetBSD versions. In future newer versions could switch
to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
and newer.

Implement as part of nbsd_nat_target:
 - thread_name()         - read descriptive thread name
 - thread_alive()        - check whether a thread is alive
 - post_attach()         - updates the list of threads after attach
 - update_thread_list()  - updates the list of threads
 - pid_to_str()          - translates ptid to a descriptive string

There are two local static functions:
 - nbsd_thread_lister()  - generic LWP lister for a specified pid
 - nbsd_add_threads()    - utility to update the list of threads

Now, GDB on NetBSD can attach to a multithreaded process, spawn
a multithreaded process, list threads, print their LWP+PID numbers
and descriptive thread names.

gdb/ChangeLog:

       * 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.
---
 gdb/ChangeLog  |  17 +++++
 gdb/nbsd-nat.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/nbsd-nat.h |   8 +++
 3 files changed, 191 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ef62216e0ad..764b65d872d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2020-04-01  Kamil Rytarowski  <[hidden email]>
+
+ * 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-01  Tankut Baris Aktemur  <[hidden email]>

  * infrun.c (stop_all_threads): Update assertion, plus when
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index 326bbe3aec3..54ae172ba7c 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 <sys/types.h>
 #include <sys/ptrace.h>
@@ -39,3 +41,167 @@ 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 void
+nbsd_thread_lister (const pid_t pid,
+    std::function<bool (const struct kinfo_lwp *)> 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<struct kinfo_lwp> kl
+    ((struct kinfo_lwp *) xcalloc (size, 1));
+  if (kl == NULL)
+    perror_with_name (("calloc"));
+
+  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.get ()[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))
+ break;
+    }
+}
+
+/* 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 ();
+  bool found = false;
+
+  auto fn
+    = [&lwp, &found] (const struct kinfo_lwp *kl)
+      {
+ if (kl->l_lid == lwp)
+  {
+    found = true;
+    return true;
+  }
+ return false;
+      };
+
+  nbsd_thread_lister (pid, fn);
+
+  return found;
+}
+
+/* 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;
+      };
+
+  nbsd_thread_lister (pid, fn);
+
+  return buf;
+}
+
+/* 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 */
--
2.25.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2] Implement basic threading support in the NetBSD target

Kamil Rytarowski
In reply to this post by Tom Tromey-2
On 01.04.2020 22:44, Tom Tromey wrote:

>>>>>> "Kamil" == Kamil Rytarowski <[hidden email]> writes:
>
> Kamil> +  auto fn =
> Kamil> +    [&lwp, &found] (const struct kinfo_lwp *kl)
>
> Also, in the gdb style, "=" is an operator and goes after the line
> break.  There were a few instances of this.
>
> Tom
>

Fixed in:

[PATCH v3] Implement basic threading support in the NetBSD target
Reply | Threaded
Open this post in threaded view
|

[PATCH v4] Implement basic threading support in the NetBSD target

Kamil Rytarowski
In reply to this post by Kamil Rytarowski
Use sysctl(3) as the portable interface to prompt NetBSD threads on
all supported NetBSD versions. In future newer versions could switch
to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
and newer.

Implement as part of nbsd_nat_target:
 - thread_name()         - read descriptive thread name
 - thread_alive()        - check whether a thread is alive
 - post_attach()         - updates the list of threads after attach
 - update_thread_list()  - updates the list of threads
 - pid_to_str()          - translates ptid to a descriptive string

There are two local static functions:
 - nbsd_thread_lister()  - generic LWP lister for a specified pid
 - nbsd_add_threads()    - utility to update the list of threads

Now, GDB on NetBSD can attach to a multithreaded process, spawn
a multithreaded process, list threads, print their LWP+PID numbers
and descriptive thread names.

gdb/ChangeLog:

       * 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.
---
 gdb/ChangeLog  |  17 ++++++
 gdb/nbsd-nat.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/nbsd-nat.h |   8 +++
 3 files changed, 187 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ef62216e0ad..764b65d872d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2020-04-01  Kamil Rytarowski  <[hidden email]>
+
+ * 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-01  Tankut Baris Aktemur  <[hidden email]>

  * infrun.c (stop_all_threads): Update assertion, plus when
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index 326bbe3aec3..e5510312ed1 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 <sys/types.h>
 #include <sys/ptrace.h>
@@ -39,3 +41,163 @@ 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<bool (const struct kinfo_lwp *)>
+    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<struct kinfo_lwp> kl
+    ((struct kinfo_lwp *) xcalloc (size, 1));
+  if (kl == NULL)
+    perror_with_name (("calloc"));
+
+  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.get ()[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 */
--
2.25.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Implement basic threading support in the NetBSD target

Kamil Rytarowski
In reply to this post by Tom Tromey-2
On 01.04.2020 22:43, Tom Tromey wrote:

>>>>>> "Kamil" == Kamil Rytarowski <[hidden email]> writes:
>
> Kamil> Use sysctl(3) as the portable interface to prompt NetBSD threads on
> Kamil> all supported NetBSD versions. In future newer versions could switch
> Kamil> to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
> Kamil> and newer.
>
> Thank you for the patch.
>
> Kamil> +static void
> Kamil> +nbsd_thread_lister (const pid_t pid,
> Kamil> +    std::function<bool (const struct kinfo_lwp *)> callback)
>
> Perhaps a const reference here would be better.
> Or maybe gdb::function_view, I'm not sure.
>

I've switched to gdb::function_view.

> Kamil> +      /* Return true if the specified thread is alive.  */
> Kamil> +      auto lwp_alive =
> Kamil> + [&l]()
> Kamil> + {
> Kamil> +  switch (kl->l_stat)
> Kamil> +    {
> Kamil> +    case LSSLEEP:
> Kamil> +    case LSRUN:
> Kamil> +    case LSONPROC:
> Kamil> +    case LSSTOP:
> Kamil> +    case LSSUSPENDED:
> Kamil> +      return true;
> Kamil> +    default:
> Kamil> +      return false;
> Kamil> +    }
> Kamil> + };
> Kamil> +
> Kamil> +      /* Ignore embryonic or demised threads.  */
> Kamil> +      if (!lwp_alive (l))
> Kamil> + continue;
>
> I don't think a lambda is needed here.
>

I like lambda here as it matches the internals of the kernel behavior
here. Normally, I would add a local lwp_alive() helper function, but as
it is not needed anywhere else, I added it as a local inline lambda
function.

Using lambda a little bit simplifies the code as I can avoid "break"
that is nested inside for() and switch(). I could rewrite the code, but
in the current form it nicer reflects the NetBSD kernel.

PT_LWPSTATUS/PT_LWPNEXT would have implied lwp_alive().

> Kamil> +bool
> Kamil> +nbsd_nat_target::thread_alive (ptid_t ptid)
> Kamil> +{
> Kamil> +  pid_t pid = ptid.pid ();
> Kamil> +  int lwp = ptid.lwp ();
> Kamil> +  bool found = false;
> Kamil> +
> Kamil> +  auto fn =
> Kamil> +    [&lwp, &found] (const struct kinfo_lwp *kl)
> Kamil> +    {
> Kamil> +      if (kl->l_lid == lwp)
> Kamil> + {
> Kamil> +  found = true;
> Kamil> +  return true;
> Kamil> + }
> Kamil> +      return false;
> Kamil> +    };
> Kamil> +
> Kamil> +  nbsd_thread_lister (pid, fn);
> Kamil> +
> Kamil> +  return found;
>
> A classic pattern in gdb is to have one of these iteration functions
> (here, nbsd_thread_lister) return bool and have it return true if any
> callback returns true, and false otherwise.
>
> That would eliminate this "found" variable.
>

Done.

> Kamil> +const char *
> Kamil> +nbsd_nat_target::thread_name (struct thread_info *thr)
> Kamil> +{
> Kamil> +  static char buf[KI_LNAMELEN] = {};
> ...
> Kamil> +  return buf;
>
> This should return NULL if no name was found.
> The above bool return would make this easy as well.
>

Done.

> Kamil> +      fprintf_unfiltered (gdb_stdlog, "NLWP: pid=%d lwp=%d\n", pid, kl->l_lid);
>
> This line should be removed.
>

It was fixed in v2.

> Tom
>

Please review:

[PATCH v4] Implement basic threading support in the NetBSD target
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4] Implement basic threading support in the NetBSD target

Sourceware - gdb-patches mailing list
In reply to this post by Kamil Rytarowski
Hi,

I skimmed the patch and noticed a couple nits.

On 4/1/20 10:33 PM, Kamil Rytarowski wrote:

> +static bool
> +nbsd_thread_lister (const pid_t pid,
> +    gdb::function_view<bool (const struct kinfo_lwp *)>
> +    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<struct kinfo_lwp> kl

You can use the array variant:

 gdb::unique_xmalloc_ptr<struct kinfo_lwp[]>

> +    ((struct kinfo_lwp *) xcalloc (size, 1));
> +  if (kl == NULL)
> +    perror_with_name (("calloc"));

xcalloc doesn't ever return NULL.

> +
> +  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.get ()[i];

If you use the array variant, then here you don't need the .get(), like:

      struct kinfo_lwp *l = &kl[i];

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4] Implement basic threading support in the NetBSD target

Kamil Rytarowski
On 02.04.2020 21:05, Pedro Alves wrote:

> Hi,
>
> I skimmed the patch and noticed a couple nits.
>
> On 4/1/20 10:33 PM, Kamil Rytarowski wrote:
>
>> +static bool
>> +nbsd_thread_lister (const pid_t pid,
>> +    gdb::function_view<bool (const struct kinfo_lwp *)>
>> +    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<struct kinfo_lwp> kl
>
> You can use the array variant:
>
>  gdb::unique_xmalloc_ptr<struct kinfo_lwp[]>
>

Done.

>> +    ((struct kinfo_lwp *) xcalloc (size, 1));
>> +  if (kl == NULL)
>> +    perror_with_name (("calloc"));
>
> xcalloc doesn't ever return NULL.
>

Done.

>> +
>> +  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.get ()[i];
>
> If you use the array variant, then here you don't need the .get(), like:
>
>       struct kinfo_lwp *l = &kl[i];
>

Done.

> Thanks,
> Pedro Alves
>

Please see v5.
Reply | Threaded
Open this post in threaded view
|

[PATCH v5] Implement basic threading support in the NetBSD target

Kamil Rytarowski
In reply to this post by Kamil Rytarowski
Use sysctl(3) as the portable interface to prompt NetBSD threads on
all supported NetBSD versions. In future newer versions could switch
to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
and newer.

Implement as part of nbsd_nat_target:
 - thread_name()         - read descriptive thread name
 - thread_alive()        - check whether a thread is alive
 - post_attach()         - updates the list of threads after attach
 - update_thread_list()  - updates the list of threads
 - pid_to_str()          - translates ptid to a descriptive string

There are two local static functions:
 - nbsd_thread_lister()  - generic LWP lister for a specified pid
 - nbsd_add_threads()    - utility to update the list of threads

Now, GDB on NetBSD can attach to a multithreaded process, spawn
a multithreaded process, list threads, print their LWP+PID numbers
and descriptive thread names.

gdb/ChangeLog:

       * 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.
---
 gdb/ChangeLog  |  17 ++++++
 gdb/nbsd-nat.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/nbsd-nat.h |   8 +++
 3 files changed, 185 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ef62216e0ad..764b65d872d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2020-04-01  Kamil Rytarowski  <[hidden email]>
+
+ * 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-01  Tankut Baris Aktemur  <[hidden email]>

  * infrun.c (stop_all_threads): Update assertion, plus when
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 <sys/types.h>
 #include <sys/ptrace.h>
@@ -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<bool (const struct kinfo_lwp *)>
+    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<struct kinfo_lwp[]> 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 */
--
2.25.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5] Implement basic threading support in the NetBSD target

Kamil Rytarowski
Ping?

On 02.04.2020 21:24, Kamil Rytarowski wrote:

> Use sysctl(3) as the portable interface to prompt NetBSD threads on
> all supported NetBSD versions. In future newer versions could switch
> to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0
> and newer.
>
> Implement as part of nbsd_nat_target:
>  - thread_name()         - read descriptive thread name
>  - thread_alive()        - check whether a thread is alive
>  - post_attach()         - updates the list of threads after attach
>  - update_thread_list()  - updates the list of threads
>  - pid_to_str()          - translates ptid to a descriptive string
>
> There are two local static functions:
>  - nbsd_thread_lister()  - generic LWP lister for a specified pid
>  - nbsd_add_threads()    - utility to update the list of threads
>
> Now, GDB on NetBSD can attach to a multithreaded process, spawn
> a multithreaded process, list threads, print their LWP+PID numbers
> and descriptive thread names.
>
> gdb/ChangeLog:
>
>        * 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.
> ---
>  gdb/ChangeLog  |  17 ++++++
>  gdb/nbsd-nat.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/nbsd-nat.h |   8 +++
>  3 files changed, 185 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index ef62216e0ad..764b65d872d 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,20 @@
> +2020-04-01  Kamil Rytarowski  <[hidden email]>
> +
> + * 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-01  Tankut Baris Aktemur  <[hidden email]>
>
>   * infrun.c (stop_all_threads): Update assertion, plus when
> 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 <sys/types.h>
>  #include <sys/ptrace.h>
> @@ -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<bool (const struct kinfo_lwp *)>
> +    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<struct kinfo_lwp[]> 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 */
> --
> 2.25.0
>

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5] Implement basic threading support in the NetBSD target

Tom Tromey-2
In reply to this post by Kamil Rytarowski
>>>>> "Kamil" == Kamil Rytarowski <[hidden email]> writes:

Kamil> gdb/ChangeLog:

Kamil>        * nbsd-nat.h (struct thread_info): Add forward declaration.
Kamil>        (nbsd_nat_target::thread_alive): Add.
Kamil>        (nbsd_nat_target::thread_name): Likewise.
Kamil>        (nbsd_nat_target::update_thread_list): Likewise.
Kamil>        (update_thread_list::post_attach): Likewise.
Kamil>        (post_attach::pid_to_str): Likewise.
Kamil>        * nbsd-nat.c: Include "gdbthread.h" and "inferior.h".
Kamil>        (nbsd_thread_lister): Add.
Kamil>        (nbsd_nat_target::thread_alive): Likewise.
Kamil>        (nbsd_nat_target::thread_name): Likewise.
Kamil>        (nbsd_add_threads): Likewise.
Kamil>        (update_thread_list::post_attach): Likewise.
Kamil>        (nbsd_nat_target::update_thread_list): Likewise.
Kamil>        (post_attach::pid_to_str): Likewise.

Thanks, this is ok.

vTom