Date: Mon, 5 Jul 2004 23:30:25 GMT From: Julian Elischer <julian@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 56557 for review Message-ID: <200407052330.i65NUPr2095079@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=56557 Change 56557 by julian@julian_jules1 on 2004/07/05 23:29:46 Part way to getting rid of struct kse. Most of its features are taken up by the td_sched substructure which is always present on each thread. Affected files ... .. //depot/projects/nsched/sys/kern/sched_4bsd.c#21 edit .. //depot/projects/nsched/sys/sys/proc.h#18 edit Differences ... ==== //depot/projects/nsched/sys/kern/sched_4bsd.c#21 (text+ko) ==== @@ -55,63 +55,7 @@ #include <vm/uma.h> #include <machine/critical.h> -/******************************************************************** - * Definitions of the "KSE" structure. - * - * This is a scheduler private structure that it uses (for now) - * to implement the thread fairness algorythm. - * The threads are made runnable by the rest of the system, but - * only NKSE of them are actually put on the run queues to compete with - * threads from other processes. For normal processes there is only one KSE - * but for threaded processes we allocate only upto NKSE kses per ksegrp. - * KSEs are what is put on the system run queue, so multithreaded - * processes must multiplex their threads onto their KSEs, making them compete - * on a similar basis to nonthreaded processes. - * In pictures: - * With a single run queue used by all processors: - * - * RUNQ: --->KSE---KSE--... - * | / - * KSEG---THREAD--THREAD--THREAD - * - * (processors run THREADs from the KSEG until they are exhausted or - * the KSEG exhausts its quantum) - * - * XXX This structure is stictly speaking, not needed any more - * and its fields will move to the thread structure. The first 'N' - * threads can be kept trak of with a simple count. Do this soon. - */ - -struct kse { - struct proc *ke_proc; /* (*) Associated process. */ - struct ksegrp *ke_ksegrp; /* (*) Associated KSEG. */ - TAILQ_ENTRY(kse) ke_kglist; /* (*) Queue of KSEs in ke_ksegrp. */ - TAILQ_ENTRY(kse) ke_kgrlist; /* (*) Queue of KSEs in this state. */ - TAILQ_ENTRY(kse) ke_procq; /* (j/z) Run queue. */ - struct thread *ke_thread; /* (*) Active associated thread. */ -#define ke_startzero ke_flags - int ke_flags; /* (j) KEF_* flags. */ - fixpt_t ke_pctcpu; /* (j) %cpu during p_swtime. */ - u_char ke_oncpu; /* (j) Which cpu we are on. */ - char ke_rqindex; /* (j) Run queue index. */ - enum { - KES_UNUSED = 0x0, - KES_IDLE, - KES_ONRUNQ, - KES_UNQUEUED, /* in transit */ - KES_THREAD /* slaved to thread state */ - } ke_state; /* (j) KSE status. */ -#define ke_endzero ke_cpticks - int ke_cpticks; /* (j) Ticks of cpu time. */ - struct runq *ke_runq; /* runq the kse is currently on */ -}; - -/* flags kept in ke_flags */ -#define KEF_BOUND 0x00001 /* Stuck on a cpu.. long term */ -#define KEF_EXIT 0x00002 /* KSE is being killed. */ -#define KEF_DIDRUN 0x00004 /* KSE actually ran. */ - /*************************************************************** * Scheduler private extensions to thread, ksegrp and proc structures. * @@ -131,42 +75,57 @@ */ struct td_sched { - struct kse *std_last_kse; /* (j) Previous value of td_kse. */ - struct kse *std_kse; /* (j) Current KSE if running. */ + TAILQ_ENTRY(td_sched) std_kgrlist; /* (*) Queue of threads in this state. */ + TAILQ_ENTRY(td_sched) std_procq; /* (j/z) Run queue. */ + + struct thread *std_thread; /* (*) Active associated thread. */ +#define std_startzero std_pctcpu + fixpt_t std_pctcpu; /* (j) %cpu during p_swtime. */ + u_char std_oncpu; /* (j) Which cpu we are on. */ + char std_rqindex; /* (j) Run queue index. */ + enum { + STDS_UNUSED = 0x0, + STDS_IDLE, + STDS_ONRUNQ, + STDS_UNQUEUED, /* in transit */ + STDS_THREAD /* slaved to thread state */ + } std_state; /* (j) KSE status. */ +#define std_endzero std_cpticks + int std_cpticks; /* (j) Ticks of cpu time. */ + struct runq *std_runq; /* runq the td_sched is currently on */ }; -#define td_last_kse td_sched->std_last_kse -#define td_kse td_sched->std_kse +#define td_kgrlist td_sched->std_kgrlist +#define td_procq td_sched->std_procq +#define td_thread td_sched->std_thread +#define td_pctcpu td_sched->std_pctcpu +#define td_oncpu td_sched->std_oncpu +#define td_rqindex td_sched->std_rqindex +#define td_state td_sched->std_state +#define td_cpticks td_sched->std_cpticks +#define td_runq td_sched->std_runq + + +/* flags kept in ke_flags */ +#define TDF_BOUND TDF_SCHED1 /* Stuck on a cpu.. long term */ +#define TDF_EXIT TDF_SCHED2 /* thread is being killed. */ +#define TDF_DIDRUN TDF_SCHED3 /* thread actually ran. */ struct kg_sched { - TAILQ_HEAD(, kse) skg_kseq; /* (ke_kglist) All KSEs. */ - TAILQ_HEAD(, kse) skg_iq; /* (ke_kgrlist) All idle KSEs. */ struct thread *skg_last_assigned; /* (j) Last thread assigned */ - /* ( to a KSE). */ - int skg_runq_kses; /* (j) Num KSEs on runq. */ - int skg_idle_kses; /* (j) Num KSEs on iq. */ - int skg_kses; /* (j) Num KSEs in group. */ + /* to the system scheduler */ + int skg_runq_threads; /* (j) Num KSEs on runq. */ + int skg_avail_opennings; /* (j) Num KSEs on iq. */ int skg_concurrancy; /* (j) desired concurrancy */ }; -#define kg_kseq kg_sched->skg_kseq -#define kg_iq kg_sched->skg_iq #define kg_last_assigned kg_sched->skg_last_assigned -#define kg_runq_kses kg_sched->skg_runq_kses -#define kg_idle_kses kg_sched->skg_idle_kses -#define kg_kses kg_sched->skg_kses +#define kg_runq_threads kg_sched->skg_runq_threads +#define kg_avail_opennings kg_sched->skg_avail_opennings -#define FIRST_KSE_IN_KSEGRP(kg) TAILQ_FIRST(&(kg)->kg_kseq) -#define FIRST_KSE_IN_PROC(p) FIRST_KSE_IN_KSEGRP(FIRST_KSEGRP_IN_PROC(p)) - /**************************************************************** * function prototypes */ -static void kse_free(struct kse *ke); -static void kse_stash(struct kse *ke); -static void kse_reassign(struct kse *ke); -static struct kse * kse_alloc(void); -static void kse_link(struct kse *ke, struct ksegrp *kg); -static void kse_unlink(struct kse *ke); +static void recycle_slot(struct ksegrp *kg); /* was kse_reassign */ #define KTR_4BSD 0x0 #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start)) @@ -185,15 +144,15 @@ #endif #define NICE_WEIGHT 1 /* Priorities per nice level. */ -#define KE_RUNQ_PCPU(ke) \ - ((ke)->ke_runq != 0 && (ke)->ke_runq != &runq) +#define STD_RUNQ_PCPU(std) \ + ((std)->std_runq != 0 && (std)->std_runq != &runq) /* - * KSE_CAN_MIGRATE macro returns true if the kse can migrate between + * TD_CAN_MIGRATE macro returns true if the thread can migrate between * cpus. */ -#define KSE_CAN_MIGRATE(ke) \ - ((ke)->ke_thread->td_pinned == 0 && ((ke)->ke_flags & KEF_BOUND) == 0) +#define TD_CAN_MIGRATE(td) \ + ((td)->td_pinned == 0 && ((td)->td_flags & TDF_BOUND) == 0) static int sched_tdcnt; /* Total runnable threads in the system. */ static int sched_quantum; /* Roundrobin scheduling quantum in ticks. */ @@ -211,7 +170,7 @@ static void resetpriority(struct ksegrp *kg); static void sched_add(struct thread *td); static void sched_rem(struct thread *td); -static struct kse * sched_choose(void); +static struct td_sched * sched_choose(void); static void adjustrunqueue( struct thread *td, int newpri) ; @@ -264,8 +223,6 @@ #include <machine/runq.h> -struct kse; - /* * Run queue parameters. */ @@ -276,7 +233,7 @@ /* * Head of run queues. */ -TAILQ_HEAD(rqhead, kse); +TAILQ_HEAD(rqhead, td_sched); /* * Bit array which maintains the status of a run queue. When a queue is @@ -295,11 +252,11 @@ struct rqhead rq_queues[RQ_NQS]; }; -static void runq_add(struct runq *, struct kse *); +static void runq_add(struct runq *, struct thread *); static int runq_check(struct runq *); -static struct kse *runq_choose(struct runq *); +static struct td_sched *runq_choose(struct runq *); static void runq_init(struct runq *); -static void runq_remove(struct runq *, struct kse *); +static void runq_remove(struct runq *, struct thread *); #endif /* end of Jake copyright file */ /* @@ -363,7 +320,7 @@ { mtx_assert(&sched_lock, MA_OWNED); - if (td->td_priority < curthread->td_priority && curthread->td_kse) + if (td->td_priority < curthread->td_priority && curthread->td_sched) curthread->td_flags |= TDF_NEEDRESCHED; } @@ -397,7 +354,7 @@ /* * Constants for digital decay and forget: * 90% of (kg_estcpu) usage in 5 * loadav time - * 95% of (ke_pctcpu) usage in 60 seconds (load insensitive) + * 95% of (td_pctcpu) usage in 60 seconds (load insensitive) * Note that, as ps(1) mentions, this can let percentages * total over 100% (I've seen 137.9% for 3 processes). * @@ -462,7 +419,7 @@ #define loadfactor(loadav) (2 * (loadav)) #define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE)) -/* decay 95% of `ke_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ +/* decay 95% of `td_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ static fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */ SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, ""); @@ -493,7 +450,7 @@ register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); struct thread *td; struct proc *p; - struct kse *ke; + struct td_sched *ts; struct ksegrp *kg; int awake, realstathz; @@ -511,54 +468,57 @@ p->p_swtime++; FOREACH_KSEGRP_IN_PROC(p, kg) { awake = 0; - FOREACH_KSE_IN_GROUP(kg, ke) { + FOREACH_THREAD(kg, td) { + ts = td->td_sched; /* * Increment sleep time (if sleeping). We * ignore overflow, as above. */ /* + * *** XXXKSE ** no longer true.... FIX * The kse slptimes are not touched in wakeup * because the thread may not HAVE a KSE. */ - if (ke->ke_state == KES_ONRUNQ) { + if (std->std_state == STDS_ONRUNQ) { awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; - } else if ((ke->ke_state == KES_THREAD) && - (TD_IS_RUNNING(ke->ke_thread))) { + td->td_flags &= ~TDF_DIDRUN; + } else if ((std->std_state == STDS_THREAD) && + (TD_IS_RUNNING(td))) { awake = 1; - /* Do not clear KEF_DIDRUN */ - } else if (ke->ke_flags & KEF_DIDRUN) { + /* Do not clear TDF_DIDRUN */ + } else if (td->td_flags & TDF_DIDRUN) { awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; - } - + td->td_flags &= ~TDF_DIDRUN; + } else + continue; + /* - * ke_pctcpu is only for ps and ttyinfo(). + * std_pctcpu is only for ps and ttyinfo(). * Do it per kse, and add them up at the end? * XXXKSE */ - ke->ke_pctcpu = (ke->ke_pctcpu * ccpu) >> + std->std_pctcpu = (std->std_pctcpu * ccpu) >> FSHIFT; /* - * If the kse has been idle the entire second, + * If the thread has been idle the entire second, * stop recalculating its priority until * it wakes up. */ - if (ke->ke_cpticks == 0) + if (std->std_cpticks == 0) continue; #if (FSHIFT >= CCPU_SHIFT) - ke->ke_pctcpu += (realstathz == 100) - ? ((fixpt_t) ke->ke_cpticks) << + std->std_pctcpu += (realstathz == 100) + ? ((fixpt_t) std->std_cpticks) << (FSHIFT - CCPU_SHIFT) : - 100 * (((fixpt_t) ke->ke_cpticks) + 100 * (((fixpt_t) std->std_cpticks) << (FSHIFT - CCPU_SHIFT)) / realstathz; #else - ke->ke_pctcpu += ((FSCALE - ccpu) * - (ke->ke_cpticks * + std->std_pctcpu += ((FSCALE - ccpu) * + (std->std_cpticks * FSCALE / realstathz)) >> FSHIFT; #endif - ke->ke_cpticks = 0; - } /* end of kse loop */ + std->std_cpticks = 0; + } /* end of thread loop */ /* * If there are ANY running threads in this KSEGRP, * then don't count it as sleeping. @@ -715,7 +675,7 @@ } /* - * report teh round-robin scheduling interval. + * report the round-robin scheduling interval. * Called from: * (posix scheduling interface) */ @@ -747,13 +707,11 @@ sched_clock(struct thread *td) { struct ksegrp *kg; - struct kse *ke; mtx_assert(&sched_lock, MA_OWNED); kg = td->td_ksegrp; - ke = td->td_kse; - ke->ke_cpticks++; + td->td_sched->std_cpticks++; kg->kg_estcpu = ESTCPULIM(kg->kg_estcpu + 1); if ((kg->kg_estcpu % INVERSE_ESTCPU_WEIGHT) == 0) { resetpriority(kg); @@ -765,7 +723,7 @@ /* * charge childs scheduling cpu usage to parent. * - * XXXKSE assume only one thread & kse & ksegrp keep estcpu in each ksegrp. + * XXXKSE assume only one thread & ksegrp keep estcpu in each ksegrp. * Charge it to the ksegrp that did the wait since process estcpu is sum of * all ksegrps, this is strictly as expected. Assume that the child process * aggregated all the estcpu into the 'built-in' ksegrp. @@ -780,13 +738,14 @@ mtx_assert(&sched_lock, MA_OWNED); kg = FIRST_KSEGRP_IN_PROC(parent); /* XXXKSE */ - td->td_kse->ke_flags |= KEF_EXIT; + td->td_flags |= TDF_EXIT; kg->kg_estcpu = ESTCPULIM(kg->kg_estcpu + td->td_ksegrp->kg_estcpu); } /* * We should give the estcpu to someone, but WHO? + * Only called on exit of last thread in the ksegrp. * Called from: * thread_exit() (for threaded programs only) */ @@ -805,14 +764,10 @@ void sched_thread_exit(struct thread *td) { - struct kse *ke; - ke = td->td_kse; - - if ((td->td_proc->p_flag & P_SA) && ke != NULL) { - ke->ke_thread = NULL; - td->td_kse = NULL; - kse_reassign(ke); + if (td->td_proc->p_flag & P_SA) { + td->td_ksegrp->kg_avail_opennings++; + recycle_slot(td->td_ksegrp); } if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt--; @@ -829,23 +784,15 @@ void sched_thr_exit(struct thread *td) { - struct kse *ke; - - ke = td->td_kse; if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt--; - - /* td is about to be freed, but keep it clean */ - td->td_kse = NULL; - td->td_last_kse = NULL; - kse_unlink(ke); /* also frees it */ } /* * Allocate any resources the scheduler needs to allocate or set up - * on a new process at fork() time. + * on a new process at fork() time. Set up our scheduler specifi extensions. * Called from: * fork1() */ @@ -853,27 +800,33 @@ sched_fork(struct thread *td, struct proc *child) { struct thread *newtd; - struct kse *newke; + struct td_sched *newstd; newtd = FIRST_THREAD_IN_PROC(child); - newke = FIRST_KSE_IN_PROC(child); - bzero(&newke->ke_startzero, - (unsigned) RANGEOF(struct kse, ke_startzero, ke_endzero)); - newke->ke_state = KES_THREAD; - newke->ke_cpticks = 0; - sched_fork_ksegrp(td, FIRST_KSEGRP_IN_PROC(child)); - newke->ke_thread = newtd; - newtd->td_kse = newke; + newstd = newtd->td_sched; + bzero(&newstd->std_startzero, + (unsigned)RANGEOF(struct td_sched, std_startzero, std_endzero)); + newstd->std_state = STDS_THREAD; + newstd->std_cpticks = 0; + + newtd->td_ksegrp->kg_concurrancy = 1; + /* non threaded process. ignore thread fairness stuff */ + newtd->td_ksegrp->kg_avail_opennings = 0; + /* Our child inherrits our estimated cpu requirement */ + newtd->td_ksegrp->kg_estcpu = td->td_ksegrp->kg_estcpu; } /* - * When we make a new ksegrp, teh scheduler may need to know about it. + * When we make a new ksegrp, the scheduler may need to know about it. + * make sure the new ksegrp inherrits our cpu estimates. * Called from: * kse_create() */ void sched_fork_ksegrp(struct thread *td, struct ksegrp *newkg) { + newkg->kg_concurrancy = 1; + newkg->kg_avail_opennings = 1; newkg->kg_estcpu = td->td_ksegrp->kg_estcpu; } @@ -958,21 +911,20 @@ void sched_switch(struct thread *td, int flags, struct thread *newtd) { - struct kse *ke; + struct td_sched *std; struct proc *p; - ke = td->td_kse; + std = td->td_sched; p = td->td_proc; mtx_assert(&sched_lock, MA_OWNED); - KASSERT((ke->ke_state == KES_THREAD), ("sched_switch: kse state?")); + KASSERT((std->std_state == STDS_THREAD), ("sched_switch: kse state?")); if ((p->p_flag & P_NOLOAD) == 0) sched_tdcnt--; if (newtd != NULL && (newtd->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt++; td->td_lastcpu = td->td_oncpu; - td->td_last_kse = ke; td->td_flags &= ~(TDF_NEEDRESCHED | TDF_OWEPREEMPT); td->td_oncpu = NOCPU; /* @@ -984,22 +936,26 @@ if (td == PCPU_GET(idlethread)) TD_SET_CAN_RUN(td); else if (TD_IS_RUNNING(td)) { - /* Put us back on the run queue (kse and all). */ + /* Put us back on the run queue. */ + if (p->p_flag & P_SA) + kg->kg_avail_opennings++; setrunqueue(td); } else if (p->p_flag & P_SA) { /* * We will not be on the run queue. So we must be * sleeping or similar. As it's available, - * someone else can use the KSE if they need it. + * another thread could use our 'slot'. */ - kse_reassign(ke); + kg->kg_avail_opennings++; + recycle_slot(kg); } if (newtd == NULL) newtd = choosethread(flags); - if (td != newtd) + if (td != newtd) { cpu_switch(td, newtd); - sched_lock.mtx_lock = (uintptr_t)td; - td->td_oncpu = PCPU_GET(cpuid); + sched_lock.mtx_lock = (uintptr_t)td; + td->td_oncpu = PCPU_GET(cpuid); + } } /* @@ -1029,24 +985,21 @@ * the fact that the thread is becoming runnable, * and decide which run queue to use. * Called from: - * kse_reassign() (local) + * recycle_slot() (local) * adjustrunqueue() (local) * setrunqueue() (local) */ static void sched_add(struct thread *td) { - struct kse *ke; + struct td_sched *std; - ke = td->td_kse; + std = td->td_sched; mtx_assert(&sched_lock, MA_OWNED); - KASSERT((ke->ke_thread != NULL), ("sched_add: No thread on KSE")); - KASSERT((ke->ke_thread->td_kse != NULL), - ("sched_add: No KSE on thread")); - KASSERT(ke->ke_state != KES_ONRUNQ, - ("sched_add: kse %p (%s) already in run queue", ke, - ke->ke_proc->p_comm)); - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, + KASSERT(std->std_state != STDS_ONRUNQ, + ("sched_add: kse %p (%s) already in run queue", std, + std->std_proc->p_comm)); + KASSERT(std->std_proc->p_sflag & PS_INMEM, ("sched_add: process swapped out")); #ifdef SMP @@ -1054,32 +1007,32 @@ * Only try to preempt if the thread is unpinned or pinned to the * current CPU. */ - if (KSE_CAN_MIGRATE(ke) || ke->ke_runq == &runq_pcpu[PCPU_GET(cpuid)]) + if (TD_CAN_MIGRATE(td) || std->std_runq == &runq_pcpu[PCPU_GET(cpuid)]) #endif if (maybe_preempt(td)) return; - ke->ke_ksegrp->kg_runq_kses++; - ke->ke_state = KES_ONRUNQ; + td->td_ksegrp->kg_runq_threads++; + std->std_state = STDS_ONRUNQ; #ifdef SMP - if (KSE_CAN_MIGRATE(ke)) { - CTR1(KTR_4BSD, "adding kse:%p to gbl runq", ke); - ke->ke_runq = &runq; + if (TD_CAN_MIGRATE(td)) { + CTR1(KTR_4BSD, "adding thread:%p to gbl runq", td); + std->std_runq = &runq; } else { - CTR1(KTR_4BSD, "adding kse:%p to pcpu runq", ke); - if (!KE_RUNQ_PCPU(ke)) - ke->ke_runq = &runq_pcpu[PCPU_GET(cpuid)]; + CTR1(KTR_4BSD, "adding thread:%p to pcpu runq", td); + if (!STD_RUNQ_PCPU(std)) + std->std_runq = &runq_pcpu[PCPU_GET(cpuid)]; } #else - ke->ke_runq = &runq; + std->std_runq = &runq; #endif if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt++; - runq_add(ke->ke_runq, ke); + runq_add(std->std_runq, std); } /* - * Change scheduler stats to reflect removal of a thread from teh run queues. + * Change scheduler stats to reflect removal of a thread from the run queues. * Called from: * remrunqueue() (local) * adjustrunqueue() (local) @@ -1088,70 +1041,21 @@ static void sched_rem(struct thread *td) { - struct kse *ke; + struct td_sched *std; - ke = td->td_kse; - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, + std = td->td_sched; + KASSERT(std->std_proc->p_sflag & PS_INMEM, ("sched_rem: process swapped out")); - KASSERT((ke->ke_state == KES_ONRUNQ), + KASSERT((std->std_state == STDS_ONRUNQ), ("sched_rem: KSE not on run queue")); mtx_assert(&sched_lock, MA_OWNED); if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt--; - runq_remove(ke->ke_runq, ke); + runq_remove(std->std_runq, std); - ke->ke_state = KES_THREAD; - ke->ke_ksegrp->kg_runq_kses--; -} - -/* - * Try find a runnable thread from teh per-cpu or - * general run queues and adjust scheduler stats accordingly. - * Called from: - * choosethread() (local) - */ -static struct kse * -sched_choose(void) -{ - struct kse *ke; - struct runq *rq; - -#ifdef SMP - struct kse *kecpu; - - rq = &runq; - ke = runq_choose(&runq); - kecpu = runq_choose(&runq_pcpu[PCPU_GET(cpuid)]); - - if (ke == NULL || - (kecpu != NULL && - kecpu->ke_thread->td_priority < ke->ke_thread->td_priority)) { - CTR2(KTR_4BSD, "choosing kse %p from pcpu runq %d", kecpu, - PCPU_GET(cpuid)); - ke = kecpu; - rq = &runq_pcpu[PCPU_GET(cpuid)]; - } else { - CTR1(KTR_4BSD, "choosing kse %p from main runq", ke); - } - -#else - rq = &runq; - ke = runq_choose(&runq); -#endif - - if (ke != NULL) { - runq_remove(rq, ke); - ke->ke_state = KES_THREAD; - - KASSERT((ke->ke_thread != NULL), - ("sched_choose: No thread on KSE")); - KASSERT((ke->ke_thread->td_kse != NULL), - ("sched_choose: No KSE on thread")); - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, - ("sched_choose: process swapped out")); - } - return (ke); + std->std_state = STDS_THREAD; + std->std_ksegrp->kg_runq_threads--; } /* @@ -1188,21 +1092,21 @@ void sched_bind(struct thread *td, int cpu) { - struct kse *ke; + struct td_sched *std; mtx_assert(&sched_lock, MA_OWNED); KASSERT(TD_IS_RUNNING(td), ("sched_bind: cannot bind non-running thread")); - ke = td->td_kse; + std = td->td_sched; - ke->ke_flags |= KEF_BOUND; + td->td_flags |= TDF_BOUND; #ifdef SMP - ke->ke_runq = &runq_pcpu[cpu]; + std->std_runq = &runq_pcpu[cpu]; if (PCPU_GET(cpuid) == cpu) return; - ke->ke_state = KES_THREAD; + std->std_state = STDS_THREAD; mi_switch(SW_VOL, NULL); #endif @@ -1217,7 +1121,7 @@ sched_unbind(struct thread* td) { mtx_assert(&sched_lock, MA_OWNED); - td->td_kse->ke_flags &= ~KEF_BOUND; + td->td_flags &= ~TDF_BOUND; } /* @@ -1265,29 +1169,13 @@ fixpt_t sched_pctcpu(struct thread *td) { - struct kse *ke; - ke = td->td_kse; - if (ke == NULL) - ke = td->td_last_kse; - if (ke) - return (ke->ke_pctcpu); - - return (0); + return (td->td_sched->std_pctcpu); } - - -static uma_zone_t kse_zone; - -struct kse kse0; static struct kg_sched kg_sched0; static struct td_sched td_sched0; - -extern struct mtx kse_zombie_lock; -TAILQ_HEAD(, kse) zombie_kses = TAILQ_HEAD_INITIALIZER(zombie_kses); - /* * Occasionally the scheduler may need to do some GC.. * Called from: @@ -1296,20 +1184,6 @@ void sched_GC(void) { - struct kse *ke_first, *ke_next; - - if (!TAILQ_EMPTY(&zombie_kses)) { - mtx_lock_spin(&kse_zombie_lock); - ke_first = TAILQ_FIRST(&zombie_kses); - if (ke_first) - TAILQ_INIT(&zombie_kses); - mtx_unlock_spin(&kse_zombie_lock); - while (ke_first) { - ke_next = TAILQ_NEXT(ke_first, ke_procq); - kse_free(ke_first); - ke_first = ke_next; - } - } } /* @@ -1328,19 +1202,14 @@ proc0.p_sched = NULL; /* XXX */ thread0.td_sched = &td_sched0; - /* - * and link in our own per scheduler struct - */ - kse_link(&kse0, &ksegrp0); /* - * and set it up as if BOUND and running + * and set it up as if running */ - kse0.ke_thread = &thread0; - thread0.td_kse = &kse0; /* we are running */ - kse0.ke_state = KES_THREAD; + std->std_oncpu = NOCPU; /* wrong.. can we use PCPU(cpuid) yet? */ + td_sched0.std_state = STDS_THREAD; + kg_sched0.concurrancy = 1; + kg_sched0.skg_avail_opennings = 0; /* we are already running */ - kse_zone = uma_zcreate("KSE", sizeof (struct kse), - NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0); } /* @@ -1352,25 +1221,18 @@ int sched_thr_newthread(struct thread *td, struct thread *newtd, int flags) { - struct kse *newke; - /* Initialize our kse structure. */ - newke = kse_alloc(); - bzero(&newke->ke_startzero, - RANGEOF(struct kse, ke_startzero, ke_endzero)); + newstd = newtd->td_sched; + bzero(&newstd->std_startzero, + RANGEOF(struct td_sched, std_startzero, std_endzero)); - /* Link the thread and kse into the ksegrp and make it runnable. */ + /* Link the thread into the ksegrp and make it runnable. */ mtx_lock_spin(&sched_lock); thread_link(newtd, td->td_ksegrp); - kse_link(newke, td->td_ksegrp); - /* Bind this thread and kse together. */ - newtd->td_kse = newke; - newke->ke_thread = newtd; - bzero(&newke->ke_startzero, - (unsigned) RANGEOF(struct kse, ke_startzero, ke_endzero)); - newke->ke_state = KES_THREAD; - newke->ke_cpticks = 0; + std->std_oncpu = NOCPU; + newstd->std_state = STDS_THREAD; + newstd->std_cpticks = 0; TD_SET_CAN_RUN(newtd); if ((flags & THR_SUSPENDED) == 0) @@ -1380,63 +1242,7 @@ return (0); /* the API could fail but not in this case */ } -/***************************** - * KSE zone/allocation methods. - */ /* - * Allocate a kse. - */ -static struct kse * -kse_alloc(void) -{ - return (uma_zalloc(kse_zone, M_WAITOK)); -} - -/* - * Deallocate a kse. - */ -static void -kse_free(struct kse *td) -{ - uma_zfree(kse_zone, td); -} - -/* - * Stash an embarasingly extra kse into the zombie kse queue. - * Called from: - * kse_unlink() (local) - */ -static void -kse_stash(struct kse *ke) -{ - mtx_lock_spin(&kse_zombie_lock); - TAILQ_INSERT_HEAD(&zombie_kses, ke, ke_procq); - mtx_unlock_spin(&kse_zombie_lock); -} - -/* - * KSE is linked into kse group. - * Called from: - * sched_newproc() (local) - * sched_thr_newthread() (local) - * schedinit() (local) - * sched_set_concurrancy() (local) - * - */ -static void -kse_link( struct kse *ke, struct ksegrp *kg) -{ - TAILQ_INSERT_HEAD(&kg->kg_kseq, ke, ke_kglist); - kg->kg_kses++; - ke->ke_state = KES_UNQUEUED; - ke->ke_proc = kg->kg_proc; /* really just a shortcut */ - ke->ke_ksegrp = kg; - ke->ke_thread = NULL; - ke->ke_oncpu = NOCPU; - ke->ke_flags = 0; -} - -/* * Allocate scheduler specific per-process resources. * The thread and ksegrp have already been linked in. * Called from: @@ -1445,19 +1251,13 @@ int sched_newproc(struct proc *p, struct ksegrp *kg, struct thread *td) { - struct kse *ke; + struct td_sched *std; + + std = td->td_sched; - /* - * For a new process, allocate a single KSE to the ksegrp. - */ - ke = kse_alloc(); - if (ke) { - kse_link(ke, kg); - td->td_kse = ke; - ke->ke_thread = td; - return (0); - } - return (ENOMEM ); + std->std_state = STDS_UNQUEUED; + std->std_oncpu = NOCPU; + return (0); } /* @@ -1471,11 +1271,9 @@ sched_init_ksegrp(struct ksegrp *kg) { - TAILQ_INIT(&kg->kg_kseq); /* all kses in ksegrp */ - TAILQ_INIT(&kg->kg_iq); /* all idle kses in ksegrp */ - kg->kg_kses = 0; - kg->kg_runq_kses = 0; /* XXXKSE change name */ - kg->kg_idle_kses = 0; + kg->kg_runq_threads = 0; /* XXXKSE change name */ + kg->kg_avail_opennings = 1; + kg->kg_concurrancy = 1; } /* @@ -1483,64 +1281,18 @@ * Fix up the per-scheduler resources associated with it. * Called from: * thread_dtor() - * thread_initi() + * thread_init() */ /* Assumes td->td_sched is already set up */ void sched_init_thread(struct thread *td) { - td->td_last_kse = NULL; - td->td_kse = NULL; -} - - -/* - * code to take the per-scheduler KSE structure - * off the ksegrp it is hanging off and free it - * Called from: - * sched_destroyproc() - * sched_thr_exit() - * sched_set_concurrancy() via REDUCE_KSES() - * kse_reassign() via REDUCE_KSES() - */ -static void -kse_unlink(struct kse *ke) -{ - struct ksegrp *kg; - - mtx_assert(&sched_lock, MA_OWNED); - kg = ke->ke_ksegrp; - TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist); - if (ke->ke_state == KES_IDLE) { - TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist); - kg->kg_idle_kses--; - } - /* - * Aggregate stats from the KSE - * ## none yet ## - */ - - kse_stash(ke); } -/* - * Whenever we have idle KSEs and there are too many for the concurrancy, - * then free as many as we can. Don't free too many if we have threads - * to run/kill. - */ -#define REDUCE_KSES(kg, skg) \ -do { \ - while ((skg->skg_concurrancy < skg->skg_kses) && \ - (skg->skg_idle_kses > 0) && \ - (skg->skg_kses > kg->kg_numthreads)) { \ - kse_unlink(TAILQ_FIRST(&skg->skg_iq)); \ - } \ -} while (0) - /* * Called by the uma process fini routine.. >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407052330.i65NUPr2095079>