#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"
/* Async mode support. */
-static event_pipe fbsd_nat_event_pipe;
-
/* Implement the "can_async_p" target method. */
bool
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
{
int old_errno = errno;
- if (fbsd_nat_event_pipe.is_open ())
- fbsd_nat_event_pipe.mark ();
+ fbsd_nat_target::async_file_mark_if_open ();
errno = old_errno;
}
if (enable)
{
- if (!fbsd_nat_event_pipe.open ())
+ if (!async_file_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");
+ add_file_handler (async_wait_fd (), handle_target_event, NULL, "fbsd-nat");
/* Trigger a poll in case there are pending events to
handle. */
- fbsd_nat_event_pipe.mark ();
+ async_file_mark ();
}
else
{
- delete_file_handler (fbsd_nat_event_pipe.event_fd ());
- fbsd_nat_event_pipe.close ();
+ delete_file_handler (async_wait_fd ());
+ async_file_close ();
}
}
-/* Implement the "close" target method. */
-
-void
-fbsd_nat_target::close ()
-{
- if (is_async_p ())
- async (0);
-
- inf_ptrace_target::close ();
-}
-
#ifdef TDP_RFPPWAIT
/*
To catch fork events, PT_FOLLOW_FORK is set on every traced process
/* 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 ();
+ async_file_mark ();
}
/* Check for a pending vfork done event for a specific PID. */
/* Ensure any subsequent events trigger a new event in the loop. */
if (is_async_p ())
- fbsd_nat_event_pipe.flush ();
+ async_file_flush ();
wptid = wait_1 (ptid, ourstatus, target_options);
&& ((ourstatus->kind () != TARGET_WAITKIND_IGNORE
&& ourstatus->kind() != TARGET_WAITKIND_NO_RESUMED)
|| ptid != minus_one_ptid))
- fbsd_nat_event_pipe.mark ();
+ async_file_mark ();
fbsd_nat_debug_printf ("returning [%s], [%s]",
target_pid_to_str (wptid).c_str (),
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; }
#endif
}
+/* The event pipe registered as a waitable file in the event loop. */
+event_pipe inf_ptrace_target::m_event_pipe;
+
inf_ptrace_target::~inf_ptrace_target ()
{}
{
return normal_pid_to_str (ptid);
}
+
+/* Implement the "close" target method. */
+
+void
+inf_ptrace_target::close ()
+{
+ /* Unregister from the event loop. */
+ if (is_async_p ())
+ async (0);
+
+ inf_child_target::close ();
+}
#ifndef INF_PTRACE_H
#define INF_PTRACE_H
+#include "gdbsupport/event-pipe.h"
#include "inf-child.h"
/* An abstract prototype ptrace target. The client can override it
void detach (inferior *inf, int) override;
+ void close () override;
+
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
+ bool is_async_p () override
+ { return m_event_pipe.is_open (); }
+
+ int async_wait_fd () override
+ { return m_event_pipe.event_fd (); }
+
+ /* Helper routine used from SIGCHLD handlers to signal the async
+ event pipe. */
+ static void async_file_mark_if_open ()
+ {
+ if (m_event_pipe.is_open ())
+ m_event_pipe.mark ();
+ }
+
protected:
+ /* Helper routines for interacting with the async event pipe. */
+ bool async_file_open ()
+ { return m_event_pipe.open (); }
+ void async_file_close ()
+ { m_event_pipe.close (); }
+ void async_file_flush ()
+ { m_event_pipe.flush (); }
+ void async_file_mark ()
+ { m_event_pipe.mark (); }
+
/* Cleanup the inferior after a successful ptrace detach. */
void detach_success (inferior *inf);
Such targets will supply an appropriate definition for this
function. */
virtual void post_startup_inferior (ptid_t ptid) = 0;
+
+private:
+ static event_pipe m_event_pipe;
};
#ifndef __NetBSD__
#include <fcntl.h> /* for O_RDONLY */
#include "inf-loop.h"
#include "gdbsupport/event-loop.h"
-#include "gdbsupport/event-pipe.h"
#include "event-top.h"
#include <pwd.h>
#include <sys/types.h>
#include "gdbsupport/filestuff.h"
#include "objfiles.h"
#include "nat/linux-namespaces.h"
+#include "gdbsupport/block-signals.h"
#include "gdbsupport/fileio.h"
#include "gdbsupport/scope-exit.h"
#include "gdbsupport/gdb-sigmask.h"
/* Whether target_thread_events is in effect. */
static int report_thread_events;
-/* Async mode support. */
-
-/* The event pipe registered as a waitable file in the event loop. */
-static event_pipe linux_nat_event_pipe;
-
-/* True if we're currently in async mode. */
-#define linux_is_async_p() (linux_nat_event_pipe.is_open ())
-
-/* Flush the event pipe. */
-
-static void
-async_file_flush (void)
-{
- linux_nat_event_pipe.flush ();
-}
-
-/* Put something (anything, doesn't matter what, or how much) in event
- pipe, so that the select/poll in the event-loop realizes we have
- something to process. */
-
-static void
-async_file_mark (void)
-{
- linux_nat_event_pipe.mark ();
-}
-
static int kill_lwp (int lwpid, int signo);
static int stop_callback (struct lwp_info *lp);
return markers;
}
-/* target_is_async_p implementation. */
-
-bool
-linux_nat_target::is_async_p ()
-{
- return linux_is_async_p ();
-}
-
/* target_can_async_p implementation. */
bool
if (debug_linux_nat)
gdb_stdlog->write_async_safe ("sigchld\n", sizeof ("sigchld\n") - 1);
- if (signo == SIGCHLD
- && linux_nat_event_pipe.is_open ())
- async_file_mark (); /* Let the event loop know that there are
- events to handle. */
+ if (signo == SIGCHLD)
+ {
+ /* Let the event loop know that there are events to handle. */
+ linux_nat_target::async_file_mark_if_open ();
+ }
errno = old_errno;
}
inferior_event_handler (INF_REG_EVENT);
}
-/* Create/destroy the target events pipe. Returns previous state. */
-
-static int
-linux_async_pipe (int enable)
-{
- int previous = linux_is_async_p ();
-
- if (previous != enable)
- {
- sigset_t prev_mask;
-
- /* Block child signals while we create/destroy the pipe, as
- their handler writes to it. */
- block_child_signals (&prev_mask);
-
- if (enable)
- {
- if (!linux_nat_event_pipe.open ())
- internal_error (__FILE__, __LINE__,
- "creating event pipe failed.");
- }
- else
- {
- linux_nat_event_pipe.close ();
- }
-
- restore_child_signals_mask (&prev_mask);
- }
-
- return previous;
-}
-
-int
-linux_nat_target::async_wait_fd ()
-{
- return linux_nat_event_pipe.event_fd ();
-}
-
/* target_async implementation. */
void
linux_nat_target::async (int enable)
{
+ if ((enable != 0) == is_async_p ())
+ return;
+
+ /* Block child signals while we create/destroy the pipe, as their
+ handler writes to it. */
+ gdb::block_signals blocker;
+
if (enable)
{
- if (!linux_async_pipe (1))
- {
- add_file_handler (linux_nat_event_pipe.event_fd (),
- handle_target_event, NULL,
- "linux-nat");
- /* There may be pending events to handle. Tell the event loop
- to poll them. */
- async_file_mark ();
- }
+ if (!async_file_open ())
+ internal_error (__FILE__, __LINE__, "creating event pipe failed.");
+
+ add_file_handler (async_wait_fd (), handle_target_event, NULL,
+ "linux-nat");
+
+ /* There may be pending events to handle. Tell the event loop
+ to poll them. */
+ async_file_mark ();
}
else
{
- delete_file_handler (linux_nat_event_pipe.event_fd ());
- linux_async_pipe (0);
+ delete_file_handler (async_wait_fd ());
+ async_file_close ();
}
- return;
}
/* Stop an LWP, and push a GDB_SIGNAL_0 stop status if no other
iterate_over_lwps (ptid, linux_nat_stop_lwp);
}
-void
-linux_nat_target::close ()
-{
- /* Unregister from the event loop. */
- if (is_async_p ())
- async (0);
-
- inf_ptrace_target::close ();
-}
-
/* When requests are passed down from the linux-nat layer to the
single threaded inf-ptrace layer, ptids of (lwpid,0,0) form are
used. The address space pointer is stored in the inferior object,
void thread_events (int) override;
bool can_async_p () override;
- bool is_async_p () override;
bool supports_non_stop () override;
bool always_non_stop_p () override;
- int async_wait_fd () override;
void async (int) override;
- void close () override;
-
void stop (ptid_t) override;
bool supports_multi_process () override;