PERFORCE change 57039 for review

David Xu davidxu at FreeBSD.org
Sat Jul 10 20:55:01 PDT 2004


http://perforce.freebsd.org/chv.cgi?CH=57039

Change 57039 by davidxu at davidxu_alona on 2004/07/11 03:54:31

	Implement ps_lstop/ps_lcontinue. Use td_thr_dbsuspend/td_thr_dbresume
	to suspend/resume thread, yeah! M:N thread debugging works now.

Affected files ...

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

Differences ...

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

@@ -68,11 +68,9 @@
 /* Connection to the libthread_db library.  */
 static td_thragent_t *thread_agent;
 
-/* The inactive M:N thread gdb is trying to single step it */
-static ptid_t single_step_inactive_thread;
+/* The last thread we are single stepping */
+static ptid_t last_single_step_thread;
 
-static CORE_ADDR single_step_inactive_thread_pc;
-
 /* Pointers to the libthread_db functions.  */
 
 static td_err_e (*td_init_p) (void);
@@ -111,6 +109,9 @@
 static td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta,
 				 td_key_iter_f *func, void *data);
 
+static td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *);
+static td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *);
+
 /* Prototypes for local functions.  */
 static void fbsd_thread_find_new_threads (void);
 
@@ -362,6 +363,18 @@
   child_ops.to_detach (args, from_tty);
 }
 
+static int
+suspend_thread_callback (const td_thrhandle_t *th_p, void *data)
+{
+  return td_thr_dbsuspend_p (th_p);
+}
+
+static int
+resume_thread_callback (const td_thrhandle_t *th_p, void *data)
+{
+  return td_thr_dbresume_p (th_p);
+}
+
 static void
 fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo)
 {
@@ -369,17 +382,19 @@
   td_thrinfo_t ti;
   ptid_t work_ptid;
   int resume_all, ret;
-  long lwp;
+  long lwp, thvalid = 0;
 
 #if 0
   printf_filtered("%s ptid=%ld.%ld.%ld step=%d\n", __func__,
 	GET_PID(ptid), GET_LWP(ptid), GET_THREAD(ptid), step);
   printf_filtered("%s inferior_ptid=%ld.%ld.%ld\n", __func__,
-	GET_PID(inferior_ptid), GET_LWP(inferior_ptid), GET_THREAD(inferior_ptid));
+	GET_PID(inferior_ptid), GET_LWP(inferior_ptid),
+	GET_THREAD(inferior_ptid));
 #endif
+
   if (proc_handle.pid == 0)
     {
-      child_resume (ptid, step, signo);
+      base_ops.to_resume (ptid, step, signo);
       return;
     }
 
@@ -416,30 +431,8 @@
       ret = td_thr_get_info_p (&th, &ti);
       if (ret)
         error (thread_db_err_str (ret));
+      thvalid = 1;
       lwp = ti.ti_lid;
-      /*
-       * if we are single stepping an inactive M:N thread,
-       * we insert all breakpoints, and resume all threads,
-       * the inactive thread may or may not be scheduled to
-       * run, but if it runs, it may hit a breakpoint and
-       * becomes the current event thread, after it hit a
-       * breakpoint, the thread will stay in kernel until
-       * debugger resumes it. In that case, gdb will single
-       * step it again, but because it was already an active
-       * thread, we can use ptrace to resume it just as 1:1
-       * thread. XXX This may not be needed, because gdb
-       * seems not switch away from event thread when resuming.
-       */
-       if (lwp == 0)
-         {
-           if (breakpoint_here_p (read_pc_pid (work_ptid)) !=
-	                          no_breakpoint_here) 
-             {
-               single_step_inactive_thread_pc = read_pc_pid (work_ptid);
-               single_step_inactive_thread = work_ptid;
-               insert_breakpoints ();
-             }
-         }
     }
 
   if (lwp)
@@ -448,13 +441,43 @@
       if (ptrace (req, (pid_t) lwp, (caddr_t) 1, target_signal_to_host(signo)))
         perror_with_name ("PT_SETSTEP/PT_CLEARSTEP");
     }
+
+  if (!ptid_equal (last_single_step_thread, null_ptid))
+    {
+       ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL,
+          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+          TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+      if (ret != TD_OK)
+        error ("resume error: %s", thread_db_err_str (ret));
+    }
+
+  if (!resume_all)
+    {
+      ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL,
+          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+          TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+      if (ret != TD_OK)
+        error ("suspend error: %s", thread_db_err_str (ret));
+      last_single_step_thread = work_ptid;
+    }
   else
-    resume_all = 1;
+    last_single_step_thread = null_ptid;
 
-  if (resume_all)
-    lwp = proc_handle.pid;
+  if (thvalid)
+    {
+      ret = td_thr_dbresume_p (&th);
+      if (ret != TD_OK)
+        error ("resume error: %s", thread_db_err_str (ret));
+    }
+  else
+    {
+      /* it is not necessary, put it here for completness */
+      ret = ptrace(PT_RESUME, lwp, 0, 0);
+    }
 
-  if (ptrace (PT_CONTINUE, (pid_t) lwp, (caddr_t)1, target_signal_to_host(signo)))
+  /* now continue the process, suspended thread wont run */
+  if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1,
+	      target_signal_to_host(signo)))
     perror_with_name ("PT_CONTINUE");
 }
 
@@ -473,25 +496,8 @@
       ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret)));
       if (!in_thread_list (ret))
         add_thread (ret);
-      /*
-       * if we previously single stepping inactive threads,
-       * the inactive threads now becomes active,
-       * we should tell gdb to ignore the event and resume
-       * thread again.
-       */
-      if (ourstatus->value.sig == TARGET_SIGNAL_TRAP)
-        {
-          stop_pc = read_pc_pid (ret) - DECR_PC_AFTER_BREAK;
-          if (ptid_equal(ret, single_step_inactive_thread) &&
-              stop_pc == single_step_inactive_thread_pc)
-            {
-	      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-            }
-	}
     }
 
-  single_step_inactive_thread = minus_one_ptid;
-  single_step_inactive_thread_pc = 0;
   return (ret);
 }
 
@@ -921,6 +927,14 @@
   if (td_ta_tsd_iter_p == NULL)
     return 0;
 
+  td_thr_dbsuspend_p = dlsym (handle, "td_thr_dbsuspend");
+  if (td_thr_dbsuspend_p == NULL)
+    return 0;
+
+  td_thr_dbresume_p = dlsym (handle, "td_thr_dbresume");
+  if (td_thr_dbresume_p == NULL)
+    return 0;
+
   /* Initialize the library.  */
   err = td_init_p ();
   if (err != TD_OK)
@@ -1061,6 +1075,18 @@
   return PS_OK;
 }
 
+ps_err_e
+ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid)
+{
+  return (ptrace (lwpid, PT_SUSPEND, 0, 0) == 0);
+}
+
+ps_err_e
+ps_lcontinue(struct ps_prochandle *ph, lwpid_t lwpid)
+{
+  return (ptrace (lwpid, PT_RESUME, 0, 0) == 0);
+}
+
 pid_t
 ps_getpid (struct ps_prochandle *ph)
 {


More information about the p4-projects mailing list