Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Jul 2004 13:11:34 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 56616 for review
Message-ID:  <200407061311.i66DBYwI022037@repoman.freebsd.org>

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

Change 56616 by davidxu@davidxu_alona on 2004/07/06 13:10:38

	Use the new mechanism in ptrace to resume only one thread.
	Some cosmetic changes.

Affected files ...

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

Differences ...

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

@@ -49,6 +49,8 @@
 /* This module's target vector.  */
 static struct target_ops thread_db_ops;
 
+static struct target_ops base_ops;
+ 
 /* Pointer to the next function on the objfile event chain.  */
 static void (*target_new_objfile_chain) (struct objfile *objfile);
 
@@ -66,6 +68,11 @@
 /* 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;
+
+static CORE_ADDR single_step_inactive_thread_pc;
+
 /* Pointers to the libthread_db functions.  */
 
 static td_err_e (*td_init_p) (void);
@@ -101,11 +108,9 @@
 
 static td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step);
 
-static td_err_e (*td_ta_activated_p) (td_thragent_t *ta, int *activated);
+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_ta_tsd_iter_p) (const td_thragent_t *ta, td_key_iter_f *func,
-				 void *data);
-
 /* Prototypes for local functions.  */
 static void fbsd_thread_find_new_threads (void);
 
@@ -294,6 +299,7 @@
 
     case TD_OK:
       /* The thread library was detected.  Activate the thread_db target.  */
+      base_ops = current_target;
       push_target (&thread_db_ops);
       using_thread_db = 1;
 
@@ -365,6 +371,14 @@
       return ptrace (req, GET_LWP (ptid), 0, 0) == 0;
     }
 
+  /*
+   * For M:N thread, we need to tell UTS to set/unset single step
+   * flag at context switch time, the flag will be written into
+   * thread mailbox. This becauses some architecture may not have
+   * machine single step flag in ucontext, so we put the flag in mailbox,
+   * when the thread switches back, kse_switchin restores the single step
+   * state.
+   */
   td_thrhandle_t th;
   if (td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th) == 0)
     {
@@ -374,53 +388,96 @@
   return 0; 
 }
 
-static int
-resume_callback (struct thread_info *info, void *ta)
-{
-  single_step (info->ptid, 0);
-  return 0;
-}
-
 static void
 fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo)
 {
-  int resume_all, ret, pid;
   td_thrhandle_t th;
-  struct thread_info *ti;
-  
+  td_thrinfo_t ti;
+  ptid_t work_ptid;
+  int resume_all, ret;
+  long lwp;
+
 #if 0
-  printf_filtered("%s ptid=%d.%x.%x step=%d\n", __func__,
+  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));
 #endif
-
   if (proc_handle.pid == 0)
     {
       child_resume (ptid, step, signo);
       return;
     }
 
-  pid = PIDGET(ptid);
-  if (pid == -1 || !step)
+  if (GET_PID(ptid) != -1 && step != 0)
     {
-      pid = PIDGET (inferior_ptid);
-      resume_all = 1;
+      resume_all = 0;
+      work_ptid = ptid;
     }
   else
     {
-      resume_all = 0;
+      resume_all = 1;
+      work_ptid = inferior_ptid;
     }
 
-  if (PIDGET (ptid) == -1)
-    ptid = inferior_ptid;
+  /*
+   * Whether it is going to resume one thread or not,
+   * we always set/unset single step state for the thread according to
+   * step parameter.
+   */  
+  if (!single_step(work_ptid, step))
+    error ("single_step failed");
 
-  if (resume_all)
-      iterate_over_threads(resume_callback, 0);
+  lwp = 0;
+  if (!resume_all)
+    {
+      /* only resume one thread */
+      lwp = GET_LWP (work_ptid);
+      if (lwp == 0)
+        {
+          /* check a user thread */
+          ret = td_ta_map_id2thr_p (thread_agent,
+                   GET_THREAD(work_ptid), &th);
+          if (ret)
+            error(thread_db_err_str (ret)); 
+          ret = td_thr_get_info_p (&th, &ti);
+          if (ret)
+            error(thread_db_err_str (ret));
+          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.
+	   */
+	  if (lwp == 0)
+	    {
+              printf_filtered("resuming inactive thread\n");
+	      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;
+		  /* XXX
+		   * We need to give UTS to a hint to prefer scheduling
+		   * the thread.
+		   */
+                  insert_breakpoints ();
+                }
+            }
+        }
+    }
 
-  if (!single_step (ptid, step))
-     error ("single step failed");
+  if (lwp == 0)
+    lwp = proc_handle.pid;
 
-  if (ptrace (PT_CONTINUE, pid, (caddr_t)1,
-              target_signal_to_host(signo)) == -1)
+  if (ptrace (PT_CONTINUE, lwp, (caddr_t)1, target_signal_to_host(signo)))
     perror_with_name ("PT_CONTINUE");
 }
 
@@ -429,6 +486,8 @@
 {
   ptid_t ret;
   lwpid_t lwp;
+  CORE_ADDR stop_pc;
+  unsigned char buf;
 
   ret = child_ops.to_wait (ptid, ourstatus);
   if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
@@ -438,8 +497,29 @@
       ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret)));
       if (!in_thread_list (ret))
         add_thread (ret);
+      printf_filtered("signal=%d\n", ourstatus->value.sig);
+      /*
+       * 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;
+	  target_read_memory(stop_pc, &buf, 1); 
+	  printf_filtered("stop_pc=%x data:%x, breakpoint?:%d\n",
+			  stop_pc, buf, breakpoint_here_p(stop_pc));
+          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);
 }
 
@@ -455,22 +535,23 @@
 fbsd_lwp_fetch_registers (int regno)
 {
   gregset_t gregs;
+  fpregset_t fpregs;
   lwpid_t lwp;
 
+#if 0
   /* FIXME, is it possible ? */
   if (!IS_LWP (inferior_ptid))
     {
       child_ops.to_fetch_registers (regno);
       return;
     }
-
+#endif
   lwp = GET_LWP (inferior_ptid);
 
   if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
     error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno));
   supply_gregset (&gregs);
   
-  fpregset_t fpregs;
   if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
     error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno));
 
@@ -493,18 +574,21 @@
 
   err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
   if (err != TD_OK)
-    error ("Cannot find thread %ld: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot find thread %d: TID=%ld, %s",
+           pid_to_thread_id (inferior_ptid),           
+           GET_THREAD (inferior_ptid), thread_db_err_str (err));
 
   err = td_thr_getgregs_p (&th, gregset);
   if (err != TD_OK)
-    error ("Cannot fetch general-purpose registers for thread %ld: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot fetch general-purpose registers for thread %d: TID=%ld, %s",
+           pid_to_thread_id (inferior_ptid),
+           GET_THREAD (inferior_ptid), thread_db_err_str (err));
 
   err = td_thr_getfpregs_p (&th, &fpregset);
   if (err != TD_OK)
-    error ("Cannot get floating-point registers for thread %ld: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot get floating-point registers for thread %d: TID=%ld, %s",
+           pid_to_thread_id (inferior_ptid),
+           GET_THREAD (inferior_ptid), thread_db_err_str (err));
 
   supply_gregset (gregset);
   supply_fpregset (&fpregset);
@@ -513,6 +597,8 @@
 static void
 fbsd_lwp_store_registers (int regno)
 {
+  gregset_t gregs;
+  fpregset_t fpregs;
   lwpid_t lwp;
 
   /* FIXME, is it possible ? */
@@ -523,21 +609,18 @@
     }
 
   lwp = GET_LWP (inferior_ptid);
-
-  gregset_t gregs;
+  if (regno != -1)
+    if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
+      error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno));
 
-  if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
-    error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno));
-
   fill_gregset (&gregs, regno);
-
   if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1)
-    error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno));
+      error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno));
 
-  fpregset_t fpregs;
-  if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
-    error ("Cannot get lwp %d float registers: %s\n", lwp,
-           safe_strerror (errno));
+  if (regno != -1)
+    if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
+      error ("Cannot get lwp %d float registers: %s\n", lwp,
+             safe_strerror (errno));
 
   fill_fpregset (&fpregs, regno);
   if (ptrace (PT_SETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
@@ -561,29 +644,38 @@
 
   err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
   if (err != TD_OK)
-    error ("Cannot find thread %lx: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot find thread %d: TID=%ld, %s",
+           pid_to_thread_id (inferior_ptid),
+           GET_THREAD (inferior_ptid),
+           thread_db_err_str (err));
 
   if (regno != -1)
     {
-      char raw[MAX_REGISTER_SIZE];
+      char old_value[MAX_REGISTER_SIZE];
 
-      deprecated_read_register_gen (regno, raw);
-      fbsd_thread_fetch_registers (-1);
-      supply_register (regno, raw);
+      regcache_collect (regno, old_value);
+      err = td_thr_getgregs_p (&th, gregset);
+      if (err != TD_OK)
+        error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err));
+      err = td_thr_getfpregs_p (&th, &fpregset);
+      if (err != TD_OK)
+        error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err));
+      supply_register (regno, old_value);
     }
 
-  fill_gregset (gregset, -1);
-  fill_fpregset (&fpregset, -1);
+  fill_gregset (gregset, regno);
+  fill_fpregset (&fpregset, regno);
 
   err = td_thr_setgregs_p (&th, gregset);
   if (err != TD_OK)
-    error ("Cannot store general-purpose registers for thread %lx: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot store general-purpose registers for thread %d: TID=%d, %s",
+           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
+           thread_db_err_str (err));
   err = td_thr_setfpregs_p (&th, &fpregset);
   if (err != TD_OK)
-    error ("Cannot store floating-point registers for thread %lx: %s",
-           (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+    error ("Cannot store floating-point registers for thread %d: TID=%d, %s",
+           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
+           thread_db_err_str (err));
 }
 
 static void
@@ -609,8 +701,10 @@
 {
   if (proc_handle.pid == 0)
     {
-      /* The child process is now the actual multi-threaded
-         program.  Snatch its process ID...  */
+      /*
+       * The child process is now the actual multi-threaded
+       * program.  Snatch its process ID... 
+       */
       proc_handle.pid = GET_PID (ptid);
 
       fbsd_thread_find_new_threads ();
@@ -621,8 +715,10 @@
 static void
 fbsd_thread_mourn_inferior (void)
 {
-  /* Forget about the child's process ID.  We shouldn't need it
-     anymore.  */
+  /*
+   * Forget about the child's process ID.  We shouldn't need it
+   * anymore.
+   */
   proc_handle.pid = 0;
 
   child_ops.to_mourn_inferior ();
@@ -646,7 +742,7 @@
       if (err != TD_OK)
         return 0;
 
-      /* A zombie thread.  */
+      /* A zombie thread. */
       if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
         return 0;
 
@@ -657,17 +753,16 @@
       /* we sometimes are called with lwp == 0 */
       return 1;
     }
-  else
-    {
-      err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
-      /*
-       * if the lwp was already mapped to user thread, don't use it
-       * directly, please use user thread id instead.
-       */
-      if (err == TD_OK)
-        return 0;
-    }
-   
+
+  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+
+   /*
+    * if the lwp was already mapped to user thread, don't use it
+    * directly, please use user thread id instead.
+    */
+  if (err == TD_OK)
+    return 0;
+
   /* check lwp in kernel */
   return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0;
 }
@@ -721,23 +816,23 @@
 
       err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
       if (err != TD_OK)
-        error ("Cannot find thread %lx: %s",
+        error ("Cannot find thread, TID=%ld, %s",
                 GET_THREAD (ptid), thread_db_err_str (err));
 
       err = td_thr_get_info_p (&th, &ti);
       if (err != TD_OK)
-        error ("Cannot get thread info for thread %lx: %s",
+        error ("Cannot get thread info, TID=%ld, %s",
                GET_THREAD (ptid), thread_db_err_str (err));
 
       if (ti.ti_lid != 0)
         {
-          snprintf (buf, sizeof (buf), "Thread %lx (LWP %d)",
-                    (long) ti.ti_tid, ti.ti_lid);
+          snprintf (buf, sizeof (buf), "TID %ld (LWP %d)",
+                    GET_THREAD (ptid), ti.ti_lid);
         }
       else
         {
-          snprintf (buf, sizeof (buf), "Thread %lx (%s)",
-                   (long) ti.ti_tid, thread_db_state_str (ti.ti_state));
+          snprintf (buf, sizeof (buf), "TID %ld (%s)",
+                    GET_THREAD (ptid), thread_db_state_str (ti.ti_state));
         }
 
       return buf;
@@ -761,9 +856,8 @@
     name = "???";
   else
     name = DEPRECATED_SYMBOL_NAME (ms);
-                                                                                                                             
+
   printf_filtered ("Destructor %p <%s>\n", destructor, name);
-                                                                                                                             
   return 0;
 }
 
@@ -858,10 +952,6 @@
   if (td_thr_sstep_p == NULL)
     return 0;
 
-  td_ta_activated_p = dlsym (handle, "td_ta_activated");
-  if (td_ta_activated_p == NULL)
-    return 0;
-
   td_ta_tsd_iter_p = dlsym (handle, "td_ta_tsd_iter");
   if (td_ta_tsd_iter_p == NULL)
     return 0;
@@ -897,9 +987,9 @@
       target_new_objfile_hook = fbsd_thread_new_objfile;
     }
   else
-   {
+    {
       printf_filtered("%s: can not load %s.\n", __func__, LIBTHREAD_DB_SO);
-   }
+    }
 }
 
 /* proc service functions */
@@ -910,6 +1000,7 @@
 
   va_start (args, fmt);
   vfprintf_filtered (gdb_stderr, fmt, args);
+  va_end (args);
 }
 
 ps_err_e
@@ -956,7 +1047,7 @@
 ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset)
 {
   /* should check data modal, .core or process ? */
-  if (ptrace (PT_GETREGS, lwpid, (caddr_t)gregset, 0) == -1)
+  if (ptrace (PT_GETREGS, lwpid, (caddr_t) gregset, 0) == -1)
     return PS_ERR;
   return PS_OK;
 }
@@ -996,7 +1087,7 @@
 ps_lsetstep (struct ps_prochandle *ph, lwpid_t lwp, int step)
 {
   if (ptrace ((step ? PT_SETSTEP : PT_CLEARSTEP), lwp, 0, 0))
-      return PS_ERR;
+    return PS_ERR;
   return PS_OK;
 }
 



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