socsvn commit: r223888 - soc2011/rudot/kern

rudot at FreeBSD.org rudot at FreeBSD.org
Sat Jul 2 10:57:16 UTC 2011


Author: rudot
Date: Sat Jul  2 10:57:13 2011
New Revision: 223888
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=223888

Log:
  threads that wake up try to preempt a lower priority running thread

Modified:
  soc2011/rudot/kern/sched_fbfs.c

Modified: soc2011/rudot/kern/sched_fbfs.c
==============================================================================
--- soc2011/rudot/kern/sched_fbfs.c	Sat Jul  2 00:38:10 2011	(r223887)
+++ soc2011/rudot/kern/sched_fbfs.c	Sat Jul  2 10:57:13 2011	(r223888)
@@ -116,6 +116,8 @@
 
 static struct	thread *edf_choose(struct rqhead * rqh);
 static struct	thread *runq_choose_bfs(struct runq * rq);
+static int 	preempt_lastcpu(struct thread *td);
+static struct	thread *worst_running_thread(void);
 
 SYSINIT(sched_setup, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, sched_setup, NULL);
 SYSINIT(sched_initticks, SI_SUB_CLOCKS, SI_ORDER_THIRD, sched_initticks, NULL);
@@ -138,7 +140,7 @@
 
 SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RD, 0, "Scheduler");
 
-SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "4BSD", 0,
+SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "FBFS", 0,
     "Scheduler name");
 
 SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
@@ -592,10 +594,90 @@
 	MPASS(td->td_lock == &sched_lock);
 }
 
+int
+preempt_lastcpu(struct thread *td)
+{
+	int cpri;
+	struct pcpu * pcpu;
+	struct td_sched *ts;
+	struct td_sched *tsc;
+	u_char c;
+
+	c = td->td_lastcpu;
+	if (c == NOCPU)
+		return (0);
+	pcpu = pcpu_find(c);
+	if (pcpu->pc_curthread == pcpu->pc_idlethread) {
+		if (PCPU_GET(cpuid) != c) 
+			ipi_cpu(c, IPI_AST);
+		return (1);
+	}
+	cpri = pcpu->pc_curthread->td_priority;
+	if (cpri < td->td_priority)
+		return (0);
+	if (cpri > td->td_priority) {
+		pcpu->pc_curthread->td_flags |= TDF_NEEDRESCHED;
+		if (PCPU_GET(cpuid) != c) 
+			ipi_cpu(c, IPI_AST);
+		return (1);
+	}
+	ts = td->td_sched;
+	tsc = pcpu->pc_curthread->td_sched;
+	if ((td->td_pri_class == PRI_TIMESHARE) ||
+	    (td->td_pri_class == PRI_IDLE)) {
+		if (ts->ts_vdeadline >= tsc->ts_vdeadline)
+			return (0);
+	} else
+		return (0);
+	/*
+	 * Here, the priorities of td, and current thread on td_lastcpu are
+	 * equal. And their scheduling class is PRI_IDLE or PRI_TIMESHARE
+	 * Further, the virtual deadline of td is lower. Therefore we
+	 * reschedule the td_lastcpu.
+	 */
+	pcpu->pc_curthread->td_flags |= TDF_NEEDRESCHED;
+	if (PCPU_GET(cpuid) != c) 
+		ipi_cpu(c, IPI_AST);
+
+	return (1);
+}
+
+struct thread *
+worst_running_thread(void)
+{
+	struct td_sched *ts, *ts2;
+	struct thread *max_thread, *cthr;
+	struct pcpu *pc;
+	u_char max_prio;
+
+	max_thread = curthread;
+	max_prio = max_thread->td_priority;
+	ts = max_thread->td_sched;
+	SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+		cthr = pc->pc_curthread;
+		if (max_prio < cthr->td_priority) {
+			max_thread = cthr;
+			max_prio = max_thread->td_priority;
+			ts = max_thread->td_sched;
+		} else if (max_prio == cthr->td_priority) {
+			ts2 = cthr->td_sched;
+			if (ts->ts_vdeadline > ts2->ts_vdeadline) {
+				max_thread = cthr;
+				ts = ts2;
+			}
+		}
+	}
+
+	return (max_thread);
+}
+
 void
 sched_wakeup(struct thread *td)
 {
 	struct td_sched *ts;
+	struct thread *thr_worst;
+	cpumask_t dontuse, map, me;
+	u_char c;
 
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
 	ts = td->td_sched;
@@ -603,6 +685,44 @@
 	td->td_slptick = 0;
 	ts->ts_slptime = 0;
 	sched_add(td, SRQ_BORING);
+
+	me = PCPU_GET(cpumask);
+	dontuse = me | stopped_cpus | hlt_cpus_mask;
+	map = idle_cpus_mask & ~dontuse;
+
+	/*
+	 * Firstly check if we should reschedule the last cpu the thread
+	 * run on.
+	 */
+	if (preempt_lastcpu(td)) {
+		if (map)
+			ipi_selected(map, IPI_AST);
+		return;
+	}
+
+	if (map) {
+		ipi_selected(map, IPI_AST);
+		return;
+	}
+
+	/* We did not wake lastcpu and there is no suitable idle cpu */
+	thr_worst = worst_running_thread();
+	c = thr_worst->td_oncpu;
+	if (thr_worst->td_priority < td->td_priority)
+		return;
+	if (thr_worst->td_priority > td->td_priority) {
+		thr_worst->td_flags |= TDF_NEEDRESCHED;
+		if ((thr_worst != curthread) && (c != NOCPU))
+			ipi_cpu(c, IPI_AST);
+		return;
+	}
+
+	/* thr_worst->td_priority == td->td_priority */
+	if (ts->ts_vdeadline < thr_worst->td_sched->ts_vdeadline) {
+		thr_worst->td_flags |= TDF_NEEDRESCHED;
+		if ((thr_worst != curthread) && (c != NOCPU))
+			ipi_cpu(c, IPI_AST);
+	}
 }
 
 void


More information about the svn-soc-all mailing list