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>