Skip to content

Commit 1b0fa45

Browse files
committed
fbsd-nat: Add a list of pending events.
The m_pending_events list stores a queue of deferred events that might be reported by the next call to the target's wait method. The set of events that are eligible is filtered by the ptid passed to resume. For now this just replaces the list of vfork_done events. A subsequent commit will reuse this to store other events.
1 parent dad9ed2 commit 1b0fa45

File tree

2 files changed

+118
-55
lines changed

2 files changed

+118
-55
lines changed

gdb/fbsd-nat.c

Lines changed: 73 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,47 @@
4747
#include "fbsd-nat.h"
4848
#include "fbsd-tdep.h"
4949

50-
#include <list>
51-
5250
#ifndef PT_GETREGSET
5351
#define PT_GETREGSET 42 /* Get a target register set */
5452
#define PT_SETREGSET 43 /* Set a target register set */
5553
#endif
5654

55+
/* See fbsd-nat.h. */
56+
57+
void
58+
fbsd_nat_target::add_pending_event (const ptid_t &ptid,
59+
const target_waitstatus &status)
60+
{
61+
gdb_assert (find_inferior_ptid (this, ptid) != nullptr);
62+
m_pending_events.emplace_back (ptid, status);
63+
}
64+
65+
/* See fbsd-nat.h. */
66+
67+
bool
68+
fbsd_nat_target::have_pending_event (ptid_t filter)
69+
{
70+
for (const pending_event &event : m_pending_events)
71+
if (event.ptid.matches (filter))
72+
return true;
73+
return false;
74+
}
75+
76+
/* See fbsd-nat.h. */
77+
78+
gdb::optional<fbsd_nat_target::pending_event>
79+
fbsd_nat_target::take_pending_event ()
80+
{
81+
for (auto it = m_pending_events.begin (); it != m_pending_events.end (); it++)
82+
if (it->ptid.matches (m_resume_ptid))
83+
{
84+
pending_event event = *it;
85+
m_pending_events.erase (it);
86+
return event;
87+
}
88+
return {};
89+
}
90+
5791
/* Return the name of a file that can be opened to get the symbols for
5892
the child process identified by PID. */
5993

@@ -1061,47 +1095,18 @@ fbsd_is_child_pending (pid_t pid)
10611095
}
10621096

10631097
#ifndef PTRACE_VFORK
1064-
static std::forward_list<ptid_t> fbsd_pending_vfork_done;
1065-
10661098
/* Record a pending vfork done event. */
10671099

10681100
static void
10691101
fbsd_add_vfork_done (ptid_t pid)
10701102
{
1071-
fbsd_pending_vfork_done.push_front (pid);
1103+
add_pending_event (ptid, target_waitstatus ().set_vfork_done ());
10721104

10731105
/* If we're in async mode, need to tell the event loop there's
10741106
something here to process. */
10751107
if (target_is_async_p ())
10761108
async_file_mark ();
10771109
}
1078-
1079-
/* Check for a pending vfork done event for a specific PID. */
1080-
1081-
static int
1082-
fbsd_is_vfork_done_pending (pid_t pid)
1083-
{
1084-
for (auto it = fbsd_pending_vfork_done.begin ();
1085-
it != fbsd_pending_vfork_done.end (); it++)
1086-
if (it->pid () == pid)
1087-
return 1;
1088-
return 0;
1089-
}
1090-
1091-
/* Check for a pending vfork done event. If one is found, remove it
1092-
from the list and return the PTID. */
1093-
1094-
static ptid_t
1095-
fbsd_next_vfork_done (void)
1096-
{
1097-
if (!fbsd_pending_vfork_done.empty ())
1098-
{
1099-
ptid_t ptid = fbsd_pending_vfork_done.front ();
1100-
fbsd_pending_vfork_done.pop_front ();
1101-
return ptid;
1102-
}
1103-
return null_ptid;
1104-
}
11051110
#endif
11061111
#endif
11071112

@@ -1110,21 +1115,18 @@ fbsd_next_vfork_done (void)
11101115
void
11111116
fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
11121117
{
1113-
#if defined(TDP_RFPPWAIT) && !defined(PTRACE_VFORK)
1114-
pid_t pid;
1115-
1116-
/* Don't PT_CONTINUE a process which has a pending vfork done event. */
1117-
if (minus_one_ptid == ptid)
1118-
pid = inferior_ptid.pid ();
1119-
else
1120-
pid = ptid.pid ();
1121-
if (fbsd_is_vfork_done_pending (pid))
1122-
return;
1123-
#endif
1124-
11251118
fbsd_nat_debug_printf ("[%s], step %d, signo %d (%s)",
11261119
target_pid_to_str (ptid).c_str (), step, signo,
11271120
gdb_signal_to_name (signo));
1121+
1122+
/* Don't PT_CONTINUE a thread or process which has a pending event. */
1123+
m_resume_ptid = ptid;
1124+
if (have_pending_event (ptid))
1125+
{
1126+
fbsd_nat_debug_printf ("found pending event");
1127+
return;
1128+
}
1129+
11281130
if (ptid.lwp_p ())
11291131
{
11301132
/* If ptid is a specific LWP, suspend all other LWPs in the process. */
@@ -1257,14 +1259,6 @@ fbsd_nat_target::wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
12571259

12581260
while (1)
12591261
{
1260-
#ifndef PTRACE_VFORK
1261-
wptid = fbsd_next_vfork_done ();
1262-
if (wptid != null_ptid)
1263-
{
1264-
ourstatus->set_vfork_done ();
1265-
return wptid;
1266-
}
1267-
#endif
12681262
wptid = inf_ptrace_target::wait (ptid, ourstatus, target_options);
12691263
if (ourstatus->kind () == TARGET_WAITKIND_STOPPED)
12701264
{
@@ -1473,16 +1467,26 @@ ptid_t
14731467
fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
14741468
target_wait_flags target_options)
14751469
{
1476-
ptid_t wptid;
1477-
14781470
fbsd_nat_debug_printf ("[%s], [%s]", target_pid_to_str (ptid).c_str (),
14791471
target_options_to_string (target_options).c_str ());
14801472

1473+
/* If there is a valid pending event, return it. */
1474+
gdb::optional<pending_event> event = take_pending_event ();
1475+
if (event.has_value ())
1476+
{
1477+
fbsd_nat_debug_printf ("returning pending event [%s], [%s]",
1478+
target_pid_to_str (event->ptid).c_str (),
1479+
event->status.to_string ().c_str ());
1480+
gdb_assert (event->ptid.matches (ptid));
1481+
*ourstatus = event->status;
1482+
return event->ptid;
1483+
}
1484+
14811485
/* Ensure any subsequent events trigger a new event in the loop. */
14821486
if (is_async_p ())
14831487
async_file_flush ();
14841488

1485-
wptid = wait_1 (ptid, ourstatus, target_options);
1489+
ptid_t wptid = wait_1 (ptid, ourstatus, target_options);
14861490

14871491
/* If we are in async mode and found an event, there may still be
14881492
another event pending. Trigger the event pipe so that that the
@@ -1585,9 +1589,23 @@ fbsd_nat_target::create_inferior (const char *exec_file,
15851589
(disable_randomization);
15861590
#endif
15871591

1592+
/* Expect a wait for the new process. */
1593+
m_resume_ptid = minus_one_ptid;
1594+
fbsd_nat_debug_printf ("setting resume_ptid to [%s]",
1595+
target_pid_to_str (m_resume_ptid).c_str ());
15881596
inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty);
15891597
}
15901598

1599+
void
1600+
fbsd_nat_target::attach (const char *args, int from_tty)
1601+
{
1602+
/* Expect a wait for the new process. */
1603+
m_resume_ptid = minus_one_ptid;
1604+
fbsd_nat_debug_printf ("setting resume_ptid to [%s]",
1605+
target_pid_to_str (m_resume_ptid).c_str ());
1606+
inf_ptrace_target::attach (args, from_tty);
1607+
}
1608+
15911609
#ifdef TDP_RFPPWAIT
15921610
/* Target hook for follow_fork. On entry and at return inferior_ptid is
15931611
the ptid of the followed inferior. */

gdb/fbsd-nat.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
#ifndef FBSD_NAT_H
2121
#define FBSD_NAT_H
2222

23+
#include "gdbsupport/gdb_optional.h"
2324
#include "inf-ptrace.h"
2425
#include "regcache.h"
2526
#include "regset.h"
2627
#include <osreldate.h>
2728
#include <sys/proc.h>
2829

30+
#include <list>
31+
2932
/* FreeBSD kernels 11.3 and later report valid si_code values for
3033
SIGTRAP on all architectures. Older FreeBSD kernels that supported
3134
TRAP_BRKPT did not report valid values for MIPS and sparc64. Even
@@ -76,6 +79,8 @@ class fbsd_nat_target : public inf_ptrace_target
7679
void create_inferior (const char *, const std::string &,
7780
char **, int) override;
7881

82+
void attach (const char *, int) override;
83+
7984
void resume (ptid_t, int, enum gdb_signal) override;
8085

8186
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
@@ -217,6 +222,46 @@ class fbsd_nat_target : public inf_ptrace_target
217222
return store_regset (regcache, regnum, note, regset, regbase, &regs,
218223
sizeof (regs));
219224
}
225+
226+
private:
227+
/* If an event is triggered asynchronously (fake vfork_done events)
228+
or occurs when the core is not expecting it, a pending event is
229+
created. This event is then returned by a future call to the
230+
target wait method. */
231+
232+
struct pending_event
233+
{
234+
pending_event (const ptid_t &_ptid, const target_waitstatus &_status) :
235+
ptid (_ptid), status (_status) {}
236+
237+
ptid_t ptid;
238+
target_waitstatus status;
239+
};
240+
241+
/* Add a new pending event to the list. */
242+
243+
void add_pending_event (const ptid_t &ptid, const target_waitstatus &status);
244+
245+
/* Return true if there is a pending event matching FILTER. */
246+
247+
bool have_pending_event (ptid_t filter);
248+
249+
/* Helper method called by the target wait method. Check if there
250+
is a pending event matching M_RESUME_PTID. If there is a
251+
matching event, the event is removed from the pending list and
252+
returned. */
253+
254+
gdb::optional<pending_event> take_pending_event ();
255+
256+
/* List of pending events. */
257+
258+
std::list<pending_event> m_pending_events;
259+
260+
/* Filter for ptid's allowed to report events from wait. Normally
261+
set in resume, but also reset to minus_one_ptid in
262+
create_inferior and attach. */
263+
264+
ptid_t m_resume_ptid;
220265
};
221266

222267
/* Fetch the signal information for PTID and store it in *SIGINFO.

0 commit comments

Comments
 (0)