summaryrefslogtreecommitdiffstats
path: root/sys/kern/sched_ule.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-02-03 05:30:07 +0000
committerjeff <jeff@FreeBSD.org>2003-02-03 05:30:07 +0000
commitd73f4537e98226118b273eee94c5989e04b2d53f (patch)
treed082971d1b27eb22e0a2b2349cbe662fe64c2d94 /sys/kern/sched_ule.c
parent639ca5a9ca3fa0f8412945e317e185be329a17fd (diff)
downloadFreeBSD-src-d73f4537e98226118b273eee94c5989e04b2d53f.zip
FreeBSD-src-d73f4537e98226118b273eee94c5989e04b2d53f.tar.gz
- Make some context switches conditional on SCHED_STRICT_RESCHED. This may
have some negative effect on interactivity but it yields great perf. gains. This also brings the conditions under which ULE context switches inline with SCHED_4BSD. - Define some new kseq_* functions for manipulating the run queue. - Add a new kseq member ksq_rslices and ksq_bload. rslices is the sum of the slices of runnable kses. This will be used for push load balance decisions. bload is the number of threads blocked waiting on IO.
Diffstat (limited to 'sys/kern/sched_ule.c')
-rw-r--r--sys/kern/sched_ule.c208
1 files changed, 146 insertions, 62 deletions
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 7529a5e..614018c 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -85,12 +85,18 @@ struct kg_sched {
struct td_sched {
int std_slptime;
+ int std_schedflag;
};
#define td_slptime td_sched->std_slptime
+#define td_schedflag td_sched->std_schedflag
+#define TD_SCHED_BLOAD 0x0001 /*
+ * thread was counted as being in short
+ * term sleep.
+ */
+struct td_sched td_sched;
struct ke_sched ke_sched;
struct kg_sched kg_sched;
-struct td_sched td_sched;
struct ke_sched *kse0_sched = &ke_sched;
struct kg_sched *ksegrp0_sched = &kg_sched;
@@ -173,6 +179,10 @@ struct kseq {
struct runq *ksq_curr;
struct runq *ksq_next;
int ksq_load; /* Total runnable */
+#ifdef SMP
+ unsigned int ksq_rslices; /* Slices on run queue */
+ unsigned int ksq_bload; /* Threads waiting on IO */
+#endif
};
/*
@@ -193,17 +203,105 @@ static int sched_priority(struct ksegrp *kg);
void sched_pctcpu_update(struct kse *ke);
int sched_pickcpu(void);
+/* Operations on per processor queues */
static struct kse * kseq_choose(struct kseq *kseq);
static void kseq_setup(struct kseq *kseq);
+static __inline void kseq_add(struct kseq *kseq, struct kse *ke);
+static __inline void kseq_rem(struct kseq *kseq, struct kse *ke);
+#ifdef SMP
+static __inline void kseq_sleep(struct kseq *kseq, struct kse *ke);
+static __inline void kseq_wakeup(struct kseq *kseq, struct kse *ke);
+struct kseq * kseq_load_highest(void);
+#endif
+
+static __inline void
+kseq_add(struct kseq *kseq, struct kse *ke)
+{
+ runq_add(ke->ke_runq, ke);
+ kseq->ksq_load++;
+#ifdef SMP
+ kseq->ksq_rslices += ke->ke_slice;
+#endif
+}
+static __inline void
+kseq_rem(struct kseq *kseq, struct kse *ke)
+{
+ kseq->ksq_load--;
+ runq_remove(ke->ke_runq, ke);
+#ifdef SMP
+ kseq->ksq_rslices -= ke->ke_slice;
+#endif
+}
+
+#ifdef SMP
+static __inline void
+kseq_sleep(struct kseq *kseq, struct kse *ke)
+{
+ kseq->ksq_bload++;
+}
+
+static __inline void
+kseq_wakeup(struct kseq *kseq, struct kse *ke)
+{
+ kseq->ksq_bload--;
+}
+
+struct kseq *
+kseq_load_highest(void)
+{
+ struct kseq *kseq;
+ int load;
+ int cpu;
+ int i;
+
+ cpu = 0;
+ load = 0;
+
+ for (i = 0; i < mp_maxid; i++) {
+ if (CPU_ABSENT(i))
+ continue;
+ kseq = KSEQ_CPU(i);
+ if (kseq->ksq_load > load) {
+ load = kseq->ksq_load;
+ cpu = i;
+ }
+ }
+ if (load)
+ return (KSEQ_CPU(cpu));
+
+ return (NULL);
+}
+#endif
+
+struct kse *
+kseq_choose(struct kseq *kseq)
+{
+ struct kse *ke;
+ struct runq *swap;
+
+ if ((ke = runq_choose(kseq->ksq_curr)) == NULL) {
+ swap = kseq->ksq_curr;
+ kseq->ksq_curr = kseq->ksq_next;
+ kseq->ksq_next = swap;
+ ke = runq_choose(kseq->ksq_curr);
+ }
+
+ return (ke);
+}
+
static void
kseq_setup(struct kseq *kseq)
{
- kseq->ksq_load = 0;
kseq->ksq_curr = &kseq->ksq_runqs[0];
kseq->ksq_next = &kseq->ksq_runqs[1];
runq_init(kseq->ksq_curr);
runq_init(kseq->ksq_next);
+ kseq->ksq_load = 0;
+#ifdef SMP
+ kseq->ksq_rslices = 0;
+ kseq->ksq_bload = 0;
+#endif
}
static void
@@ -296,6 +394,7 @@ sched_pctcpu_update(struct kse *ke)
}
#ifdef SMP
+/* XXX Should be changed to kseq_load_lowest() */
int
sched_pickcpu(void)
{
@@ -384,9 +483,11 @@ sched_switchin(struct thread *td)
mtx_assert(&sched_lock, MA_OWNED);
td->td_kse->ke_oncpu = PCPU_GET(cpuid);
+#if SCHED_STRICT_RESCHED
if (td->td_ksegrp->kg_pri_class == PRI_TIMESHARE &&
td->td_priority != td->td_ksegrp->kg_user_pri)
curthread->td_kse->ke_flags |= KEF_NEEDRESCHED;
+#endif
}
void
@@ -416,9 +517,11 @@ sched_sleep(struct thread *td, u_char prio)
*/
if (SCHED_CURR(td->td_kse->ke_ksegrp))
td->td_kse->ke_runq = NULL;
-#if 0
- if (td->td_priority < PZERO)
- kseq_cpu[td->td_kse->ke_cpu].ksq_load++;
+#ifdef SMP
+ if (td->td_priority < PZERO) {
+ kseq_sleep(KSEQ_CPU(td->td_kse->ke_cpu), td->td_kse);
+ td->td_schedflag |= TD_SCHED_BLOAD;
+ }
#endif
}
@@ -442,13 +545,17 @@ sched_wakeup(struct thread *td)
td->td_priority = sched_priority(kg);
}
td->td_slptime = 0;
-#if 0
- if (td->td_priority < PZERO)
- kseq_cpu[td->td_kse->ke_cpu].ksq_load--;
+#ifdef SMP
+ if (td->td_priority < PZERO && td->td_schedflag & TD_SCHED_BLOAD) {
+ kseq_wakeup(KSEQ_CPU(td->td_kse->ke_cpu), td->td_kse);
+ td->td_schedflag &= ~TD_SCHED_BLOAD;
+ }
#endif
setrunqueue(td);
+#if SCHED_STRICT_RESCHED
if (td->td_priority < curthread->td_priority)
curthread->td_kse->ke_flags |= KEF_NEEDRESCHED;
+#endif
}
/*
@@ -503,8 +610,10 @@ void
sched_clock(struct thread *td)
{
struct kse *ke;
+#if SCHED_STRICT_RESCHED
struct kse *nke;
struct kseq *kseq;
+#endif
struct ksegrp *kg;
@@ -528,12 +637,14 @@ sched_clock(struct thread *td)
* Check for a higher priority task on the run queue. This can happen
* on SMP if another processor woke up a process on our runq.
*/
+#if SCHED_STRICT_RESCHED
kseq = KSEQ_SELF();
nke = runq_choose(kseq->ksq_curr);
if (nke && nke->ke_thread &&
nke->ke_thread->td_priority < td->td_priority)
ke->ke_flags |= KEF_NEEDRESCHED;
+#endif
/*
* We used a tick, decrease our total sleep time. This decreases our
* "interactivity".
@@ -572,6 +683,11 @@ sched_runnable(void)
if (smp_started) {
int i;
+#if 0
+ if (kseq->ksq_bload)
+ return (0);
+#endif
+
for (i = 0; i < mp_maxid; i++) {
if (CPU_ABSENT(i))
continue;
@@ -599,22 +715,6 @@ sched_userret(struct thread *td)
}
struct kse *
-kseq_choose(struct kseq *kseq)
-{
- struct kse *ke;
- struct runq *swap;
-
- if ((ke = runq_choose(kseq->ksq_curr)) == NULL) {
- swap = kseq->ksq_curr;
- kseq->ksq_curr = kseq->ksq_next;
- kseq->ksq_next = swap;
- ke = runq_choose(kseq->ksq_curr);
- }
-
- return (ke);
-}
-
-struct kse *
sched_choose(void)
{
struct kseq *kseq;
@@ -624,42 +724,28 @@ sched_choose(void)
ke = kseq_choose(kseq);
if (ke) {
- runq_remove(ke->ke_runq, ke);
- kseq->ksq_load--;
ke->ke_state = KES_THREAD;
+ kseq_rem(kseq, ke);
}
#ifdef SMP
if (ke == NULL && smp_started) {
- int load;
- int cpu;
- int i;
-
- load = 0;
- cpu = 0;
-
+#if 0
+ if (kseq->ksq_bload)
+ return (NULL);
+#endif
/*
* Find the cpu with the highest load and steal one proc.
*/
- for (i = 0; i < mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
- kseq = KSEQ_CPU(i);
- if (kseq->ksq_load > load) {
- load = kseq->ksq_load;
- cpu = i;
- }
- }
- if (load) {
- kseq = KSEQ_CPU(cpu);
- ke = kseq_choose(kseq);
- kseq->ksq_load--;
- ke->ke_state = KES_THREAD;
- runq_remove(ke->ke_runq, ke);
- ke->ke_runq = NULL;
- ke->ke_cpu = PCPU_GET(cpuid);
- }
+ kseq = kseq_load_highest();
+ if (kseq == NULL)
+ return (NULL);
+ ke = kseq_choose(kseq);
+ kseq_rem(kseq, ke);
+ ke->ke_state = KES_THREAD;
+ ke->ke_runq = NULL;
+ ke->ke_cpu = PCPU_GET(cpuid);
}
#endif
return (ke);
@@ -668,22 +754,21 @@ sched_choose(void)
void
sched_add(struct kse *ke)
{
+ struct kseq *kseq;
mtx_assert(&sched_lock, MA_OWNED);
- KASSERT((ke->ke_thread != NULL), ("runq_add: No thread on KSE"));
+ KASSERT((ke->ke_thread != NULL), ("sched_add: No thread on KSE"));
KASSERT((ke->ke_thread->td_kse != NULL),
- ("runq_add: No KSE on thread"));
+ ("sched_add: No KSE on thread"));
KASSERT(ke->ke_state != KES_ONRUNQ,
- ("runq_add: kse %p (%s) already in run queue", ke,
+ ("sched_add: kse %p (%s) already in run queue", ke,
ke->ke_proc->p_comm));
KASSERT(ke->ke_proc->p_sflag & PS_INMEM,
- ("runq_add: process swapped out"));
+ ("sched_add: process swapped out"));
+ kseq = KSEQ_CPU(ke->ke_cpu);
if (ke->ke_runq == NULL) {
- struct kseq *kseq;
-
- kseq = KSEQ_CPU(ke->ke_cpu);
if (SCHED_CURR(ke->ke_ksegrp))
ke->ke_runq = kseq->ksq_curr;
else
@@ -692,8 +777,7 @@ sched_add(struct kse *ke)
ke->ke_ksegrp->kg_runq_kses++;
ke->ke_state = KES_ONRUNQ;
- runq_add(ke->ke_runq, ke);
- KSEQ_CPU(ke->ke_cpu)->ksq_load++;
+ kseq_add(kseq, ke);
}
void
@@ -702,11 +786,11 @@ sched_rem(struct kse *ke)
mtx_assert(&sched_lock, MA_OWNED);
/* KASSERT((ke->ke_state == KES_ONRUNQ), ("KSE not on run queue")); */
- runq_remove(ke->ke_runq, ke);
ke->ke_runq = NULL;
ke->ke_state = KES_THREAD;
ke->ke_ksegrp->kg_runq_kses--;
- KSEQ_CPU(ke->ke_cpu)->ksq_load--;
+
+ kseq_rem(KSEQ_CPU(ke->ke_cpu), ke);
}
fixpt_t
OpenPOWER on IntegriCloud