This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Make linux-nat.c's non-stop mode target_stop implementation really asynchronous.
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 10 Oct 2011 14:28:40 +0100
- Subject: Re: Make linux-nat.c's non-stop mode target_stop implementation really asynchronous.
- References: <201109092051.55884.pedro@codesourcery.com>
On Friday 09 September 2011 20:51:55, Pedro Alves wrote:
> This makes non-stop mode's "(gdb) interrupt", or rather the linux-nat.c's
> target_stop implementation truly asynchronous, like remote.c's counterpart,
> closer to gdbserver's linux-low.c implementation.
>
> Currently, we
>
> - queue a SIGSTOP
> - wait for it to be reported
> - leave a event pending
> - tell the event loop there's something to handle
>
> all from within linux_nat_stop_lwp (from interrupt -> target_stop).
>
> Back to the event loop, we'd noticing a target event,
> and go do target_wait, collecting the pending event.
>
> Now we'll just
>
> - queue a SIGSTOP and leave.
>
> Eventually, the lwp really stops, and we'll collect
> the stop as usual. We do need to record in the lwp that
> we're stopping it, and that's what the new last_resume_kind
> field is for.
...
> /* A pending SIGSTOP may interfere with the normal stream of
> events. In a typical case where interference is a problem,
> @@ -3747,7 +3781,10 @@ retry:
> iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
> }
> else
> - lp->resumed = 0;
> + {
> + lp->resumed = 0;
> + lp->last_resume_kind = resume_stop;
> + }
>
> if (linux_nat_status_is_event (status))
> {
> @@ -3770,6 +3807,16 @@ retry:
>
> restore_child_signals_mask (&prev_mask);
>
> + if (lp->last_resume_kind == resume_stop
Whoops, obvious blunder here. We're always clearing
lp->last_resume_kind to resume_stop just a bit above,
so this will always be true. The patch below
corrects this. I've applied it.
> + && ourstatus->kind == TARGET_WAITKIND_STOPPED
> + && WSTOPSIG (status) == SIGSTOP)
2011-10-10 Pedro Alves <pedro@codesourcery.com>
gdb/
* linux-nat.c (linux_nat_wait_1): Copy the event lwp's
last_resume_kind before clearing it, and use the copy instead to
determine whether to report a SIGSTOP as TARGET_SIGNAL_0. Use
resume_clear_callback in the non-stop path too.
---
gdb/linux-nat.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2011-10-10 14:19:22.087660163 +0100
+++ src/gdb/linux-nat.c 2011-10-10 14:20:00.527660156 +0100
@@ -3335,6 +3335,7 @@ linux_nat_wait_1 (struct target_ops *ops
int target_options)
{
static sigset_t prev_mask;
+ enum resume_kind last_resume_kind;
struct lwp_info *lp = NULL;
int options = 0;
int status = 0;
@@ -3747,14 +3748,20 @@ retry:
why. */
iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
+ /* We'll need this to determine whether to report a SIGSTOP as
+ TARGET_WAITKIND_0. Need to take a copy because
+ resume_clear_callback clears it. */
+ last_resume_kind = lp->last_resume_kind;
+
/* In all-stop, from the core's perspective, all LWPs are now
stopped until a new resume action is sent over. */
iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
}
else
{
- lp->resumed = 0;
- lp->last_resume_kind = resume_stop;
+ /* See above. */
+ last_resume_kind = lp->last_resume_kind;
+ resume_clear_callback (lp, NULL);
}
if (linux_nat_status_is_event (status))
@@ -3778,7 +3785,7 @@ retry:
restore_child_signals_mask (&prev_mask);
- if (lp->last_resume_kind == resume_stop
+ if (last_resume_kind == resume_stop
&& ourstatus->kind == TARGET_WAITKIND_STOPPED
&& WSTOPSIG (status) == SIGSTOP)
{