Date: Sat, 10 Jul 2004 13:47:14 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 56956 for review Message-ID: <200407101347.i6ADlE6D027054@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=56956 Change 56956 by davidxu@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407101347.i6ADlE6D027054>