Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Jeff Johnston <jjohnstn@redhat.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: drow@false.org, cagney@gnu.org, gdb-patches@sources.redhat.com
Subject: Re: [RFA]: Watchpoints per thread patch
Date: Thu, 04 Nov 2004 18:25:00 -0000	[thread overview]
Message-ID: <418A741C.4080306@redhat.com> (raw)
In-Reply-To: <01c4bca9$Blat.v2.2.2$adcffb00@zahav.net.il>

[-- Attachment #1: Type: text/plain, Size: 6455 bytes --]

Eli Zaretskii wrote:
>>Date: Wed, 27 Oct 2004 18:36:14 -0400
>>From: Jeff Johnston <jjohnstn@redhat.com>
>>Cc: Andrew Cagney <cagney@gnu.org>, gdb-patches@sources.redhat.com
>>
>>The attached patch is the rework of my original attempt.  It no longer uses 
>>configuration or magic defines.  Per Mark's suggestion, it uses an observer to 
>>handle inserting watchpoints on a new thread and only the low-level code knows 
>>about inserting/removing watchpoints on all threads.
>>
>>Ok to commit?
> 
> 
> A few comments:
> 
> 
>>+/* External function to insert all existing watchpoints on a newly
>>+   attached thread.  IWPFN is a callback function to perform
>>+   the target insert watchpoint.  This function is used to support
>>+   platforms whereby a watchpoint must be inserted/removed on each
>>+   individual thread (e.g. ia64-linux and s390-linux).  For
>>+   ia64 and s390 linux, this function is called via a new thread
>>+   observer.  */
> 
> 
> In this comment, the word "whereby" should be replaced by "where", I
> think.
>

Ok, done.

> 
>>--- target.h	8 Oct 2004 20:29:55 -0000	1.65
>>+++ target.h	27 Oct 2004 21:43:51 -0000
>>@@ -178,6 +178,15 @@ extern char *target_signal_to_name (enum
>> /* Given a name (SIGHUP, etc.), return its signal.  */
>> enum target_signal target_signal_from_name (char *);
>> \f
>>+
>>+/* Watchpoint specification.  */
>>+struct target_watchpoint
>>+  {
>>+    CORE_ADDR addr;
>>+    int len;
>>+    int type;
>>+  };
>>+
> 
> 
> Why do we put on target.h, which is a general header, a definition of
> a struct used only on certain platforms?
> 

I have moved this to linux-nat.h and renamed it struct linux_watchpoint.

> 
>>--- doc/observer.texi	1 Sep 2004 17:59:37 -0000	1.8
>>+++ doc/observer.texi	27 Oct 2004 21:43:51 -0000
>>@@ -95,3 +95,7 @@ inferior, and before any information on 
>> The specified shared library has been discovered to be unloaded.
>> @end deftypefun
>> 
>>+@deftypefun void new_thread (ptid_t @var{ptid})
>>+A new thread has been attached to.
> 
> 
> "A new thread has been attached" to what?  The description of the
> observer should at least reference the argument @var{ptid}.
>

I have changed the definition to be more meaningful now that it is being used 
generically by all.

On Thu, Oct 28, 2004 at 03:47:22PM -0400, Jeff Johnston wrote:

 >> Daniel Jacobowitz wrote:
 >
 >>> >On Wed, Oct 27, 2004 at 07:17:13PM -0400, Jeff Johnston wrote:
 >>> >
 >>
 >>>> >>Were you thinking of add_thread()?  If so, we would have to move the
 >>>> >>calls to add_thread so they never occur before an attach because the
 >>>> >>low-level observers will need the thread already attached.
 >>
 >>> >
 >>> >
 >>> >Oh, that's a good point.  Do you think that's a reasonable change to
 >>> >make?
 >>> >
 >
 >>

Daniel, I have moved the observer notification to add_thread as suggested.  To 
do this, I had to move a few things in attach_thread.  As well, I had to add 
another part of my full patch in because the ptid that add_thread knows about is 
in the wrong format (pid, 0, tid).  The low-level insert watchpoint code needs 
the lwp so I have added in my target_get_lwp change.  I realize you have plans 
to change how the ptid is kept, but until that is fleshed out, this change is 
required.  I used a call-back to allow breakpoint.c which knows how to handle 
watchpoints to communicate with the low-level linux code that knows how to 
insert/remove a watchpoint.

I have tested on ia64 and s390 linux.  The ia64 requires another patch to make 
it pass the watchthreads.exp test.  S390 linux can't pass that test without 
additional hardware support, however, I will note that s390 is properly 
recognizing hardware watchpoints on threads which is a major step forward.

Ok to commit?

2004-11-04  Jeff Johnston  <jjohnstn@redhat.com>

         * breakpoint.c (insert_watchpoints_for_new_thread): New function.
         (print_it_typical): Do not issue an error for bp_thread_event
         if a subsequent event is on the chain.
         * breakpoint.h (insert_watchpoints_for_new_thread): New prototype.
         * ia64-linux-nat.c (ia64_linux_insert_one_watchpoint): New function.
         (ia64_linux_insert_watchpoint_callback): Ditto.
         (ia64_linux_insert_watchpoint): Change to iterate through lwps
         and insert the specified watchpoint per thread.
         (ia64_stopped_data_address): Call target_get_lwp to ensure
         the ptid has its lwp field filled in.
         (ia64_linux_remove_one_watchpoint): New function.
         (ia64_linux_remove_watchpoint_callback): Ditto.
         (ia64_linux_remove_watchpoint): Change to iterate through lwps and
         remove the specified watchpoint for each thread.
         (ia64_linux_new_thread): New thread observer.
         (_initialize_ia64_linux_nat): New function.  Initialize
         new thread observer.
         * linux-nat.h (struct linux_watchpoint): New structure.
         * thread-db.c (attach_thread): Add the thread after attaching
         to it.  Before allocating the thread private info area, check
         to see if it has already been allocated.
         (thread_db_get_info): Allocate a thread private info area if
         one doesn't already exist.
         (init_thread_db_ops): Point to_get_lwp to lwp_from_thread function.
         * thread.c (add_thread): Notify any observers of a new thread event.
         * s390-nat.c (s390_tid): New function.
         (s390_inferior_tid): Change to call s390_tid.
         (s390_remove_one_watchpoint): New function.
         (s390_remove_watchpoint_callback): Ditto.
         (s390_remove_watchpoint): Change to iterate through lwps and
         remove the specified watchpoint for each thread.
         (s390_insert_one_watchpoint): New function.
         (s390_insert_watchpoint_callback): Ditto.
         (s390_insert_watchpoint): Change to iterate through lwps and
         insert the specified watchpoint on each thread.
         (s390_new_thread): New thread observer.
         (_initialize_s390_nat): New function.  Initialize
         new thread observer.
         * target.c (return_ptid): New static function.
         (update_current_target): Add support for new to_get_lwp.
         (init_dummy_target): Ditto.
         * target.h (struct target_ops): Add to_get_lwp.
         (target_get_lwp): New macro.


doc/ChangeLog:

2004-11-04  Jeff Johnston  <jjohnstn@redhat.com>

         * observer.texi (new_thread): New observer.






[-- Attachment #2: newwatchthreads3.patch --]
[-- Type: text/plain, Size: 20750 bytes --]

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.184
diff -u -p -r1.184 breakpoint.c
--- breakpoint.c	29 Oct 2004 20:23:04 -0000	1.184
+++ breakpoint.c	4 Nov 2004 18:19:11 -0000
@@ -748,6 +748,91 @@ insert_catchpoint (struct ui_out *uo, vo
   return 0;
 }
 
+/* External function to insert all existing watchpoints on a newly
+   attached thread.  IWPFN is a callback function to perform
+   the target insert watchpoint.  This function is used to support
+   platforms where a watchpoint must be inserted/removed on each
+   individual thread (e.g. ia64-linux and s390-linux).  For
+   ia64 and s390 linux, this function is called via a new thread
+   observer.  */
+int
+insert_watchpoints_for_new_thread (ptid_t new_thread, 
+				   insert_watchpoint_ftype *iwpfn)
+{
+  struct bp_location *b;
+  int val = 0;
+  int return_val = 0;
+  struct ui_file *tmp_error_stream = mem_fileopen ();
+  make_cleanup_ui_file_delete (tmp_error_stream);
+
+  /* Explicitly mark the warning -- this will only be printed if
+     there was an error.  */
+  fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+
+  ALL_BP_LOCATIONS (b)
+    {
+      /* Skip disabled breakpoints.  */
+      if (!breakpoint_enabled (b->owner))
+	continue;
+
+      /* For every active watchpoint, we need to insert the watchpoint on 
+         the new thread.  */
+      if ((b->loc_type == bp_loc_hardware_watchpoint
+	   || b->owner->type == bp_watchpoint))
+	{
+	  struct value *v = b->owner->val_chain;
+
+	  /* Look at each value on the value chain.  */
+	  for (; v; v = v->next)
+	    {
+	      /* If it's a memory location, and GDB actually needed
+		 its contents to evaluate the expression, then we
+		 must watch it.  */
+	      if (VALUE_LVAL (v) == lval_memory
+		  && ! VALUE_LAZY (v))
+		{
+		  struct type *vtype = check_typedef (VALUE_TYPE (v));
+		  
+		  /* We only watch structs and arrays if user asked
+		     for it explicitly, never if they just happen to
+		     appear in the middle of some value chain.  */
+		  if (v == b->owner->val_chain
+		      || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+			  && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+		    {
+		      CORE_ADDR addr;
+		      int len, type;
+		      
+		      addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+		      len = TYPE_LENGTH (VALUE_TYPE (v));
+		      type = hw_write;
+		      if (b->owner->type == bp_read_watchpoint)
+			type = hw_read;
+		      else if (b->owner->type == bp_access_watchpoint)
+			type = hw_access;
+		      val = (*iwpfn) (new_thread, addr, len, type); 
+		    }
+		}
+	    }
+	}
+
+      if (val)
+	return_val = val;
+    }
+
+  /* Failure to insert a watchpoint on any memory value in the
+     value chain brings us here.  */
+  if (return_val)
+    {
+      fprintf_unfiltered (tmp_error_stream,
+			  "%s\n",
+			  "Could not insert hardware watchpoints on new thread."); 
+      target_terminal_ours_for_output ();
+      error_stream (tmp_error_stream);
+    }
+  return return_val;
+}
+
 /* Helper routine: free the value chain for a breakpoint (watchpoint).  */
 
 static void free_valchain (struct bp_location *b)
@@ -2122,8 +2207,13 @@ print_it_typical (bpstat bs)
       break;
 
     case bp_thread_event:
-      /* Not sure how we will get here. 
-	 GDB should not stop for these breakpoints.  */
+      /* We can only get here legitimately if something further on the bs 
+	 list has caused the stop status to be noisy.  A valid example
+	 of this is a new thread event and a software watchpoint have
+	 both occurred.  */
+      if (bs->next)
+        return PRINT_UNKNOWN;
+
       printf_filtered ("Thread Event Breakpoint: gdb should not stop!\n");
       return PRINT_NOTHING;
       break;
Index: breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.34
diff -u -p -r1.34 breakpoint.h
--- breakpoint.h	13 May 2004 16:39:11 -0000	1.34
+++ breakpoint.h	4 Nov 2004 18:19:11 -0000
@@ -663,6 +663,12 @@ extern void tbreak_command (char *, int)
 
 extern int insert_breakpoints (void);
 
+/* The following provides a callback mechanism to insert watchpoints
+   for a new thread.  This is needed, for example, on ia64 linux.  */
+typedef int (insert_watchpoint_ftype) (ptid_t, CORE_ADDR, int, int);
+extern int insert_watchpoints_for_new_thread (ptid_t ptid,
+					      insert_watchpoint_ftype *fn);
+
 extern int remove_breakpoints (void);
 
 /* This function can be used to physically insert eventpoints from the
Index: ia64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ia64-linux-nat.c,v
retrieving revision 1.26
diff -u -p -r1.26 ia64-linux-nat.c
--- ia64-linux-nat.c	13 Oct 2004 21:40:41 -0000	1.26
+++ ia64-linux-nat.c	4 Nov 2004 18:19:11 -0000
@@ -39,6 +39,8 @@
 
 #include <asm/ptrace_offsets.h>
 #include <sys/procfs.h>
+#include "observer.h"
+#include "linux-nat.h"
 
 /* Prototypes for supply_gregset etc. */
 #include "gregset.h"
@@ -559,8 +561,9 @@ is_power_of_2 (int val)
   return onecount <= 1;
 }
 
-int
-ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
+/* Internal routine to insert one watchpoint for a specified thread.  */
+static int
+ia64_linux_insert_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
 {
   int idx;
   long dbr_addr, dbr_mask;
@@ -606,8 +609,38 @@ ia64_linux_insert_watchpoint (ptid_t pti
   return 0;
 }
 
+/* Internal callback routine which can be used via iterate_over_lwps
+   to insert a specific watchpoint from all active threads.  */
+static int
+ia64_linux_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return ia64_linux_insert_one_watchpoint (lwp->ptid, args->addr,
+		 		     	   args->len, args->type);
+}
+
+/* Insert a watchpoint for all threads.  */
 int
-ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
+ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+  args.type = rw;
+
+  /* For ia64, watchpoints must be inserted/removed on each thread so
+     we iterate over the lwp list.  */
+  if (iterate_over_lwps (&ia64_linux_insert_watchpoint_callback, &args))
+    return -1;
+
+  return 0;
+}
+
+/* Internal routine to remove one watchpoint for a specified thread.  */
+static int
+ia64_linux_remove_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
 {
   int idx;
   long dbr_addr, dbr_mask;
@@ -630,13 +663,41 @@ ia64_linux_remove_watchpoint (ptid_t pti
   return -1;
 }
 
+/* Internal callback routine which can be used via iterate_over_lwps
+   to remove a specific watchpoint from all active threads.  */
+static int
+ia64_linux_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return ia64_linux_remove_one_watchpoint (lwp->ptid, args->addr,
+		 		     	   args->len);
+}
+
+/* Remove a watchpoint for all threads.  */
+int
+ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+
+  /* For ia64, watchpoints must be inserted/removed on each thread so
+     we iterate over the lwp list.  */
+  if (iterate_over_lwps (&ia64_linux_remove_watchpoint_callback, &args))
+    return -1;
+
+  return 0;
+}
+
 int
 ia64_linux_stopped_data_address (CORE_ADDR *addr_p)
 {
   CORE_ADDR psr;
   int tid;
   struct siginfo siginfo;
-  ptid_t ptid = inferior_ptid;
+  ptid_t ptid = target_get_lwp (inferior_ptid);
 
   tid = TIDGET(ptid);
   if (tid == 0)
@@ -674,3 +735,31 @@ ia64_linux_xfer_unwind_table (struct tar
 {
   return syscall (__NR_getunwind, readbuf, len);
 }
+
+/* Internal callback for insert_watchpoints_for_new_thread to call.
+   The PTID will be in the thread-level format and must be
+   translated to the lwp-level format before calling
+   ia64_linux_insert_one_watchpoint to insert any watchpoint.  */
+static int
+ia64_linux_insert_watchpoint_for_thread (ptid_t ptid, CORE_ADDR addr, 
+		                         int len, int rw)
+{
+  ptid_t lwp_ptid = target_get_lwp (ptid);
+  return ia64_linux_insert_one_watchpoint (lwp_ptid, addr, len, rw);
+}
+  
+/* Observer function for a new thread attach.  We need to insert
+   existing watchpoints on the new thread.  */
+static void
+ia64_linux_new_thread (ptid_t ptid)
+{
+  insert_watchpoints_for_new_thread (ptid, 
+		  		     &ia64_linux_insert_watchpoint_for_thread);
+}
+
+void
+_initialize_ia64_linux_nat (void)
+{
+  observer_attach_new_thread (ia64_linux_new_thread);
+}
+    
Index: linux-nat.h
===================================================================
RCS file: /cvs/src/src/gdb/linux-nat.h,v
retrieving revision 1.6
diff -u -p -r1.6 linux-nat.h
--- linux-nat.h	29 Mar 2004 18:07:14 -0000	1.6
+++ linux-nat.h	4 Nov 2004 18:19:11 -0000
@@ -63,6 +63,14 @@ struct lwp_info
   struct lwp_info *next;
 };
 
+/* Watchpoint description.  */
+struct linux_watchpoint
+{
+  CORE_ADDR addr;
+  int len;
+  int type;
+};
+
 /* Read/write to target memory via the Linux kernel's "proc file
    system".  */
 struct mem_attrib;
Index: s390-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-nat.c,v
retrieving revision 1.12
diff -u -p -r1.12 s390-nat.c
--- s390-nat.c	18 Feb 2004 04:17:35 -0000	1.12
+++ s390-nat.c	4 Nov 2004 18:19:12 -0000
@@ -27,6 +27,8 @@
 #include "inferior.h"
 
 #include "s390-tdep.h"
+#include "linux-nat.h"
+#include "observer.h"
 
 #include <asm/ptrace.h>
 #include <sys/ptrace.h>
@@ -112,18 +114,32 @@ fill_fpregset (fpregset_t *regp, int reg
 			      ((char *)regp) + regmap_fpregset[i]);
 }
 
-/* Find the TID for the current inferior thread to use with ptrace.  */
+/* Find the TID for use with ptrace.  */
 static int
-s390_inferior_tid (void)
+s390_tid (ptid_t ptid)
 {
   /* GNU/Linux LWP ID's are process ID's.  */
-  int tid = TIDGET (inferior_ptid);
+  int tid = TIDGET (ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+    {
+      /* In some cases, we have a thread-level format ptid which
+         must be converted to an lwp-level format ptid.  */
+      ptid_t lwp_ptid = target_get_lwp (ptid);
+      tid = TIDGET (lwp_ptid);
+      if (tid == 0)
+        tid = PIDGET (lwp_ptid); /* Not a threaded program.  */
+    }
 
   return tid;
 }
 
+/* Find the TID for the current inferior thread to use with ptrace.  */
+static int
+s390_inferior_tid (void)
+{
+  return s390_tid (inferior_ptid);
+}
+
 /* Fetch all general-purpose registers from process/thread TID and
    store their values in GDB's register cache.  */
 static void
@@ -269,9 +285,9 @@ s390_stopped_by_watchpoint (void)
 }
 
 static void
-s390_fix_watch_points (void)
+s390_fix_watch_points (ptid_t ptid)
 {
-  int tid = s390_inferior_tid ();
+  int tid = s390_tid (ptid);
 
   per_struct per_info;
   ptrace_area parea;
@@ -308,8 +324,9 @@ s390_fix_watch_points (void)
     perror_with_name ("Couldn't modify watchpoint status");
 }
 
-int
-s390_insert_watchpoint (CORE_ADDR addr, int len)
+/* Insert a specified watchpoint on a specified thread.  */
+static int
+s390_insert_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int type)
 {
   struct watch_area *area = xmalloc (sizeof (struct watch_area));
   if (!area)
@@ -321,12 +338,36 @@ s390_insert_watchpoint (CORE_ADDR addr, 
   area->next = watch_base;
   watch_base = area;
 
-  s390_fix_watch_points ();
+  s390_fix_watch_points (ptid);
   return 0;
 }
 
+/* Callback routine to use with iterate_over_lwps to insert a specified
+   watchpoint on all threads.  */
+static int
+s390_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return s390_insert_one_watchpoint (lwp->ptid, args->addr, args->len, 0);
+}
+
+/* Insert a specified watchpoint on all threads.  */
 int
-s390_remove_watchpoint (CORE_ADDR addr, int len)
+s390_insert_watchpoint (CORE_ADDR addr, int len)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+  /* For the S390, a watchpoint must be inserted/removed for each
+     thread so we iterate over the list of existing lwps.  */
+  return iterate_over_lwps (&s390_insert_watchpoint_callback, &args);
+}
+
+/* Remove a specified watchpoint from a specified thread.  */
+static int
+s390_remove_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
 {
   struct watch_area *area, **parea;
 
@@ -346,10 +387,32 @@ s390_remove_watchpoint (CORE_ADDR addr, 
   *parea = area->next;
   xfree (area);
 
-  s390_fix_watch_points ();
+  s390_fix_watch_points (ptid);
   return 0;
 }
 
+/* Callback routine to use with iterate_over_lwps to remove a specified
+   watchpoint from all threads.  */
+static int
+s390_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return s390_remove_one_watchpoint (lwp->ptid, args->addr, args->len);
+}
+
+/* Remove a specified watchpoint from all threads.  */
+int
+s390_remove_watchpoint (CORE_ADDR addr, int len)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+  /* For the S390, a watchpoint must be inserted/removed for each
+     thread so we iterate over the list of existing lwps.  */
+  return iterate_over_lwps (&s390_remove_watchpoint_callback, &args);
+}
 
 int
 kernel_u_size (void)
@@ -357,3 +420,18 @@ kernel_u_size (void)
   return sizeof (struct user);
 }
 
+/* New thread observer that inserts all existing watchpoints on the
+   new thread.  */
+static void
+s390_new_thread (ptid_t ptid)
+{
+  insert_watchpoints_for_new_thread (ptid, &s390_insert_one_watchpoint);
+}
+
+void
+_initialize_s390_nat (void)
+{
+  observer_attach_new_thread (s390_new_thread);
+}
+
+
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.90
diff -u -p -r1.90 target.c
--- target.c	8 Oct 2004 20:29:55 -0000	1.90
+++ target.c	4 Nov 2004 18:19:12 -0000
@@ -61,6 +61,8 @@ static int return_one (void);
 
 static int return_minus_one (void);
 
+static ptid_t return_ptid (ptid_t ptid);
+
 void target_ignore (void);
 
 static void target_command (char *, int);
@@ -430,6 +432,7 @@ update_current_target (void)
       INHERIT (to_notice_signals, t);
       INHERIT (to_thread_alive, t);
       INHERIT (to_find_new_threads, t);
+      INHERIT (to_get_lwp, t);
       INHERIT (to_pid_to_str, t);
       INHERIT (to_extra_thread_info, t);
       INHERIT (to_stop, t);
@@ -606,6 +609,9 @@ update_current_target (void)
   de_fault (to_find_new_threads, 
 	    (void (*) (void)) 
 	    target_ignore);
+  de_fault (to_get_lwp,
+            (ptid_t (*) (ptid_t))
+            return_ptid);
   de_fault (to_extra_thread_info, 
 	    (char *(*) (struct thread_info *)) 
 	    return_zero);
@@ -1541,6 +1547,12 @@ return_minus_one (void)
   return -1;
 }
 
+static ptid_t
+return_ptid (ptid_t ptid)
+{
+  return ptid;
+}
+
 /*
  * Resize the to_sections pointer.  Also make sure that anyone that
  * was holding on to an old value of it gets updated.
@@ -1793,6 +1805,7 @@ init_dummy_target (void)
   dummy_target.to_find_memory_regions = dummy_find_memory_regions;
   dummy_target.to_make_corefile_notes = dummy_make_corefile_notes;
   dummy_target.to_xfer_partial = default_xfer_partial;
+  dummy_target.to_get_lwp = return_ptid;
   dummy_target.to_magic = OPS_MAGIC;
 }
 \f
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.65
diff -u -p -r1.65 target.h
--- target.h	8 Oct 2004 20:29:55 -0000	1.65
+++ target.h	4 Nov 2004 18:19:12 -0000
@@ -372,6 +372,7 @@ struct target_ops
     void (*to_notice_signals) (ptid_t ptid);
     int (*to_thread_alive) (ptid_t ptid);
     void (*to_find_new_threads) (void);
+    ptid_t (*to_get_lwp) (ptid_t ptid);
     char *(*to_pid_to_str) (ptid_t);
     char *(*to_extra_thread_info) (struct thread_info *);
     void (*to_stop) (void);
@@ -802,6 +803,10 @@ extern void target_load (char *arg, int 
 #define target_find_new_threads() \
      (*current_target.to_find_new_threads) (); \
 
+/* Get the lwp for a thread.  */
+#define target_get_lwp(ptid) \
+     (*current_target.to_get_lwp) (ptid); \
+
 /* Make target stop in a continuable fashion.  (For instance, under
    Unix, this should act like SIGSTOP).  This function is normally
    used by GUIs to implement a stop button.  */
Index: thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/thread-db.c,v
retrieving revision 1.46
diff -u -p -r1.46 thread-db.c
--- thread-db.c	8 Oct 2004 20:29:56 -0000	1.46
+++ thread-db.c	4 Nov 2004 18:19:12 -0000
@@ -34,6 +34,7 @@
 #include "target.h"
 #include "regcache.h"
 #include "solib-svr4.h"
+#include "observer.h"
 
 #ifdef HAVE_GNU_LIBC_VERSION_H
 #include <gnu/libc-version.h>
@@ -333,6 +334,17 @@ thread_db_get_info (struct thread_info *
 {
   td_err_e err;
 
+  /* Allocate a private area if needed.  This can occur for ia64 or
+     s390 linux which must insert breakpoints on newly found threads.
+     The observer for a new thread event will be called on an add_thread
+     call before the private area has been set up and will need to
+     get the lwp for the new ptid using this function.  */
+  if (!thread_info->private)
+    {
+      thread_info->private = xmalloc (sizeof (struct private_thread_info));
+      memset (thread_info->private, 0, sizeof (struct private_thread_info));
+    }
+
   if (thread_info->private->ti_valid)
     return &thread_info->private->ti;
 
@@ -746,14 +758,6 @@ attach_thread (ptid_t ptid, const td_thr
 
   check_thread_signals ();
 
-  /* Add the thread to GDB's thread list.  */
-  tp = add_thread (ptid);
-  tp->private = xmalloc (sizeof (struct private_thread_info));
-  memset (tp->private, 0, sizeof (struct private_thread_info));
-
-  if (verbose)
-    printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
-
   if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
     return;			/* A zombie thread -- do not attach.  */
 
@@ -762,6 +766,21 @@ attach_thread (ptid_t ptid, const td_thr
   ATTACH_LWP (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0);
 #endif
 
+  /* Add the thread to GDB's thread list.  
+     We do this after attaching so any observers of a new
+     thread event can perform PTRACE operations on the thread
+     if needed.  An observer may end up allocating the
+     private info area, so check first.  */
+  tp = add_thread (ptid);
+  if (!tp->private)
+    {
+      tp->private = xmalloc (sizeof (struct private_thread_info));
+      memset (tp->private, 0, sizeof (struct private_thread_info));
+    }
+
+  if (verbose)
+    printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
+
   /* Enable thread event reporting for this thread.  */
   err = td_thr_event_enable_p (th_p, 1);
   if (err != TD_OK)
@@ -1346,6 +1365,7 @@ init_thread_db_ops (void)
   thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
   thread_db_ops.to_thread_alive = thread_db_thread_alive;
   thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
+  thread_db_ops.to_get_lwp = lwp_from_thread;
   thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
   thread_db_ops.to_stratum = thread_stratum;
   thread_db_ops.to_has_thread_control = tc_schedlock;
Index: thread.c
===================================================================
RCS file: /cvs/src/src/gdb/thread.c,v
retrieving revision 1.39
diff -u -p -r1.39 thread.c
--- thread.c	29 Oct 2004 20:23:13 -0000	1.39
+++ thread.c	4 Nov 2004 18:19:12 -0000
@@ -130,6 +130,10 @@ add_thread (ptid_t ptid)
   tp->num = ++highest_thread_num;
   tp->next = thread_list;
   thread_list = tp;
+
+  /* Inform any observers of the new thread.  */
+  observer_notify_new_thread (ptid);
+
   return tp;
 }
 
Index: doc/observer.texi
===================================================================
RCS file: /cvs/src/src/gdb/doc/observer.texi,v
retrieving revision 1.8
diff -u -p -r1.8 observer.texi
--- doc/observer.texi	1 Sep 2004 17:59:37 -0000	1.8
+++ doc/observer.texi	4 Nov 2004 18:19:12 -0000
@@ -95,3 +95,7 @@ inferior, and before any information on 
 The specified shared library has been discovered to be unloaded.
 @end deftypefun
 
+@deftypefun void new_thread (ptid_t @var{ptid})
+A new thread described by @var{ptid} has been detected by gdb.
+@end deftypefun
+

  reply	other threads:[~2004-11-04 18:25 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-19 23:57 Jeff Johnston
2004-10-20  5:04 ` Eli Zaretskii
2004-10-20 11:03 ` Mark Kettenis
2004-10-20 16:21   ` Jeff Johnston
2004-10-20 17:27 ` Andrew Cagney
2004-10-20 17:30   ` Daniel Jacobowitz
2004-10-27 22:36     ` Jeff Johnston
2004-10-27 22:41       ` Daniel Jacobowitz
2004-10-27 23:17         ` Jeff Johnston
2004-10-28 13:33           ` Daniel Jacobowitz
2004-10-28 19:47             ` Jeff Johnston
2004-10-28 19:52               ` Daniel Jacobowitz
2004-10-28 20:13                 ` Jeff Johnston
2004-10-28  4:55       ` Eli Zaretskii
2004-11-04 18:25         ` Jeff Johnston [this message]
2004-11-04 21:21           ` Eli Zaretskii
2004-11-05  4:49           ` Daniel Jacobowitz
2004-11-05 16:52             ` Andrew Cagney
2004-11-05 18:29               ` Daniel Jacobowitz
2004-11-08 21:33                 ` Andrew Cagney
2004-11-09  1:04                   ` Daniel Jacobowitz
2004-11-09  2:20                     ` Andrew Cagney
2004-11-09  2:33                       ` Daniel Jacobowitz
2004-11-09  4:53                         ` Eli Zaretskii
2004-11-09 15:11                         ` Andrew Cagney
2004-11-09 18:41                           ` Daniel Jacobowitz
2004-11-11 21:22                             ` Andrew Cagney
2004-11-09 19:06                         ` Jeff Johnston
2004-11-09 19:31                           ` Daniel Jacobowitz
2004-11-09 20:24                             ` Jim Blandy
2004-11-10  0:02                               ` Jeff Johnston
2004-11-10 14:39                                 ` Jim Blandy
2004-11-11 21:23                                 ` Andrew Cagney
2004-11-09 20:48                             ` Jeff Johnston
2004-11-09 20:50                               ` Daniel Jacobowitz
2004-11-10 19:45                               ` Eli Zaretskii
2004-11-10 22:08                                 ` Jeff Johnston
2004-11-10 19:43                             ` Eli Zaretskii
2004-10-20 19:27   ` Eli Zaretskii
2004-11-05 11:49 Ulrich Weigand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=418A741C.4080306@redhat.com \
    --to=jjohnstn@redhat.com \
    --cc=cagney@gnu.org \
    --cc=drow@false.org \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox