This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch 2/4] Fix hw watchpoints: reordered / simultaneously hit [fixup #1]


On Wed, 07 Oct 2009 20:38:58 +0200, Joel Brobecker wrote:
> My suggestion, instead of wrapping that one call to
> target_stopped_by_watchpoint was to turn that macro into a function which
> does the wrapping for you, before it eventually calls the target_ops method.

Provided some patch, it is regression tested on
{x86_64,x86_64-m32,i686}-fedora11-linux-gnu, it would be better to regression
test it in with the hw-watchpoints patchset after its complete regression
testing also for the upgraded (not deprecated_* symbols using) targets ia64,
ppc*, s390*.

If we should do the upgrade my primary reason for this change is that I find
the single functionality being split into two target functions
(to_stopped_by_watchpoint and to_stopped_data_address) to be confusing.  Chose
a new name to easily be able to keep the old deprecated implementations
working until its host maintainers can get to update them as I cannot even
compile some of the host files.

Asking if this is approved to rebase the hw-watchpoints fixes on top of this
patch.

This patch also changes the former sentence in the doc which I was not aware
of before as internally x86 was violating this rule:
	Then @value{GDBN} calls @code{target_stopped_data_address} exactly
	once.
But maybe if this rule is still valid linux_nat_stopped_data_address can be
dropped and I should rework the patchset including this patch instead.


> I cannot find the linux_nat_stopped_data_address that you are refering to,

[patch 2/4] Fix hw watchpoints: reordered / simultaneously hit [fixup #1]
http://sourceware.org/ml/gdb-patches/2009-10/msg00075.html


Thanks,
Jan


gdb/
	Introduce new target_thread_stopped_by_watchpoint.
	* amd64-linux-nat.c (amd64_linux_dr_set, amd64_linux_dr_set_control)
	(amd64_linux_dr_set_addr, amd64_linux_dr_reset_addr): New comments.
	(amd64_linux_dr_get_status): New parameter ptid, use it, new comment.
	* breakpoint.c (update_watchpoint): Extend the comment.
	(watchpoints_triggered): Drop the parameter ws, new parameter ptid.
	Call the new relay target_thread_stopped_by_watchpoint.  Move the state
	specific code to ...
	(watchpoints_triggered_no, watchpoints_triggered_yes_address_unknown)
	(watchpoints_triggered_yes_address_known): ... these new functions.
	* breakpoint.h (watchpoints_triggered): Update the prototype.
	* go32-nat.c (go32_get_dr6): New parameter ptid.
	* i386-darwin-nat.c (i386_darwin_dr_get_status): Likewise.
	* i386-linux-nat.c (i386_linux_dr_get, i386_linux_dr_set)
	(i386_linux_dr_set_control, i386_linux_dr_set_addr)
	(i386_linux_dr_reset_addr): New comments.
	(i386_linux_dr_get_status): New parameter ptid, use it, new comment.
	* i386-nat.c (i386_stopped_data_address): Rename to ...
	(i386_thread_stopped_by_watchpoint): ... this function, drop parameter
	ops, new parameter ptid, new return type.  Call i386_dr_low.get_status
	with new ptid.  Drop variables addr and rc.  Permit addr_p to be NULL.
	Drop redundant check of addr if maint_show_dr.
	(i386_stopped_by_watchpoint): Remove.
	(i386_use_watchpoints): Drop the initialization of
	to_stopped_by_watchpoint and to_stopped_data_address.  New
	initialization of to_thread_stopped_by_watchpoint.
	* i386-nat.h (struct i386_dr_low_type): Extend comments for
	set_control, set_addr, reset_addr and get_status.
	(struct i386_dr_low_type <get_status>): New parameter ptid.
	* i386bsd-nat.c (i386bsd_dr_get_status): New parameter ptid, use it.
	* i386bsd-nat.h (i386bsd_dr_get_status): New parameter ptid.
	* ia64-linux-nat.c (ia64_linux_stopped_data_address): Rename to ...
	(ia64_linux_thread_stopped_by_watchpoint): ... this function, drop
	parameter ops, new parameter ptid, use it, rename addr_p to
	data_address_p, new return type.  Move the regcache initialization
	later.  Permit data_address_p to be NULL.
	(ia64_linux_stopped_by_watchpoint): Remove.
	(_initialize_ia64_linux_nat): Drop the initialization of
	to_stopped_by_watchpoint and to_stopped_data_address.  New
	initialization of to_thread_stopped_by_watchpoint.
	* inf-ttrace.c (inf_ttrace_target): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.
	* infrun.c (handle_inferior_event <debug_infrun>): Rename the variable
	addr as data_address.  Convert the call of target_stopped_by_watchpoint
	and target_stopped_data_address to target_thread_stopped_by_watchpoint.
	(handle_inferior_event): Update the parameters of watchpoints_triggered.
	* mips-linux-nat.c: Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.  Rename to_stopped_data_address to
	deprecated_stopped_data_address.
	* nto-procfs.c (init_procfs_ops): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.
	* ppc-linux-nat.c (ppc_linux_stopped_data_address): Rename to ...
	(ppc_linux_thread_stopped_by_watchpoint): ... this function, drop
	parameter ops, new parameter ptid, use it, rename addr_p to
	data_address_p, new return type.  Permit data_address_p to be NULL.
	(ppc_linux_stopped_by_watchpoint): Remove.
	(_initialize_ppc_linux_nat): Drop the initialization of
	to_stopped_by_watchpoint and to_stopped_data_address.  New
	initialization of to_thread_stopped_by_watchpoint.
	* procfs.c (procfs_use_watchpoints): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.
	* remote-m32r-sdi.c (init_m32r_ops): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.  Rename to_stopped_data_address to
	deprecated_stopped_data_address.
	* remote-mips.c (_initialize_remote_mips): Rename
	to_stopped_by_watchpoint to deprecated_stopped_by_watchpoint.
	* remote.c (init_remote_ops): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.  Rename to_stopped_data_address to
	deprecated_stopped_data_address.
	* s390-nat.c (s390_stopped_by_watchpoint): Rename to ...
	(s390_thread_stopped_by_watchpoint): ... this function, new parameter
	ptid, use it, new parameter data_address_p, new return type, new
	variable tid, initialize it.  New FIXME comment on removing the trigger.
	(_initialize_s390_nat): Drop the initialization of
	to_stopped_by_watchpoint.  New initialization of
	to_thread_stopped_by_watchpoint.
	* score-tdep.c (score_stopped_by_watch): Rename
	to_stopped_by_watchpoint to deprecated_stopped_by_watchpoint.
	* target.c (debug_to_stopped_by_watchpoint)
	(debug_to_stopped_data_address): Remove.
	(update_current_target): Stop calling INHERIT and de_fault for
	to_stopped_data_address and to_stopped_by_watchpoint.  New comment for
	to_thread_stopped_by_watchpoint.
	(target_thread_stopped_by_watchpoint): New function.
	(setup_target_debug): Drop the initialization of
	to_stopped_by_watchpoint and to_stopped_data_address.
	* target.h (struct target_ops): Rename to_stopped_by_watchpoint to
	deprecated_stopped_by_watchpoint.  Rename to_stopped_data_address to
	deprecated_stopped_data_address.  New field
	to_thread_stopped_by_watchpoint.
	(target_stopped_by_watchpoint, target_stopped_data_address): Remove.
	(enum stopped_by_watchpoint, target_thread_stopped_by_watchpoint): New.
	* windows-nat.c (cygwin_get_dr6): New parameter ptid.
    
gdb/doc/
	* gdbint.texinfo (Watchpoints): Change STOPPED_BY_WATCHPOINT with
	target_stopped_data_address to target_thread_stopped_by_watchpoint,
	note the new return value.
	(target_stopped_data_address): Together with ...
	(STOPPED_BY_WATCHPOINT): ... merge and rename to ...
	(target_thread_stopped_by_watchpoint): ... a new node, describe the new
	parameters and return value.  Reference the update_watchpoint comment.
	(target_watchpoint_addr_within_range): Update the former reference to
	target_stopped_data_address.
	(Watchpoints and Threads): Rename former STOPPED_BY_WATCHPOINT.
	(i386_stopped_data_address): Rename to ...
	(i386_thread_stopped_by_watchpoint): ... this function.
	(i386_stopped_by_watchpoint): Remove.

--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -270,6 +270,8 @@ amd64_linux_dr_get (ptid_t ptid, int regnum)
   return value;
 }
 
+/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
+
 static void
 amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
 {
@@ -286,6 +288,8 @@ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
     perror_with_name (_("Couldn't write debug register"));
 }
 
+/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
+
 static void
 amd64_linux_dr_set_control (unsigned long control)
 {
@@ -297,6 +301,8 @@ amd64_linux_dr_set_control (unsigned long control)
     amd64_linux_dr_set (ptid, DR_CONTROL, control);
 }
 
+/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
+
 static void
 amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
 {
@@ -310,16 +316,20 @@ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
     amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
 }
 
+/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
+
 static void
 amd64_linux_dr_reset_addr (int regnum)
 {
   amd64_linux_dr_set_addr (regnum, 0);
 }
 
+/* Get DR_STATUS from only the one LWP PTID.  */
+
 static unsigned long
-amd64_linux_dr_get_status (void)
+amd64_linux_dr_get_status (ptid_t ptid)
 {
-  return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
+  return amd64_linux_dr_get (ptid, DR_STATUS);
 }
 
 static void
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -903,7 +903,46 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp,
    - Update the list of values that must be watched in B->loc.
 
    If the watchpoint disposition is disp_del_at_next_stop, then do nothing.
-   If this is local watchpoint that is out of scope, delete it.  */
+   If this is local watchpoint that is out of scope, delete it.
+
+   Even with `set breakpoint always-inserted on' the watchpoints are removed
+   + inserted on each stop here.  Normal breakpoints must never be removed
+   because they might be missed by a running thread when debugging in non-stop
+   mode.  On the other hand, hardware watchpoints (is_hardware_watchpoint;
+   processed here) are specific to each LWP since they are stored in each LWP's
+   hardware debug registers.  Therefore, such LWP must be stopped first in
+   order to be able to modify its hardware watchpoints.
+
+   Hardware watchpoints must be reset exactly once after being presented to the
+   user.  It cannot be done sooner, because it would reset the data used to
+   present the watchpoint hit to the user.  And it must not be done later
+   because it could display the same single watchpoint hit during multiple GDB
+   stops.  Note that the latter is relevant only to the hardware watchpoint
+   types bp_read_watchpoint and bp_access_watchpoint.  False hit by
+   bp_hardware_watchpoint is not user-visible - its hit is suppressed if the
+   memory content has not changed.
+
+   The following constraints influence the location where we can reset hardware
+   watchpoints:
+
+   * target_stopped_by_watchpoint and target_stopped_data_address are called
+     several times when GDB stops.
+
+   [linux]
+   * Multiple hardware watchpoints can be hit at the same time, causing GDB to
+     stop.  GDB only presents one hardware watchpoint hit at a time as the
+     reason for stopping, and all the other hits are presented later, one after
+     the other, each time the user requests the execution to be resumed.
+     Execution is not resumed for the threads still having pending hit event
+     stored in LWP_INFO->STATUS.  While the watchpoint is already removed from
+     the inferior on the first stop the thread hit event is kept being reported
+     from its cached value by linux_nat_stopped_data_address until the real
+     thread resume happens after the watchpoint gets presented and thus its
+     LWP_INFO->STATUS gets reset.
+
+   Therefore the hardware watchpoint hit can get safely reset on the watchpoint
+   removal from inferior.  */
+
 static void
 update_watchpoint (struct breakpoint *b, int reparse)
 {
@@ -2721,46 +2760,44 @@ bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */
   bs->print_it = print_it_normal;
   return bs;
 }
-
-/* The target has stopped with waitstatus WS.  Check if any hardware
-   watchpoints have triggered, according to the target.  */
 
-int
-watchpoints_triggered (struct target_waitstatus *ws)
+/* We were not stopped by a watchpoint.  Mark all watchpoints as not triggered.
+   */
+
+static void
+watchpoints_triggered_no (void)
 {
-  int stopped_by_watchpoint = target_stopped_by_watchpoint ();
-  CORE_ADDR addr;
   struct breakpoint *b;
 
-  if (!stopped_by_watchpoint)
-    {
-      /* We were not stopped by a watchpoint.  Mark all watchpoints
-	 as not triggered.  */
-      ALL_BREAKPOINTS (b)
-	if (b->type == bp_hardware_watchpoint
-	    || b->type == bp_read_watchpoint
-	    || b->type == bp_access_watchpoint)
-	  b->watchpoint_triggered = watch_triggered_no;
+  ALL_BREAKPOINTS (b)
+    if (b->type == bp_hardware_watchpoint
+	|| b->type == bp_read_watchpoint
+	|| b->type == bp_access_watchpoint)
+      b->watchpoint_triggered = watch_triggered_no;
+}
 
-      return 0;
-    }
+/* We were stopped by a watchpoint, but we don't know where.  Mark all
+   watchpoints as unknown.  */
 
-  if (!target_stopped_data_address (&current_target, &addr))
-    {
-      /* We were stopped by a watchpoint, but we don't know where.
-	 Mark all watchpoints as unknown.  */
-      ALL_BREAKPOINTS (b)
-	if (b->type == bp_hardware_watchpoint
-	    || b->type == bp_read_watchpoint
-	    || b->type == bp_access_watchpoint)
-	  b->watchpoint_triggered = watch_triggered_unknown;
+static void
+watchpoints_triggered_yes_address_unknown (void)
+{
+  struct breakpoint *b;
 
-      return stopped_by_watchpoint;
-    }
+  ALL_BREAKPOINTS (b)
+    if (b->type == bp_hardware_watchpoint
+	|| b->type == bp_read_watchpoint
+	|| b->type == bp_access_watchpoint)
+      b->watchpoint_triggered = watch_triggered_unknown;
+}
 
-  /* The target could report the data address.  Mark watchpoints
-     affected by this data address as triggered, and all others as not
-     triggered.  */
+/* The target could report the data address.  Mark watchpoints affected by this
+   data address as triggered, and all others as not triggered.  */
+
+static void
+watchpoints_triggered_yes_address_known (CORE_ADDR data_address)
+{
+  struct breakpoint *b;
 
   ALL_BREAKPOINTS (b)
     if (b->type == bp_hardware_watchpoint
@@ -2775,15 +2812,40 @@ watchpoints_triggered (struct target_waitstatus *ws)
 	  /* Exact match not required.  Within range is
 	     sufficient.  */
 	  if (target_watchpoint_addr_within_range (&current_target,
-						   addr, loc->address,
+						   data_address, loc->address,
 						   loc->length))
 	    {
 	      b->watchpoint_triggered = watch_triggered_yes;
 	      break;
 	    }
       }
+}
 
-  return 1;
+/* The target has stopped with waitstatus WS.  Check if any hardware
+   watchpoints have triggered, according to the target.  */
+
+int
+watchpoints_triggered (ptid_t ptid)
+{
+  CORE_ADDR data_address;
+
+  switch (target_thread_stopped_by_watchpoint (ptid, &data_address))
+    {
+    case stopped_by_watchpoint_no:
+      watchpoints_triggered_no ();
+      return 0;
+
+    case stopped_by_watchpoint_yes_address_unknown:
+      watchpoints_triggered_yes_address_unknown ();
+      return 1;
+
+    case stopped_by_watchpoint_yes_address_known:
+      watchpoints_triggered_yes_address_known (data_address);
+      return 1;
+    }
+
+  /* NOTREACHED */
+  return 0;
 }
 
 /* Possible return values for watchpoint_check (this can't be an enum
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -918,9 +918,10 @@ extern void remove_single_step_breakpoints (void);
 extern void *deprecated_insert_raw_breakpoint (struct gdbarch *, CORE_ADDR);
 extern int deprecated_remove_raw_breakpoint (struct gdbarch *, void *);
 
-/* Check if any hardware watchpoints have triggered, according to the
-   target.  */
-int watchpoints_triggered (struct target_waitstatus *);
+/* Check if any hardware watchpoints have triggered in thread PTID, according
+   to the target.  */
+
+int watchpoints_triggered (ptid_t ptid);
 
 /* Update BUF, which is LEN bytes read from the target address MEMADDR,
    by replacing any memory breakpoints with their shadowed contents.  */
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -667,11 +667,11 @@ section is mostly irrelevant for software watchpoints.
 
 When the inferior stops, @value{GDBN} tries to establish, among other
 possible reasons, whether it stopped due to a watchpoint being hit.
-It first uses @code{STOPPED_BY_WATCHPOINT} to see if any watchpoint
-was hit.  If not, all watchpoint checking is skipped.
+It uses @code{target_thread_stopped_by_watchpoint} to see if any watchpoint was
+hit.  If its returns @code{stopped_by_watchpoint_no}, all watchpoint checking
+is skipped.
 
-Then @value{GDBN} calls @code{target_stopped_data_address} exactly
-once.  This method returns the address of the watchpoint which
+This can also return the address of the watchpoint which
 triggered, if the target can determine it.  If the triggered address
 is available, @value{GDBN} compares the address returned by this
 method with each watched memory address in each active watchpoint.
@@ -733,24 +733,30 @@ defined by @file{breakpoint.h} as follows:
 @noindent
 These two macros should return 0 for success, non-zero for failure.
 
-@findex target_stopped_data_address
-@item target_stopped_data_address (@var{addr_p})
+@findex target_thread_stopped_by_watchpoint
+@item target_thread_stopped_by_watchpoint (@var{ptid}, @var{data_address_p})
 If the inferior has some watchpoint that triggered, place the address
 associated with the watchpoint at the location pointed to by
-@var{addr_p} and return non-zero.  Otherwise, return zero.  This
-is required for data-read and data-access watchpoints.  It is
-not required for data-write watchpoints, but @value{GDBN} uses
-it to improve handling of those also.
-
-@value{GDBN} will only call this method once per watchpoint stop,
-immediately after calling @code{STOPPED_BY_WATCHPOINT}.  If the
-target's watchpoint indication is sticky, i.e., stays set after
-resuming, this method should clear it.  For instance, the x86 debug
-control register has sticky triggered flags.
+@var{data_address_p} and return @code{stopped_by_watchpoint_yes_address_known}.
+If some watchpoint has triggered but the target does not know any specific
+location, return @code{stopped_by_watchpoint_yes_address_unknown}.  Otherwise,
+return @code{stopped_by_watchpoint_no}.  This is required for data-read and
+data-access watchpoints.  It is not required for data-write watchpoints, but
+@value{GDBN} uses it to improve handling of those also.
+
+See the comment at function @code{update_watchpoint} for more info.
+
+@value{GDBN} does not require the
+@code{stopped_by_watchpoint_yes_address_unknown} vs.
+@code{stopped_by_watchpoint_no} determination to be 100% correct, so if
+a target cannot determine for sure whether the inferior stopped due to
+a watchpoint, it could return @code{stopped_by_watchpoint_yes_address_unknown}
+``just in case''.
 
 @findex target_watchpoint_addr_within_range
 @item target_watchpoint_addr_within_range (@var{target}, @var{addr}, @var{start}, @var{length})
-Check whether @var{addr} (as returned by @code{target_stopped_data_address})
+Check whether @var{addr} (as returned in @code{data_address_p}
+from @code{target_thread_stopped_by_watchpoint})
 lies within the hardware-defined watchpoint region described by
 @var{start} and @var{length}.  This only needs to be provided if the
 granularity of a watchpoint is greater than one byte, i.e., if the
@@ -785,21 +791,6 @@ read or write.
 @item CANNOT_STEP_HW_WATCHPOINTS
 If this is defined to a non-zero value, @value{GDBN} will remove all
 watchpoints before stepping the inferior.
-
-@findex STOPPED_BY_WATCHPOINT
-@item STOPPED_BY_WATCHPOINT (@var{wait_status})
-Return non-zero if stopped by a watchpoint.  @var{wait_status} is of
-the type @code{struct target_waitstatus}, defined by @file{target.h}.
-Normally, this macro is defined to invoke the function pointed to by
-the @code{to_stopped_by_watchpoint} member of the structure (of the
-type @code{target_ops}, defined on @file{target.h}) that describes the
-target-specific operations; @code{to_stopped_by_watchpoint} ignores
-the @var{wait_status} argument.
-
-@value{GDBN} does not require the non-zero value returned by
-@code{STOPPED_BY_WATCHPOINT} to be 100% correct, so if a target cannot
-determine for sure whether the inferior stopped due to a watchpoint,
-it could return non-zero ``just in case''.
 @end table
 
 @subsection Watchpoints and Threads
@@ -822,11 +813,10 @@ threads.
 at a time, although multiple events can trigger simultaneously for
 multi-threaded programs.  When multiple events occur, @file{linux-nat.c}
 queues subsequent events and returns them the next time the program
-is resumed.  This means that @code{STOPPED_BY_WATCHPOINT} and
-@code{target_stopped_data_address} only need to consult the current
-thread's state---the thread indicated by @code{inferior_ptid}.  If
-two threads have hit watchpoints simultaneously, those routines
-will be called a second time for the second thread.
+is resumed.  This means that @code{thread_stopped_by_watchpoint} only needs to
+consult the specified thread's state.  If two threads have hit watchpoints
+simultaneously, that routine will be called a second time for the second
+thread.
 
 @subsection x86 Watchpoints
 @cindex x86 debug registers
@@ -921,26 +911,16 @@ watch a given region, and returns a non-zero value if that number is
 less than 4, the number of debug registers available to x86
 processors.
 
-@findex i386_stopped_data_address
-@item i386_stopped_data_address (@var{addr_p})
+@findex i386_thread_stopped_by_watchpoint
+@item i386_thread_stopped_by_watchpoint (@var{ptid}, @var{addr_p})
 The target function
-@code{target_stopped_data_address} is set to call this function.
+@code{target_thread_stopped_by_watchpoint} is set to call this function.
 This
 function examines the breakpoint condition bits in the DR6 Debug
 Status register, as returned by the @code{I386_DR_LOW_GET_STATUS}
 macro, and returns the address associated with the first bit that is
 set in DR6.
 
-@findex i386_stopped_by_watchpoint
-@item i386_stopped_by_watchpoint (void)
-The macro @code{STOPPED_BY_WATCHPOINT}
-is set to call this function.  The
-argument passed to @code{STOPPED_BY_WATCHPOINT} is ignored.  This
-function examines the breakpoint condition bits in the DR6 Debug
-Status register, as returned by the @code{I386_DR_LOW_GET_STATUS}
-macro, and returns true if any bit is set.  Otherwise, false is
-returned.
-
 @findex i386_insert_watchpoint
 @findex i386_remove_watchpoint
 @item i386_insert_watchpoint (@var{addr}, @var{len}, @var{type})
--- a/gdb/go32-nat.c
+++ b/gdb/go32-nat.c
@@ -791,7 +791,7 @@ go32_set_dr7 (unsigned long val)
    Here we just return the value stored in D_REGS, as we've got it
    from the last go32_wait call.  */
 static unsigned long
-go32_get_dr6 (void)
+go32_get_dr6 (ptid_t ptid)
 {
   return STATUS;
 }
--- a/gdb/i386-darwin-nat.c
+++ b/gdb/i386-darwin-nat.c
@@ -404,7 +404,7 @@ i386_darwin_dr_reset_addr (int regnum)
 }
 
 unsigned long
-i386_darwin_dr_get_status (void)
+i386_darwin_dr_get_status (ptid_t ptid)
 {
   return i386_darwin_dr_get (DR_STATUS);
 }
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -586,6 +586,8 @@ i386_linux_store_inferior_registers (struct target_ops *ops,
 
 static unsigned long i386_linux_dr[DR_CONTROL + 1];
 
+/* Get debug register REGNUM value from only the one LWP of PTID.  */
+
 static unsigned long
 i386_linux_dr_get (ptid_t ptid, int regnum)
 {
@@ -614,6 +616,8 @@ i386_linux_dr_get (ptid_t ptid, int regnum)
   return value;
 }
 
+/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
+
 static void
 i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
 {
@@ -630,6 +634,8 @@ i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
     perror_with_name (_("Couldn't write debug register"));
 }
 
+/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
+
 static void
 i386_linux_dr_set_control (unsigned long control)
 {
@@ -641,6 +647,8 @@ i386_linux_dr_set_control (unsigned long control)
     i386_linux_dr_set (ptid, DR_CONTROL, control);
 }
 
+/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
+
 static void
 i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
 {
@@ -654,16 +662,20 @@ i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
     i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
 }
 
+/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
+
 static void
 i386_linux_dr_reset_addr (int regnum)
 {
   i386_linux_dr_set_addr (regnum, 0);
 }
 
+/* Get DR_STATUS from only the one LWP PTID.  */
+
 static unsigned long
-i386_linux_dr_get_status (void)
+i386_linux_dr_get_status (ptid_t ptid)
 {
-  return i386_linux_dr_get (inferior_ptid, DR_STATUS);
+  return i386_linux_dr_get (ptid, DR_STATUS);
 }
 
 static void
--- a/gdb/i386-nat.c
+++ b/gdb/i386-nat.c
@@ -538,14 +538,12 @@ i386_region_ok_for_watchpoint (CORE_ADDR addr, int len)
    address associated with that watchpoint and return non-zero.  
    Otherwise, return zero.  */
 
-static int
-i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+static enum stopped_by_watchpoint
+i386_thread_stopped_by_watchpoint (ptid_t ptid, CORE_ADDR *addr_p)
 {
-  CORE_ADDR addr = 0;
   int i;
-  int rc = 0;
 
-  dr_status_mirror = i386_dr_low.get_status ();
+  dr_status_mirror = i386_dr_low.get_status (ptid);
 
   ALL_DEBUG_REGISTERS(i)
     {
@@ -560,25 +558,17 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 	     avoids false positives in windows-nat.c.  */
 	  && !I386_DR_VACANT (i))
 	{
-	  addr = dr_mirror[i];
-	  rc = 1;
+	  if (addr_p)
+	    *addr_p = dr_mirror[i];
 	  if (maint_show_dr)
-	    i386_show_dr ("watchpoint_hit", addr, -1, hw_write);
+	    i386_show_dr ("watchpoint_hit", dr_mirror[i], -1, hw_write);
+	  return stopped_by_watchpoint_yes_address_known;
 	}
     }
-  if (maint_show_dr && addr == 0)
+  if (maint_show_dr)
     i386_show_dr ("stopped_data_addr", 0, 0, hw_write);
 
-  if (rc)
-    *addr_p = addr;
-  return rc;
-}
-
-static int
-i386_stopped_by_watchpoint (void)
-{
-  CORE_ADDR addr = 0;
-  return i386_stopped_data_address (&current_target, &addr);
+  return stopped_by_watchpoint_no;
 }
 
 /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
@@ -668,8 +658,7 @@ i386_use_watchpoints (struct target_ops *t)
 
   t->to_can_use_hw_breakpoint = i386_can_use_hw_breakpoint;
   t->to_region_ok_for_hw_watchpoint = i386_region_ok_for_watchpoint;
-  t->to_stopped_by_watchpoint = i386_stopped_by_watchpoint;
-  t->to_stopped_data_address = i386_stopped_data_address;
+  t->to_thread_stopped_by_watchpoint = i386_thread_stopped_by_watchpoint;
   t->to_insert_watchpoint = i386_insert_watchpoint;
   t->to_remove_watchpoint = i386_remove_watchpoint;
   t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint;
--- a/gdb/i386-nat.h
+++ b/gdb/i386-nat.h
@@ -49,16 +49,16 @@ extern void i386_use_watchpoints (struct target_ops *);
    functions are:
 
       set_control              -- set the debug control (DR7)
-				  register to a given value
+				  register to a given value for all LWPs
 
       set_addr                 -- put an address into one debug
-				  register
+				  register for all LWPs
 
       reset_addr               -- reset the address stored in
-				  one debug register
+				  one debug register for all LWPs
 
       get_status               -- return the value of the debug
-				  status (DR6) register.
+				  status (DR6) register for LWP PTID
 
    Additionally, the native file should set the debug_register_length
    field to 4 or 8 depending on the number of bytes used for
@@ -69,7 +69,7 @@ struct i386_dr_low_type
     void (*set_control) (unsigned long);
     void (*set_addr) (int, CORE_ADDR);
     void (*reset_addr) (int);
-    unsigned long (*get_status) (void);
+    unsigned long (*get_status) (ptid_t ptid);
     int debug_register_length;
   };
 
--- a/gdb/i386bsd-nat.c
+++ b/gdb/i386bsd-nat.c
@@ -308,7 +308,7 @@ i386bsd_dr_reset_addr (int regnum)
 }
 
 unsigned long
-i386bsd_dr_get_status (void)
+i386bsd_dr_get_status (ptid_t ptid)
 {
   struct dbreg dbregs;
 
@@ -317,7 +317,7 @@ i386bsd_dr_get_status (void)
      way to fix this is to add the hardware breakpoint and watchpoint
      stuff to the target vector.  For now, just return zero if the
      ptrace call fails.  */
-  if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
+  if (ptrace (PT_GETDBREGS, PIDGET (ptid),
 	      (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
 #if 0
     perror_with_name (_("Couldn't read debug registers"));
--- a/gdb/i386bsd-nat.h
+++ b/gdb/i386bsd-nat.h
@@ -33,6 +33,6 @@ extern void i386bsd_dr_set_addr (int regnum, CORE_ADDR addr);
 
 extern void i386bsd_dr_reset_addr (int regnum);
 
-extern unsigned long i386bsd_dr_get_status (void);
+extern unsigned long i386bsd_dr_get_status (ptid_t ptid);
 
 #endif /* i386bsd-nat.h */
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -633,33 +633,29 @@ ia64_linux_new_thread (ptid_t ptid)
     enable_watchpoints_in_psr (ptid);
 }
 
-static int
-ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+static enum stopped_by_watchpoint
+ia64_linux_thread_stopped_by_watchpoint (ptid_t ptid, CORE_ADDR *data_address_p)
 {
   CORE_ADDR psr;
   struct siginfo *siginfo_p;
-  struct regcache *regcache = get_current_regcache ();
-
-  siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+  struct regcache *regcache;
+  
+  siginfo_p = linux_nat_get_siginfo (ptid);
 
   if (siginfo_p->si_signo != SIGTRAP
       || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
-    return 0;
+    return stopped_by_watchpoint_no;
+
+  regcache = get_thread_regcache (ptid);
 
   regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr);
   psr |= IA64_PSR_DD;	/* Set the dd bit - this will disable the watchpoint
                            for the next instruction */
   regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
 
-  *addr_p = (CORE_ADDR)siginfo_p->si_addr;
-  return 1;
-}
-
-static int
-ia64_linux_stopped_by_watchpoint (void)
-{
-  CORE_ADDR addr;
-  return ia64_linux_stopped_data_address (&current_target, &addr);
+  if (data_address_p)
+    *data_address_p = (uintptr_t) siginfo_p->si_addr;
+  return stopped_by_watchpoint_yes_address_known;
 }
 
 static int
@@ -831,15 +827,14 @@ _initialize_ia64_linux_nat (void)
      it again) if the "dd" (data debug fault disable) bit in the processor
      status word is set.
 
-     This PSR bit is set in ia64_linux_stopped_by_watchpoint when the
+     This PSR bit is set in ia64_linux_thread_stopped_by_watchpoint when the
      code there has determined that a hardware watchpoint has indeed
      been hit.  The CPU will then be able to execute one instruction
      without triggering a watchpoint. */
 
   t->to_have_steppable_watchpoint = 1;
   t->to_can_use_hw_breakpoint = ia64_linux_can_use_hw_breakpoint;
-  t->to_stopped_by_watchpoint = ia64_linux_stopped_by_watchpoint;
-  t->to_stopped_data_address = ia64_linux_stopped_data_address;
+  t->to_thread_stopped_by_watchpoint = ia64_linux_thread_stopped_by_watchpoint;
   t->to_insert_watchpoint = ia64_linux_insert_watchpoint;
   t->to_remove_watchpoint = ia64_linux_remove_watchpoint;
 
--- a/gdb/inf-ttrace.c
+++ b/gdb/inf-ttrace.c
@@ -1260,7 +1260,7 @@ inf_ttrace_target (void)
   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
-  t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
+  t->deprecated_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
   t->to_region_ok_for_hw_watchpoint =
     inf_ttrace_region_ok_for_hw_watchpoint;
   t->to_kill = inf_ttrace_kill;
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2837,21 +2837,28 @@ targets should add new threads to the thread list themselves in non-stop mode.")
     {
       struct regcache *regcache = get_thread_regcache (ecs->ptid);
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      CORE_ADDR data_address;
 
       fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
                           paddress (gdbarch, stop_pc));
-      if (target_stopped_by_watchpoint ())
+
+      switch (target_thread_stopped_by_watchpoint (ecs->ptid, &data_address))
 	{
-          CORE_ADDR addr;
-	  fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
+	case stopped_by_watchpoint_no:
+	  break;
 
-          if (target_stopped_data_address (&current_target, &addr))
-            fprintf_unfiltered (gdb_stdlog,
-                                "infrun: stopped data address = %s\n",
-                                paddress (gdbarch, addr));
-          else
-            fprintf_unfiltered (gdb_stdlog,
-                                "infrun: (no data address available)\n");
+	case stopped_by_watchpoint_yes_address_unknown:
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: stopped by watchpoint\n"
+			      "infrun: (no data address available)\n");
+	  break;
+
+	case stopped_by_watchpoint_yes_address_known:
+	  fprintf_unfiltered (gdb_stdlog,
+	                      "infrun: stopped by watchpoint\n"
+			      "infrun: stopped data address = %s\n",
+			      paddress (gdbarch, data_address));
+	  break;
 	}
     }
 
@@ -3099,7 +3106,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
   if (stepped_after_stopped_by_watchpoint)
     stopped_by_watchpoint = 0;
   else
-    stopped_by_watchpoint = watchpoints_triggered (&ecs->ws);
+    stopped_by_watchpoint = watchpoints_triggered (ecs->ptid);
 
   /* If necessary, step over this watchpoint.  We'll be back to display
      it in a moment.  */
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -708,7 +708,7 @@ mips_linux_can_use_hw_breakpoint (int type, int cnt, int ot)
   return (cnt == 0) ? 1 : 0;
 }
 
-/* Target to_stopped_by_watchpoint implementation.  Return 1 if
+/* Target deprecated_stopped_by_watchpoint implementation.  Return 1 if
    stopped by watchpoint.  The watchhi R and W bits indicate the watch
    register triggered. */
 
@@ -730,7 +730,7 @@ mips_linux_stopped_by_watchpoint (void)
   return 0;
 }
 
-/* Target to_stopped_data_address implementation.  Set the address
+/* Target deprecated_stopped_data_address implementation.  Set the address
    where the watch triggered (if known).  Return 1 if the address was
    known.  */
 
@@ -1074,8 +1074,8 @@ triggers a breakpoint or watchpoint."),
   t->to_can_use_hw_breakpoint = mips_linux_can_use_hw_breakpoint;
   t->to_remove_watchpoint = mips_linux_remove_watchpoint;
   t->to_insert_watchpoint = mips_linux_insert_watchpoint;
-  t->to_stopped_by_watchpoint = mips_linux_stopped_by_watchpoint;
-  t->to_stopped_data_address = mips_linux_stopped_data_address;
+  t->deprecated_stopped_by_watchpoint = mips_linux_stopped_by_watchpoint;
+  t->deprecated_stopped_data_address = mips_linux_stopped_data_address;
   t->to_region_ok_for_hw_watchpoint = mips_linux_region_ok_for_hw_watchpoint;
 
   t->to_read_description = mips_linux_read_description;
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -1413,7 +1413,7 @@ init_procfs_ops (void)
   procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
   procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
   procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
-  procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+  procfs_ops.deprecated_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
   procfs_ops.to_terminal_init = terminal_init_inferior;
   procfs_ops.to_terminal_inferior = terminal_inferior;
   procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1397,26 +1397,20 @@ ppc_linux_new_thread (ptid_t ptid)
   ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value);
 }
 
-static int
-ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+static enum stopped_by_watchpoint
+ppc_linux_thread_stopped_by_watchpoint (ptid_t ptid, CORE_ADDR *data_address_p)
 {
   struct siginfo *siginfo_p;
 
-  siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+  siginfo_p = linux_nat_get_siginfo (ptid);
 
   if (siginfo_p->si_signo != SIGTRAP
       || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
-    return 0;
+    return stopped_by_watchpoint_no;
 
-  *addr_p = (CORE_ADDR) (uintptr_t) siginfo_p->si_addr;
-  return 1;
-}
-
-static int
-ppc_linux_stopped_by_watchpoint (void)
-{
-  CORE_ADDR addr;
-  return ppc_linux_stopped_data_address (&current_target, &addr);
+  if (data_address_p)
+    *data_address_p = (uintptr_t) siginfo_p->si_addr;
+  return stopped_by_watchpoint_yes_address_known;
 }
 
 static int
@@ -1648,8 +1642,7 @@ _initialize_ppc_linux_nat (void)
   t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
   t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
   t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
-  t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
-  t->to_stopped_data_address = ppc_linux_stopped_data_address;
+  t->to_thread_stopped_by_watchpoint = ppc_linux_thread_stopped_by_watchpoint;
   t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
 
   t->to_read_description = ppc_linux_read_description;
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -5390,7 +5390,7 @@ procfs_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 void
 procfs_use_watchpoints (struct target_ops *t)
 {
-  t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+  t->deprecated_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
   t->to_insert_watchpoint = procfs_insert_watchpoint;
   t->to_remove_watchpoint = procfs_remove_watchpoint;
   t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint;
--- a/gdb/remote-m32r-sdi.c
+++ b/gdb/remote-m32r-sdi.c
@@ -1625,8 +1625,8 @@ init_m32r_ops (void)
   m32r_ops.to_can_use_hw_breakpoint = m32r_can_use_hw_watchpoint;
   m32r_ops.to_insert_watchpoint = m32r_insert_watchpoint;
   m32r_ops.to_remove_watchpoint = m32r_remove_watchpoint;
-  m32r_ops.to_stopped_by_watchpoint = m32r_stopped_by_watchpoint;
-  m32r_ops.to_stopped_data_address = m32r_stopped_data_address;
+  m32r_ops.deprecated_stopped_by_watchpoint = m32r_stopped_by_watchpoint;
+  m32r_ops.deprecated_stopped_data_address = m32r_stopped_data_address;
   m32r_ops.to_kill = m32r_kill;
   m32r_ops.to_load = m32r_load;
   m32r_ops.to_create_inferior = m32r_create_inferior;
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -3345,7 +3345,7 @@ _initialize_remote_mips (void)
   mips_ops.to_remove_breakpoint = mips_remove_breakpoint;
   mips_ops.to_insert_watchpoint = mips_insert_watchpoint;
   mips_ops.to_remove_watchpoint = mips_remove_watchpoint;
-  mips_ops.to_stopped_by_watchpoint = mips_stopped_by_watchpoint;
+  mips_ops.deprecated_stopped_by_watchpoint = mips_stopped_by_watchpoint;
   mips_ops.to_can_use_hw_breakpoint = mips_can_use_watchpoint;
   mips_ops.to_kill = mips_kill;
   mips_ops.to_load = mips_load;
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -8798,8 +8798,8 @@ Specify the serial device it is connected to\n\
   remote_ops.to_files_info = remote_files_info;
   remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
-  remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
-  remote_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_ops.deprecated_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_ops.deprecated_stopped_data_address = remote_stopped_data_address;
   remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
   remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
   remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
--- a/gdb/s390-nat.c
+++ b/gdb/s390-nat.c
@@ -253,35 +253,42 @@ struct watch_area
 
 static struct watch_area *watch_base = NULL;
 
-static int
-s390_stopped_by_watchpoint (void)
+static enum stopped_by_watchpoint
+s390_thread_stopped_by_watchpoint (ptid_t ptid, CORE_ADDR *data_address_p)
 {
   per_lowcore_bits per_lowcore;
   ptrace_area parea;
   int result;
+  int tid;
 
   /* Speed up common case.  */
   if (!watch_base)
-    return 0;
+    return stopped_by_watchpoint_no;
+
+  tid = TIDGET (ptid);
+  if (tid == 0)
+    tid = PIDGET (ptid);
 
   parea.len = sizeof (per_lowcore);
   parea.process_addr = (addr_t) & per_lowcore;
   parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
-  if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
+  if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
     perror_with_name (_("Couldn't retrieve watchpoint status"));
 
   result = (per_lowcore.perc_storage_alteration == 1
 	    && per_lowcore.perc_store_real_address == 0);
 
+  /* FIXME: To be done only in s390_remove_watchpoint.  */
   if (result)
     {
       /* Do not report this watchpoint again.  */
       memset (&per_lowcore, 0, sizeof (per_lowcore));
-      if (ptrace (PTRACE_POKEUSR_AREA, s390_inferior_tid (), &parea) < 0)
+      if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
 	perror_with_name (_("Couldn't clear watchpoint status"));
     }
 
-  return result;
+  return result ? stopped_by_watchpoint_yes_address_unknown
+		: stopped_by_watchpoint_no;
 }
 
 static void
@@ -408,7 +415,7 @@ _initialize_s390_nat (void)
   t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
   t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
   t->to_have_continuable_watchpoint = 1;
-  t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
+  t->to_thread_stopped_by_watchpoint = s390_thread_stopped_by_watchpoint;
   t->to_insert_watchpoint = s390_insert_watchpoint;
   t->to_remove_watchpoint = s390_remove_watchpoint;
 
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -70,7 +70,7 @@ score_stopped_by_watch (void)
 {
   if (strcmp (current_target.to_shortname, "sim") == 0)
       return soc_gh_stopped_by_watch ();
-  return (*current_target.to_stopped_by_watchpoint) ();
+  return (*current_target.deprecated_stopped_by_watchpoint) ();
 }
 
 int
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -124,10 +124,6 @@ static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
 
 static int debug_to_remove_watchpoint (CORE_ADDR, int, int);
 
-static int debug_to_stopped_by_watchpoint (void);
-
-static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
-
 static int debug_to_watchpoint_addr_within_range (struct target_ops *,
 						  CORE_ADDR, CORE_ADDR, int);
 
@@ -622,10 +618,9 @@ update_current_target (void)
       INHERIT (to_remove_hw_breakpoint, t);
       INHERIT (to_insert_watchpoint, t);
       INHERIT (to_remove_watchpoint, t);
-      INHERIT (to_stopped_data_address, t);
       INHERIT (to_have_steppable_watchpoint, t);
       INHERIT (to_have_continuable_watchpoint, t);
-      INHERIT (to_stopped_by_watchpoint, t);
+      /* Do not inherit to_thread_stopped_by_watchpoint.  */
       INHERIT (to_watchpoint_addr_within_range, t);
       INHERIT (to_region_ok_for_hw_watchpoint, t);
       INHERIT (to_terminal_init, t);
@@ -733,12 +728,6 @@ update_current_target (void)
   de_fault (to_remove_watchpoint,
 	    (int (*) (CORE_ADDR, int, int))
 	    return_minus_one);
-  de_fault (to_stopped_by_watchpoint,
-	    (int (*) (void))
-	    return_zero);
-  de_fault (to_stopped_data_address,
-	    (int (*) (struct target_ops *, CORE_ADDR *))
-	    return_zero);
   de_fault (to_watchpoint_addr_within_range,
 	    default_watchpoint_addr_within_range);
   de_fault (to_region_ok_for_hw_watchpoint,
@@ -2207,6 +2196,79 @@ target_mourn_inferior (void)
 		  "could not find a target to follow mourn inferiour");
 }
 
+enum stopped_by_watchpoint
+target_thread_stopped_by_watchpoint (ptid_t ptid, CORE_ADDR *data_address_p)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    {
+      enum stopped_by_watchpoint retval;
+
+      if (t->to_thread_stopped_by_watchpoint != NULL)
+	retval = t->to_thread_stopped_by_watchpoint (ptid, data_address_p);
+      /* Deprecated.  */
+      else if (t->deprecated_stopped_by_watchpoint != NULL)
+	{
+	  CORE_ADDR data_address;
+	  struct cleanup *old_chain = save_inferior_ptid ();
+
+	  inferior_ptid = ptid;
+
+	  if (!t->deprecated_stopped_by_watchpoint ())
+	    retval = stopped_by_watchpoint_no;
+	  else if (t->deprecated_stopped_data_address == NULL
+		   || !t->deprecated_stopped_data_address (t, &data_address))
+	    retval = stopped_by_watchpoint_yes_address_unknown;
+	  else
+	    {
+	      retval = stopped_by_watchpoint_yes_address_known;
+	      if (data_address_p)
+		*data_address_p = data_address;
+	    }
+
+	  do_cleanups (old_chain);
+	}
+      else
+	continue;
+
+      if (targetdebug)
+	{
+	  fprintf_unfiltered (gdb_stdlog,
+			      "target_thread_stopped_by_watchpoint (");
+	  if (TIDGET (ptid) != 0)
+	    fprintf_unfiltered (gdb_stdlog, "TID %ld", TIDGET (ptid));
+	  else
+	    fprintf_unfiltered (gdb_stdlog, "PID %d", PIDGET (ptid));
+	  fprintf_unfiltered (gdb_stdlog, ") = ");
+	  switch (retval)
+	    {
+	    case stopped_by_watchpoint_no:
+	      fprintf_unfiltered (gdb_stdlog, "stopped_by_watchpoint_no");
+	      break;
+	    case stopped_by_watchpoint_yes_address_unknown:
+	      fprintf_unfiltered (gdb_stdlog,
+				  "stopped_by_watchpoint_yes_address_unknown");
+	      break;
+	    case stopped_by_watchpoint_yes_address_known:
+	      fprintf_unfiltered (gdb_stdlog,
+				  "stopped_by_watchpoint_yes_address_known ");
+	      if (data_address_p)
+		fprintf_unfiltered (gdb_stdlog, "(%s)",
+				    paddress (target_gdbarch, *data_address_p));
+	      else
+		fprintf_unfiltered (gdb_stdlog, "<NULL>");
+	      break;
+	    }
+	  fprintf_unfiltered (gdb_stdlog, "\n");
+	}
+
+      return retval;
+    }
+
+  return stopped_by_watchpoint_no;
+}
+
 /* Look for a target which can describe architectural features, starting
    from TARGET.  If we find one, return its description.  */
 
@@ -3074,33 +3136,6 @@ debug_to_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 }
 
 static int
-debug_to_stopped_by_watchpoint (void)
-{
-  int retval;
-
-  retval = debug_target.to_stopped_by_watchpoint ();
-
-  fprintf_unfiltered (gdb_stdlog,
-		      "target_stopped_by_watchpoint () = %ld\n",
-		      (unsigned long) retval);
-  return retval;
-}
-
-static int
-debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr)
-{
-  int retval;
-
-  retval = debug_target.to_stopped_data_address (target, addr);
-
-  fprintf_unfiltered (gdb_stdlog,
-		      "target_stopped_data_address ([0x%lx]) = %ld\n",
-		      (unsigned long)*addr,
-		      (unsigned long)retval);
-  return retval;
-}
-
-static int
 debug_to_watchpoint_addr_within_range (struct target_ops *target,
 				       CORE_ADDR addr,
 				       CORE_ADDR start, int length)
@@ -3420,8 +3455,6 @@ setup_target_debug (void)
   current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint;
   current_target.to_insert_watchpoint = debug_to_insert_watchpoint;
   current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
-  current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
-  current_target.to_stopped_data_address = debug_to_stopped_data_address;
   current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
   current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
   current_target.to_terminal_init = debug_to_terminal_init;
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -395,10 +395,14 @@ struct target_ops
     int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
     int (*to_remove_watchpoint) (CORE_ADDR, int, int);
     int (*to_insert_watchpoint) (CORE_ADDR, int, int);
-    int (*to_stopped_by_watchpoint) (void);
+    enum stopped_by_watchpoint (*to_thread_stopped_by_watchpoint)
+      (ptid_t ptid, CORE_ADDR *data_address_p);
+    /* Deprecated, to be replaced by to_thread_stopped_by_watchpoint.  */
+    int (*deprecated_stopped_by_watchpoint) (void);
+    /* Deprecated, to be replaced by to_thread_stopped_by_watchpoint.  */
+    int (*deprecated_stopped_data_address) (struct target_ops *, CORE_ADDR *);
     int to_have_steppable_watchpoint;
     int to_have_continuable_watchpoint;
-    int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
     int (*to_watchpoint_addr_within_range) (struct target_ops *,
 					    CORE_ADDR, CORE_ADDR, int);
     int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int);
@@ -1126,8 +1130,15 @@ extern char *normal_pid_to_str (ptid_t ptid);
 /* Returns non-zero if we were stopped by a hardware watchpoint (memory read or
    write).  */
 
-#define target_stopped_by_watchpoint \
-   (*current_target.to_stopped_by_watchpoint)
+enum stopped_by_watchpoint
+  {
+    stopped_by_watchpoint_no,
+    stopped_by_watchpoint_yes_address_unknown,
+    stopped_by_watchpoint_yes_address_known
+  };
+
+extern enum stopped_by_watchpoint target_thread_stopped_by_watchpoint
+  (ptid_t ptid, CORE_ADDR *data_address_p);
 
 /* Non-zero if we have steppable watchpoints  */
 
@@ -1172,9 +1183,6 @@ extern char *normal_pid_to_str (ptid_t ptid);
 #define target_remove_hw_breakpoint(gdbarch, bp_tgt) \
      (*current_target.to_remove_hw_breakpoint) (gdbarch, bp_tgt)
 
-#define target_stopped_data_address(target, x) \
-    (*target.to_stopped_data_address) (target, x)
-
 #define target_watchpoint_addr_within_range(target, addr, start, length) \
   (*target.to_watchpoint_addr_within_range) (target, addr, start, length)
 
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -143,7 +143,7 @@ static void windows_kill_inferior (struct target_ops *);
 
 static void cygwin_set_dr (int i, CORE_ADDR addr);
 static void cygwin_set_dr7 (unsigned long val);
-static unsigned long cygwin_get_dr6 (void);
+static unsigned long cygwin_get_dr6 (ptid_t ptid);
 
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 /* Set if a signal was received from the debugged process */
@@ -2313,7 +2313,7 @@ cygwin_set_dr7 (unsigned long val)
    Here we just return the value stored in dr[6]
    by the last call to thread_rec for current_event.dwThreadId id.  */
 static unsigned long
-cygwin_get_dr6 (void)
+cygwin_get_dr6 (ptid_t ptid)
 {
   return (unsigned long) dr[6];
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]