Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Jul 2004 14:04:36 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 56959 for review
Message-ID:  <200407101404.i6AE4a6x027460@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=56959

Change 56959 by davidxu@davidxu_alona on 2004/07/10 14:03:38

	Check TMDF_DONOTRUNUSER when being debugged. If the flag is set by
	debugger, the current thread should relinquish CPU after left critical
	region, UTS should select a thread without TMDF_DONOTRUNUSER set
	in mailbox to run.

Affected files ...

.. //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_kern.c#4 edit
.. //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_priority_queue.c#2 edit
.. //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_private.h#5 edit

Differences ...

==== //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_kern.c#4 (text+ko) ====

@@ -99,7 +99,10 @@
 	_pq_insert_tail(&(kse)->k_schedq->sq_runq, thrd)
 #define	KSE_RUNQ_REMOVE(kse, thrd)			\
 	_pq_remove(&(kse)->k_schedq->sq_runq, thrd)
-#define	KSE_RUNQ_FIRST(kse)	_pq_first(&(kse)->k_schedq->sq_runq)
+#define	KSE_RUNQ_FIRST(kse)				\
+	((_libkse_debug == 0) ?				\
+	 _pq_first(&(kse)->k_schedq->sq_runq) :		\
+	 _pq_first_debug(&(kse)->k_schedq->sq_runq))
 
 #define KSE_RUNQ_THREADS(kse)	((kse)->k_schedq->sq_runq.pq_threads)
 
@@ -2517,3 +2520,27 @@
 	}
 	return (NULL);
 }
+
+void
+_thr_debug_check_yield(struct pthread *curthread)
+{
+	/*
+	 * Note that TMDF_DONOTRUNUSER is set after process is suspended.
+	 * When we are being debugged, every suspension in process
+	 * will cause all KSEs to schedule an upcall in kernel, unless the
+	 * KSE is in critical region.
+	 * If the function is being called, it means the KSE is no longer
+	 * in critical region, if the TMDF_DONOTRUNUSER is set by debugger
+	 * before KSE leaves critical region, we will catch it here, else
+	 * if the flag is changed during testing, it also not a problem,
+	 * because the change only occurs after a process suspension event
+	 * occurs. A suspension event will always cause KSE to schedule an
+	 * upcall, in the case, because we are not in critical region,
+	 * upcall will be scheduled sucessfully, the flag will be checked
+	 * again in kse_sched_multi, we won't back until the flag
+	 * is cleared by debugger, the flag will be cleared in next
+	 * suspension event. 
+	 */
+	if (curthread->tcb->tcb_tmbx.tm_dflags & TMDF_DONOTRUNUSER)
+		_thr_sched_switch(curthread);
+}

==== //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_priority_queue.c#2 (text+ko) ====

@@ -242,6 +242,46 @@
 	return (pthread);
 }
 
+/*
+ * Select a thread which is allowed to run by debugger, we probably
+ * should merge the function into _pq_first if that function is only
+ * used by scheduler to select a thread.
+ */
+pthread_t
+_pq_first_debug(pq_queue_t *pq)
+{
+	pq_list_t *pql;
+	pthread_t pthread = NULL;
+
+	/*
+	 * Make some assertions when debugging is enabled:
+	 */
+	PQ_ASSERT_INACTIVE(pq, "_pq_first: pq_active");
+	PQ_SET_ACTIVE(pq);
+
+	while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) &&
+	    (pthread == NULL)) {
+		if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) {
+			/*
+			 * The priority list is empty; remove the list
+			 * from the queue.
+			 */
+			TAILQ_REMOVE(&pq->pq_queue, pql, pl_link);
+
+			/* Mark the list as not being in the queue: */
+			pql->pl_queued = 0;
+		} else {
+			while (pthread != NULL && !THR_IN_CRITICAL(pthread) &&
+			       (pthread->tcb->tcb_tmbx.tm_dflags &
+			         TMDF_DONOTRUNUSER)) {
+				pthread = TAILQ_NEXT(pthread, pqe);
+			}
+		}
+	}
+
+	PQ_CLEAR_ACTIVE(pq);
+	return (pthread);
+}
 
 static void
 pq_insert_prio_list(pq_queue_t *pq, int prio)

==== //depot/projects/davidxu_ksedbg/src/lib/libpthread/thread/thr_private.h#5 (text+ko) ====

@@ -820,12 +820,14 @@
 
 #define	THR_YIELD_CHECK(thrd)					\
 do {								\
-	if (((thrd)->critical_yield != 0) &&			\
-	    !(THR_IN_CRITICAL(thrd)))				\
-		_thr_sched_switch(thrd);			\
-	else if (((thrd)->check_pending != 0) &&		\
-	    !(THR_IN_CRITICAL(thrd)))				\
-		_thr_sig_check_pending(thrd);			\
+	if (!THR_IN_CRITICAL(thrd)) {				\
+		if (__predict_false(_libkse_debug))		\
+			_thr_debug_check_yield(thrd);		\
+		if ((thrd)->critical_yield != 0)		\
+			_thr_sched_switch(thrd);		\
+		if ((thrd)->check_pending != 0) 		\
+			_thr_sig_check_pending(thrd);		\
+	}							\
 } while (0)
 
 #define	THR_LOCK_ACQUIRE(thrd, lck)				\
@@ -886,8 +888,6 @@
 	_pq_insert_tail(&(thrd)->kseg->kg_schedq.sq_runq, thrd)
 #define THR_RUNQ_REMOVE(thrd)		\
 	_pq_remove(&(thrd)->kseg->kg_schedq.sq_runq, thrd)
-#define THR_RUNQ_FIRST(thrd)		\
-	_pq_first(&(thrd)->kseg->kg_schedq.sq_runq)
 
 /*
  * Macros to insert/remove threads to the all thread list and
@@ -1086,6 +1086,7 @@
 void	_pq_insert_head(struct pq_queue *pq, struct pthread *);
 void	_pq_insert_tail(struct pq_queue *pq, struct pthread *);
 struct pthread *_pq_first(struct pq_queue *pq);
+struct pthread *_pq_first_debug(struct pq_queue *pq);
 void	*_pthread_getspecific(pthread_key_t);
 int	_pthread_key_create(pthread_key_t *, void (*) (void *));
 int	_pthread_key_delete(pthread_key_t);
@@ -1157,6 +1158,7 @@
 struct pthread *_thr_hash_find(struct pthread *);
 void	_thr_finish_cancellation(void *arg);
 int	_thr_sigonstack(void *sp);
+void	_thr_debug_check_yield(struct pthread *);
 
 /*
  * Aliases for _pthread functions. Should be called instead of



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407101404.i6AE4a6x027460>