Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Apr 2005 09:31:16 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 74657 for review
Message-ID:  <200504070931.j379VGg2032997@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=74657

Change 74657 by davidxu@davidxu_celeron on 2005/04/07 09:30:51

	Add event reporting code.

Affected files ...

.. //depot/projects/davidxu_thread/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#5 edit

Differences ...

==== //depot/projects/davidxu_thread/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#5 (text+ko) ====

@@ -130,6 +130,11 @@
 static td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *);
 static td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *);
 
+static CORE_ADDR td_create_bp_addr;
+
+/* Location of the thread death event breakpoint.  */
+static CORE_ADDR td_death_bp_addr;
+
 /* Prototypes for local functions.  */
 static void fbsd_thread_find_new_threads (void);
 static int fbsd_thread_alive (ptid_t ptid);
@@ -319,7 +324,99 @@
   init_thread_list ();
 }
 
+static td_err_e
+enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp)
+{
+  td_notify_t notify;
+  td_err_e err;
+
+  /* Get the breakpoint address for thread EVENT.  */
+  err = td_ta_event_addr_p (thread_agent, event, &notify);
+  if (err != TD_OK)
+    return err;
+
+  /* Set up the breakpoint.  */
+  (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+					      (CORE_ADDR) notify.u.bptaddr,
+					      &current_target);
+  create_thread_event_breakpoint ((*bp));
+
+  return TD_OK;
+}
+
+static void
+enable_thread_event_reporting (void)
+{
+  td_thr_events_t events;
+  td_notify_t notify;
+  td_err_e err;
+
+  /* We cannot use the thread event reporting facility if these
+     functions aren't available.  */
+  if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
+      || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
+    return;
+
+  /* Set the process wide mask saying which events we're interested in.  */
+  td_event_emptyset (&events);
+  td_event_addset (&events, TD_CREATE);
+#if 0
+  /* FIXME: kettenis/2000-04-23: The event reporting facility is
+     broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
+     now.  */
+  td_event_addset (&events, TD_DEATH);
+#endif
+
+  err = td_ta_set_event_p (thread_agent, &events);
+  if (err != TD_OK)
+    {
+      warning ("Unable to set global thread event mask: %s",
+	       thread_db_err_str (err));
+      return;
+    }
+
+  /* Delete previous thread event breakpoints, if any.  */
+  remove_thread_event_breakpoints ();
+  td_create_bp_addr = 0;
+  td_death_bp_addr = 0;
+
+  /* Set up the thread creation event.  */
+  err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr);
+  if (err != TD_OK)
+    {
+      warning ("Unable to get location for thread creation breakpoint: %s",
+	       thread_db_err_str (err));
+      return;
+    }
+
+  /* Set up the thread death event.  */
+  err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr);
+  if (err != TD_OK)
+    {
+      warning ("Unable to get location for thread death breakpoint: %s",
+	       thread_db_err_str (err));
+      return;
+    }
+}
+
 static void
+disable_thread_event_reporting (void)
+{
+  td_thr_events_t events;
+
+  /* Set the process wide mask saying we aren't interested in any
+     events anymore.  */
+  td_event_emptyset (&events);
+  td_ta_set_event_p (thread_agent, &events);
+
+  /* Delete thread event breakpoints, if any.  */
+  remove_thread_event_breakpoints ();
+  td_create_bp_addr = 0;
+  td_death_bp_addr = 0;
+}
+
+
+static void
 fbsd_thread_new_objfile (struct objfile *objfile)
 {
   td_err_e err;
@@ -544,6 +641,85 @@
     perror_with_name ("PT_CONTINUE");
 }
 
+static void
+attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
+               const td_thrinfo_t *ti_p, int verbose)
+{
+  td_err_e err;
+
+  /* Add the thread to GDB's thread list.  */
+  add_thread (ptid);
+ 
+  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.  */
+
+  /* Enable thread event reporting for this thread. */
+  err = td_thr_event_enable_p (th_p, 1);
+  if (err != TD_OK)
+    error ("Cannot enable thread event reporting for %s: %s",
+           target_pid_to_str (ptid), thread_db_err_str (err));
+}
+
+static void
+detach_thread (ptid_t ptid, int verbose)
+{
+  if (verbose)
+    printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid));
+}
+
+static void
+check_event (ptid_t ptid)
+{
+  td_event_msg_t msg;
+  td_thrinfo_t ti;
+  td_err_e err;
+  CORE_ADDR stop_pc;
+  int loop = 0;
+
+  /* Bail out early if we're not at a thread event breakpoint.  */
+  stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK;
+  if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
+    return;
+
+  loop = 1;
+
+  do
+    {
+      err = td_ta_event_getmsg_p (thread_agent, &msg);
+      if (err != TD_OK)
+        {
+	  if (err == TD_NOMSG)
+	    return;
+          error ("Cannot get thread event message: %s", thread_db_err_str (err));
+        }
+      err = td_thr_get_info_p (msg.th_p, &ti);
+      if (err != TD_OK)
+        error ("Cannot get thread info: %s", thread_db_err_str (err));
+      ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
+      switch (msg.event)
+        {
+        case TD_CREATE:
+          /* We may already know about this thread, for instance when the
+             user has issued the `info threads' command before the SIGTRAP
+             for hitting the thread creation breakpoint was reported.  */
+          if (!in_thread_list (ptid))
+            attach_thread (ptid, msg.th_p, &ti, 1);
+          break;
+       case TD_DEATH:
+         if (!in_thread_list (ptid))
+           error ("Spurious thread death event.");
+         detach_thread (ptid, 1);
+         break;
+       default:
+          error ("Spurious thread event.");
+       }
+    }
+  while (loop);
+}
+
 static ptid_t
 fbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 {
@@ -554,6 +730,8 @@
   ret = child_ops.to_wait (ptid, ourstatus);
   if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
     {
+      if (ourstatus->value.sig == TARGET_SIGNAL_TRAP)
+        check_event(ptid);
       lwp = get_current_lwp (GET_PID(ret));
       ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret)));
       if (!in_thread_list (ret))
@@ -567,7 +745,7 @@
         {
           delete_thread (inferior_ptid);
           inferior_ptid = ret;
-       }
+        }
     }
 
   return (ret);
@@ -1180,6 +1358,13 @@
       return 0;
     }
 
+  /* These are not essential.  */
+  td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
+  td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
+  td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
+  td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
+  td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
+  
   return 1;
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200504070931.j379VGg2032997>