Skip site navigation (1)Skip section navigation (2)
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>