Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions gdb/amd-dbgapi-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ struct amd_dbgapi_target final : public target_ops
void detach (inferior *inf, int from_tty) override;

void async (bool enable) override;
bool is_async_p () override;
std::vector<int> async_wait_fds () override;

bool has_pending_events () override;
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
Expand Down Expand Up @@ -1945,6 +1947,28 @@ dbgapi_notifier_handler (int err, gdb_client_data client_data)
}
}

std::vector<int>
amd_dbgapi_target::async_wait_fds ()
{
std::vector<int> vec = beneath ()->async_wait_fds ();

/* The library gives us one notifier file descriptor per inferior (even
the ones that have not yet loaded their runtime). Register them
all with the event loop. */
process_stratum_target *proc_target
= current_inferior ()->process_target ();

for (inferior *inf : all_non_exited_inferiors (proc_target))
{
auto &info = get_amd_dbgapi_inferior_info (inf);

if (info.notifier != -1)
vec.push_back (info.notifier);
}

return vec;
}

void
amd_dbgapi_target::async (bool enable)
{
Expand Down Expand Up @@ -2002,6 +2026,13 @@ amd_dbgapi_target::async (bool enable)
}
}

bool
amd_dbgapi_target::is_async_p ()
{
return (amd_dbgapi_async_event_handler != nullptr
|| this->beneath ()->is_async_p ());
}

/* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */

static ptid_t
Expand Down Expand Up @@ -2191,6 +2222,8 @@ process_one_event (amd_dbgapi_inferior_info &info,
error (_("event_get_info for event_%ld failed (%s)"),
event_id.handle, get_status_string (status));

/* Expect only "runtime unloaded" events here. process_one_event is
only called for inferiors that already have the runtime loaded. */
gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
gdb_assert
(info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
Expand Down Expand Up @@ -2252,6 +2285,7 @@ process_event_queue (amd_dbgapi_inferior_info &info,
/* Pulling events with forward progress required may result in bad
performance, make sure it is not required. */
gdb_assert (!info.forward_progress_required);
gdb_assert (info.process_id != AMD_DBGAPI_PROCESS_NONE);

while (true)
{
Expand Down Expand Up @@ -2375,11 +2409,20 @@ amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
if (event_ptid == minus_one_ptid)
{
/* Drain the events for the current inferior from the amd_dbgapi and
preserve the ordering. */
amd_dbgapi_inferior_info &info
= get_amd_dbgapi_inferior_info (current_inferior ());
process_event_queue (info);
/* No event for inferiors matching PTID is readily available. Pull
events for for all inferiors with a runtime loaded that match PTID. */
for (inferior *inf : all_non_exited_inferiors ())
{
if (!ptid_t (inf->pid).matches (ptid))
continue;

auto &info = get_amd_dbgapi_inferior_info (inf);

if (info.runtime_state != AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS)
continue;

process_event_queue (info);
}

std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
if (event_ptid == minus_one_ptid)
Expand Down
6 changes: 4 additions & 2 deletions gdb/inf-ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ struct inf_ptrace_target : public inf_child_target
bool is_async_p () override
{ return m_event_pipe.is_open (); }

int async_wait_fd () override
{ return m_event_pipe.event_fd (); }
std::vector<int> async_wait_fds () override
{ return {async_wait_fd ()}; }

/* Helper routine used from SIGCHLD handlers to signal the async
event pipe. */
Expand All @@ -84,6 +84,8 @@ struct inf_ptrace_target : public inf_child_target
{ m_event_pipe.flush (); }
void async_file_mark ()
{ m_event_pipe.mark (); }
int async_wait_fd ()
{ return m_event_pipe.event_fd (); }

/* Cleanup the inferior after a successful ptrace detach. */
void detach_success (inferior *inf);
Expand Down
73 changes: 47 additions & 26 deletions gdb/infrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -5430,27 +5430,41 @@ poll_one_curr_target (struct target_waitstatus *ws)
static wait_one_event
wait_one ()
{
/* Skip INF if it can't report events. That is:

- it has no process target or...
- it has no threads executing or...
- it is currently not async */
const auto skip_inferior = [] (inferior *inf)
{
process_stratum_target *target = inf->process_target ();
if (target == nullptr || !target->threads_executing)
return true;

switch_to_inferior_no_thread (inf);

return !inf->top_target ()->is_async_p ();
};

while (1)
{
for (inferior *inf : all_inferiors ())
{
process_stratum_target *target = inf->process_target ();
if (target == nullptr
|| !target->is_async_p ()
|| !target->threads_executing)
if (skip_inferior (inf))
continue;

switch_to_inferior_no_thread (inf);
/* skip_inferior leaves INF as the current inferior, necessary for
the target call below. */

wait_one_event event;
event.target = target;
event.target = inf->process_target ();
event.ptid = poll_one_curr_target (&event.ws);

if (event.ws.kind () == TARGET_WAITKIND_NO_RESUMED)
{
/* If nothing is resumed, remove the target from the
event loop. */
target_async (false);
inf->top_target ()->async (false);
}
else if (event.ws.kind () != TARGET_WAITKIND_IGNORE)
return event;
Expand All @@ -5465,16 +5479,18 @@ wait_one ()

for (inferior *inf : all_inferiors ())
{
process_stratum_target *target = inf->process_target ();
if (target == nullptr
|| !target->is_async_p ()
|| !target->threads_executing)
if (skip_inferior (inf))
continue;

int fd = target->async_wait_fd ();
FD_SET (fd, &readfds);
if (nfds <= fd)
nfds = fd + 1;
/* skip_inferior leaves INF as the current inferior, necessary for
the target call below. */

for (int fd : inf->top_target ()->async_wait_fds ())
{
FD_SET (fd, &readfds);
if (nfds <= fd)
nfds = fd + 1;
}
}

if (nfds == 0)
Expand Down Expand Up @@ -5803,14 +5819,19 @@ reenable_target_async ()
for (inferior *inf : all_inferiors ())
{
process_stratum_target *target = inf->process_target ();
if (target != nullptr
&& target->threads_executing
&& target->can_async_p ()
&& !target->is_async_p ())
{
switch_to_inferior_no_thread (inf);
target_async (1);
}

if (target == nullptr || !target->threads_executing)
continue;

switch_to_inferior_no_thread (inf);

/* If the target can't async or is already async, no need to call
`async (true)`. */
if (!inf->top_target ()->can_async_p ()
|| inf->top_target ()->is_async_p ())
continue;

inf->top_target ()->async (true);
}
}

Expand Down Expand Up @@ -5888,12 +5909,12 @@ stop_all_threads (const char *reason, inferior *inf)
{
int waits_needed = 0;

for (auto *target : all_non_exited_process_targets ())
for (auto *this_inf : all_non_exited_inferiors ())
{
if (inf != nullptr && inf->process_target () != target)
if (inf != nullptr && inf != this_inf)
continue;

switch_to_target_no_thread (target);
switch_to_inferior_no_thread (this_inf);
update_thread_list ();
}

Expand Down
8 changes: 4 additions & 4 deletions gdb/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ class remote_target : public process_stratum_target

void async (bool) override;

int async_wait_fd () override;
std::vector<int> async_wait_fds () override;

void thread_events (bool) override;

Expand Down Expand Up @@ -15975,11 +15975,11 @@ remote_async_serial_handler (struct serial *scb, void *context)
inferior_event_handler (INF_REG_EVENT);
}

int
remote_target::async_wait_fd ()
std::vector<int>
remote_target::async_wait_fds ()
{
struct remote_state *rs = get_remote_state ();
return rs->remote_desc->fd;
return {rs->remote_desc->fd};
}

void
Expand Down
26 changes: 26 additions & 0 deletions gdb/target-debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,30 @@ target_debug_print_opt_size_t (opt_size_t size)
return "";
}

static std::string
target_debug_print (int i)
{ return std::to_string (i); }

template<typename T>
static std::string
target_debug_print (const std::vector<T> &vec)
{
std::string s = "{ ";
const char *comma = "";

for (const auto &v : vec)
{
string_appendf (s, "%s%s", comma, target_debug_print (v).c_str ());
comma = ", ";
}

s += " }";

return s;
}

static std::string
target_debug_print_std_vector_int (const std::vector<int> &vec)
{ return target_debug_print (vec); }

#endif /* GDB_TARGET_DEBUG_H */
28 changes: 14 additions & 14 deletions gdb/target-delegates-gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct dummy_target : public target_ops
bool can_async_p () override;
bool is_async_p () override;
void async (bool arg0) override;
int async_wait_fd () override;
std::vector<int> async_wait_fds () override;
bool has_pending_events () override;
void thread_events (bool arg0) override;
bool supports_set_thread_options (gdb_thread_options arg0) override;
Expand Down Expand Up @@ -305,7 +305,7 @@ struct debug_target : public target_ops
bool can_async_p () override;
bool is_async_p () override;
void async (bool arg0) override;
int async_wait_fd () override;
std::vector<int> async_wait_fds () override;
bool has_pending_events () override;
void thread_events (bool arg0) override;
bool supports_set_thread_options (gdb_thread_options arg0) override;
Expand Down Expand Up @@ -2394,27 +2394,27 @@ debug_target::async (bool arg0)
target_debug_print_bool (arg0).c_str ());
}

int
target_ops::async_wait_fd ()
std::vector<int>
target_ops::async_wait_fds ()
{
return this->beneath ()->async_wait_fd ();
return this->beneath ()->async_wait_fds ();
}

int
dummy_target::async_wait_fd ()
std::vector<int>
dummy_target::async_wait_fds ()
{
noprocess ();
}

int
debug_target::async_wait_fd ()
std::vector<int>
debug_target::async_wait_fds ()
{
target_debug_printf_nofunc ("-> %s->async_wait_fd (...)", this->beneath ()->shortname ());
int result
= this->beneath ()->async_wait_fd ();
target_debug_printf_nofunc ("<- %s->async_wait_fd () = %s",
target_debug_printf_nofunc ("-> %s->async_wait_fds (...)", this->beneath ()->shortname ());
std::vector<int> result
= this->beneath ()->async_wait_fds ();
target_debug_printf_nofunc ("<- %s->async_wait_fds () = %s",
this->beneath ()->shortname (),
target_debug_print_int (result).c_str ());
target_debug_print_std_vector_int (result).c_str ());
return result;
}

Expand Down
2 changes: 1 addition & 1 deletion gdb/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ struct target_ops
TARGET_DEFAULT_RETURN (false);
virtual void async (bool)
TARGET_DEFAULT_NORETURN (tcomplain ());
virtual int async_wait_fd ()
virtual std::vector<int> async_wait_fds ()
TARGET_DEFAULT_NORETURN (noprocess ());
/* Return true if the target has pending events to report to the
core. If true, then GDB avoids resuming the target until all
Expand Down
Loading
Loading