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