[PATCH 05/18] remote: stop reason and watchpoint data address per thread

Pedro Alves
2015-10-14T15:33:38Z

Running local-watch-wrong-thread.exp with "maint set target-non-stop
on" exposes that gdb/remote.c only records whether the target stopped
for a breakpoint/watchpoint plus the watchpoint data address *for the
last reported remote event*. But in non-stop mode, we need to keep
that info per-thread, as each thread can end up with its own
last-status pending.

gdb/ChangeLog:
2015-10-14 Pedro Alves <palves@redhat.com>

* remote.c (struct remote_state) <remote_watch_data_address,
stop_reason>: Delete fields.
(struct private_thread_info) <stop_reason, watch_data_address>:
New fields.
(resume_clear_thread_private_info): New function.
(append_pending_thread_resumptions): Call it.
(remote_resume): Clear all threads' private info.
(process_stop_reply): Adjust.
(remote_wait_as): Don't reference remote_state's stop_reason
field.
(remote_stopped_by_sw_breakpoint)
(remote_stopped_by_hw_breakpoint, remote_stopped_by_watchpoint)
(remote_stopped_data_address): Adjust to refer get data from the
current thread.
---
gdb/remote.c | 69 ++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 44 insertions(+), 25 deletions(-)

diff --git a/gdb/remote.c b/gdb/remote.c
index ff25a76..10c65e2 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -401,13 +401,6 @@ struct remote_state
int use_threadinfo_query;
int use_threadextra_query;

- /* This is set to the data address of the access causing the target
- to stop for a watchpoint. */
- CORE_ADDR remote_watch_data_address;
-
- /* Whether the target stopped for a breakpoint/watchpoint. */
- enum target_stop_reason stop_reason;
-
threadref echo_nextthread;
threadref nextthread;
threadref resultthreadlist[MAXTHREADLISTRESULTS];
@@ -438,6 +431,13 @@ struct private_thread_info
{
char *extra;
int core;
+
+ /* Whether the target stopped for a breakpoint/watchpoint. */
+ enum target_stop_reason stop_reason;
+
+ /* This is set to the data address of the access causing the target
+ to stop for a watchpoint. */
+ CORE_ADDR watch_data_address;
};

static void
@@ -5299,6 +5299,18 @@ append_resumption (char *p, char *endp,
return p;
}

+/* Clear the thread's private info on resume. */
+
+static void
+resume_clear_thread_private_info (struct thread_info *thread)
+{
+ if (thread->priv != NULL)
+ {
+ thread->priv->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+ thread->priv->watch_data_address = 0;
+ }
+}
+
/* Append a vCont continue-with-signal action for threads that have a
non-zero stop signal. */

@@ -5315,6 +5327,7 @@ append_pending_thread_resumptions (char *p, char *endp, ptid_t ptid)
p = append_resumption (p, endp, thread->ptid,
0, thread->suspend.stop_signal);
thread->suspend.stop_signal = GDB_SIGNAL_0;
+ resume_clear_thread_private_info (thread);
}

return p;
@@ -5409,6 +5422,7 @@ remote_resume (struct target_ops *ops,
{
struct remote_state *rs = get_remote_state ();
char *buf;
+ struct thread_info *thread;

/* In all-stop, we can't mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
(explained in remote-notif.c:handle_notification) so
@@ -5435,6 +5449,9 @@ remote_resume (struct target_ops *ops,
else
set_continue_thread (ptid);

+ ALL_NON_EXITED_THREADS (thread)
+ resume_clear_thread_private_info (thread);
+
buf = rs->buf;
if (execution_direction == EXEC_REVERSE)
{
@@ -6581,6 +6598,7 @@ process_stop_reply (struct stop_reply *stop_reply,
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
struct remote_state *rs = get_remote_state ();
+ struct private_thread_info *remote_thr;

/* Expedited registers. */
if (stop_reply->regcache)
@@ -6597,11 +6615,11 @@ process_stop_reply (struct stop_reply *stop_reply,
VEC_free (cached_reg_t, stop_reply->regcache);
}

- rs->stop_reason = stop_reply->stop_reason;
- rs->remote_watch_data_address = stop_reply->watch_data_address;
-
remote_notice_new_inferior (ptid, 0);
- demand_private_info (ptid)->core = stop_reply->core;
+ remote_thr = demand_private_info (ptid);
+ remote_thr->core = stop_reply->core;
+ remote_thr->stop_reason = stop_reply->stop_reason;
+ remote_thr->watch_data_address = stop_reply->watch_data_address;
}

stop_reply_xfree (stop_reply);
@@ -6735,8 +6753,6 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)

buf = rs->buf;

- rs->stop_reason = TARGET_STOPPED_BY_NO_REASON;
-
/* We got something. */
rs->waiting_for_stop_reply = 0;

@@ -9311,9 +9327,10 @@ remote_check_watch_resources (struct target_ops *self,
static int
remote_stopped_by_sw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();

- return rs->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT);
}

/* The to_supports_stopped_by_sw_breakpoint method of target
@@ -9332,9 +9349,10 @@ remote_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
static int
remote_stopped_by_hw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();

- return rs->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT);
}

/* The to_supports_stopped_by_hw_breakpoint method of target
@@ -9351,24 +9369,25 @@ remote_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
static int
remote_stopped_by_watchpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();

- return rs->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_WATCHPOINT);
}

static int
remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
{
- struct remote_state *rs = get_remote_state ();
- int rc = 0;
+ struct thread_info *thread = inferior_thread ();

- if (remote_stopped_by_watchpoint (target))
+ if (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
{
- *addr_p = rs->remote_watch_data_address;
- rc = 1;
+ *addr_p = thread->priv->watch_data_address;
+ return 1;
}

- return rc;
+ return 0;
}

--
1.9.3