Date: Sun, 18 Jul 2004 13:34:29 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 57628 for review Message-ID: <200407181334.i6IDYTWl090214@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=57628 Change 57628 by davidxu@davidxu_alona on 2004/07/18 13:34:11 Rewrite fbsd_thread_resume. Use ptrace to control LWP, when single stepping a thread, we don't use td_thr_dbsuspend or td_thr_dbresume, I think those two functions are used by user on command line to suspend/resume thread, do not try to use them internally, it may involve too much thing not related to single stepping. because we now bind thread in kernel if the thread generates a SIGTRAP, we are safe to single step it without bothering UTS which may can not run when process stops. Current, I still use PT_SUSPEND PT_RESUME, I think we may need change ptrace code to let PT_CONTINUE/PT_STEP resume only one LWP, TBD... Affected files ... .. //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#14 edit Differences ... ==== //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#14 (text+ko) ==== @@ -70,7 +70,7 @@ static td_thragent_t *thread_agent; /* The last thread we are single stepping */ -static ptid_t last_single_step_thread; +static lwpid_t last_single_step_lwp; /* Pointers to the libthread_db functions. */ @@ -316,7 +316,6 @@ gdb_assert (proc_handle.pid == 0); keep_thread_db = 1; } - /* We can only poke around if there actually is a child process. If there is no child process alive, postpone the steps below until one has been created. */ @@ -383,7 +382,7 @@ td_thrinfo_t ti; ptid_t work_ptid; int resume_all, ret; - long lwp, thvalid = 0; + long lwp; #if 0 printf_filtered("%s ptid=%ld.%ld.%ld step=%d\n", __func__, @@ -399,7 +398,7 @@ return; } - if (GET_PID(ptid) != -1 && step != 0) + if (GET_PID (ptid) != -1 && step != 0) { resume_all = 0; work_ptid = ptid; @@ -432,49 +431,59 @@ ret = td_thr_get_info_p (&th, &ti); if (ret) error (thread_db_err_str (ret)); - thvalid = 1; lwp = ti.ti_lid; } + if (!resume_all && lwp == 0) + { + error ("sorry this version of FreeBSD can not resume inactivated thread"); + } + if (lwp) { int req = step ? PT_SETSTEP : PT_CLEARSTEP; - if (ptrace (req, (pid_t) lwp, (caddr_t) 1, target_signal_to_host(signo))) + if (ptrace (req, (pid_t) lwp, 0, 0)) perror_with_name ("PT_SETSTEP/PT_CLEARSTEP"); } - if (!ptid_equal (last_single_step_thread, null_ptid)) + int nlwps = ptrace (PT_GETNUMLWPS, proc_handle.pid, 0, 0); + if (nlwps == -1) + perror_with_name ("PT_GETNUMLWPS"); + lwpid_t *lwps = malloc (nlwps * sizeof(lwpid_t)); + nlwps = ptrace (PT_GETLWPLIST, proc_handle.pid, (caddr_t)lwps, nlwps); + if (nlwps == -1) { - 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)); + perror_with_name ("PT_GETLWPLIST"); + free (lwps); } - if (!resume_all) + int i; + if (last_single_step_lwp != 0) { - 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; + /* resume all threads if ever suspend them */ + for (i = 0; i < nlwps; ++i) + { + if (ptrace (PT_RESUME, lwps[i], 0, 0)) + perror_with_name ("PT_SUSPEND"); + } } - else - last_single_step_thread = null_ptid; - if (thvalid) + if (!resume_all) { - ret = td_thr_dbresume_p (&th); - if (ret != TD_OK) - error ("resume error: %s", thread_db_err_str (ret)); + for (i = 0; i < nlwps; ++i) + { + if (lwps[i] == lwp) + continue; + if (ptrace (PT_SUSPEND, lwps[i], 0, 0)) + perror_with_name ("PT_SUSPEND"); + } + last_single_step_lwp = lwp; } else - { - /* it is not necessary, put it here for completness */ - ret = ptrace(PT_RESUME, lwp, 0, 0); - } + last_single_step_lwp = 0; + + free (lwps); +/* ret = ptrace(PT_RESUME, lwp, 0, 0); */ /* now continue the process, suspended thread wont run */ if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1, @@ -496,6 +505,17 @@ ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret))); if (!in_thread_list (ret)) add_thread (ret); + /* this is a hack, if an event won't cause gdb to stop, for example, + SIGARLM, gdb resumes the process immediatly without setting + inferior_ptid to the new thread returned here, this is a bug + because inferior_ptid may already not exist there, and passing + a none existing thread to fbsd_thread_resume causes error, this + should be treated as a bug of gdb. */ + if (!fbsd_thread_alive (inferior_ptid)) + { + delete_thread (inferior_ptid); + inferior_ptid = ret; + } } return (ret);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407181334.i6IDYTWl090214>