PERFORCE change 56956 for review
David Xu
davidxu at FreeBSD.org
Sat Jul 10 06:47:15 PDT 2004
http://perforce.freebsd.org/chv.cgi?CH=56956
Change 56956 by davidxu at davidxu_alona on 2004/07/10 13:46:17
Check TMDF_DONOTRUNUSER when being debugged, reformat
thread_user_enter. Add thread_continued(), the function
should be called after debugger resumed the process, it
is used to force all KSEs to schedule upcall after a
suspension.
Affected files ...
.. //depot/projects/davidxu_ksedbg/src/sys/kern/kern_kse.c#4 edit
.. //depot/projects/davidxu_ksedbg/src/sys/sys/proc.h#5 edit
Differences ...
==== //depot/projects/davidxu_ksedbg/src/sys/kern/kern_kse.c#4 (text+ko) ====
@@ -161,6 +161,13 @@
ptrace_single_step(td);
else
ptrace_clear_single_step(td);
+ if (tmbx.tm_dflags & TMDF_DONOTRUNUSER) {
+ mtx_lock_spin(&sched_lock);
+ /* fuword can block, check again */
+ if (td->td_upcall)
+ ku->ku_flags |= KUF_DOUPCALL;
+ mtx_unlock_spin(&sched_lock);
+ }
}
}
return ((error == 0) ? EJUSTRETURN : error);
@@ -835,18 +842,8 @@
td->td_flags |= (TDF_USTATCLOCK|TDF_ASTPENDING);
mtx_unlock_spin(&sched_lock);
td->td_uuticks++;
- } else {
- if (td->td_mailbox != NULL)
- td->td_usticks++;
- else {
- /* XXXKSE
- * We will call thread_user_enter() for every
- * kernel entry in future, so if the thread mailbox
- * is NULL, it must be a UTS kernel, don't account
- * clock ticks for it.
- */
- }
- }
+ } else if (td->td_mailbox != NULL)
+ td->td_usticks++;
return (0);
}
@@ -1032,15 +1029,13 @@
struct ksegrp *kg;
struct kse_upcall *ku;
struct kse_thr_mailbox *tmbx;
- uint32_t tflags;
+ uint32_t flags;
- kg = td->td_ksegrp;
-
/*
* First check that we shouldn't just abort.
* But check if we are the single thread first!
*/
- if (p->p_flag & P_SINGLE_EXIT) {
+ if (__predict_false(p->p_flag & P_SINGLE_EXIT)) {
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
thread_stopped(p);
@@ -1048,41 +1043,53 @@
/* NOTREACHED */
}
+ if (!(td->td_pflags & TDP_SA))
+ return;
+
/*
* If we are doing a syscall in a KSE environment,
- * note where our mailbox is. There is always the
- * possibility that we could do this lazily (in kse_reassign()),
- * but for now do it every time.
+ * note where our mailbox is.
*/
+
kg = td->td_ksegrp;
- if (td->td_pflags & TDP_SA) {
- ku = td->td_upcall;
- KASSERT(ku, ("%s: no upcall owned", __func__));
- KASSERT((ku->ku_owner == td), ("%s: wrong owner", __func__));
- KASSERT(!TD_CAN_UNBIND(td), ("%s: can unbind", __func__));
- ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
- tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
- if ((tmbx == NULL) || (tmbx == (void *)-1L) ||
- (ku->ku_mflags & KMF_NOUPCALL)) {
+ ku = td->td_upcall;
+
+ KASSERT(ku != NULL, ("no upcall owned"));
+ KASSERT(ku->ku_owner == td, ("wrong owner"));
+ KASSERT(!TD_CAN_UNBIND(td), ("can unbind"));
+
+ ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
+ tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
+ if ((tmbx == NULL) || (tmbx == (void *)-1L) ||
+ (ku->ku_mflags & KMF_NOUPCALL)) {
+ td->td_mailbox = NULL;
+ } else {
+ if (td->td_standin == NULL)
+ thread_alloc_spare(td, NULL);
+ flags = fuword32(&tmbx->tm_flags);
+ /*
+ * On some architectures, TP register points to thread
+ * mailbox but not points to kse mailbox, and userland
+ * can not atomically clear km_curthread, but can
+ * use TP register, and set TMF_NOUPCALL in thread
+ * flag to indicate a critical region.
+ */
+ if (flags & TMF_NOUPCALL) {
td->td_mailbox = NULL;
} else {
- if (td->td_standin == NULL)
- thread_alloc_spare(td, NULL);
- tflags = fuword32(&tmbx->tm_flags);
- /*
- * On some architectures, TP register points to thread
- * mailbox but not points to kse mailbox, and userland
- * can not atomically clear km_curthread, but can
- * use TP register, and set TMF_NOUPCALL in thread
- * flag to indicate a critical region.
- */
- if (tflags & TMF_NOUPCALL) {
- td->td_mailbox = NULL;
- } else {
- td->td_mailbox = tmbx;
- mtx_lock_spin(&sched_lock);
- td->td_flags |= TDF_CAN_UNBIND;
- mtx_unlock_spin(&sched_lock);
+ td->td_mailbox = tmbx;
+ mtx_lock_spin(&sched_lock);
+ td->td_flags |= TDF_CAN_UNBIND;
+ mtx_unlock_spin(&sched_lock);
+ if (__predict_false(p->p_flag & P_TRACED)) {
+ flags = fuword32(&tmbx->tm_dflags);
+ if (flags & TMDF_DONOTRUNUSER) {
+ mtx_lock_spin(&sched_lock);
+ /* fuword can block, check again */
+ if (td->td_upcall)
+ ku->ku_flags |= KUF_DOUPCALL;
+ mtx_unlock_spin(&sched_lock);
+ }
}
}
}
@@ -1103,11 +1110,11 @@
int
thread_userret(struct thread *td, struct trapframe *frame)
{
- int error = 0, upcalls, uts_crit;
struct kse_upcall *ku;
struct ksegrp *kg, *kg2;
struct proc *p;
struct timespec ts;
+ int error = 0, upcalls, uts_crit;
p = td->td_proc;
kg = td->td_ksegrp;
@@ -1131,7 +1138,8 @@
/*
* Check if we should unbind and schedule upcall
- * after returned from interrupt or etcs.
+ * after returned from interrupt or etcs, this
+ * is usually true when process is being debugged.
*/
if (td->td_mailbox == NULL && ku != NULL &&
!(td->td_pflags & TDP_UPCALLING) &&
@@ -1311,3 +1319,39 @@
return (0);
}
+/*
+ * called after ptrace resumed a process, force all
+ * virtual CPUs to schedule upcall for SA process,
+ * because debugger may have changed something in userland,
+ * we should notice UTS as soon as possible.
+ */
+void
+thread_continued(struct proc *p)
+{
+ struct ksegrp *kg;
+ struct kse_upcall *ku;
+ struct thread *td;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ mtx_assert(&sched_lock, MA_OWNED);
+
+ if (!(p->p_flag & P_SA))
+ return;
+
+ if (p->p_flag & P_TRACED) {
+ FOREACH_KSEGRP_IN_PROC(p, kg) {
+ td = TAILQ_FIRST(&kg->kg_threads);
+ if (td == NULL)
+ continue;
+ /* not a SA group, nothing to do */
+ if (!(td->td_pflags & TDP_SA))
+ continue;
+ FOREACH_UPCALL_IN_GROUP(kg, ku) {
+ ku->ku_flags |= KUF_DOUPCALL;
+ if (TD_IS_SUSPENDED(ku->ku_owner)) {
+ thread_unsuspend_one(ku->ku_owner);
+ }
+ }
+ }
+ }
+}
==== //depot/projects/davidxu_ksedbg/src/sys/sys/proc.h#5 (text+ko) ====
@@ -357,6 +357,7 @@
#define TDF_XSIG 0x040000 /* Thread is exchanging signal under traced */
#define TDF_UMTXWAKEUP 0x080000 /* Libthr thread must not sleep on a umtx. */
#define TDF_THRWAKEUP 0x100000 /* Libthr thread must not suspend itself. */
+#define TDF_DBSUSPEND 0x200000 /* Thread is suspended by debugger */
/* "Private" flags kept in td_pflags: */
#define TDP_OLDMASK 0x0001 /* Need to restore mask after suspend. */
@@ -938,6 +939,7 @@
void thread_sanity_check(struct thread *td, char *);
void thread_stopped(struct proc *p);
void thread_switchout(struct thread *td);
+void thread_continued(struct proc *p);
void thr_exit1(void);
#endif /* _KERNEL */
More information about the p4-projects
mailing list