scheduler (sched_4bsd) questions
Peter Holm
peter at holm.cc
Sat Oct 2 11:31:24 PDT 2004
On Sat, Oct 02, 2004 at 11:14:22AM -0700, Julian Elischer wrote:
> Peter Holm wrote:
> >On Fri, Oct 01, 2004 at 09:25:51PM +0200, Peter Holm wrote:
> >
> >>>>For once I'm the bearer of good news. The switch_patch_v2 + the
> >>>>sched_4bsd patch ran the tests for more than one hour without
> >>>>any freeze. The sched_4bsd alone did not stop the freezes. I'm
> >>>>now testing the switch_patch_v2 alone and it's looking good for
> >>>>55+ minutes of testing.
> >>>
> >>>Great !
> >>>I guess I should roll a cleaned up cumulative patch soon.
> >>>
> >>> Stephan
> >>
> >>I have now been running the stress test for more than 3½ hours, without
> >>any freezes. I have included the two of your changes I have been using.
> >>
> >>- Peter
> >
> >
> >After more testing, I'm sad to report that the freeze is still there.
> >The patch has however decreased the number of freezes dramatically:
> >
> >During 14 hours of testing 3 separate freezes has been seen:
> >
> >24 Giant held for more than 60 sec by td 0xc244e900, pid 27683
> >31 Giant held for more than 60 sec by td 0xc1b7b600, pid 12098
> >79 Giant held for more than 60 sec by td 0xc25f3180, pid 75531
> >
> >- Peter
> >_______________________________________________
> >freebsd-arch at freebsd.org mailing list
> >http://lists.freebsd.org/mailman/listinfo/freebsd-arch
> >To unsubscribe, send any mail to "freebsd-arch-unsubscribe at freebsd.org"
> When this happes, drop to debugger..
>
> using:
>
> kdb_enter("Giant too long");
>
> and dump out teh thread backtrace, and the output of show ktr
> iff you have ktr enabled.. (as we discussed before)
OK, right now I'm testing with all of Stephan's patches + the
MUTEX_WAKE_ALL flag. Uptime is 3 3/4 hour and looking good.
--
Peter Holm
-------------- next part --------------
Index: sys/kern/kern_mutex.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_mutex.c,v
retrieving revision 1.149
diff -u -r1.149 kern_mutex.c
--- sys/kern/kern_mutex.c 2 Sep 2004 18:59:15 -0000 1.149
+++ sys/kern/kern_mutex.c 2 Oct 2004 14:46:26 -0000
@@ -492,7 +492,9 @@
if (v == MTX_CONTESTED) {
MPASS(ts != NULL);
m->mtx_lock = (uintptr_t)td | MTX_CONTESTED;
+ critical_enter();
turnstile_claim(ts);
+ critical_exit();
break;
}
#endif
@@ -651,6 +653,9 @@
#else
MPASS(ts != NULL);
#endif
+
+ critical_enter();
+
#ifndef PREEMPTION
/* XXX */
td1 = turnstile_head(ts);
@@ -671,6 +676,7 @@
}
#endif
turnstile_unpend(ts);
+ critical_exit();
#ifndef PREEMPTION
/*
Index: sys/kern/kern_switch.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_switch.c,v
retrieving revision 1.95
diff -u -r1.95 kern_switch.c
--- sys/kern/kern_switch.c 19 Sep 2004 18:34:17 -0000 1.95
+++ sys/kern/kern_switch.c 2 Oct 2004 14:46:27 -0000
@@ -315,6 +315,106 @@
td->td_priority = newpri;
setrunqueue(td, SRQ_BORING);
}
+
+
+/*
+ * This function is called when a thread is about to be put on a
+ * ksegrp run queue because it has been made runnable or its
+ * priority has been adjusted and the ksegrp does not have a
+ * free kse slot. It determines if a thread from the same ksegrp
+ * should be preempted. If so, it tries to switch threads
+ * if the thread is on the same cpu or notifies another cpu that
+ * it should switch threads.
+ */
+
+static void
+maybe_preempt_in_ksegrp(struct thread *td)
+{
+#if defined(SMP)
+ int highest_pri;
+ struct ksegrp *kg;
+ cpumask_t cpumask,dontuse;
+ struct pcpu *pc;
+ struct pcpu *highest_pcpu;
+ struct thread *running_thread;
+
+#ifndef FULL_PREEMPTION
+ int pri;
+
+ pri = td->td_priority;
+
+ if (!(pri >= PRI_MIN_ITHD && pri <= PRI_MAX_ITHD))
+ return;
+#endif
+
+ mtx_assert(&sched_lock, MA_OWNED);
+
+ running_thread = curthread;
+
+#if !defined(KSEG_PEEMPT_BEST_CPU)
+ if(running_thread->td_ksegrp != td->td_ksegrp)
+#endif
+ {
+ kg = td->td_ksegrp;
+
+ /* Anyone waiting in front ? */
+ if(td != TAILQ_FIRST(&kg->kg_runq)) {
+ return; /* Yes - wait your turn*/
+ }
+ highest_pri = td->td_priority;
+ highest_pcpu = NULL;
+ dontuse = stopped_cpus | idle_cpus_mask;
+
+ /* Find a cpu with the worst priority that runs at thread from the
+ * same ksegrp - if multiple exist give first the last run cpu and then
+ * the current cpu priority
+ */
+
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ cpumask = pc->pc_cpumask;
+ if ( (cpumask & dontuse) == 0 &&
+ pc->pc_curthread->td_ksegrp == kg) {
+ if (pc->pc_curthread->td_priority > highest_pri) {
+ highest_pri = pc->pc_curthread->td_priority;
+ highest_pcpu = pc;
+ } else if (pc->pc_curthread->td_priority == highest_pri &&
+ highest_pcpu != NULL) {
+ if (td->td_lastcpu == pc->pc_cpuid ||
+ (PCPU_GET(cpumask) == cpumask &&
+ td->td_lastcpu != highest_pcpu->pc_cpuid)) {
+ highest_pcpu = pc;
+ }
+ }
+ }
+ }
+
+ /* Check if we need to preempt someone */
+ if (highest_pcpu == NULL) return;
+
+ if (PCPU_GET(cpuid) != highest_pcpu->pc_cpuid) {
+ highest_pcpu->pc_curthread->td_flags |= TDF_NEEDRESCHED;
+ ipi_selected(highest_pcpu->pc_cpumask, IPI_AST);
+ return;
+ }
+ }
+#else
+ KASSERT(running_thread->td_ksegrp == td->td_ksegrp,("maybe_preempt_in_ksegrp: No chance to run thread"));
+#endif
+
+ if (td->td_priority > running_thread->td_priority)
+ return;
+#ifdef PREEMPTION
+ if (running_thread->td_critnest > 1) {
+ running_thread->td_pflags |= TDP_OWEPREEMPT;
+ } else {
+ mi_switch(SW_INVOL, NULL);
+ }
+#else
+ running_thread->td_flags |= TDF_NEEDRESCHED;
+#endif
+ return;
+}
+
int limitcount;
void
setrunqueue(struct thread *td, int flags)
@@ -422,6 +522,7 @@
} else {
CTR3(KTR_RUNQ, "setrunqueue: held: td%p kg%p pid%d",
td, td->td_ksegrp, td->td_proc->p_pid);
+ maybe_preempt_in_ksegrp(td);
}
}
Index: sys/kern/sched_4bsd.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sched_4bsd.c,v
retrieving revision 1.65
diff -u -r1.65 sched_4bsd.c
--- sys/kern/sched_4bsd.c 16 Sep 2004 07:12:59 -0000 1.65
+++ sys/kern/sched_4bsd.c 2 Oct 2004 14:46:29 -0000
@@ -823,6 +823,7 @@
TD_SET_CAN_RUN(td);
else {
td->td_ksegrp->kg_avail_opennings++;
+ critical_enter();
if (TD_IS_RUNNING(td)) {
/* Put us back on the run queue (kse and all). */
setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING);
@@ -834,6 +835,8 @@
*/
slot_fill(td->td_ksegrp);
}
+ critical_exit();
+ td->td_pflags &= ~TDP_OWEPREEMPT;
}
if (newtd == NULL)
newtd = choosethread();
--- sys/i386/conf/GENERIC Sun Sep 19 02:52:22 2004
+++ sys/i386/conf/PHO Sat Oct 2 16:06:19 2004
@@ -66,6 +66,7 @@
options KDB # Enable kernel debugger support.
options DDB # Support DDB.
options GDB # Support remote GDB.
+options BREAK_TO_DEBUGGER
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
options WITNESS # Enable checks to detect deadlocks and cycles
@@ -285,3 +286,4 @@
device firewire # FireWire bus code
device sbp # SCSI over FireWire (Requires scbus and da)
device fwe # Ethernet over FireWire (non-standard!)
+options MUTEX_WAKE_ALL # Needed do not remove
More information about the freebsd-arch
mailing list