From: John Baldwin <jhb@FreeBSD.org>
To: gdb-patches@sourceware.org
Subject: [PATCH v5 09/15] fbsd-nat: Implement async target support.
Date: Fri, 21 Jan 2022 12:16:25 -0800 [thread overview]
Message-ID: <20220121201631.63530-10-jhb@FreeBSD.org> (raw)
In-Reply-To: <20220121201631.63530-1-jhb@FreeBSD.org>
This is a fairly simple version of async target support.
Synchronous mode still uses blocking waitpid() calls in
inf_ptrace::wait() unlike the Linux native target which always uses
WNOHANG and uses sigsuspend() for synchronous operation.
Asynchronous mode registers an event pipe with the core as a file
handle and writes to the pipe when SIGCHLD is raised. TARGET_WNOHANG
is handled by inf_ptrace::wait().
---
gdb/fbsd-nat.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++-
gdb/fbsd-nat.h | 12 ++++
2 files changed, 164 insertions(+), 2 deletions(-)
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index c485fff6ed4..1ed7092fece 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -18,7 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
+#include "gdbsupport/block-signals.h"
#include "gdbsupport/byte-vector.h"
+#include "gdbsupport/event-loop.h"
+#include "gdbsupport/event-pipe.h"
#include "gdbcore.h"
#include "inferior.h"
#include "regcache.h"
@@ -28,6 +31,7 @@
#include "gdbthread.h"
#include "gdbsupport/buildargv.h"
#include "gdbsupport/gdb_wait.h"
+#include "inf-loop.h"
#include "inf-ptrace.h"
#include <sys/types.h>
#ifdef HAVE_SYS_PROCCTL_H
@@ -927,6 +931,114 @@ fbsd_nat_target::update_thread_list ()
#endif
}
+/* Async mode support. */
+
+static event_pipe fbsd_nat_event_pipe;
+
+/* Implement the "can_async_p" target method. */
+
+bool
+fbsd_nat_target::can_async_p ()
+{
+ /* This flag should be checked in the common target.c code. */
+ gdb_assert (target_async_permitted);
+
+ /* Otherwise, this targets is always able to support async mode. */
+ return true;
+}
+
+/* Implement the "is_async_p" target method. */
+
+bool
+fbsd_nat_target::is_async_p ()
+{
+ return fbsd_nat_event_pipe.is_open ();
+}
+
+/* Implement the "async_wait_fd" target method. */
+
+int
+fbsd_nat_target::async_wait_fd ()
+{
+ return fbsd_nat_event_pipe.event_fd ();
+}
+
+/* SIGCHLD handler notifies the event-loop in async mode. */
+
+static void
+sigchld_handler (int signo)
+{
+ int old_errno = errno;
+
+ if (fbsd_nat_event_pipe.is_open ())
+ fbsd_nat_event_pipe.mark ();
+
+ errno = old_errno;
+}
+
+/* Callback registered with the target events file descriptor. */
+
+static void
+handle_target_event (int error, gdb_client_data client_data)
+{
+ inferior_event_handler (INF_REG_EVENT);
+}
+
+/* Implement the "async" target method. */
+
+void
+fbsd_nat_target::async (int enable)
+{
+ if ((enable != 0) == is_async_p ())
+ return;
+
+ /* Block SIGCHILD while we create/destroy the pipe, as the handler
+ writes to it. */
+ gdb::block_signals blocker;
+
+ if (enable)
+ {
+ if (!fbsd_nat_event_pipe.open ())
+ internal_error (__FILE__, __LINE__, "failed to create event pipe.");
+
+ add_file_handler (fbsd_nat_event_pipe.event_fd (),
+ handle_target_event, NULL, "fbsd-nat");
+
+ /* Trigger a poll in case there are pending events to
+ handle. */
+ fbsd_nat_event_pipe.mark ();
+ }
+ else
+ {
+ delete_file_handler (fbsd_nat_event_pipe.event_fd ());
+ fbsd_nat_event_pipe.close ();
+ }
+}
+
+/* Implement the "close" target method. */
+
+void
+fbsd_nat_target::close ()
+{
+ if (is_async_p ())
+ async (0);
+
+ inf_ptrace_target::close ();
+}
+
+/* Implement the "attach" target method. */
+
+void
+fbsd_nat_target::attach (const char *args, int from_tty)
+{
+ inf_ptrace_target::attach (args, from_tty);
+
+ /* Curiously, the core does not do this automatically. */
+ if (target_can_async_p ())
+ target_async (1);
+}
+
+
#ifdef TDP_RFPPWAIT
/*
To catch fork events, PT_FOLLOW_FORK is set on every traced process
@@ -998,6 +1110,11 @@ static void
fbsd_add_vfork_done (ptid_t pid)
{
fbsd_pending_vfork_done.push_front (pid);
+
+ /* If we're in async mode, need to tell the event loop there's
+ something here to process. */
+ if (target_is_async_p ())
+ fbsd_nat_event_pipe.mark ();
}
/* Check for a pending vfork done event for a specific PID. */
@@ -1166,8 +1283,8 @@ fbsd_handle_debug_trap (fbsd_nat_target *target, ptid_t ptid,
the status in *OURSTATUS. */
ptid_t
-fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
- target_wait_flags target_options)
+fbsd_nat_target::wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
+ target_wait_flags target_options)
{
ptid_t wptid;
@@ -1382,6 +1499,36 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
}
}
+ptid_t
+fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+ target_wait_flags target_options)
+{
+ ptid_t wptid;
+
+ fbsd_nat_debug_printf ("[%s], [%s]", target_pid_to_str (ptid).c_str (),
+ target_options_to_string (target_options).c_str ());
+
+ /* Ensure any subsequent events trigger a new event in the loop. */
+ if (is_async_p ())
+ fbsd_nat_event_pipe.flush ();
+
+ wptid = wait_1 (ptid, ourstatus, target_options);
+
+ /* If we are in async mode and found an event, there may still be
+ another event pending. Trigger the event pipe so that that the
+ event loop keeps polling until no event is returned. */
+ if (is_async_p ()
+ && ((ourstatus->kind () != TARGET_WAITKIND_IGNORE
+ && ourstatus->kind() != TARGET_WAITKIND_NO_RESUMED)
+ || ptid != minus_one_ptid))
+ fbsd_nat_event_pipe.mark ();
+
+ fbsd_nat_debug_printf ("returning [%s], [%s]",
+ target_pid_to_str (wptid).c_str (),
+ ourstatus->to_string ().c_str ());
+ return wptid;
+}
+
#ifdef USE_SIGTRAP_SIGINFO
/* Implement the "stopped_by_sw_breakpoint" target_ops method. */
@@ -1676,4 +1823,7 @@ Enables printf debugging output."),
NULL,
&show_fbsd_nat_debug,
&setdebuglist, &showdebuglist);
+
+ /* Install a SIGCHLD handler. */
+ signal (SIGCHLD, sigchld_handler);
}
diff --git a/gdb/fbsd-nat.h b/gdb/fbsd-nat.h
index 6f8b206dcd5..4ac8faad4df 100644
--- a/gdb/fbsd-nat.h
+++ b/gdb/fbsd-nat.h
@@ -66,9 +66,19 @@ class fbsd_nat_target : public inf_ptrace_target
void update_thread_list () override;
+ bool can_async_p () override;
+ bool is_async_p () override;
+
+ int async_wait_fd () override;
+ void async (int) override;
+
+ void close () override;
+
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
+ void attach (const char *, int) override;
+
void create_inferior (const char *, const std::string &,
char **, int) override;
@@ -110,6 +120,8 @@ class fbsd_nat_target : public inf_ptrace_target
void post_startup_inferior (ptid_t) override;
private:
+ ptid_t wait_1 (ptid_t, struct target_waitstatus *, target_wait_flags);
+
/* Helper routines for use in fetch_registers and store_registers in
subclasses. These routines fetch and store a single set of
registers described by REGSET. The REGSET's 'regmap' field must
--
2.34.1
next prev parent reply other threads:[~2022-01-21 20:16 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-21 20:16 [PATCH v5 00/15] FreeBSD target async mode and related refactoring John Baldwin
2022-01-21 20:16 ` [PATCH v5 01/15] gdbsupport: Add an event-pipe class John Baldwin
2022-01-21 20:16 ` [PATCH v5 02/15] gdb linux-nat: Convert linux_nat_event_pipe to the event_pipe class John Baldwin
2022-01-21 20:16 ` [PATCH v5 03/15] gdbserver linux-low: Convert linux_event_pipe " John Baldwin
2022-01-21 20:16 ` [PATCH v5 04/15] Enable async mode on supported targets in target_resume John Baldwin
2022-02-20 10:47 ` Joel Brobecker
2022-01-21 20:16 ` [PATCH v5 05/15] Don't enable async mode at the end of target ::resume methods John Baldwin
2022-02-20 10:49 ` Joel Brobecker
2022-01-21 20:16 ` [PATCH v5 06/15] do_target_wait_1: Clear TARGET_WNOHANG if the target isn't async John Baldwin
2022-02-22 22:38 ` Simon Marchi
2022-02-23 0:07 ` John Baldwin
2022-02-23 1:40 ` Simon Marchi
2022-02-23 15:51 ` Simon Marchi
2022-02-23 16:12 ` John Baldwin
2022-02-24 2:46 ` Simon Marchi
2022-02-24 19:02 ` John Baldwin
2022-02-24 19:16 ` Simon Marchi
2022-01-21 20:16 ` [PATCH v5 07/15] inf-ptrace: Return an IGNORE event if waitpid() fails John Baldwin
2022-02-20 11:38 ` Joel Brobecker
2022-01-21 20:16 ` [PATCH v5 08/15] inf-ptrace: Support async targets in inf_ptrace_target::wait John Baldwin
2022-01-21 20:16 ` John Baldwin [this message]
2022-01-21 20:16 ` [PATCH v5 10/15] fbsd-nat: Include ptrace operation in error messages John Baldwin
2022-01-21 20:16 ` [PATCH v5 11/15] fbsd-nat: Various cleanups to the ::resume entry debug message John Baldwin
2022-01-21 20:16 ` [PATCH v5 12/15] fbsd-nat: Return nullptr rather than failing ::thread_name John Baldwin
2022-01-21 20:16 ` [PATCH v5 13/15] Enable async mode in the target in attach_cmd John Baldwin
2022-01-21 20:16 ` [PATCH v5 14/15] inf-ptrace: Add an event_pipe to be used for async mode in subclasses John Baldwin
2022-01-21 20:16 ` [PATCH v5 15/15] NEWS: Note that the FreeBSD async target supports async mode John Baldwin
2022-01-22 6:28 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220121201631.63530-10-jhb@FreeBSD.org \
--to=jhb@freebsd.org \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).