diff options
author | jeff <jeff@FreeBSD.org> | 2003-02-03 05:30:07 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2003-02-03 05:30:07 +0000 |
commit | d73f4537e98226118b273eee94c5989e04b2d53f (patch) | |
tree | d082971d1b27eb22e0a2b2349cbe662fe64c2d94 /sys | |
parent | 639ca5a9ca3fa0f8412945e317e185be329a17fd (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/kern/sched_ule.c | 208 |
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 |