From owner-freebsd-arch@FreeBSD.ORG Tue Sep 28 02:52:19 2004 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B4C4F16A4CE for ; Tue, 28 Sep 2004 02:52:19 +0000 (GMT) Received: from duchess.speedfactory.net (duchess.speedfactory.net [66.23.201.84]) by mx1.FreeBSD.org (Postfix) with SMTP id 58C2A43D49 for ; Tue, 28 Sep 2004 02:52:19 +0000 (GMT) (envelope-from ups@tree.com) Received: (qmail 18056 invoked by uid 89); 28 Sep 2004 02:52:18 -0000 Received: from duchess.speedfactory.net (66.23.201.84) by duchess.speedfactory.net with SMTP; 28 Sep 2004 02:52:18 -0000 Received: (qmail 18036 invoked by uid 89); 28 Sep 2004 02:52:18 -0000 Received: from unknown (HELO palm.tree.com) (66.23.216.49) by duchess.speedfactory.net with SMTP; 28 Sep 2004 02:52:18 -0000 Received: from [127.0.0.1] (localhost.tree.com [127.0.0.1]) by palm.tree.com (8.12.10/8.12.10) with ESMTP id i8S2qGmt006097; Mon, 27 Sep 2004 22:52:17 -0400 (EDT) (envelope-from ups@tree.com) From: Stephan Uphoff To: Peter Holm In-Reply-To: <20040926075218.GA85983@peter.osted.lan> References: <1095468747.31297.241.camel@palm.tree.com> <1095529353.31297.1192.camel@palm.tree.com> <1096135220.53798.17754.camel@palm.tree.com> <20040926075218.GA85983@peter.osted.lan> Content-Type: multipart/mixed; boundary="=-rj4c4DOGe8hfA+4+RE6p" Message-Id: <1096339936.3733.279.camel@palm.tree.com> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.4.6 Date: Mon, 27 Sep 2004 22:52:16 -0400 cc: Julian Elischer cc: "freebsd-arch@freebsd.org" Subject: Re: scheduler (sched_4bsd) questions X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Sep 2004 02:52:19 -0000 --=-rj4c4DOGe8hfA+4+RE6p Content-Type: text/plain Content-Transfer-Encoding: 7bit On Sun, 2004-09-26 at 03:52, Peter Holm wrote: > On Sat, Sep 25, 2004 at 08:50:45PM -0700, Julian Elischer wrote: > > Stephan Uphoff wrote: > > > > >>Maybe something brutal like: > > >> if ((curthread->td_ksegrp == kg) && > > >> (td->td_priority > curthread->td_priority)) > > >> curthread->td_flags |= TDF_NEEDRESCHED; > > >> > > >>in setrunqueue for > > >>the else case of "if (kg->kg_avail_opennings > 0)" > > >>would do the trick (without preemption) for the easy but probably more > > >>common cases? > > >> > > >>Maybe I can find some time next week to think about a clean > > >>fix. I find it always helpful having a small task in mind while reading > > >>source code. > > > > > > > > >I wrote a fix that should cover all cases. > > >However I would like to test it a little bit before posting the patch. > > >Is there any multi-threaded kernel torture program that you can > > >recommend? > > > > > > Peter Holm (CC'd) has a really cool set of torture tests. > > he has also seen all sorts of failures others have not (yet) triggered. :-) > > > > I'm 'busy" for the next couple of weeks so you may want to communicate > > directly with him and see if you and he together can figure out some of the > > things he's > > been seeing :-) > > > > his tests are at: > > http://www.holm.cc/stress/src/stress.tgz > > > > > > > >Thanks > > > > > > Stephan > > > > > I'll be glad to test any patches. Great. Can you try the attached patch to see if it changes any of your previously observed behaviour? Thanks Stephan --=-rj4c4DOGe8hfA+4+RE6p Content-Disposition: attachment; filename=switch_patch Content-Type: text/x-patch; name=switch_patch; charset=ASCII Content-Transfer-Encoding: 7bit Index: sys/kern/kern_switch.c =================================================================== RCS file: /cvsroot/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 28 Sep 2004 02:48:43 -0000 @@ -315,6 +315,94 @@ 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; + + mtx_assert(&sched_lock, MA_OWNED); + +#if !defined(KSEG_PEEMPT_BEST_CPU) + if(curthread->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) { + pc->pc_curthread->td_flags |= TDF_NEEDRESCHED; + ipi_selected(highest_pcpu->pc_cpumask, IPI_AST); + return; + } + } +#else + KASSERT(curthread->td_ksegrp == td->td_ksegrp,("maybe_preempt_in_ksegrp: No chance to run thread")); +#endif + + if (td->td_priority <= curthread->td_priority) + return; +#ifdef PREEMPTION + if (td->td_critnest > 1) { + td->td_pflags |= TDP_OWEPREEMPT; + } else { + mi_switch(SW_INVOL, NULL); + } +#else + curthread->td_flags |= TDF_NEEDRESCHED; +#endif + return; +} + int limitcount; void setrunqueue(struct thread *td, int flags) @@ -422,6 +510,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); } } --=-rj4c4DOGe8hfA+4+RE6p--