From patchwork Tue Feb 28 18:18:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 65806 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4A32D3858296 for ; Tue, 28 Feb 2023 18:19:51 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail.baldwin.cx (bigwig.baldwin.cx [IPv6:2607:f138:0:13::2]) by sourceware.org (Postfix) with ESMTPS id 9C3D13858D3C for ; Tue, 28 Feb 2023 18:19:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9C3D13858D3C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=FreeBSD.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=FreeBSD.org Received: from gimli.baldwin.net (c-98-35-126-114.hsd1.ca.comcast.net [98.35.126.114]) by mail.baldwin.cx (Postfix) with ESMTPSA id C68461A84E32 for ; Tue, 28 Feb 2023 13:18:56 -0500 (EST) From: John Baldwin To: gdb-patches@sourceware.org Subject: [PATCH 4/9] fbsd-nat: Add a list of pending events. Date: Tue, 28 Feb 2023 10:18:40 -0800 Message-Id: <20230228181845.99936-5-jhb@FreeBSD.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230228181845.99936-1-jhb@FreeBSD.org> References: <20230228181845.99936-1-jhb@FreeBSD.org> MIME-Version: 1.0 X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (mail.baldwin.cx [0.0.0.0]); Tue, 28 Feb 2023 13:18:57 -0500 (EST) X-Virus-Scanned: clamav-milter 0.103.1 at mail.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_STATUS, KHOP_HELO_FCRDNS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" The 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. --- gdb/fbsd-nat.c | 146 ++++++++++++++++++++++++++++++++----------------- gdb/fbsd-nat.h | 2 + 2 files changed, 98 insertions(+), 50 deletions(-) diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index 04d67fc5278..ca278b871ef 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -54,6 +54,66 @@ #define PT_SETREGSET 43 /* Set a target register set */ #endif +/* Filter for ptid's allowed to report events from wait. Normally set + in resume, but also reset to minus_one_ptid in create_inferior and + attach. */ + +static ptid_t resume_ptid; + +/* If an event is triggered asynchronously (fake vfork_done events) or + occurs when the core is not expecting it, a pending event is + created. This event is then returned by a future call to the + target wait method. */ + +struct pending_event +{ + pending_event (const ptid_t &_ptid, const target_waitstatus &_status) : + ptid(_ptid), status(_status) {} + + ptid_t ptid; + target_waitstatus status; +}; + +static std::list pending_events; + +/* Add a new pending event to the list. */ + +static void +add_pending_event (const ptid_t &ptid, const target_waitstatus &status) +{ + pending_events.emplace_back (ptid, status); +} + +/* Return true if there is a pending event matching FILTER. */ + +static bool +have_pending_event (ptid_t filter) +{ + for (const pending_event &event : pending_events) + if (event.ptid.matches (filter)) + return true; + return false; +} + +/* Helper method called by the target wait method. Returns true if + there is a pending event matching resume_ptid. If there is a + matching event, PTID and *STATUS contain the event details, and the + event is removed from the pending list. */ + +static bool +take_pending_event (ptid_t &ptid, target_waitstatus *status) +{ + for (auto it = pending_events.begin (); it != pending_events.end (); it++) + if (it->ptid.matches (resume_ptid)) + { + ptid = it->ptid; + *status = it->status; + pending_events.erase (it); + return true; + } + return false; +} + /* Return the name of a file that can be opened to get the symbols for the child process identified by PID. */ @@ -1061,47 +1121,20 @@ fbsd_is_child_pending (pid_t pid) } #ifndef PTRACE_VFORK -static std::forward_list fbsd_pending_vfork_done; - /* Record a pending vfork done event. */ static void fbsd_add_vfork_done (ptid_t pid) { - fbsd_pending_vfork_done.push_front (pid); + target_waitstatus status; + status.set_vfork_done (); + add_pending_event (ptid, status); /* If we're in async mode, need to tell the event loop there's something here to process. */ if (target_is_async_p ()) async_file_mark (); } - -/* Check for a pending vfork done event for a specific PID. */ - -static int -fbsd_is_vfork_done_pending (pid_t pid) -{ - for (auto it = fbsd_pending_vfork_done.begin (); - it != fbsd_pending_vfork_done.end (); it++) - if (it->pid () == pid) - return 1; - return 0; -} - -/* Check for a pending vfork done event. If one is found, remove it - from the list and return the PTID. */ - -static ptid_t -fbsd_next_vfork_done (void) -{ - if (!fbsd_pending_vfork_done.empty ()) - { - ptid_t ptid = fbsd_pending_vfork_done.front (); - fbsd_pending_vfork_done.pop_front (); - return ptid; - } - return null_ptid; -} #endif #endif @@ -1110,21 +1143,18 @@ fbsd_next_vfork_done (void) void fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo) { -#if defined(TDP_RFPPWAIT) && !defined(PTRACE_VFORK) - pid_t pid; - - /* Don't PT_CONTINUE a process which has a pending vfork done event. */ - if (minus_one_ptid == ptid) - pid = inferior_ptid.pid (); - else - pid = ptid.pid (); - if (fbsd_is_vfork_done_pending (pid)) - return; -#endif - fbsd_nat_debug_printf ("[%s], step %d, signo %d (%s)", target_pid_to_str (ptid).c_str (), step, signo, gdb_signal_to_name (signo)); + + /* Don't PT_CONTINUE a thread or process which has a pending event. */ + resume_ptid = ptid; + if (have_pending_event (ptid)) + { + fbsd_nat_debug_printf ("found pending event"); + return; + } + if (ptid.lwp_p ()) { /* If ptid is a specific LWP, suspend all other LWPs in the process. */ @@ -1257,14 +1287,6 @@ fbsd_nat_target::wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus, while (1) { -#ifndef PTRACE_VFORK - wptid = fbsd_next_vfork_done (); - if (wptid != null_ptid) - { - ourstatus->set_vfork_done (); - return wptid; - } -#endif wptid = inf_ptrace_target::wait (ptid, ourstatus, target_options); if (ourstatus->kind () == TARGET_WAITKIND_STOPPED) { @@ -1478,6 +1500,16 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, fbsd_nat_debug_printf ("[%s], [%s]", target_pid_to_str (ptid).c_str (), target_options_to_string (target_options).c_str ()); + /* If there is a valid pending event, return it. */ + if (take_pending_event (wptid, ourstatus)) + { + fbsd_nat_debug_printf ("returning pending event [%s], [%s]", + target_pid_to_str (wptid).c_str (), + ourstatus->to_string ().c_str ()); + gdb_assert (wptid.matches (ptid)); + return wptid; + } + /* Ensure any subsequent events trigger a new event in the loop. */ if (is_async_p ()) async_file_flush (); @@ -1585,9 +1617,23 @@ fbsd_nat_target::create_inferior (const char *exec_file, (disable_randomization); #endif + /* Expect a wait for the new process. */ + resume_ptid = minus_one_ptid; + fbsd_nat_debug_printf ("setting resume_ptid to [%s]", + target_pid_to_str (resume_ptid).c_str ()); inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty); } +void +fbsd_nat_target::attach (const char *args, int from_tty) +{ + /* Expect a wait for the new process. */ + resume_ptid = minus_one_ptid; + fbsd_nat_debug_printf ("setting resume_ptid to [%s]", + target_pid_to_str (resume_ptid).c_str ()); + inf_ptrace_target::attach (args, from_tty); +} + #ifdef TDP_RFPPWAIT /* Target hook for follow_fork. On entry and at return inferior_ptid is the ptid of the followed inferior. */ diff --git a/gdb/fbsd-nat.h b/gdb/fbsd-nat.h index a19bceaf5e4..cda150ac465 100644 --- a/gdb/fbsd-nat.h +++ b/gdb/fbsd-nat.h @@ -76,6 +76,8 @@ class fbsd_nat_target : public inf_ptrace_target void create_inferior (const char *, const std::string &, char **, int) override; + void attach (const char *, int) override; + void resume (ptid_t, int, enum gdb_signal) override; ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;