diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_main.c | 32 | ||||
-rw-r--r-- | sys/kern/kern_clock.c | 20 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 18 | ||||
-rw-r--r-- | sys/kern/kern_idle.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_intr.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_kse.c | 329 | ||||
-rw-r--r-- | sys/kern/kern_poll.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 39 | ||||
-rw-r--r-- | sys/kern/kern_resource.c | 89 | ||||
-rw-r--r-- | sys/kern/kern_subr.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_switch.c | 635 | ||||
-rw-r--r-- | sys/kern/kern_thr.c | 36 | ||||
-rw-r--r-- | sys/kern/kern_thread.c | 254 | ||||
-rw-r--r-- | sys/kern/kern_umtx.c | 6 | ||||
-rw-r--r-- | sys/kern/ksched.c | 45 | ||||
-rw-r--r-- | sys/kern/sched_4bsd.c | 764 | ||||
-rw-r--r-- | sys/kern/sched_ule.c | 1131 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 12 | ||||
-rw-r--r-- | sys/kern/tty.c | 27 |
19 files changed, 890 insertions, 2565 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index d002a99..a911e11 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -95,9 +95,6 @@ static struct session session0; static struct pgrp pgrp0; struct proc proc0; struct thread thread0 __aligned(8); -#ifdef KSE -struct ksegrp ksegrp0; -#endif struct vmspace vmspace0; struct proc *initproc; @@ -366,34 +363,16 @@ proc0_init(void *dummy __unused) struct proc *p; unsigned i; struct thread *td; -#ifdef KSE - struct ksegrp *kg; -#endif GIANT_REQUIRED; p = &proc0; td = &thread0; -#ifdef KSE - kg = &ksegrp0; -#endif /* * Initialize magic number. */ p->p_magic = P_MAGIC; -#ifdef KSE - /* - * Initialize thread, process and ksegrp structures. - */ - procinit(); /* set up proc zone */ - threadinit(); /* set up thead, upcall and KSEGRP zones */ - - /* - * Initialise scheduler resources. - * Add scheduler specific parts to proc, ksegrp, thread as needed. - */ -#else /* * Initialize thread and process structures. */ @@ -404,7 +383,6 @@ proc0_init(void *dummy __unused) * Initialise scheduler resources. * Add scheduler specific parts to proc, thread as needed. */ -#endif schedinit(); /* scheduler gets its house in order */ /* * Initialize sleep queue hash table @@ -440,15 +418,9 @@ proc0_init(void *dummy __unused) STAILQ_INIT(&p->p_ktr); p->p_nice = NZERO; td->td_state = TDS_RUNNING; -#ifdef KSE - kg->kg_pri_class = PRI_TIMESHARE; - kg->kg_user_pri = PUSER; - kg->kg_base_user_pri = PUSER; -#else td->td_pri_class = PRI_TIMESHARE; td->td_user_pri = PUSER; td->td_base_user_pri = PUSER; -#endif td->td_priority = PVM; td->td_base_pri = PUSER; td->td_oncpu = 0; @@ -758,11 +730,7 @@ kick_init(const void *udata __unused) td = FIRST_THREAD_IN_PROC(initproc); mtx_lock_spin(&sched_lock); TD_SET_CAN_RUN(td); -#ifdef KSE - setrunqueue(td, SRQ_BORING); /* XXXKSE */ -#else setrunqueue(td, SRQ_BORING); -#endif mtx_unlock_spin(&sched_lock); } SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index cd98bdd..a3732a8 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -203,23 +203,12 @@ hardclock_cpu(int usermode) mtx_lock_spin_flags(&sched_lock, MTX_QUIET); sched_tick(); #ifdef KSE +#if 0 /* for now do nothing */ if (p->p_flag & P_SA) { - /* XXXKSE What to do? */ - } else { - pstats = p->p_stats; - if (usermode && - timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) { - p->p_sflag |= PS_ALRMPEND; - td->td_flags |= TDF_ASTPENDING; - } - if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) { - p->p_sflag |= PS_PROFPEND; - td->td_flags |= TDF_ASTPENDING; - } + /* XXXKSE What to do? Should do more. */ } -#else +#endif +#endif pstats = p->p_stats; if (usermode && timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) && @@ -232,7 +221,6 @@ hardclock_cpu(int usermode) p->p_sflag |= PS_PROFPEND; td->td_flags |= TDF_ASTPENDING; } -#endif mtx_unlock_spin_flags(&sched_lock, MTX_QUIET); #ifdef HWPMC_HOOKS diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 9c5597e..a12ed64 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -205,9 +205,6 @@ fork1(td, flags, pages, procp) struct filedesc *fd; struct filedesc_to_leader *fdtol; struct thread *td2; -#ifdef KSE - struct ksegrp *kg2; -#endif struct sigacts *newsigacts; int error; @@ -477,9 +474,6 @@ again: * then copy the section that is copied directly from the parent. */ td2 = FIRST_THREAD_IN_PROC(p2); -#ifdef KSE - kg2 = FIRST_KSEGRP_IN_PROC(p2); -#endif /* Allocate and switch to an alternate kstack if specified. */ if (pages != 0) @@ -492,19 +486,11 @@ again: __rangeof(struct proc, p_startzero, p_endzero)); bzero(&td2->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); -#ifdef KSE - bzero(&kg2->kg_startzero, - __rangeof(struct ksegrp, kg_startzero, kg_endzero)); -#endif bcopy(&p1->p_startcopy, &p2->p_startcopy, __rangeof(struct proc, p_startcopy, p_endcopy)); bcopy(&td->td_startcopy, &td2->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); -#ifdef KSE - bcopy(&td->td_ksegrp->kg_startcopy, &kg2->kg_startcopy, - __rangeof(struct ksegrp, kg_startcopy, kg_endcopy)); -#endif td2->td_sigstk = td->td_sigstk; td2->td_sigmask = td->td_sigmask; @@ -526,11 +512,7 @@ again: mtx_unlock_spin(&sched_lock); p2->p_ucred = crhold(td->td_ucred); -#ifdef KSE - td2->td_ucred = crhold(p2->p_ucred); /* XXXKSE */ -#else td2->td_ucred = crhold(p2->p_ucred); -#endif #ifdef AUDIT audit_proc_fork(p1, p2); #endif diff --git a/sys/kern/kern_idle.c b/sys/kern/kern_idle.c index f66056a..9096d985 100644 --- a/sys/kern/kern_idle.c +++ b/sys/kern/kern_idle.c @@ -79,11 +79,7 @@ idle_setup(void *dummy) td = FIRST_THREAD_IN_PROC(p); TD_SET_CAN_RUN(td); td->td_flags |= TDF_IDLETD; -#ifdef KSE - sched_class(td->td_ksegrp, PRI_IDLE); -#else sched_class(td, PRI_IDLE); -#endif sched_prio(td, PRI_MAX_IDLE); mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index 2aa4c47..53cbc4b 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -296,11 +296,7 @@ ithread_create(const char *name) panic("kthread_create() failed with %d", error); td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */ mtx_lock_spin(&sched_lock); -#ifdef KSE - td->td_ksegrp->kg_pri_class = PRI_ITHD; -#else - td->td_pri_class = PRI_ITHD; -#endif + sched_class(td, PRI_ITHD); TD_SET_IWAIT(td); mtx_unlock_spin(&sched_lock); td->td_pflags |= TDP_ITHREAD; diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index fadaa44..4d27d71 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -48,9 +48,6 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> #ifdef KSE -/* - * KSEGRP related storage. - */ static uma_zone_t upcall_zone; /* DEBUG ONLY */ @@ -86,24 +83,24 @@ upcall_free(struct kse_upcall *ku) } void -upcall_link(struct kse_upcall *ku, struct ksegrp *kg) +upcall_link(struct kse_upcall *ku, struct proc *p) { mtx_assert(&sched_lock, MA_OWNED); - TAILQ_INSERT_TAIL(&kg->kg_upcalls, ku, ku_link); - ku->ku_ksegrp = kg; - kg->kg_numupcalls++; + TAILQ_INSERT_TAIL(&p->p_upcalls, ku, ku_link); + ku->ku_proc = p; + p->p_numupcalls++; } void upcall_unlink(struct kse_upcall *ku) { - struct ksegrp *kg = ku->ku_ksegrp; + struct proc *p = ku->ku_proc; mtx_assert(&sched_lock, MA_OWNED); KASSERT(ku->ku_owner == NULL, ("%s: have owner", __func__)); - TAILQ_REMOVE(&kg->kg_upcalls, ku, ku_link); - kg->kg_numupcalls--; + TAILQ_REMOVE(&p->p_upcalls, ku, ku_link); + p->p_numupcalls--; upcall_stash(ku); } @@ -305,7 +302,6 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) { #ifdef KSE struct proc *p; - struct ksegrp *kg; struct kse_upcall *ku, *ku2; int error, count; @@ -316,11 +312,10 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) if ((ku = td->td_upcall) == NULL || TD_CAN_UNBIND(td)) return (EINVAL); - kg = td->td_ksegrp; count = 0; /* - * Calculate the existing non-exiting upcalls in this ksegroup. + * Calculate the existing non-exiting upcalls in this process. * If we are the last upcall but there are still other threads, * then do not exit. We need the other threads to be able to * complete whatever they are doing. @@ -330,12 +325,12 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) */ PROC_LOCK(p); mtx_lock_spin(&sched_lock); - FOREACH_UPCALL_IN_GROUP(kg, ku2) { + FOREACH_UPCALL_IN_PROC(p, ku2) { if (ku2->ku_flags & KUF_EXITING) count++; } - if ((kg->kg_numupcalls - count) == 1 && - (kg->kg_numthreads > 1)) { + if ((p->p_numupcalls - count) == 1 && + (p->p_numthreads > 1)) { mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); return (EDEADLK); @@ -360,20 +355,12 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) mtx_lock_spin(&sched_lock); upcall_remove(td); if (p->p_numthreads != 1) { - /* - * If we are not the last thread, but we are the last - * thread in this ksegrp, then by definition this is not - * the last group and we need to clean it up as well. - * thread_exit will clean up the kseg as needed. - */ thread_stopped(p); thread_exit(); /* NOTREACHED */ } /* * This is the last thread. Just return to the user. - * We know that there is only one ksegrp too, as any others - * would have been discarded in previous calls to thread_exit(). * Effectively we have left threading mode.. * The only real thing left to do is ensure that the * scheduler sets out concurrency back to 1 as that may be a @@ -409,7 +396,6 @@ kse_release(struct thread *td, struct kse_release_args *uap) { #ifdef KSE struct proc *p; - struct ksegrp *kg; struct kse_upcall *ku; struct timespec timeout; struct timeval tv; @@ -417,7 +403,6 @@ kse_release(struct thread *td, struct kse_release_args *uap) int error; p = td->td_proc; - kg = td->td_ksegrp; if ((ku = td->td_upcall) == NULL || TD_CAN_UNBIND(td)) return (EINVAL); if (uap->timeout != NULL) { @@ -452,14 +437,14 @@ kse_release(struct thread *td, struct kse_release_args *uap) } else { if ((ku->ku_flags & KUF_DOUPCALL) == 0 && ((ku->ku_mflags & KMF_NOCOMPLETED) || - (kg->kg_completed == NULL))) { - kg->kg_upsleeps++; + (p->p_completed == NULL))) { + p->p_upsleeps++; td->td_kflags |= TDK_KSEREL; - error = msleep(&kg->kg_completed, &p->p_mtx, + error = msleep(&p->p_completed, &p->p_mtx, PPAUSE|PCATCH, "kserel", (uap->timeout ? tvtohz(&tv) : 0)); td->td_kflags &= ~(TDK_KSEREL | TDK_WAKEUP); - kg->kg_upsleeps--; + p->p_upsleeps--; } PROC_UNLOCK(p); } @@ -482,7 +467,6 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap) { #ifdef KSE struct proc *p; - struct ksegrp *kg; struct kse_upcall *ku; struct thread *td2; @@ -495,23 +479,18 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap) PROC_LOCK(p); mtx_lock_spin(&sched_lock); if (uap->mbx) { - FOREACH_KSEGRP_IN_PROC(p, kg) { - FOREACH_UPCALL_IN_GROUP(kg, ku) { - if (ku->ku_mailbox == uap->mbx) - break; - } - if (ku) + FOREACH_UPCALL_IN_PROC(p, ku) { + if (ku->ku_mailbox == uap->mbx) break; } } else { - kg = td->td_ksegrp; - if (kg->kg_upsleeps) { + if (p->p_upsleeps) { mtx_unlock_spin(&sched_lock); - wakeup(&kg->kg_completed); + wakeup(&p->p_completed); PROC_UNLOCK(p); return (0); } - ku = TAILQ_FIRST(&kg->kg_upcalls); + ku = TAILQ_FIRST(&p->p_upcalls); } if (ku == NULL) { mtx_unlock_spin(&sched_lock); @@ -526,7 +505,7 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap) if (!(td2->td_kflags & TDK_WAKEUP)) { td2->td_kflags |= TDK_WAKEUP; if (td2->td_kflags & TDK_KSEREL) - sleepq_remove(td2, &kg->kg_completed); + sleepq_remove(td2, &p->p_completed); else sleepq_remove(td2, &p->p_siglist); } @@ -542,11 +521,11 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap) } /* - * No new KSEG: first call: use current KSE, don't schedule an upcall + * newgroup == 0: first call: use current KSE, don't schedule an upcall * All other situations, do allocate max new KSEs and schedule an upcall. * * XXX should be changed so that 'first' behaviour lasts for as long - * as you have not made a kse in this ksegrp. i.e. as long as we do not have + * as you have not made a thread in this proc. i.e. as long as we do not have * a mailbox.. */ /* struct kse_create_args { @@ -557,8 +536,6 @@ int kse_create(struct thread *td, struct kse_create_args *uap) { #ifdef KSE - struct ksegrp *newkg; - struct ksegrp *kg; struct proc *p; struct kse_mailbox mbx; struct kse_upcall *newku; @@ -566,135 +543,66 @@ kse_create(struct thread *td, struct kse_create_args *uap) struct thread *newtd; p = td->td_proc; - kg = td->td_ksegrp; - if ((err = copyin(uap->mbx, &mbx, sizeof(mbx)))) - return (err); - ncpus = mp_ncpus; - if (virtual_cpu != 0) - ncpus = virtual_cpu; - /* - * If the new UTS mailbox says that this - * will be a BOUND lwp, then it had better - * have its thread mailbox already there. - * In addition, this ksegrp will be limited to - * a concurrency of 1. There is more on this later. - */ - if (mbx.km_flags & KMF_BOUND) { - if (mbx.km_curthread == NULL) - return (EINVAL); - ncpus = 1; - } else { - sa = TDP_SA; - } - - PROC_LOCK(p); /* * Processes using the other threading model can't * suddenly start calling this one + * XXX maybe... */ if ((p->p_flag & (P_SA|P_HADTHREADS)) == P_HADTHREADS) { PROC_UNLOCK(p); return (EINVAL); } - - /* - * Limit it to NCPU upcall contexts per ksegrp in any case. - * There is a small race here as we don't hold proclock - * until we inc the ksegrp count, but it's not really a big problem - * if we get one too many, but we save a proc lock. - */ - if ((!uap->newgroup) && (kg->kg_numupcalls >= ncpus)) { - PROC_UNLOCK(p); - return (EPROCLIM); - } - if (!(p->p_flag & P_SA)) { first = 1; p->p_flag |= P_SA|P_HADTHREADS; } - PROC_UNLOCK(p); + if ((err = copyin(uap->mbx, &mbx, sizeof(mbx)))) + return (err); + + ncpus = mp_ncpus; + if (virtual_cpu != 0) + ncpus = virtual_cpu; /* - * Now pay attention! - * If we are going to be bound, then we need to be either - * a new group, or the first call ever. In either - * case we will be creating (or be) the only thread in a group. - * and the concurrency will be set to 1. - * This is not quite right, as we may still make ourself - * bound after making other ksegrps but it will do for now. - * The library will only try do this much. + * If the new UTS mailbox says that this + * will be a BOUND lwp, then it had better + * have its thread mailbox already there. */ - if (!sa && !(uap->newgroup || first)) - return (EINVAL); - - if (uap->newgroup) { - newkg = ksegrp_alloc(); - bzero(&newkg->kg_startzero, - __rangeof(struct ksegrp, kg_startzero, kg_endzero)); - bcopy(&kg->kg_startcopy, &newkg->kg_startcopy, - __rangeof(struct ksegrp, kg_startcopy, kg_endcopy)); - sched_init_concurrency(newkg); + if ((mbx.km_flags & KMF_BOUND) || uap->newgroup) { + if (mbx.km_curthread == NULL) + return (EINVAL); + ncpus = 1; + if (!(uap->newgroup || first)) + return (EINVAL); + } else { + sa = TDP_SA; PROC_LOCK(p); - if (p->p_numksegrps >= max_groups_per_proc) { + /* + * Limit it to NCPU upcall contexts per proc in any case. + */ + if (p->p_numupcalls >= ncpus) { PROC_UNLOCK(p); - ksegrp_free(newkg); return (EPROCLIM); } - ksegrp_link(newkg, p); - mtx_lock_spin(&sched_lock); - sched_fork_ksegrp(td, newkg); - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); - } else { /* - * We want to make a thread in our own ksegrp. + * We want to make a thread (bound or unbound). * If we are just the first call, either kind * is ok, but if not then either we must be * already an upcallable thread to make another, * or a bound thread to make one of those. * Once again, not quite right but good enough for now.. XXXKSE + * XXX bogus */ + PROC_UNLOCK(p); if (!first && ((td->td_pflags & TDP_SA) != sa)) return (EINVAL); - - newkg = kg; + if (p->p_numupcalls == 0) { + sched_set_concurrency(p, ncpus); + } } /* - * This test is a bit "indirect". - * It might simplify things if we made a direct way of testing - * if a ksegrp has been worked on before. - * In the case of a bound request and the concurrency being set to - * one, the concurrency will already be 1 so it's just inefficient - * but not dangerous to call this again. XXX - */ - if (newkg->kg_numupcalls == 0) { - /* - * Initialize KSE group with the appropriate - * concurrency. - * - * For a multiplexed group, create as as much concurrency - * as the number of physical cpus. - * This increases concurrency in the kernel even if the - * userland is not MP safe and can only run on a single CPU. - * In an ideal world, every physical cpu should execute a - * thread. If there is enough concurrency, threads in the - * kernel can be executed parallel on different cpus at - * full speed without being restricted by the number of - * upcalls the userland provides. - * Adding more upcall structures only increases concurrency - * in userland. - * - * For a bound thread group, because there is only one thread - * in the group, we only set the concurrency for the group - * to 1. A thread in this kind of group will never schedule - * an upcall when blocked. This simulates pthread system - * scope thread behaviour. - */ - sched_set_concurrency(newkg, ncpus); - } - /* * Even bound LWPs get a mailbox and an upcall to hold it. */ newku = upcall_alloc(); @@ -711,33 +619,38 @@ kse_create(struct thread *td, struct kse_create_args *uap) PROC_LOCK(p); mtx_lock_spin(&sched_lock); - if (newkg->kg_numupcalls >= ncpus) { - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); - upcall_free(newku); - return (EPROCLIM); - } + if (sa) { + if( p->p_numupcalls >= ncpus) { + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(p); + upcall_free(newku); + return (EPROCLIM); + } - /* - * If we are the first time, and a normal thread, - * then transfer all the signals back to the 'process'. - * SA threading will make a special thread to handle them. - */ - if (first && sa) { - sigqueue_move_set(&td->td_sigqueue, &p->p_sigqueue, - &td->td_sigqueue.sq_signals); - SIGFILLSET(td->td_sigmask); - SIG_CANTMASK(td->td_sigmask); + /* + * If we are the first time, and a normal thread, + * then transfer all the signals back to the 'process'. + * SA threading will make a special thread to handle them. + */ + if (first) { + sigqueue_move_set(&td->td_sigqueue, &p->p_sigqueue, + &td->td_sigqueue.sq_signals); + SIGFILLSET(td->td_sigmask); + SIG_CANTMASK(td->td_sigmask); + } + } else { + /* should subtract from process count (later) */ } /* - * Make the new upcall available to the ksegrp. + * Make the new upcall available to the process. * It may or may not use it, but it's available. */ - upcall_link(newku, newkg); + upcall_link(newku, p); PROC_UNLOCK(p); if (mbx.km_quantum) - newkg->kg_upquantum = max(1, mbx.km_quantum / tick); +/* XXX should this be in the thread? */ + p->p_upquantum = max(1, mbx.km_quantum / tick); /* * Each upcall structure has an owner thread, find which @@ -745,8 +658,11 @@ kse_create(struct thread *td, struct kse_create_args *uap) */ if (uap->newgroup) { /* - * Because the new ksegrp hasn't a thread, - * create an initial upcall thread to own it. + * The newgroup parameter now means + * "bound, non SA, system scope" + * It is only used for the interrupt thread at the + * moment I think + * We'll rename it later. */ newtd = thread_schedule_upcall(td, newku); } else { @@ -771,6 +687,7 @@ kse_create(struct thread *td, struct kse_create_args *uap) /* * Let the UTS instance know its LWPID. * It doesn't really care. But the debugger will. + * XXX warning.. remember that this moves. */ suword32(&newku->ku_mailbox->km_lwp, newtd->td_tid); @@ -785,6 +702,14 @@ kse_create(struct thread *td, struct kse_create_args *uap) if (sa) { newtd->td_pflags |= TDP_SA; + /* + * If we are starting a new thread, kick it off. + */ + if (newtd != td) { + mtx_lock_spin(&sched_lock); + setrunqueue(newtd, SRQ_BORING); + mtx_unlock_spin(&sched_lock); + } } else { newtd->td_pflags &= ~TDP_SA; @@ -816,17 +741,11 @@ kse_create(struct thread *td, struct kse_create_args *uap) _PRELE(p); } PROC_UNLOCK(p); + mtx_lock_spin(&sched_lock); + setrunqueue(newtd, SRQ_BORING); + mtx_unlock_spin(&sched_lock); } } - - /* - * If we are starting a new thread, kick it off. - */ - if (newtd != td) { - mtx_lock_spin(&sched_lock); - setrunqueue(newtd, SRQ_BORING); - mtx_unlock_spin(&sched_lock); - } return (0); #else /* !KSE */ return (EOPNOTSUPP); @@ -886,20 +805,18 @@ kse_GC(void) /* * Store the thread context in the UTS's mailbox. * then add the mailbox at the head of a list we are building in user space. - * The list is anchored in the ksegrp structure. + * The list is anchored in the proc structure. */ int thread_export_context(struct thread *td, int willexit) { struct proc *p; - struct ksegrp *kg; uintptr_t mbx; void *addr; int error = 0, sig; mcontext_t mc; p = td->td_proc; - kg = td->td_ksegrp; /* * Post sync signal, or process SIGKILL and SIGSTOP. @@ -940,14 +857,14 @@ thread_export_context(struct thread *td, int willexit) * entry into this one */ for (;;) { - mbx = (uintptr_t)kg->kg_completed; + mbx = (uintptr_t)p->p_completed; if (suword(addr, mbx)) { error = EFAULT; goto bad; } PROC_LOCK(p); - if (mbx == (uintptr_t)kg->kg_completed) { - kg->kg_completed = td->td_mailbox; + if (mbx == (uintptr_t)p->p_completed) { + p->p_completed = td->td_mailbox; /* * The thread context may be taken away by * other upcall threads when we unlock @@ -970,19 +887,18 @@ bad: } /* - * Take the list of completed mailboxes for this KSEGRP and put them on this + * Take the list of completed mailboxes for this Process and put them on this * upcall's mailbox as it's the next one going up. */ static int -thread_link_mboxes(struct ksegrp *kg, struct kse_upcall *ku) +thread_link_mboxes(struct proc *p, struct kse_upcall *ku) { - struct proc *p = kg->kg_proc; void *addr; uintptr_t mbx; addr = (void *)(&ku->ku_mailbox->km_completed); for (;;) { - mbx = (uintptr_t)kg->kg_completed; + mbx = (uintptr_t)p->p_completed; if (suword(addr, mbx)) { PROC_LOCK(p); psignal(p, SIGSEGV); @@ -990,8 +906,8 @@ thread_link_mboxes(struct ksegrp *kg, struct kse_upcall *ku) return (EFAULT); } PROC_LOCK(p); - if (mbx == (uintptr_t)kg->kg_completed) { - kg->kg_completed = NULL; + if (mbx == (uintptr_t)p->p_completed) { + p->p_completed = NULL; PROC_UNLOCK(p); break; } @@ -1109,7 +1025,7 @@ thread_schedule_upcall(struct thread *td, struct kse_upcall *ku) */ bcopy(&td->td_startcopy, &td2->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); - thread_link(td2, ku->ku_ksegrp); + thread_link(td2, ku->ku_proc); /* inherit parts of blocked thread's context as a good template */ cpu_set_upcall(td2, td); /* Let the new thread become owner of the upcall */ @@ -1210,7 +1126,6 @@ void thread_user_enter(struct thread *td) { struct proc *p = td->td_proc; - struct ksegrp *kg; struct kse_upcall *ku; struct kse_thr_mailbox *tmbx; uint32_t flags; @@ -1233,7 +1148,6 @@ thread_user_enter(struct thread *td) * note where our mailbox is. */ - kg = td->td_ksegrp; ku = td->td_upcall; KASSERT(ku != NULL, ("no upcall owned")); @@ -1291,10 +1205,9 @@ int thread_userret(struct thread *td, struct trapframe *frame) { struct kse_upcall *ku; - struct ksegrp *kg, *kg2; struct proc *p; struct timespec ts; - int error = 0, upcalls, uts_crit; + int error = 0, uts_crit; /* Nothing to do with bound thread */ if (!(td->td_pflags & TDP_SA)) @@ -1311,7 +1224,6 @@ thread_userret(struct thread *td, struct trapframe *frame) } p = td->td_proc; - kg = td->td_ksegrp; ku = td->td_upcall; /* @@ -1323,9 +1235,9 @@ thread_userret(struct thread *td, struct trapframe *frame) if (TD_CAN_UNBIND(td)) { td->td_pflags &= ~TDP_CAN_UNBIND; if ((td->td_flags & TDF_NEEDSIGCHK) == 0 && - (kg->kg_completed == NULL) && + (p->p_completed == NULL) && (ku->ku_flags & KUF_DOUPCALL) == 0 && - (kg->kg_upquantum && ticks < kg->kg_nextupcall)) { + (p->p_upquantum && ticks < p->p_nextupcall)) { nanotime(&ts); error = copyout(&ts, (caddr_t)&ku->ku_mailbox->km_timeofday, @@ -1346,8 +1258,8 @@ thread_userret(struct thread *td, struct trapframe *frame) } else if (td->td_mailbox && (ku == NULL)) { thread_export_context(td, 1); PROC_LOCK(p); - if (kg->kg_upsleeps) - wakeup(&kg->kg_completed); + if (p->p_upsleeps) + wakeup(&p->p_completed); WITNESS_WARN(WARN_PANIC, &p->p_mtx.mtx_object, "thread exiting in userret"); sigqueue_flush(&td->td_sigqueue); @@ -1366,14 +1278,7 @@ thread_userret(struct thread *td, struct trapframe *frame) mtx_lock_spin(&sched_lock); p->p_maxthrwaits++; while (p->p_numthreads > max_threads_per_proc) { - upcalls = 0; - FOREACH_KSEGRP_IN_PROC(p, kg2) { - if (kg2->kg_numupcalls == 0) - upcalls++; - else - upcalls += kg2->kg_numupcalls; - } - if (upcalls >= max_threads_per_proc) + if (p->p_numupcalls >= max_threads_per_proc) break; mtx_unlock_spin(&sched_lock); if (msleep(&p->p_numthreads, &p->p_mtx, PPAUSE|PCATCH, @@ -1391,7 +1296,7 @@ thread_userret(struct thread *td, struct trapframe *frame) if (td->td_pflags & TDP_UPCALLING) { uts_crit = 0; - kg->kg_nextupcall = ticks + kg->kg_upquantum; + p->p_nextupcall = ticks + p->p_upquantum; /* * There is no more work to do and we are going to ride * this thread up to userland as an upcall. @@ -1436,7 +1341,7 @@ thread_userret(struct thread *td, struct trapframe *frame) * this KSE's mailbox. */ if (!(ku->ku_mflags & KMF_NOCOMPLETED) && - (error = thread_link_mboxes(kg, ku)) != 0) + (error = thread_link_mboxes(p, ku)) != 0) goto out; } if (!uts_crit) { @@ -1479,7 +1384,6 @@ out: void thread_continued(struct proc *p) { - struct ksegrp *kg; struct kse_upcall *ku; struct thread *td; @@ -1490,18 +1394,13 @@ thread_continued(struct proc *p) return; if (p->p_flag & P_TRACED) { - FOREACH_KSEGRP_IN_PROC(p, kg) { - td = TAILQ_FIRST(&kg->kg_threads); - if (td == NULL) - continue; - /* not a SA group, nothing to do */ - if (!(td->td_pflags & TDP_SA)) - continue; - FOREACH_UPCALL_IN_GROUP(kg, ku) { + td = TAILQ_FIRST(&p->p_threads); + if (td && (td->td_pflags & TDP_SA)) { + FOREACH_UPCALL_IN_PROC(p, ku) { mtx_lock_spin(&sched_lock); ku->ku_flags |= KUF_DOUPCALL; mtx_unlock_spin(&sched_lock); - wakeup(&kg->kg_completed); + wakeup(&p->p_completed); } } } diff --git a/sys/kern/kern_poll.c b/sys/kern/kern_poll.c index 67338b0..8e87607 100644 --- a/sys/kern/kern_poll.c +++ b/sys/kern/kern_poll.c @@ -581,11 +581,7 @@ poll_idle(void) rtp.prio = RTP_PRIO_MAX; /* lowest priority */ rtp.type = RTP_PRIO_IDLE; mtx_lock_spin(&sched_lock); -#ifdef KSE - rtp_to_pri(&rtp, td->td_ksegrp); -#else rtp_to_pri(&rtp, td); -#endif mtx_unlock_spin(&sched_lock); for (;;) { diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 2401b6b..0eb4407 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -141,9 +141,6 @@ proc_dtor(void *mem, int size, void *arg) { struct proc *p; struct thread *td; -#if defined(INVARIANTS) && defined(KSE) - struct ksegrp *kg; -#endif /* INVARIANTS checks go here */ p = (struct proc *)mem; @@ -151,14 +148,7 @@ proc_dtor(void *mem, int size, void *arg) #ifdef INVARIANTS KASSERT((p->p_numthreads == 1), ("bad number of threads in exiting process")); -#ifdef KSE - KASSERT((p->p_numksegrps == 1), ("free proc with > 1 ksegrp")); -#endif KASSERT((td != NULL), ("proc_dtor: bad thread pointer")); -#ifdef KSE - kg = FIRST_KSEGRP_IN_PROC(p); - KASSERT((kg != NULL), ("proc_dtor: bad kg pointer")); -#endif KASSERT(STAILQ_EMPTY(&p->p_ktr), ("proc_dtor: non-empty p_ktr")); #endif @@ -181,25 +171,15 @@ proc_init(void *mem, int size, int flags) { struct proc *p; struct thread *td; -#ifdef KSE - struct ksegrp *kg; -#endif p = (struct proc *)mem; p->p_sched = (struct p_sched *)&p[1]; td = thread_alloc(); -#ifdef KSE - kg = ksegrp_alloc(); -#endif bzero(&p->p_mtx, sizeof(struct mtx)); mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK); p->p_stats = pstats_alloc(); -#ifdef KSE - proc_linkup(p, kg, td); - sched_newproc(p, kg, td); -#else proc_linkup(p, td); -#endif + sched_newproc(p, td); return (0); } @@ -215,9 +195,6 @@ proc_fini(void *mem, int size) p = (struct proc *)mem; pstats_free(p->p_stats); -#ifdef KSE - ksegrp_free(FIRST_KSEGRP_IN_PROC(p)); -#endif thread_free(FIRST_THREAD_IN_PROC(p)); mtx_destroy(&p->p_mtx); if (p->p_ksi != NULL) @@ -782,9 +759,6 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp) static void fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp) { -#ifdef KSE - struct ksegrp *kg; -#endif struct proc *p; p = td->td_proc; @@ -824,15 +798,6 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp) kp->ki_stat = SIDL; } -#ifdef KSE - kg = td->td_ksegrp; - - /* things in the KSE GROUP */ - kp->ki_estcpu = kg->kg_estcpu; - kp->ki_slptime = kg->kg_slptime; - kp->ki_pri.pri_user = kg->kg_user_pri; - kp->ki_pri.pri_class = kg->kg_pri_class; -#endif /* Things in the thread */ kp->ki_wchan = td->td_wchan; kp->ki_pri.pri_level = td->td_priority; @@ -845,12 +810,10 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp) kp->ki_pcb = td->td_pcb; kp->ki_kstack = (void *)td->td_kstack; kp->ki_pctcpu = sched_pctcpu(td); -#ifndef KSE kp->ki_estcpu = td->td_estcpu; kp->ki_slptime = td->td_slptime; kp->ki_pri.pri_class = td->td_pri_class; kp->ki_pri.pri_user = td->td_user_pri; -#endif /* We can't get this anymore but ps etc never used it anyway. */ kp->ki_rqindex = 0; diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index f885953..e351d18 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -319,11 +319,7 @@ rtprio_thread(struct thread *td, struct rtprio_thread_args *uap) else td1 = thread_find(p, uap->lwpid); if (td1 != NULL) -#ifdef KSE - pri_to_rtp(td1->td_ksegrp, &rtp); -#else pri_to_rtp(td1, &rtp); -#endif else error = ESRCH; mtx_unlock_spin(&sched_lock); @@ -359,11 +355,7 @@ rtprio_thread(struct thread *td, struct rtprio_thread_args *uap) else td1 = thread_find(p, uap->lwpid); if (td1 != NULL) -#ifdef KSE - error = rtp_to_pri(&rtp, td1->td_ksegrp); -#else error = rtp_to_pri(&rtp, td1); -#endif else error = ESRCH; mtx_unlock_spin(&sched_lock); @@ -396,11 +388,7 @@ rtprio(td, uap) { struct proc *curp; struct proc *p; -#ifdef KSE - struct ksegrp *kg; -#else struct thread *tdp; -#endif struct rtprio rtp; int cierror, error; @@ -436,23 +424,14 @@ rtprio(td, uap) * as leaving it zero. */ if (uap->pid == 0) { -#ifdef KSE - pri_to_rtp(td->td_ksegrp, &rtp); -#else pri_to_rtp(td, &rtp); -#endif } else { struct rtprio rtp2; rtp.type = RTP_PRIO_IDLE; rtp.prio = RTP_PRIO_MAX; -#ifdef KSE - FOREACH_KSEGRP_IN_PROC(p, kg) { - pri_to_rtp(kg, &rtp2); -#else FOREACH_THREAD_IN_PROC(p, tdp) { pri_to_rtp(tdp, &rtp2); -#endif if (rtp2.type < rtp.type || (rtp2.type == rtp.type && rtp2.prio < rtp.prio)) { @@ -493,39 +472,19 @@ rtprio(td, uap) } } -#ifdef KSE - /* - * If we are setting our own priority, set just our - * KSEGRP but if we are doing another process, - * do all the groups on that process. If we - * specify our own pid we do the latter. - */ -#else /* * If we are setting our own priority, set just our * thread but if we are doing another process, * do all the threads on that process. If we * specify our own pid we do the latter. */ -#endif mtx_lock_spin(&sched_lock); if (uap->pid == 0) { -#ifdef KSE - error = rtp_to_pri(&rtp, td->td_ksegrp); -#else error = rtp_to_pri(&rtp, td); -#endif } else { -#ifdef KSE - FOREACH_KSEGRP_IN_PROC(p, kg) { - if ((error = rtp_to_pri(&rtp, kg)) != 0) { - break; - } -#else FOREACH_THREAD_IN_PROC(p, td) { if ((error = rtp_to_pri(&rtp, td)) != 0) break; -#endif } } mtx_unlock_spin(&sched_lock); @@ -539,11 +498,7 @@ rtprio(td, uap) } int -#ifdef KSE -rtp_to_pri(struct rtprio *rtp, struct ksegrp *kg) -#else rtp_to_pri(struct rtprio *rtp, struct thread *td) -#endif { u_char newpri; @@ -552,87 +507,43 @@ rtp_to_pri(struct rtprio *rtp, struct thread *td) return (EINVAL); switch (RTP_PRIO_BASE(rtp->type)) { case RTP_PRIO_REALTIME: -#ifdef KSE newpri = PRI_MIN_REALTIME + rtp->prio; -#else - newpri = PRI_MIN_REALTIME + rtp->prio; -#endif break; case RTP_PRIO_NORMAL: -#ifdef KSE newpri = PRI_MIN_TIMESHARE + rtp->prio; -#else - newpri = PRI_MIN_TIMESHARE + rtp->prio; -#endif break; case RTP_PRIO_IDLE: -#ifdef KSE newpri = PRI_MIN_IDLE + rtp->prio; -#else - newpri = PRI_MIN_IDLE + rtp->prio; -#endif break; default: return (EINVAL); } -#ifdef KSE - sched_class(kg, rtp->type); - sched_user_prio(kg, newpri); - if (curthread->td_ksegrp == kg) { - sched_prio(curthread, kg->kg_user_pri); /* XXX dubious */ - } -#else sched_class(td, rtp->type); /* XXX fix */ sched_user_prio(td, newpri); if (curthread == td) sched_prio(curthread, td->td_user_pri); /* XXX dubious */ -#endif return (0); } void -#ifdef KSE -pri_to_rtp(struct ksegrp *kg, struct rtprio *rtp) -#else pri_to_rtp(struct thread *td, struct rtprio *rtp) -#endif { mtx_assert(&sched_lock, MA_OWNED); -#ifdef KSE - switch (PRI_BASE(kg->kg_pri_class)) { -#else switch (PRI_BASE(td->td_pri_class)) { -#endif case PRI_REALTIME: -#ifdef KSE - rtp->prio = kg->kg_base_user_pri - PRI_MIN_REALTIME; -#else rtp->prio = td->td_base_user_pri - PRI_MIN_REALTIME; -#endif break; case PRI_TIMESHARE: -#ifdef KSE - rtp->prio = kg->kg_base_user_pri - PRI_MIN_TIMESHARE; -#else rtp->prio = td->td_base_user_pri - PRI_MIN_TIMESHARE; -#endif break; case PRI_IDLE: -#ifdef KSE - rtp->prio = kg->kg_base_user_pri - PRI_MIN_IDLE; -#else rtp->prio = td->td_base_user_pri - PRI_MIN_IDLE; -#endif break; default: break; } -#ifdef KSE - rtp->type = kg->kg_pri_class; -#else rtp->type = td->td_pri_class; -#endif } #if defined(COMPAT_43) diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 631dfa2..ba288ac 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -430,11 +430,7 @@ uio_yield(void) td = curthread; mtx_lock_spin(&sched_lock); DROP_GIANT(); -#ifdef KSE - sched_prio(td, td->td_ksegrp->kg_user_pri); /* XXXKSE */ -#else sched_prio(td, td->td_user_pri); -#endif mi_switch(SW_INVOL, NULL); mtx_unlock_spin(&sched_lock); PICKUP_GIANT(); diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index 1521143..039c781 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -24,68 +24,6 @@ * SUCH DAMAGE. */ -#ifdef KSE -/*** -Here is the logic.. - -If there are N processors, then there are at most N KSEs (kernel -schedulable entities) working to process threads that belong to a -KSEGROUP (kg). If there are X of these KSEs actually running at the -moment in question, then there are at most M (N-X) of these KSEs on -the run queue, as running KSEs are not on the queue. - -Runnable threads are queued off the KSEGROUP in priority order. -If there are M or more threads runnable, the top M threads -(by priority) are 'preassigned' to the M KSEs not running. The KSEs take -their priority from those threads and are put on the run queue. - -The last thread that had a priority high enough to have a KSE associated -with it, AND IS ON THE RUN QUEUE is pointed to by -kg->kg_last_assigned. If no threads queued off the KSEGROUP have KSEs -assigned as all the available KSEs are activly running, or because there -are no threads queued, that pointer is NULL. - -When a KSE is removed from the run queue to become runnable, we know -it was associated with the highest priority thread in the queue (at the head -of the queue). If it is also the last assigned we know M was 1 and must -now be 0. Since the thread is no longer queued that pointer must be -removed from it. Since we know there were no more KSEs available, -(M was 1 and is now 0) and since we are not FREEING our KSE -but using it, we know there are STILL no more KSEs available, we can prove -that the next thread in the ksegrp list will not have a KSE to assign to -it, so we can show that the pointer must be made 'invalid' (NULL). - -The pointer exists so that when a new thread is made runnable, it can -have its priority compared with the last assigned thread to see if -it should 'steal' its KSE or not.. i.e. is it 'earlier' -on the list than that thread or later.. If it's earlier, then the KSE is -removed from the last assigned (which is now not assigned a KSE) -and reassigned to the new thread, which is placed earlier in the list. -The pointer is then backed up to the previous thread (which may or may not -be the new thread). - -When a thread sleeps or is removed, the KSE becomes available and if there -are queued threads that are not assigned KSEs, the highest priority one of -them is assigned the KSE, which is then placed back on the run queue at -the approipriate place, and the kg->kg_last_assigned pointer is adjusted down -to point to it. - -The following diagram shows 2 KSEs and 3 threads from a single process. - - RUNQ: --->KSE---KSE--... (KSEs queued at priorities from threads) - \ \____ - \ \ - KSEGROUP---thread--thread--thread (queued in priority order) - \ / - \_______________/ - (last_assigned) - -The result of this scheme is that the M available KSEs are always -queued at the priorities they have inherrited from the M highest priority -threads for that KSEGROUP. If this situation changes, the KSEs are -reassigned to keep this true. -***/ -#endif #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -126,8 +64,6 @@ __FBSDID("$FreeBSD$"); CTASSERT((RQB_BPW * RQB_LEN) == RQ_NQS); -#define td_kse td_sched - /* * kern.sched.preemption allows user space to determine if preemption support * is compiled in or not. It is not currently a boot or runtime flag that @@ -144,79 +80,40 @@ SYSCTL_INT(_kern_sched, OID_AUTO, preemption, CTLFLAG_RD, /************************************************************************ * Functions that manipulate runnability from a thread perspective. * ************************************************************************/ -#ifdef KSE -/* - * Select the KSE that will be run next. From that find the thread, and - * remove it from the KSEGRP's run queue. If there is thread clustering, - * this will be what does it. - */ -#else /* * Select the thread that will be run next. */ -#endif struct thread * choosethread(void) { -#ifdef KSE - struct kse *ke; -#endif + struct td_sched *ts; struct thread *td; -#ifdef KSE - struct ksegrp *kg; -#endif #if defined(SMP) && (defined(__i386__) || defined(__amd64__)) if (smp_active == 0 && PCPU_GET(cpuid) != 0) { /* Shutting down, run idlethread on AP's */ td = PCPU_GET(idlethread); -#ifdef KSE - ke = td->td_kse; -#endif + ts = td->td_sched; CTR1(KTR_RUNQ, "choosethread: td=%p (idle)", td); -#ifdef KSE - ke->ke_flags |= KEF_DIDRUN; -#else - td->td_kse->ke_flags |= KEF_DIDRUN; -#endif + ts->ts_flags |= TSF_DIDRUN; TD_SET_RUNNING(td); return (td); } #endif retry: -#ifdef KSE - ke = sched_choose(); - if (ke) { - td = ke->ke_thread; - KASSERT((td->td_kse == ke), ("kse/thread mismatch")); - kg = ke->ke_ksegrp; - if (td->td_proc->p_flag & P_HADTHREADS) { - if (kg->kg_last_assigned == td) { - kg->kg_last_assigned = TAILQ_PREV(td, - threadqueue, td_runq); - } - TAILQ_REMOVE(&kg->kg_runq, td, td_runq); - } -#else - td = sched_choose(); - if (td) { -#endif + ts = sched_choose(); + if (ts) { + td = ts->ts_thread; CTR2(KTR_RUNQ, "choosethread: td=%p pri=%d", td, td->td_priority); } else { /* Simulate runq_choose() having returned the idle thread */ td = PCPU_GET(idlethread); -#ifdef KSE - ke = td->td_kse; -#endif + ts = td->td_sched; CTR1(KTR_RUNQ, "choosethread: td=%p (idle)", td); } -#ifdef KSE - ke->ke_flags |= KEF_DIDRUN; -#else - td->td_kse->ke_flags |= KEF_DIDRUN; -#endif + ts->ts_flags |= TSF_DIDRUN; /* * If we are in panic, only allow system threads, @@ -233,91 +130,24 @@ retry: return (td); } -#ifdef KSE -/* - * Given a surplus system slot, try assign a new runnable thread to it. - * Called from: - * sched_thread_exit() (local) - * sched_switch() (local) - * sched_thread_exit() (local) - * remrunqueue() (local) (not at the moment) - */ -static void -slot_fill(struct ksegrp *kg) -{ - struct thread *td; - - mtx_assert(&sched_lock, MA_OWNED); - while (kg->kg_avail_opennings > 0) { - /* - * Find the first unassigned thread - */ - if ((td = kg->kg_last_assigned) != NULL) - td = TAILQ_NEXT(td, td_runq); - else - td = TAILQ_FIRST(&kg->kg_runq); - - /* - * If we found one, send it to the system scheduler. - */ - if (td) { - kg->kg_last_assigned = td; - sched_add(td, SRQ_YIELDING); - CTR2(KTR_RUNQ, "slot_fill: td%p -> kg%p", td, kg); - } else { - /* no threads to use up the slots. quit now */ - break; - } - } -} -#ifdef SCHED_4BSD +#if 0 /* - * Remove a thread from its KSEGRP's run queue. - * This in turn may remove it from a KSE if it was already assigned - * to one, possibly causing a new thread to be assigned to the KSE - * and the KSE getting a new priority. + * currently not used.. threads remove themselves from the + * run queue by running. */ static void remrunqueue(struct thread *td) { - struct thread *td2, *td3; - struct ksegrp *kg; - struct kse *ke; - mtx_assert(&sched_lock, MA_OWNED); KASSERT((TD_ON_RUNQ(td)), ("remrunqueue: Bad state on run queue")); - kg = td->td_ksegrp; - ke = td->td_kse; CTR1(KTR_RUNQ, "remrunqueue: td%p", td); TD_SET_CAN_RUN(td); - /* - * If it is not a threaded process, take the shortcut. - */ - if ((td->td_proc->p_flag & P_HADTHREADS) == 0) { - /* remve from sys run queue and free up a slot */ - sched_rem(td); - return; - } - td3 = TAILQ_PREV(td, threadqueue, td_runq); - TAILQ_REMOVE(&kg->kg_runq, td, td_runq); - if (ke->ke_state == KES_ONRUNQ) { - /* - * This thread has been assigned to the system run queue. - * We need to dissociate it and try assign the - * KSE to the next available thread. Then, we should - * see if we need to move the KSE in the run queues. - */ - sched_rem(td); - td2 = kg->kg_last_assigned; - KASSERT((td2 != NULL), ("last assigned has wrong value")); - if (td2 == td) - kg->kg_last_assigned = td3; - /* slot_fill(kg); */ /* will replace it with another */ - } + /* remove from sys run queue */ + sched_rem(td); + return; } #endif -#endif /* * Change the priority of a thread that is on the run queue. @@ -325,229 +155,32 @@ remrunqueue(struct thread *td) void adjustrunqueue( struct thread *td, int newpri) { -#ifdef KSE - struct ksegrp *kg; -#endif - struct kse *ke; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); KASSERT((TD_ON_RUNQ(td)), ("adjustrunqueue: Bad state on run queue")); - ke = td->td_kse; + ts = td->td_sched; CTR1(KTR_RUNQ, "adjustrunqueue: td%p", td); -#ifdef KSE - /* - * If it is not a threaded process, take the shortcut. - */ - if ((td->td_proc->p_flag & P_HADTHREADS) == 0) { - /* We only care about the kse in the run queue. */ - td->td_priority = newpri; -#ifndef SCHED_CORE - if (ke->ke_rqindex != (newpri / RQ_PPQ)) -#else - if (ke->ke_rqindex != newpri) -#endif - { - sched_rem(td); - sched_add(td, SRQ_BORING); - } - return; - } - - /* It is a threaded process */ - kg = td->td_ksegrp; - if (ke->ke_state == KES_ONRUNQ -#ifdef SCHED_ULE - || ((ke->ke_flags & KEF_ASSIGNED) != 0 && - (ke->ke_flags & KEF_REMOVED) == 0) -#endif - ) { - if (kg->kg_last_assigned == td) { - kg->kg_last_assigned = - TAILQ_PREV(td, threadqueue, td_runq); - } - sched_rem(td); - } - TAILQ_REMOVE(&kg->kg_runq, td, td_runq); - TD_SET_CAN_RUN(td); - td->td_priority = newpri; - setrunqueue(td, SRQ_BORING); -#else - /* We only care about the kse in the run queue. */ + /* We only care about the td_sched in the run queue. */ td->td_priority = newpri; #ifndef SCHED_CORE - if (ke->ke_rqindex != (newpri / RQ_PPQ)) + if (ts->ts_rqindex != (newpri / RQ_PPQ)) #else - if (ke->ke_rqindex != newpri) + if (ts->ts_rqindex != newpri) #endif { sched_rem(td); sched_add(td, SRQ_BORING); } -#endif -} - -#ifdef KSE -/* - * 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) -{ - struct thread *running_thread; - - mtx_assert(&sched_lock, MA_OWNED); - running_thread = curthread; - - if (running_thread->td_ksegrp != td->td_ksegrp) - return; - - if (td->td_priority >= running_thread->td_priority) - return; -#ifdef PREEMPTION -#ifndef FULL_PREEMPTION - if (td->td_priority > PRI_MAX_ITHD) { - running_thread->td_flags |= TDF_NEEDRESCHED; - return; - } -#endif /* FULL_PREEMPTION */ - - if (running_thread->td_critnest > 1) - running_thread->td_owepreempt = 1; - else - mi_switch(SW_INVOL, NULL); - -#else /* PREEMPTION */ - running_thread->td_flags |= TDF_NEEDRESCHED; -#endif /* PREEMPTION */ - return; } -#else /* SMP */ -{ - struct thread *running_thread; - int worst_pri; - struct ksegrp *kg; - cpumask_t cpumask,dontuse; - struct pcpu *pc; - struct pcpu *best_pcpu; - struct thread *cputhread; - - mtx_assert(&sched_lock, MA_OWNED); - - running_thread = curthread; - -#if !defined(KSEG_PEEMPT_BEST_CPU) - if (running_thread->td_ksegrp != td->td_ksegrp) { -#endif - kg = td->td_ksegrp; - - /* if someone is ahead of this thread, wait our turn */ - if (td != TAILQ_FIRST(&kg->kg_runq)) - return; - - worst_pri = td->td_priority; - best_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; - cputhread = pc->pc_curthread; - - if ((cpumask & dontuse) || - cputhread->td_ksegrp != kg) - continue; - - if (cputhread->td_priority > worst_pri) { - worst_pri = cputhread->td_priority; - best_pcpu = pc; - continue; - } - - if (cputhread->td_priority == worst_pri && - best_pcpu != NULL && - (td->td_lastcpu == pc->pc_cpuid || - (PCPU_GET(cpumask) == cpumask && - td->td_lastcpu != best_pcpu->pc_cpuid))) - best_pcpu = pc; - } - - /* Check if we need to preempt someone */ - if (best_pcpu == NULL) - return; - -#if defined(IPI_PREEMPTION) && defined(PREEMPTION) -#if !defined(FULL_PREEMPTION) - if (td->td_priority <= PRI_MAX_ITHD) -#endif /* ! FULL_PREEMPTION */ - { - ipi_selected(best_pcpu->pc_cpumask, IPI_PREEMPT); - return; - } -#endif /* defined(IPI_PREEMPTION) && defined(PREEMPTION) */ - - if (PCPU_GET(cpuid) != best_pcpu->pc_cpuid) { - best_pcpu->pc_curthread->td_flags |= TDF_NEEDRESCHED; - ipi_selected(best_pcpu->pc_cpumask, IPI_AST); - return; - } -#if !defined(KSEG_PEEMPT_BEST_CPU) - } -#endif - - if (td->td_priority >= running_thread->td_priority) - return; -#ifdef PREEMPTION - -#if !defined(FULL_PREEMPTION) - if (td->td_priority > PRI_MAX_ITHD) { - running_thread->td_flags |= TDF_NEEDRESCHED; - } -#endif /* ! FULL_PREEMPTION */ - - if (running_thread->td_critnest > 1) - running_thread->td_owepreempt = 1; - else - mi_switch(SW_INVOL, NULL); - -#else /* PREEMPTION */ - running_thread->td_flags |= TDF_NEEDRESCHED; -#endif /* PREEMPTION */ - return; -} -#endif /* !SMP */ - - -int limitcount; -#endif void setrunqueue(struct thread *td, int flags) { -#ifdef KSE - struct ksegrp *kg; - struct thread *td2; - struct thread *tda; - CTR3(KTR_RUNQ, "setrunqueue: td:%p kg:%p pid:%d", - td, td->td_ksegrp, td->td_proc->p_pid); -#else CTR2(KTR_RUNQ, "setrunqueue: td:%p pid:%d", td, td->td_proc->p_pid); -#endif CTR5(KTR_SCHED, "setrunqueue: %p(%s) prio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, curthread, curthread->td_proc->p_comm); @@ -557,101 +190,7 @@ setrunqueue(struct thread *td, int flags) KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)), ("setrunqueue: bad thread state")); TD_SET_RUNQ(td); -#ifdef KSE - kg = td->td_ksegrp; - if ((td->td_proc->p_flag & P_HADTHREADS) == 0) { - /* - * Common path optimisation: Only one of everything - * and the KSE is always already attached. - * Totally ignore the ksegrp run queue. - */ - if (kg->kg_avail_opennings != 1) { - if (limitcount < 1) { - limitcount++; - printf("pid %d: corrected slot count (%d->1)\n", - td->td_proc->p_pid, kg->kg_avail_opennings); - - } - kg->kg_avail_opennings = 1; - } - sched_add(td, flags); - return; - } - - /* - * If the concurrency has reduced, and we would go in the - * assigned section, then keep removing entries from the - * system run queue, until we are not in that section - * or there is room for us to be put in that section. - * What we MUST avoid is the case where there are threads of less - * priority than the new one scheduled, but it can not - * be scheduled itself. That would lead to a non contiguous set - * of scheduled threads, and everything would break. - */ - tda = kg->kg_last_assigned; - while ((kg->kg_avail_opennings <= 0) && - (tda && (tda->td_priority > td->td_priority))) { - /* - * None free, but there is one we can commandeer. - */ - CTR2(KTR_RUNQ, - "setrunqueue: kg:%p: take slot from td: %p", kg, tda); - sched_rem(tda); - tda = kg->kg_last_assigned = - TAILQ_PREV(tda, threadqueue, td_runq); - } - - /* - * Add the thread to the ksegrp's run queue at - * the appropriate place. - */ - TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) { - if (td2->td_priority > td->td_priority) { - TAILQ_INSERT_BEFORE(td2, td, td_runq); - break; - } - } - if (td2 == NULL) { - /* We ran off the end of the TAILQ or it was empty. */ - TAILQ_INSERT_TAIL(&kg->kg_runq, td, td_runq); - } - - /* - * If we have a slot to use, then put the thread on the system - * run queue and if needed, readjust the last_assigned pointer. - * it may be that we need to schedule something anyhow - * even if the availabel slots are -ve so that - * all the items < last_assigned are scheduled. - */ - if (kg->kg_avail_opennings > 0) { - if (tda == NULL) { - /* - * No pre-existing last assigned so whoever is first - * gets the slot.. (maybe us) - */ - td2 = TAILQ_FIRST(&kg->kg_runq); - kg->kg_last_assigned = td2; - } else if (tda->td_priority > td->td_priority) { - td2 = td; - } else { - /* - * We are past last_assigned, so - * give the next slot to whatever is next, - * which may or may not be us. - */ - td2 = TAILQ_NEXT(tda, td_runq); - kg->kg_last_assigned = td2; - } - sched_add(td2, flags); - } else { - CTR3(KTR_RUNQ, "setrunqueue: held: td%p kg%p pid%d", - td, td->td_ksegrp, td->td_proc->p_pid); - if ((flags & SRQ_YIELDING) == 0) - maybe_preempt_in_ksegrp(td); - } -#else sched_add(td, flags); -#endif } /* @@ -737,14 +276,14 @@ maybe_preempt(struct thread *td) * to the new thread. */ ctd = curthread; - KASSERT ((ctd->td_kse != NULL && ctd->td_kse->ke_thread == ctd), + KASSERT ((ctd->td_sched != NULL && ctd->td_sched->ts_thread == ctd), ("thread has no (or wrong) sched-private part.")); KASSERT((td->td_inhibitors == 0), ("maybe_preempt: trying to run inhibitted thread")); pri = td->td_priority; cpri = ctd->td_priority; if (panicstr != NULL || pri >= cpri || cold /* || dumping */ || - TD_IS_INHIBITED(ctd) || td->td_kse->ke_state != KES_THREAD) + TD_IS_INHIBITED(ctd) || td->td_sched->ts_state != TSS_THREAD) return (0); #ifndef FULL_PREEMPTION if (pri > PRI_MAX_ITHD && cpri < PRI_MIN_IDLE) @@ -762,25 +301,7 @@ maybe_preempt(struct thread *td) * Thread is runnable but not yet put on system run queue. */ MPASS(TD_ON_RUNQ(td)); - MPASS(td->td_sched->ke_state != KES_ONRUNQ); -#ifdef KSE - if (td->td_proc->p_flag & P_HADTHREADS) { - /* - * If this is a threaded process we actually ARE on the - * ksegrp run queue so take it off that first. - * Also undo any damage done to the last_assigned pointer. - * XXX Fix setrunqueue so this isn't needed - */ - struct ksegrp *kg; - - kg = td->td_ksegrp; - if (kg->kg_last_assigned == td) - kg->kg_last_assigned = - TAILQ_PREV(td, threadqueue, td_runq); - TAILQ_REMOVE(&kg->kg_runq, td, td_runq); - } - -#endif + MPASS(td->td_sched->ts_state != TSS_ONRUNQ); TD_SET_RUNNING(td); CTR3(KTR_PROC, "preempting to thread %p (pid %d, %s)\n", td, td->td_proc->p_pid, td->td_proc->p_comm); @@ -880,25 +401,25 @@ runq_setbit(struct runq *rq, int pri) } /* - * Add the KSE to the queue specified by its priority, and set the + * Add the thread to the queue specified by its priority, and set the * corresponding status bit. */ void -runq_add(struct runq *rq, struct kse *ke, int flags) +runq_add(struct runq *rq, struct td_sched *ts, int flags) { struct rqhead *rqh; int pri; - pri = ke->ke_thread->td_priority / RQ_PPQ; - ke->ke_rqindex = pri; + pri = ts->ts_thread->td_priority / RQ_PPQ; + ts->ts_rqindex = pri; runq_setbit(rq, pri); rqh = &rq->rq_queues[pri]; - CTR5(KTR_RUNQ, "runq_add: td=%p ke=%p pri=%d %d rqh=%p", - ke->ke_thread, ke, ke->ke_thread->td_priority, pri, rqh); + CTR5(KTR_RUNQ, "runq_add: td=%p ts=%p pri=%d %d rqh=%p", + ts->ts_thread, ts, ts->ts_thread->td_priority, pri, rqh); if (flags & SRQ_PREEMPTED) { - TAILQ_INSERT_HEAD(rqh, ke, ke_procq); + TAILQ_INSERT_HEAD(rqh, ts, ts_procq); } else { - TAILQ_INSERT_TAIL(rqh, ke, ke_procq); + TAILQ_INSERT_TAIL(rqh, ts, ts_procq); } } @@ -933,11 +454,11 @@ SYSCTL_INT(_kern_sched, OID_AUTO, runq_fuzz, CTLFLAG_RW, &runq_fuzz, 0, ""); /* * Find the highest priority process on the run queue. */ -struct kse * +struct td_sched * runq_choose(struct runq *rq) { struct rqhead *rqh; - struct kse *ke; + struct td_sched *ts; int pri; mtx_assert(&sched_lock, MA_OWNED); @@ -952,23 +473,23 @@ runq_choose(struct runq *rq) */ int count = runq_fuzz; int cpu = PCPU_GET(cpuid); - struct kse *ke2; - ke2 = ke = TAILQ_FIRST(rqh); + struct td_sched *ts2; + ts2 = ts = TAILQ_FIRST(rqh); - while (count-- && ke2) { - if (ke->ke_thread->td_lastcpu == cpu) { - ke = ke2; + while (count-- && ts2) { + if (ts->ts_thread->td_lastcpu == cpu) { + ts = ts2; break; } - ke2 = TAILQ_NEXT(ke2, ke_procq); + ts2 = TAILQ_NEXT(ts2, ts_procq); } } else #endif - ke = TAILQ_FIRST(rqh); - KASSERT(ke != NULL, ("runq_choose: no proc on busy queue")); + ts = TAILQ_FIRST(rqh); + KASSERT(ts != NULL, ("runq_choose: no proc on busy queue")); CTR3(KTR_RUNQ, - "runq_choose: pri=%d kse=%p rqh=%p", pri, ke, rqh); - return (ke); + "runq_choose: pri=%d td_sched=%p rqh=%p", pri, ts, rqh); + return (ts); } CTR1(KTR_RUNQ, "runq_choose: idleproc pri=%d", pri); @@ -976,28 +497,24 @@ runq_choose(struct runq *rq) } /* - * Remove the KSE from the queue specified by its priority, and clear the + * Remove the thread from the queue specified by its priority, and clear the * corresponding status bit if the queue becomes empty. - * Caller must set ke->ke_state afterwards. + * Caller must set ts->ts_state afterwards. */ void -runq_remove(struct runq *rq, struct kse *ke) +runq_remove(struct runq *rq, struct td_sched *ts) { struct rqhead *rqh; int pri; -#ifdef KSE - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, -#else - KASSERT(ke->ke_thread->td_proc->p_sflag & PS_INMEM, -#endif + KASSERT(ts->ts_thread->td_proc->p_sflag & PS_INMEM, ("runq_remove: process swapped out")); - pri = ke->ke_rqindex; + pri = ts->ts_rqindex; rqh = &rq->rq_queues[pri]; - CTR5(KTR_RUNQ, "runq_remove: td=%p, ke=%p pri=%d %d rqh=%p", - ke->ke_thread, ke, ke->ke_thread->td_priority, pri, rqh); - KASSERT(ke != NULL, ("runq_remove: no proc on busy queue")); - TAILQ_REMOVE(rqh, ke, ke_procq); + CTR5(KTR_RUNQ, "runq_remove: td=%p, ts=%p pri=%d %d rqh=%p", + ts->ts_thread, ts, ts->ts_thread->td_priority, pri, rqh); + KASSERT(ts != NULL, ("runq_remove: no proc on busy queue")); + TAILQ_REMOVE(rqh, ts, ts_procq); if (TAILQ_EMPTY(rqh)) { CTR0(KTR_RUNQ, "runq_remove: empty"); runq_clrbit(rq, pri); @@ -1008,23 +525,17 @@ runq_remove(struct runq *rq, struct kse *ke) #include <vm/uma.h> extern struct mtx kse_zombie_lock; -#ifdef KSE /* * Allocate scheduler specific per-process resources. - * The thread and ksegrp have already been linked in. - * In this case just set the default concurrency value. + * The thread and proc have already been linked in. * * Called from: * proc_init() (UMA init method) */ void -sched_newproc(struct proc *p, struct ksegrp *kg, struct thread *td) +sched_newproc(struct proc *p, struct thread *td) { - - /* This can go in sched_fork */ - sched_init_concurrency(kg); } -#endif /* * thread is being either created or recycled. @@ -1037,37 +548,27 @@ sched_newproc(struct proc *p, struct ksegrp *kg, struct thread *td) void sched_newthread(struct thread *td) { - struct td_sched *ke; + struct td_sched *ts; - ke = (struct td_sched *) (td + 1); - bzero(ke, sizeof(*ke)); - td->td_sched = ke; - ke->ke_thread = td; - ke->ke_state = KES_THREAD; + ts = (struct td_sched *) (td + 1); + bzero(ts, sizeof(*ts)); + td->td_sched = ts; + ts->ts_thread = td; + ts->ts_state = TSS_THREAD; } -#ifdef KSE /* - * Set up an initial concurrency of 1 - * and set the given thread (if given) to be using that - * concurrency slot. - * May be used "offline"..before the ksegrp is attached to the world - * and thus wouldn't need schedlock in that case. * Called from: * thr_create() * proc_init() (UMA) via sched_newproc() */ void -sched_init_concurrency(struct ksegrp *kg) +sched_init_concurrency(struct proc *p) { - - CTR1(KTR_RUNQ,"kg %p init slots and concurrency to 1", kg); - kg->kg_concurrency = 1; - kg->kg_avail_opennings = 1; } /* - * Change the concurrency of an existing ksegrp to N + * Change the concurrency of an existing proc to N * Called from: * kse_create() * kse_exit() @@ -1075,16 +576,8 @@ sched_init_concurrency(struct ksegrp *kg) * thread_single() */ void -sched_set_concurrency(struct ksegrp *kg, int concurrency) +sched_set_concurrency(struct proc *p, int concurrency) { - - CTR4(KTR_RUNQ,"kg %p set concurrency to %d, slots %d -> %d", - kg, - concurrency, - kg->kg_avail_opennings, - kg->kg_avail_opennings + (concurrency - kg->kg_concurrency)); - kg->kg_avail_opennings += (concurrency - kg->kg_concurrency); - kg->kg_concurrency = concurrency; } /* @@ -1099,10 +592,6 @@ sched_set_concurrency(struct ksegrp *kg, int concurrency) void sched_thread_exit(struct thread *td) { - - SLOT_RELEASE(td->td_ksegrp); - slot_fill(td->td_ksegrp); } -#endif #endif /* KERN_SWITCH_INCLUDE */ diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 37e3df2..2769f45 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -142,18 +142,12 @@ create_thread(struct thread *td, mcontext_t *ctx, { stack_t stack; struct thread *newtd; -#ifdef KSE - struct ksegrp *kg, *newkg; -#endif struct proc *p; long id; int error; error = 0; p = td->td_proc; -#ifdef KSE - kg = td->td_ksegrp; -#endif /* Have race condition but it is cheap. */ if (p->p_numthreads >= max_threads_per_proc) @@ -177,7 +171,7 @@ create_thread(struct thread *td, mcontext_t *ctx, } } - /* Initialize our td and new ksegrp.. */ + /* Initialize our td */ newtd = thread_alloc(); /* @@ -229,50 +223,22 @@ create_thread(struct thread *td, mcontext_t *ctx, } } -#ifdef KSE - newkg = ksegrp_alloc(); - bzero(&newkg->kg_startzero, - __rangeof(struct ksegrp, kg_startzero, kg_endzero)); - bcopy(&kg->kg_startcopy, &newkg->kg_startcopy, - __rangeof(struct ksegrp, kg_startcopy, kg_endcopy)); - sched_init_concurrency(newkg); PROC_LOCK(td->td_proc); td->td_proc->p_flag |= P_HADTHREADS; newtd->td_sigmask = td->td_sigmask; mtx_lock_spin(&sched_lock); - ksegrp_link(newkg, p); - thread_link(newtd, newkg); - PROC_UNLOCK(p); -#else - PROC_LOCK(td->td_proc); - td->td_proc->p_flag |= P_HADTHREADS; - newtd->td_sigmask = td->td_sigmask; - mtx_lock_spin(&sched_lock); thread_link(newtd, p); PROC_UNLOCK(p); -#endif -#ifdef KSE /* let the scheduler know about these things. */ - sched_fork_ksegrp(td, newkg); sched_fork_thread(td, newtd); if (rtp != NULL) { - if (!(kg->kg_pri_class == PRI_TIMESHARE && - rtp->type == RTP_PRIO_NORMAL)) { - rtp_to_pri(rtp, newkg); - sched_prio(newtd, newkg->kg_user_pri); - } /* ignore timesharing class */ - } -#else - sched_fork(td, newtd); - if (rtp != NULL) { if (!(td->td_pri_class == PRI_TIMESHARE && rtp->type == RTP_PRIO_NORMAL)) { rtp_to_pri(rtp, newtd); sched_prio(newtd, newtd->td_user_pri); } /* ignore timesharing class */ } -#endif TD_SET_CAN_RUN(newtd); /* if ((flags & THR_SUSPENDED) == 0) */ setrunqueue(newtd, SRQ_BORING); diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 74af901..1f9e80f 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -50,16 +50,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_extern.h> #include <vm/uma.h> -#ifdef KSE -/* - * KSEGRP related storage. - */ -static uma_zone_t ksegrp_zone; -#else /* * thread related storage. */ -#endif static uma_zone_t thread_zone; /* DEBUG ONLY */ @@ -85,9 +78,6 @@ int virtual_cpu; #endif TAILQ_HEAD(, thread) zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads); -#ifdef KSE -TAILQ_HEAD(, ksegrp) zombie_ksegrps = TAILQ_HEAD_INITIALIZER(zombie_ksegrps); -#endif struct mtx kse_zombie_lock; MTX_SYSINIT(kse_zombie_lock, &kse_zombie_lock, "kse zombie lock", MTX_SPIN); @@ -228,59 +218,6 @@ thread_fini(void *mem, int size) vm_thread_dispose(td); } -#ifdef KSE -/* - * Initialize type-stable parts of a ksegrp (when newly created). - */ -static int -ksegrp_ctor(void *mem, int size, void *arg, int flags) -{ - struct ksegrp *kg; - - kg = (struct ksegrp *)mem; - bzero(mem, size); - kg->kg_sched = (struct kg_sched *)&kg[1]; - return (0); -} - -void -ksegrp_link(struct ksegrp *kg, struct proc *p) -{ - - TAILQ_INIT(&kg->kg_threads); - TAILQ_INIT(&kg->kg_runq); /* links with td_runq */ - TAILQ_INIT(&kg->kg_upcalls); /* all upcall structure in ksegrp */ - kg->kg_proc = p; - /* - * the following counters are in the -zero- section - * and may not need clearing - */ - kg->kg_numthreads = 0; - kg->kg_numupcalls = 0; - /* link it in now that it's consistent */ - p->p_numksegrps++; - TAILQ_INSERT_HEAD(&p->p_ksegrps, kg, kg_ksegrp); -} - -/* - * Called from: - * thread-exit() - */ -void -ksegrp_unlink(struct ksegrp *kg) -{ - struct proc *p; - - mtx_assert(&sched_lock, MA_OWNED); - KASSERT((kg->kg_numthreads == 0), ("ksegrp_unlink: residual threads")); - KASSERT((kg->kg_numupcalls == 0), ("ksegrp_unlink: residual upcalls")); - - p = kg->kg_proc; - TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp); - p->p_numksegrps--; -} -#endif - /* * For a newly created process, * link up all the structures and its initial threads etc. @@ -290,18 +227,10 @@ ksegrp_unlink(struct ksegrp *kg) * proc_init() */ void -#ifdef KSE -proc_linkup(struct proc *p, struct ksegrp *kg, struct thread *td) -#else proc_linkup(struct proc *p, struct thread *td) -#endif { - -#ifdef KSE - TAILQ_INIT(&p->p_ksegrps); /* all ksegrps in proc */ -#endif TAILQ_INIT(&p->p_threads); /* all threads in proc */ - TAILQ_INIT(&p->p_suspended); /* Threads suspended */ + TAILQ_INIT(&p->p_upcalls); /* upcall list */ sigqueue_init(&p->p_sigqueue, p); p->p_ksi = ksiginfo_alloc(1); if (p->p_ksi != NULL) { @@ -309,17 +238,8 @@ proc_linkup(struct proc *p, struct thread *td) p->p_ksi->ksi_flags = KSI_EXT | KSI_INS; } LIST_INIT(&p->p_mqnotifier); -#ifdef KSE - p->p_numksegrps = 0; -#endif p->p_numthreads = 0; - -#ifdef KSE - ksegrp_link(kg, p); - thread_link(td, kg); -#else thread_link(td, p); -#endif } /* @@ -336,37 +256,22 @@ threadinit(void) thread_ctor, thread_dtor, thread_init, thread_fini, UMA_ALIGN_CACHE, 0); #ifdef KSE - ksegrp_zone = uma_zcreate("KSEGRP", sched_sizeof_ksegrp(), - ksegrp_ctor, NULL, NULL, NULL, - UMA_ALIGN_CACHE, 0); kseinit(); /* set up kse specific stuff e.g. upcall zone*/ #endif } /* * Stash an embarasingly extra thread into the zombie thread queue. + * Use the slpq as that must be unused by now. */ void thread_stash(struct thread *td) { mtx_lock_spin(&kse_zombie_lock); - TAILQ_INSERT_HEAD(&zombie_threads, td, td_runq); + TAILQ_INSERT_HEAD(&zombie_threads, td, td_slpq); mtx_unlock_spin(&kse_zombie_lock); } -#ifdef KSE -/* - * Stash an embarasingly extra ksegrp into the zombie ksegrp queue. - */ -void -ksegrp_stash(struct ksegrp *kg) -{ - mtx_lock_spin(&kse_zombie_lock); - TAILQ_INSERT_HEAD(&zombie_ksegrps, kg, kg_ksegrp); - mtx_unlock_spin(&kse_zombie_lock); -} -#endif - /* * Reap zombie kse resource. */ @@ -374,65 +279,27 @@ void thread_reap(void) { struct thread *td_first, *td_next; -#ifdef KSE - struct ksegrp *kg_first, * kg_next; -#endif /* * Don't even bother to lock if none at this instant, * we really don't care about the next instant.. */ -#ifdef KSE - if ((!TAILQ_EMPTY(&zombie_threads)) - || (!TAILQ_EMPTY(&zombie_ksegrps))) { -#else if (!TAILQ_EMPTY(&zombie_threads)) { -#endif mtx_lock_spin(&kse_zombie_lock); td_first = TAILQ_FIRST(&zombie_threads); -#ifdef KSE - kg_first = TAILQ_FIRST(&zombie_ksegrps); -#endif if (td_first) TAILQ_INIT(&zombie_threads); -#ifdef KSE - if (kg_first) - TAILQ_INIT(&zombie_ksegrps); -#endif mtx_unlock_spin(&kse_zombie_lock); while (td_first) { - td_next = TAILQ_NEXT(td_first, td_runq); + td_next = TAILQ_NEXT(td_first, td_slpq); if (td_first->td_ucred) crfree(td_first->td_ucred); thread_free(td_first); td_first = td_next; } -#ifdef KSE - while (kg_first) { - kg_next = TAILQ_NEXT(kg_first, kg_ksegrp); - ksegrp_free(kg_first); - kg_first = kg_next; - } - /* - * there will always be a thread on the list if one of these - * is there. - */ - kse_GC(); -#endif } } -#ifdef KSE -/* - * Allocate a ksegrp. - */ -struct ksegrp * -ksegrp_alloc(void) -{ - return (uma_zalloc(ksegrp_zone, M_WAITOK)); -} -#endif - /* * Allocate a thread. */ @@ -444,16 +311,6 @@ thread_alloc(void) return (uma_zalloc(thread_zone, M_WAITOK)); } -#ifdef KSE -/* - * Deallocate a ksegrp. - */ -void -ksegrp_free(struct ksegrp *td) -{ - uma_zfree(ksegrp_zone, td); -} -#endif /* * Deallocate a thread. @@ -503,23 +360,14 @@ thread_exit(void) uint64_t new_switchtime; struct thread *td; struct proc *p; -#ifdef KSE - struct ksegrp *kg; -#endif td = curthread; -#ifdef KSE - kg = td->td_ksegrp; -#endif p = td->td_proc; mtx_assert(&sched_lock, MA_OWNED); mtx_assert(&Giant, MA_NOTOWNED); PROC_LOCK_ASSERT(p, MA_OWNED); KASSERT(p != NULL, ("thread exiting without a process")); -#ifdef KSE - KASSERT(kg != NULL, ("thread exiting without a kse group")); -#endif CTR3(KTR_PROC, "thread_exit: thread %p (pid %ld, %s)", td, (long)p->p_pid, p->p_comm); KASSERT(TAILQ_EMPTY(&td->td_sigqueue.sq_list), ("signal pending")); @@ -583,13 +431,8 @@ thread_exit(void) if (p->p_flag & P_HADTHREADS) { if (p->p_numthreads > 1) { thread_unlink(td); -#ifdef KSE - /* XXX first arg not used in 4BSD or ULE */ sched_exit_thread(FIRST_THREAD_IN_PROC(p), td); -#else - sched_exit(p, td); -#endif /* * The test below is NOT true if we are the @@ -614,38 +457,9 @@ thread_exit(void) * there somehow. */ upcall_remove(td); - - /* - * If the thread we unlinked above was the last one, - * then this ksegrp should go away too. - */ - if (kg->kg_numthreads == 0) { - /* - * let the scheduler know about this in case - * it needs to recover stats or resources. - * Theoretically we could let - * sched_exit_ksegrp() do the equivalent of - * setting the concurrency to 0 - * but don't do it yet to avoid changing - * the existing scheduler code until we - * are ready. - * We supply a random other ksegrp - * as the recipient of any built up - * cpu usage etc. (If the scheduler wants it). - * XXXKSE - * This is probably not fair so think of - * a better answer. - */ - sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), td); - sched_set_concurrency(kg, 0); /* XXX TEMP */ - ksegrp_unlink(kg); - ksegrp_stash(kg); - } #endif + PROC_UNLOCK(p); -#ifdef KSE - td->td_ksegrp = NULL; -#endif PCPU_SET(deadthread, td); } else { /* @@ -689,9 +503,6 @@ thread_wait(struct proc *p) mtx_assert(&Giant, MA_NOTOWNED); KASSERT((p->p_numthreads == 1), ("Multiple threads in wait1()")); -#ifdef KSE - KASSERT((p->p_numksegrps == 1), ("Multiple ksegrps in wait1()")); -#endif FOREACH_THREAD_IN_PROC(p, td) { #ifdef KSE if (td->td_standin != NULL) { @@ -718,46 +529,22 @@ thread_wait(struct proc *p) * The thread is linked as if running but no KSE assigned. * Called from: * proc_linkup() - * ifdef KSE * thread_schedule_upcall() - * endif * thr_create() */ void -#ifdef KSE -thread_link(struct thread *td, struct ksegrp *kg) -#else thread_link(struct thread *td, struct proc *p) -#endif { -#ifdef KSE - struct proc *p; -#endif -#ifdef KSE - p = kg->kg_proc; -#endif td->td_state = TDS_INACTIVE; td->td_proc = p; -#ifdef KSE - td->td_ksegrp = kg; -#endif td->td_flags = 0; -#ifdef KSE - td->td_kflags = 0; -#endif LIST_INIT(&td->td_contested); sigqueue_init(&td->td_sigqueue, p); callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist); -#ifdef KSE - TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist); -#endif p->p_numthreads++; -#ifdef KSE - kg->kg_numthreads++; -#endif } /* @@ -781,7 +568,7 @@ thread_unthread(struct thread *td) thread_stash(td->td_standin); td->td_standin = NULL; } - sched_set_concurrency(td->td_ksegrp, 1); + sched_set_concurrency(p, 1); #else p->p_flag &= ~P_HADTHREADS; #endif @@ -795,23 +582,12 @@ void thread_unlink(struct thread *td) { struct proc *p = td->td_proc; -#ifdef KSE - struct ksegrp *kg = td->td_ksegrp; -#endif mtx_assert(&sched_lock, MA_OWNED); TAILQ_REMOVE(&p->p_threads, td, td_plist); p->p_numthreads--; -#ifdef KSE - TAILQ_REMOVE(&kg->kg_threads, td, td_kglist); - kg->kg_numthreads--; -#endif /* could clear a few other things here */ -#ifdef KSE - /* Must NOT clear links to proc and ksegrp! */ -#else /* Must NOT clear links to proc! */ -#endif } /* @@ -1040,8 +816,7 @@ thread_suspend_check(int return_instead) /* * When a thread suspends, it just - * moves to the processes's suspend queue - * and stays there. + * gets taken off all queues. */ thread_suspend_one(td); if (return_instead == 0) { @@ -1074,7 +849,6 @@ thread_suspend_one(struct thread *td) KASSERT(!TD_IS_SUSPENDED(td), ("already suspended")); p->p_suspcount++; TD_SET_SUSPENDED(td); - TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq); } void @@ -1084,7 +858,7 @@ thread_unsuspend_one(struct thread *td) mtx_assert(&sched_lock, MA_OWNED); PROC_LOCK_ASSERT(p, MA_OWNED); - TAILQ_REMOVE(&p->p_suspended, td, td_runq); + KASSERT(TD_IS_SUSPENDED(td), ("Thread not suspended")); TD_CLR_SUSPENDED(td); p->p_suspcount--; setrunnable(td); @@ -1101,8 +875,10 @@ thread_unsuspend(struct proc *p) mtx_assert(&sched_lock, MA_OWNED); PROC_LOCK_ASSERT(p, MA_OWNED); if (!P_SHOULDSTOP(p)) { - while ((td = TAILQ_FIRST(&p->p_suspended))) { - thread_unsuspend_one(td); + FOREACH_THREAD_IN_PROC(p, td) { + if (TD_IS_SUSPENDED(td)) { + thread_unsuspend_one(td); + } } } else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) && (p->p_numthreads == p->p_suspcount)) { @@ -1137,8 +913,10 @@ thread_single_end(void) * to continue however as this is a bad place to stop. */ if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) { - while ((td = TAILQ_FIRST(&p->p_suspended))) { - thread_unsuspend_one(td); + FOREACH_THREAD_IN_PROC(p, td) { + if (TD_IS_SUSPENDED(td)) { + thread_unsuspend_one(td); + } } } mtx_unlock_spin(&sched_lock); diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 328fb57..645f02d 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -167,15 +167,9 @@ struct umtxq_chain { * if it is using 100%CPU, this is unfair to other processes. */ -#ifdef KSE -#define UPRI(td) (((td)->td_ksegrp->kg_user_pri >= PRI_MIN_TIMESHARE &&\ - (td)->td_ksegrp->kg_user_pri <= PRI_MAX_TIMESHARE) ?\ - PRI_MAX_TIMESHARE : (td)->td_ksegrp->kg_user_pri) -#else #define UPRI(td) (((td)->td_user_pri >= PRI_MIN_TIMESHARE &&\ (td)->td_user_pri <= PRI_MAX_TIMESHARE) ?\ PRI_MAX_TIMESHARE : (td)->td_user_pri) -#endif #define GOLDEN_RATIO_PRIME 2654404609U #define UMTX_CHAINS 128 diff --git a/sys/kern/ksched.c b/sys/kern/ksched.c index 4127367..785c04c 100644 --- a/sys/kern/ksched.c +++ b/sys/kern/ksched.c @@ -105,11 +105,7 @@ getscheduler(struct ksched *ksched, struct thread *td, int *policy) int e = 0; mtx_lock_spin(&sched_lock); -#ifdef KSE - pri_to_rtp(td->td_ksegrp, &rtp); -#else pri_to_rtp(td, &rtp); -#endif mtx_unlock_spin(&sched_lock); switch (rtp.type) { @@ -156,11 +152,7 @@ ksched_getparam(struct ksched *ksched, struct rtprio rtp; mtx_lock_spin(&sched_lock); -#ifdef KSE - pri_to_rtp(td->td_ksegrp, &rtp); -#else pri_to_rtp(td, &rtp); -#endif mtx_unlock_spin(&sched_lock); if (RTP_PRIO_IS_REALTIME(rtp.type)) param->sched_priority = rtpprio_to_p4prio(rtp.prio); @@ -181,9 +173,6 @@ ksched_setscheduler(struct ksched *ksched, { int e = 0; struct rtprio rtp; -#ifdef KSE - struct ksegrp *kg = td->td_ksegrp; -#endif switch(policy) { @@ -198,20 +187,7 @@ ksched_setscheduler(struct ksched *ksched, ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME; mtx_lock_spin(&sched_lock); -#ifdef KSE - rtp_to_pri(&rtp, kg); - FOREACH_THREAD_IN_GROUP(kg, td) { /* XXXKSE */ - if (TD_IS_RUNNING(td)) { - td->td_flags |= TDF_NEEDRESCHED; - } else if (TD_ON_RUNQ(td)) { - if (td->td_priority > kg->kg_user_pri) { - sched_prio(td, kg->kg_user_pri); - } - } - } -#else rtp_to_pri(&rtp, td); -#endif mtx_unlock_spin(&sched_lock); } else @@ -225,28 +201,7 @@ ksched_setscheduler(struct ksched *ksched, rtp.type = RTP_PRIO_NORMAL; rtp.prio = p4prio_to_rtpprio(param->sched_priority); mtx_lock_spin(&sched_lock); -#ifdef KSE - rtp_to_pri(&rtp, kg); - - /* XXX Simply revert to whatever we had for last - * normal scheduler priorities. - * This puts a requirement - * on the scheduling code: You must leave the - * scheduling info alone. - */ - FOREACH_THREAD_IN_GROUP(kg, td) { - if (TD_IS_RUNNING(td)) { - td->td_flags |= TDF_NEEDRESCHED; - } else if (TD_ON_RUNQ(td)) { - if (td->td_priority > kg->kg_user_pri) { - sched_prio(td, kg->kg_user_pri); - } - } - - } -#else rtp_to_pri(&rtp, td); -#endif mtx_unlock_spin(&sched_lock); } break; diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index dc9d288..3fe2682 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -37,8 +37,6 @@ __FBSDID("$FreeBSD$"); #include "opt_hwpmc_hooks.h" -#define kse td_sched - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -75,99 +73,38 @@ __FBSDID("$FreeBSD$"); #endif #define NICE_WEIGHT 1 /* Priorities per nice level. */ -#ifdef KSE -/* - * The schedulable entity that can be given a context to run. - * A process may have several of these. Probably one per processor - * but possibly a few more. In this universe they are grouped - * with a KSEG that contains the priority and niceness - * for the group. - */ -#else /* * The schedulable entity that runs a context. - * A process may have several of these. Probably one per processor - * but posibly a few more. + * This is an extension to the thread structure and is tailored to + * the requirements of this scheduler */ -#endif -struct kse { - TAILQ_ENTRY(kse) ke_procq; /* (j/z) Run queue. */ - struct thread *ke_thread; /* (*) Active associated thread. */ - fixpt_t ke_pctcpu; /* (j) %cpu during p_swtime. */ - u_char ke_rqindex; /* (j) Run queue index. */ +struct td_sched { + TAILQ_ENTRY(td_sched) ts_procq; /* (j/z) Run queue. */ + struct thread *ts_thread; /* (*) Active associated thread. */ + fixpt_t ts_pctcpu; /* (j) %cpu during p_swtime. */ + u_char ts_rqindex; /* (j) Run queue index. */ enum { - KES_THREAD = 0x0, /* slaved to thread state */ - KES_ONRUNQ - } ke_state; /* (j) KSE status. */ - int ke_cpticks; /* (j) Ticks of cpu time. */ - struct runq *ke_runq; /* runq the kse is currently on */ + TSS_THREAD = 0x0, /* slaved to thread state */ + TSS_ONRUNQ + } ts_state; /* (j) TD_STAT in scheduler status. */ + int ts_cpticks; /* (j) Ticks of cpu time. */ + struct runq *ts_runq; /* runq the thread is currently on */ }; -#ifdef KSE -#define ke_proc ke_thread->td_proc -#define ke_ksegrp ke_thread->td_ksegrp -#endif - -#define td_kse td_sched - /* flags kept in td_flags */ -#define TDF_DIDRUN TDF_SCHED0 /* KSE actually ran. */ -#define TDF_EXIT TDF_SCHED1 /* KSE is being killed. */ +#define TDF_DIDRUN TDF_SCHED0 /* thread actually ran. */ +#define TDF_EXIT TDF_SCHED1 /* thread is being killed. */ #define TDF_BOUND TDF_SCHED2 -#define ke_flags ke_thread->td_flags -#define KEF_DIDRUN TDF_DIDRUN /* KSE actually ran. */ -#define KEF_EXIT TDF_EXIT /* KSE is being killed. */ -#define KEF_BOUND TDF_BOUND /* stuck to one CPU */ - -#define SKE_RUNQ_PCPU(ke) \ - ((ke)->ke_runq != 0 && (ke)->ke_runq != &runq) - -#ifdef KSE -struct kg_sched { - struct thread *skg_last_assigned; /* (j) Last thread assigned to */ - /* the system scheduler. */ - int skg_avail_opennings; /* (j) Num KSEs requested in group. */ - int skg_concurrency; /* (j) Num KSEs requested in group. */ -}; -#define kg_last_assigned kg_sched->skg_last_assigned -#define kg_avail_opennings kg_sched->skg_avail_opennings -#define kg_concurrency kg_sched->skg_concurrency - -#define SLOT_RELEASE(kg) \ -do { \ - kg->kg_avail_opennings++; \ - CTR3(KTR_RUNQ, "kg %p(%d) Slot released (->%d)", \ - kg, \ - kg->kg_concurrency, \ - kg->kg_avail_opennings); \ -/* KASSERT((kg->kg_avail_opennings <= kg->kg_concurrency), \ - ("slots out of whack"));*/ \ -} while (0) - -#define SLOT_USE(kg) \ -do { \ - kg->kg_avail_opennings--; \ - CTR3(KTR_RUNQ, "kg %p(%d) Slot used (->%d)", \ - kg, \ - kg->kg_concurrency, \ - kg->kg_avail_opennings); \ -/* KASSERT((kg->kg_avail_opennings >= 0), \ - ("slots out of whack"));*/ \ -} while (0) -#endif +#define ts_flags ts_thread->td_flags +#define TSF_DIDRUN TDF_DIDRUN /* thread actually ran. */ +#define TSF_EXIT TDF_EXIT /* thread is being killed. */ +#define TSF_BOUND TDF_BOUND /* stuck to one CPU */ -/* - * KSE_CAN_MIGRATE macro returns true if the kse can migrate between - * cpus. - */ -#define KSE_CAN_MIGRATE(ke) \ - ((ke)->ke_thread->td_pinned == 0 && ((ke)->ke_flags & KEF_BOUND) == 0) +#define SKE_RUNQ_PCPU(ts) \ + ((ts)->ts_runq != 0 && (ts)->ts_runq != &runq) -static struct kse kse0; -#ifdef KSE -static struct kg_sched kg_sched0; -#endif +static struct td_sched td_sched0; static int sched_tdcnt; /* Total runnable threads in the system. */ static int sched_quantum; /* Roundrobin scheduling quantum in ticks. */ @@ -175,12 +112,7 @@ static int sched_quantum; /* Roundrobin scheduling quantum in ticks. */ static struct callout roundrobin_callout; -#ifdef KSE -static void slot_fill(struct ksegrp *kg); -static struct kse *sched_choose(void); /* XXX Should be thread * */ -#else -static struct thread *sched_choose(void); -#endif +static struct td_sched *sched_choose(void); static void setup_runqs(void); static void roundrobin(void *arg); @@ -189,15 +121,9 @@ static void schedcpu_thread(void); static void sched_priority(struct thread *td, u_char prio); static void sched_setup(void *dummy); static void maybe_resched(struct thread *td); -#ifdef KSE -static void updatepri(struct ksegrp *kg); -static void resetpriority(struct ksegrp *kg); -static void resetpriority_thread(struct thread *td, struct ksegrp *kg); -#else static void updatepri(struct thread *td); static void resetpriority(struct thread *td); static void resetpriority_thread(struct thread *td); -#endif #ifdef SMP static int forward_wakeup(int cpunum); #endif @@ -300,21 +226,11 @@ SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, htt2, CTLFLAG_RW, "account for htt"); #endif -#ifdef KSE +#if 0 static int sched_followon = 0; SYSCTL_INT(_kern_sched, OID_AUTO, followon, CTLFLAG_RW, &sched_followon, 0, "allow threads to share a quantum"); - -static int sched_pfollowons = 0; -SYSCTL_INT(_kern_sched, OID_AUTO, pfollowons, CTLFLAG_RD, - &sched_pfollowons, 0, - "number of followons done to a different ksegrp"); - -static int sched_kgfollowons = 0; -SYSCTL_INT(_kern_sched, OID_AUTO, kgfollowons, CTLFLAG_RD, - &sched_kgfollowons, 0, - "number of followons done in a ksegrp"); #endif static __inline void @@ -366,40 +282,20 @@ roundrobin(void *arg) /* * Constants for digital decay and forget: - * ifdef KSE - * 90% of (kg_estcpu) usage in 5 * loadav time - * else * 90% of (td_estcpu) usage in 5 * loadav time - * endif - * 95% of (ke_pctcpu) usage in 60 seconds (load insensitive) + * 95% of (ts_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). * - * ifdef KSE - * Note that schedclock() updates kg_estcpu and p_cpticks asynchronously. - * else * Note that schedclock() updates td_estcpu and p_cpticks asynchronously. - * endif * - * ifdef KSE - * We wish to decay away 90% of kg_estcpu in (5 * loadavg) seconds. - * else * We wish to decay away 90% of td_estcpu in (5 * loadavg) seconds. - * endif * That is, the system wants to compute a value of decay such * that the following for loop: * for (i = 0; i < (5 * loadavg); i++) - * ifdef KSE - * kg_estcpu *= decay; - * else * td_estcpu *= decay; - * endif * will compute - * ifdef KSE - * kg_estcpu *= 0.1; - * else * td_estcpu *= 0.1; - * endif * for all values of loadavg: * * Mathematically this loop can be expressed by saying: @@ -452,7 +348,7 @@ roundrobin(void *arg) #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 `ts_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, ""); @@ -481,10 +377,7 @@ schedcpu(void) register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); struct thread *td; struct proc *p; - struct kse *ke; -#ifdef KSE - struct ksegrp *kg; -#endif + struct td_sched *ts; int awake, realstathz; realstathz = stathz ? stathz : hz; @@ -499,126 +392,63 @@ schedcpu(void) * 16-bit int's (remember them?) overflow takes 45 days. */ p->p_swtime++; -#ifdef KSE - FOREACH_KSEGRP_IN_PROC(p, kg) { -#else FOREACH_THREAD_IN_PROC(p, td) { -#endif awake = 0; -#ifdef KSE - FOREACH_THREAD_IN_GROUP(kg, td) { - ke = td->td_kse; - /* - * Increment sleep time (if sleeping). We - * ignore overflow, as above. - */ - /* - * The kse slptimes are not touched in wakeup - * because the thread may not HAVE a KSE. - */ - if (ke->ke_state == KES_ONRUNQ) { - awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; - } else if ((ke->ke_state == KES_THREAD) && - (TD_IS_RUNNING(td))) { - awake = 1; - /* Do not clear KEF_DIDRUN */ - } else if (ke->ke_flags & KEF_DIDRUN) { - awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; - } - - /* - * ke_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) >> - FSHIFT; - /* - * If the kse has been idle the entire second, - * stop recalculating its priority until - * it wakes up. - */ - if (ke->ke_cpticks == 0) - continue; -#if (FSHIFT >= CCPU_SHIFT) - ke->ke_pctcpu += (realstathz == 100) - ? ((fixpt_t) ke->ke_cpticks) << - (FSHIFT - CCPU_SHIFT) : - 100 * (((fixpt_t) ke->ke_cpticks) - << (FSHIFT - CCPU_SHIFT)) / realstathz; -#else - ke->ke_pctcpu += ((FSCALE - ccpu) * - (ke->ke_cpticks * - FSCALE / realstathz)) >> FSHIFT; -#endif - ke->ke_cpticks = 0; - } /* end of kse loop */ -#else - ke = td->td_kse; + ts = td->td_sched; /* * Increment sleep time (if sleeping). We * ignore overflow, as above. */ /* - * The kse slptimes are not touched in wakeup - * because the thread may not HAVE a KSE. + * The td_sched slptimes are not touched in wakeup + * because the thread may not HAVE everything in + * memory? XXX I think this is out of date. */ - if (ke->ke_state == KES_ONRUNQ) { + if (ts->ts_state == TSS_ONRUNQ) { awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; - } else if ((ke->ke_state == KES_THREAD) && + ts->ts_flags &= ~TSF_DIDRUN; + } else if ((ts->ts_state == TSS_THREAD) && (TD_IS_RUNNING(td))) { awake = 1; - /* Do not clear KEF_DIDRUN */ - } else if (ke->ke_flags & KEF_DIDRUN) { + /* Do not clear TSF_DIDRUN */ + } else if (ts->ts_flags & TSF_DIDRUN) { awake = 1; - ke->ke_flags &= ~KEF_DIDRUN; + ts->ts_flags &= ~TSF_DIDRUN; } /* - * ke_pctcpu is only for ps and ttyinfo(). - * Do it per kse, and add them up at the end? + * ts_pctcpu is only for ps and ttyinfo(). + * Do it per td_sched, and add them up at the end? * XXXKSE */ - ke->ke_pctcpu = (ke->ke_pctcpu * ccpu) >> - FSHIFT; + ts->ts_pctcpu = (ts->ts_pctcpu * ccpu) >> FSHIFT; /* - * If the kse has been idle the entire second, + * If the td_sched has been idle the entire second, * stop recalculating its priority until * it wakes up. */ - if (ke->ke_cpticks != 0) { + if (ts->ts_cpticks != 0) { #if (FSHIFT >= CCPU_SHIFT) - ke->ke_pctcpu += (realstathz == 100) - ? ((fixpt_t) ke->ke_cpticks) << - (FSHIFT - CCPU_SHIFT) : - 100 * (((fixpt_t) ke->ke_cpticks) - << (FSHIFT - CCPU_SHIFT)) / realstathz; + ts->ts_pctcpu += (realstathz == 100) + ? ((fixpt_t) ts->ts_cpticks) << + (FSHIFT - CCPU_SHIFT) : + 100 * (((fixpt_t) ts->ts_cpticks) + << (FSHIFT - CCPU_SHIFT)) / realstathz; #else - ke->ke_pctcpu += ((FSCALE - ccpu) * - (ke->ke_cpticks * - FSCALE / realstathz)) >> FSHIFT; + ts->ts_pctcpu += ((FSCALE - ccpu) * + (ts->ts_cpticks * + FSCALE / realstathz)) >> FSHIFT; #endif - ke->ke_cpticks = 0; + ts->ts_cpticks = 0; } -#endif - /* - * ifdef KSE - * If there are ANY running threads in this KSEGRP, - * else * If there are ANY running threads in this process, - * endif * then don't count it as sleeping. +XXX this is broken + */ if (awake) { -#ifdef KSE - if (kg->kg_slptime > 1) { -#else - if (td->td_slptime > 1) { -#endif + if (p->p_slptime > 1) { /* * In an ideal world, this should not * happen, because whoever woke us @@ -628,21 +458,6 @@ schedcpu(void) * priority. Should KASSERT at some * point when all the cases are fixed. */ -#ifdef KSE - updatepri(kg); - } - kg->kg_slptime = 0; - } else - kg->kg_slptime++; - if (kg->kg_slptime > 1) - continue; - kg->kg_estcpu = decay_cpu(loadfac, kg->kg_estcpu); - resetpriority(kg); - FOREACH_THREAD_IN_GROUP(kg, td) { - resetpriority_thread(td, kg); - } - } /* end of ksegrp loop */ -#else updatepri(td); } td->td_slptime = 0; @@ -654,7 +469,6 @@ schedcpu(void) resetpriority(td); resetpriority_thread(td); } /* end of thread loop */ -#endif mtx_unlock_spin(&sched_lock); } /* end of process loop */ sx_sunlock(&allproc_lock); @@ -676,48 +490,24 @@ schedcpu_thread(void) /* * Recalculate the priority of a process after it has slept for a while. - * ifdef KSE - * For all load averages >= 1 and max kg_estcpu of 255, sleeping for at - * least six times the loadfactor will decay kg_estcpu to zero. - * else * For all load averages >= 1 and max td_estcpu of 255, sleeping for at * least six times the loadfactor will decay td_estcpu to zero. - * endif */ static void -#ifdef KSE -updatepri(struct ksegrp *kg) -#else updatepri(struct thread *td) -#endif { register fixpt_t loadfac; register unsigned int newcpu; loadfac = loadfactor(averunnable.ldavg[0]); -#ifdef KSE - if (kg->kg_slptime > 5 * loadfac) - kg->kg_estcpu = 0; -#else if (td->td_slptime > 5 * loadfac) td->td_estcpu = 0; -#endif else { -#ifdef KSE - newcpu = kg->kg_estcpu; - kg->kg_slptime--; /* was incremented in schedcpu() */ - while (newcpu && --kg->kg_slptime) -#else newcpu = td->td_estcpu; td->td_slptime--; /* was incremented in schedcpu() */ while (newcpu && --td->td_slptime) -#endif newcpu = decay_cpu(loadfac, newcpu); -#ifdef KSE - kg->kg_estcpu = newcpu; -#else td->td_estcpu = newcpu; -#endif } } @@ -727,43 +517,25 @@ updatepri(struct thread *td) * than that of the current process. */ static void -#ifdef KSE -resetpriority(struct ksegrp *kg) -#else resetpriority(struct thread *td) -#endif { register unsigned int newpriority; -#ifdef KSE - if (kg->kg_pri_class == PRI_TIMESHARE) { - newpriority = PUSER + kg->kg_estcpu / INVERSE_ESTCPU_WEIGHT + - NICE_WEIGHT * (kg->kg_proc->p_nice - PRIO_MIN); -#else if (td->td_pri_class == PRI_TIMESHARE) { newpriority = PUSER + td->td_estcpu / INVERSE_ESTCPU_WEIGHT + NICE_WEIGHT * (td->td_proc->p_nice - PRIO_MIN); -#endif newpriority = min(max(newpriority, PRI_MIN_TIMESHARE), PRI_MAX_TIMESHARE); -#ifdef KSE - sched_user_prio(kg, newpriority); -#else sched_user_prio(td, newpriority); -#endif } } /* - * Update the thread's priority when the associated ksegroup's user + * Update the thread's priority when the associated process's user * priority changes. */ static void -#ifdef KSE -resetpriority_thread(struct thread *td, struct ksegrp *kg) -#else resetpriority_thread(struct thread *td) -#endif { /* Only change threads with a time sharing user priority. */ @@ -774,11 +546,7 @@ resetpriority_thread(struct thread *td) /* XXX the whole needresched thing is broken, but not silly. */ maybe_resched(td); -#ifdef KSE - sched_prio(td, kg->kg_user_pri); -#else sched_prio(td, td->td_user_pri); -#endif } /* ARGSUSED */ @@ -814,16 +582,9 @@ schedinit(void) * Set up the scheduler specific parts of proc0. */ proc0.p_sched = NULL; /* XXX */ -#ifdef KSE - ksegrp0.kg_sched = &kg_sched0; -#endif - thread0.td_sched = &kse0; - kse0.ke_thread = &thread0; - kse0.ke_state = KES_THREAD; -#ifdef KSE - kg_sched0.skg_concurrency = 1; - kg_sched0.skg_avail_opennings = 0; /* we are already running */ -#endif + thread0.td_sched = &td_sched0; + td_sched0.ts_thread = &thread0; + td_sched0.ts_state = TSS_THREAD; } int @@ -847,13 +608,8 @@ sched_rr_interval(void) /* * We adjust the priority of the current process. The priority of * a process gets worse as it accumulates CPU time. The cpu usage - * ifdef KSE - * estimator (kg_estcpu) is increased here. resetpriority() will - * compute a different priority each time kg_estcpu increases by - * else * estimator (td_estcpu) is increased here. resetpriority() will * compute a different priority each time td_estcpu increases by - * endif * INVERSE_ESTCPU_WEIGHT * (until MAXPRI is reached). The cpu usage estimator ramps up * quite quickly when the process is running (linearly), and decays @@ -866,163 +622,83 @@ sched_rr_interval(void) void sched_clock(struct thread *td) { -#ifdef KSE - struct ksegrp *kg; -#endif - struct kse *ke; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); -#ifdef KSE - kg = td->td_ksegrp; -#endif - ke = td->td_kse; - - ke->ke_cpticks++; -#ifdef KSE - kg->kg_estcpu = ESTCPULIM(kg->kg_estcpu + 1); - if ((kg->kg_estcpu % INVERSE_ESTCPU_WEIGHT) == 0) { - resetpriority(kg); - resetpriority_thread(td, kg); -#else + ts = td->td_sched; + + ts->ts_cpticks++; td->td_estcpu = ESTCPULIM(td->td_estcpu + 1); if ((td->td_estcpu % INVERSE_ESTCPU_WEIGHT) == 0) { resetpriority(td); resetpriority_thread(td); -#endif } } -#ifdef KSE -/* - * charge childs scheduling cpu usage to parent. - * - * XXXKSE assume only one thread & kse & 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. - */ -#else /* * charge childs scheduling cpu usage to parent. */ -#endif void sched_exit(struct proc *p, struct thread *td) { -#ifdef KSE - sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), td); - sched_exit_thread(FIRST_THREAD_IN_PROC(p), td); -#else - struct thread *parent = FIRST_THREAD_IN_PROC(p); CTR3(KTR_SCHED, "sched_exit: %p(%s) prio %d", td, td->td_proc->p_comm, td->td_priority); - parent->td_estcpu = ESTCPULIM(parent->td_estcpu + td->td_estcpu); - if ((td->td_proc->p_flag & P_NOLOAD) == 0) - sched_load_rem(); -#endif -} - -#ifdef KSE -void -sched_exit_ksegrp(struct ksegrp *kg, struct thread *childtd) -{ - - mtx_assert(&sched_lock, MA_OWNED); - kg->kg_estcpu = ESTCPULIM(kg->kg_estcpu + childtd->td_ksegrp->kg_estcpu); + sched_exit_thread(FIRST_THREAD_IN_PROC(p), td); } void sched_exit_thread(struct thread *td, struct thread *child) { + struct proc *childproc = child->td_proc; + CTR3(KTR_SCHED, "sched_exit_thread: %p(%s) prio %d", - child, child->td_proc->p_comm, child->td_priority); + child, childproc->p_comm, child->td_priority); + td->td_estcpu = ESTCPULIM(td->td_estcpu + child->td_estcpu); + childproc->p_estcpu = ESTCPULIM(childproc->p_estcpu + + child->td_estcpu); if ((child->td_proc->p_flag & P_NOLOAD) == 0) sched_load_rem(); } -#endif void sched_fork(struct thread *td, struct thread *childtd) { -#ifdef KSE - sched_fork_ksegrp(td, childtd->td_ksegrp); sched_fork_thread(td, childtd); -#else - childtd->td_estcpu = td->td_estcpu; - sched_newthread(childtd); -#endif -} - -#ifdef KSE -void -sched_fork_ksegrp(struct thread *td, struct ksegrp *child) -{ - mtx_assert(&sched_lock, MA_OWNED); - child->kg_estcpu = td->td_ksegrp->kg_estcpu; } void sched_fork_thread(struct thread *td, struct thread *childtd) { + childtd->td_estcpu = td->td_estcpu; sched_newthread(childtd); } -#endif void sched_nice(struct proc *p, int nice) { -#ifdef KSE - struct ksegrp *kg; -#endif struct thread *td; PROC_LOCK_ASSERT(p, MA_OWNED); mtx_assert(&sched_lock, MA_OWNED); p->p_nice = nice; -#ifdef KSE - FOREACH_KSEGRP_IN_PROC(p, kg) { - resetpriority(kg); - FOREACH_THREAD_IN_GROUP(kg, td) { - resetpriority_thread(td, kg); - } - } -#else FOREACH_THREAD_IN_PROC(p, td) { resetpriority(td); resetpriority_thread(td); } -#endif } void -#ifdef KSE -sched_class(struct ksegrp *kg, int class) -#else sched_class(struct thread *td, int class) -#endif { mtx_assert(&sched_lock, MA_OWNED); -#ifdef KSE - kg->kg_pri_class = class; -#else td->td_pri_class = class; -#endif } -#ifdef KSE -/* - * Adjust the priority of a thread. - * This may include moving the thread within the KSEGRP, - * changing the assignment of a kse to the thread, - * and moving a KSE in the system run queue. - */ -#else /* * Adjust the priority of a thread. */ -#endif static void sched_priority(struct thread *td, u_char prio) { @@ -1067,11 +743,7 @@ sched_unlend_prio(struct thread *td, u_char prio) if (td->td_base_pri >= PRI_MIN_TIMESHARE && td->td_base_pri <= PRI_MAX_TIMESHARE) -#ifdef KSE - base_pri = td->td_ksegrp->kg_user_pri; -#else base_pri = td->td_user_pri; -#endif else base_pri = td->td_base_pri; if (prio >= base_pri) { @@ -1109,40 +781,15 @@ sched_prio(struct thread *td, u_char prio) } void -#ifdef KSE -sched_user_prio(struct ksegrp *kg, u_char prio) -#else sched_user_prio(struct thread *td, u_char prio) -#endif { -#ifdef KSE - struct thread *td; -#endif u_char oldprio; -#ifdef KSE - kg->kg_base_user_pri = prio; - - /* XXXKSE only for 1:1 */ - - td = TAILQ_FIRST(&kg->kg_threads); - if (td == NULL) { - kg->kg_user_pri = prio; - return; - } - - if (td->td_flags & TDF_UBORROWING && kg->kg_user_pri <= prio) - return; - - oldprio = kg->kg_user_pri; - kg->kg_user_pri = prio; -#else td->td_base_user_pri = prio; if (td->td_flags & TDF_UBORROWING && td->td_user_pri <= prio) return; oldprio = td->td_user_pri; td->td_user_pri = prio; -#endif if (TD_ON_UPILOCK(td) && oldprio != prio) umtx_pi_adjust(td, oldprio); @@ -1155,13 +802,8 @@ sched_lend_user_prio(struct thread *td, u_char prio) td->td_flags |= TDF_UBORROWING; -#ifdef KSE - oldprio = td->td_ksegrp->kg_user_pri; - td->td_ksegrp->kg_user_pri = prio; -#else oldprio = td->td_user_pri; td->td_user_pri = prio; -#endif if (TD_ON_UPILOCK(td) && oldprio != prio) umtx_pi_adjust(td, oldprio); @@ -1170,23 +812,12 @@ sched_lend_user_prio(struct thread *td, u_char prio) void sched_unlend_user_prio(struct thread *td, u_char prio) { -#ifdef KSE - struct ksegrp *kg = td->td_ksegrp; -#endif u_char base_pri; -#ifdef KSE - base_pri = kg->kg_base_user_pri; -#else base_pri = td->td_base_user_pri; -#endif if (prio >= base_pri) { td->td_flags &= ~TDF_UBORROWING; -#ifdef KSE - sched_user_prio(kg, base_pri); -#else sched_user_prio(td, base_pri); -#endif } else sched_lend_user_prio(td, prio); } @@ -1196,59 +827,37 @@ sched_sleep(struct thread *td) { mtx_assert(&sched_lock, MA_OWNED); -#ifdef KSE - td->td_ksegrp->kg_slptime = 0; -#else td->td_slptime = 0; -#endif } -#ifdef KSE -static void remrunqueue(struct thread *td); -#endif - void sched_switch(struct thread *td, struct thread *newtd, int flags) { - struct kse *ke; -#ifdef KSE - struct ksegrp *kg; -#endif + struct td_sched *ts; struct proc *p; - ke = td->td_kse; + ts = td->td_sched; p = td->td_proc; mtx_assert(&sched_lock, MA_OWNED); if ((p->p_flag & P_NOLOAD) == 0) sched_load_rem(); -#ifdef KSE +#if 0 /* * We are volunteering to switch out so we get to nominate * a successor for the rest of our quantum - * First try another thread in our ksegrp, and then look for - * other ksegrps in our process. + * First try another thread in our process + * + * this is too expensive to do without per process run queues + * so skip it for now. + * XXX keep this comment as a marker. */ if (sched_followon && (p->p_flag & P_HADTHREADS) && (flags & SW_VOL) && - newtd == NULL) { - /* lets schedule another thread from this process */ - kg = td->td_ksegrp; - if ((newtd = TAILQ_FIRST(&kg->kg_runq))) { - remrunqueue(newtd); - sched_kgfollowons++; - } else { - FOREACH_KSEGRP_IN_PROC(p, kg) { - if ((newtd = TAILQ_FIRST(&kg->kg_runq))) { - sched_pfollowons++; - remrunqueue(newtd); - break; - } - } - } - } + newtd == NULL) + newtd = mumble(); #endif if (newtd) @@ -1267,25 +876,11 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) if (td == PCPU_GET(idlethread)) TD_SET_CAN_RUN(td); else { -#ifdef KSE - SLOT_RELEASE(td->td_ksegrp); -#endif if (TD_IS_RUNNING(td)) { - /* Put us back on the run queue (kse and all). */ + /* Put us back on the run queue. */ setrunqueue(td, (flags & SW_PREEMPT) ? SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED : SRQ_OURSELF|SRQ_YIELDING); -#ifdef KSE - } else if (p->p_flag & P_HADTHREADS) { - /* - * 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. - * It's NOT available if we are about to need it - */ - if (newtd == NULL || newtd->td_ksegrp != td->td_ksegrp) - slot_fill(td->td_ksegrp); -#endif } } if (newtd) { @@ -1294,17 +889,12 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) * as if it had been added to the run queue and selected. * It came from: * * A preemption - * ifdef KSE * * An upcall - * endif * * A followon */ KASSERT((newtd->td_inhibitors == 0), ("trying to run inhibitted thread")); -#ifdef KSE - SLOT_USE(newtd->td_ksegrp); -#endif - newtd->td_kse->ke_flags |= KEF_DIDRUN; + newtd->td_sched->ts_flags |= TSF_DIDRUN; TD_SET_RUNNING(newtd); if ((newtd->td_proc->p_flag & P_NOLOAD) == 0) sched_load_add(); @@ -1332,25 +922,12 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) void sched_wakeup(struct thread *td) { -#ifdef KSE - struct ksegrp *kg; -#endif - mtx_assert(&sched_lock, MA_OWNED); -#ifdef KSE - kg = td->td_ksegrp; - if (kg->kg_slptime > 1) { - updatepri(kg); - resetpriority(kg); - } - kg->kg_slptime = 0; -#else if (td->td_slptime > 1) { updatepri(td); resetpriority(td); } td->td_slptime = 0; -#endif setrunqueue(td, SRQ_BORING); } @@ -1481,22 +1058,17 @@ void sched_add(struct thread *td, int flags) #ifdef SMP { - struct kse *ke; + struct td_sched *ts; int forwarded = 0; int cpu; int single_cpu = 0; - ke = td->td_kse; + ts = td->td_sched; mtx_assert(&sched_lock, MA_OWNED); - KASSERT(ke->ke_state != KES_ONRUNQ, - ("sched_add: kse %p (%s) already in run queue", ke, -#ifdef KSE - ke->ke_proc->p_comm)); - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, -#else + KASSERT(ts->ts_state != TSS_ONRUNQ, + ("sched_add: td_sched %p (%s) already in run queue", ts, td->td_proc->p_comm)); KASSERT(td->td_proc->p_sflag & PS_INMEM, -#endif ("sched_add: process swapped out")); CTR5(KTR_SCHED, "sched_add: %p(%s) prio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, curthread, @@ -1505,22 +1077,22 @@ sched_add(struct thread *td, int flags) if (td->td_pinned != 0) { cpu = td->td_lastcpu; - ke->ke_runq = &runq_pcpu[cpu]; + ts->ts_runq = &runq_pcpu[cpu]; single_cpu = 1; CTR3(KTR_RUNQ, - "sched_add: Put kse:%p(td:%p) on cpu%d runq", ke, td, cpu); - } else if ((ke)->ke_flags & KEF_BOUND) { + "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); + } else if ((ts)->ts_flags & TSF_BOUND) { /* Find CPU from bound runq */ - KASSERT(SKE_RUNQ_PCPU(ke),("sched_add: bound kse not on cpu runq")); - cpu = ke->ke_runq - &runq_pcpu[0]; + KASSERT(SKE_RUNQ_PCPU(ts),("sched_add: bound td_sched not on cpu runq")); + cpu = ts->ts_runq - &runq_pcpu[0]; single_cpu = 1; CTR3(KTR_RUNQ, - "sched_add: Put kse:%p(td:%p) on cpu%d runq", ke, td, cpu); + "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); } else { CTR2(KTR_RUNQ, - "sched_add: adding kse:%p (td:%p) to gbl runq", ke, td); + "sched_add: adding td_sched:%p (td:%p) to gbl runq", ts, td); cpu = NOCPU; - ke->ke_runq = &runq; + ts->ts_runq = &runq; } if (single_cpu && (cpu != PCPU_GET(cpuid))) { @@ -1546,32 +1118,24 @@ sched_add(struct thread *td, int flags) if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_load_add(); -#ifdef KSE - SLOT_USE(td->td_ksegrp); -#endif - runq_add(ke->ke_runq, ke, flags); - ke->ke_state = KES_ONRUNQ; + runq_add(ts->ts_runq, ts, flags); + ts->ts_state = TSS_ONRUNQ; } #else /* SMP */ { - struct kse *ke; - ke = td->td_kse; + struct td_sched *ts; + ts = td->td_sched; mtx_assert(&sched_lock, MA_OWNED); - KASSERT(ke->ke_state != KES_ONRUNQ, - ("sched_add: kse %p (%s) already in run queue", ke, -#ifdef KSE - ke->ke_proc->p_comm)); - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, -#else + KASSERT(ts->ts_state != TSS_ONRUNQ, + ("sched_add: td_sched %p (%s) already in run queue", ts, td->td_proc->p_comm)); KASSERT(td->td_proc->p_sflag & PS_INMEM, -#endif ("sched_add: process swapped out")); CTR5(KTR_SCHED, "sched_add: %p(%s) prio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, curthread, curthread->td_proc->p_comm); - CTR2(KTR_RUNQ, "sched_add: adding kse:%p (td:%p) to runq", ke, td); - ke->ke_runq = &runq; + CTR2(KTR_RUNQ, "sched_add: adding td_sched:%p (td:%p) to runq", ts, td); + ts->ts_runq = &runq; /* * If we are yielding (on the way out anyhow) @@ -1590,11 +1154,8 @@ sched_add(struct thread *td, int flags) } if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_load_add(); -#ifdef KSE - SLOT_USE(td->td_ksegrp); -#endif - runq_add(ke->ke_runq, ke, flags); - ke->ke_state = KES_ONRUNQ; + runq_add(ts->ts_runq, ts, flags); + ts->ts_state = TSS_ONRUNQ; maybe_resched(td); } #endif /* SMP */ @@ -1602,17 +1163,13 @@ sched_add(struct thread *td, int flags) void sched_rem(struct thread *td) { - struct kse *ke; + struct td_sched *ts; - ke = td->td_kse; -#ifdef KSE - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, -#else + ts = td->td_sched; KASSERT(td->td_proc->p_sflag & PS_INMEM, -#endif ("sched_rem: process swapped out")); - KASSERT((ke->ke_state == KES_ONRUNQ), - ("sched_rem: KSE not on run queue")); + KASSERT((ts->ts_state == TSS_ONRUNQ), + ("sched_rem: thread not on run queue")); mtx_assert(&sched_lock, MA_OWNED); CTR5(KTR_SCHED, "sched_rem: %p(%s) prio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, curthread, @@ -1620,81 +1177,57 @@ sched_rem(struct thread *td) if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_load_rem(); -#ifdef KSE - SLOT_RELEASE(td->td_ksegrp); -#endif - runq_remove(ke->ke_runq, ke); + runq_remove(ts->ts_runq, ts); - ke->ke_state = KES_THREAD; + ts->ts_state = TSS_THREAD; } /* * Select threads to run. * Notice that the running threads still consume a slot. */ -#ifdef KSE -struct kse * -#else -struct thread * -#endif +struct td_sched * sched_choose(void) { - struct kse *ke; + struct td_sched *ts; struct runq *rq; #ifdef SMP - struct kse *kecpu; + struct td_sched *kecpu; rq = &runq; - ke = runq_choose(&runq); + ts = runq_choose(&runq); kecpu = runq_choose(&runq_pcpu[PCPU_GET(cpuid)]); - if (ke == NULL || + if (ts == NULL || (kecpu != NULL && - kecpu->ke_thread->td_priority < ke->ke_thread->td_priority)) { - CTR2(KTR_RUNQ, "choosing kse %p from pcpu runq %d", kecpu, + kecpu->ts_thread->td_priority < ts->ts_thread->td_priority)) { + CTR2(KTR_RUNQ, "choosing td_sched %p from pcpu runq %d", kecpu, PCPU_GET(cpuid)); - ke = kecpu; + ts = kecpu; rq = &runq_pcpu[PCPU_GET(cpuid)]; } else { - CTR1(KTR_RUNQ, "choosing kse %p from main runq", ke); + CTR1(KTR_RUNQ, "choosing td_sched %p from main runq", ts); } #else rq = &runq; - ke = runq_choose(&runq); + ts = runq_choose(&runq); #endif -#ifdef KSE - if (ke != NULL) { -#else - if (ke) { -#endif - runq_remove(rq, ke); - ke->ke_state = KES_THREAD; + if (ts) { + runq_remove(rq, ts); + ts->ts_state = TSS_THREAD; -#ifdef KSE - KASSERT(ke->ke_proc->p_sflag & PS_INMEM, + KASSERT(ts->ts_thread->td_proc->p_sflag & PS_INMEM, ("sched_choose: process swapped out")); -#else - KASSERT(ke->ke_thread->td_proc->p_sflag & PS_INMEM, - ("sched_choose: process swapped out")); - return (ke->ke_thread); -#endif } -#ifdef KSE - return (ke); -#else - return (NULL); -#endif + return (ts); } void sched_userret(struct thread *td) { -#ifdef KSE - struct ksegrp *kg; -#endif /* * XXX we cheat slightly on the locking here to avoid locking in * the usual case. Setting td_priority here is essentially an @@ -1706,42 +1239,32 @@ sched_userret(struct thread *td) */ KASSERT((td->td_flags & TDF_BORROWING) == 0, ("thread with borrowed priority returning to userland")); -#ifdef KSE - kg = td->td_ksegrp; - if (td->td_priority != kg->kg_user_pri) { - mtx_lock_spin(&sched_lock); - td->td_priority = kg->kg_user_pri; - td->td_base_pri = kg->kg_user_pri; - mtx_unlock_spin(&sched_lock); - } -#else if (td->td_priority != td->td_user_pri) { mtx_lock_spin(&sched_lock); td->td_priority = td->td_user_pri; td->td_base_pri = td->td_user_pri; mtx_unlock_spin(&sched_lock); } -#endif } void sched_bind(struct thread *td, int cpu) { - struct kse *ke; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); KASSERT(TD_IS_RUNNING(td), ("sched_bind: cannot bind non-running thread")); - ke = td->td_kse; + ts = td->td_sched; - ke->ke_flags |= KEF_BOUND; + ts->ts_flags |= TSF_BOUND; #ifdef SMP - ke->ke_runq = &runq_pcpu[cpu]; + ts->ts_runq = &runq_pcpu[cpu]; if (PCPU_GET(cpuid) == cpu) return; - ke->ke_state = KES_THREAD; + ts->ts_state = TSS_THREAD; mi_switch(SW_VOL, NULL); #endif @@ -1751,30 +1274,21 @@ void sched_unbind(struct thread* td) { mtx_assert(&sched_lock, MA_OWNED); - td->td_kse->ke_flags &= ~KEF_BOUND; + td->td_sched->ts_flags &= ~TSF_BOUND; } int sched_is_bound(struct thread *td) { mtx_assert(&sched_lock, MA_OWNED); - return (td->td_kse->ke_flags & KEF_BOUND); + return (td->td_sched->ts_flags & TSF_BOUND); } void sched_relinquish(struct thread *td) { -#ifdef KSE - struct ksegrp *kg; - - kg = td->td_ksegrp; -#endif mtx_lock_spin(&sched_lock); -#ifdef KSE - if (kg->kg_pri_class == PRI_TIMESHARE) -#else if (td->td_pri_class == PRI_TIMESHARE) -#endif sched_prio(td, PRI_MAX_TIMESHARE); mi_switch(SW_VOL, NULL); mtx_unlock_spin(&sched_lock); @@ -1786,14 +1300,6 @@ sched_load(void) return (sched_tdcnt); } -#ifdef KSE -int -sched_sizeof_ksegrp(void) -{ - return (sizeof(struct ksegrp) + sizeof(struct kg_sched)); -} -#endif - int sched_sizeof_proc(void) { @@ -1803,16 +1309,16 @@ sched_sizeof_proc(void) int sched_sizeof_thread(void) { - return (sizeof(struct thread) + sizeof(struct kse)); + return (sizeof(struct thread) + sizeof(struct td_sched)); } fixpt_t sched_pctcpu(struct thread *td) { - struct kse *ke; + struct td_sched *ts; - ke = td->td_kse; - return (ke->ke_pctcpu); + ts = td->td_sched; + return (ts->ts_pctcpu); } void diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index 7afe0fb..98b867b 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -30,8 +30,6 @@ __FBSDID("$FreeBSD$"); #include "opt_hwpmc_hooks.h" #include "opt_sched.h" -#define kse td_sched - #include <sys/param.h> #include <sys/systm.h> #include <sys/kdb.h> @@ -92,46 +90,45 @@ int tickincr = 1 << 10; * but are scheduler specific. */ /* - * The schedulable entity that can be given a context to run. A process may - * have several of these. + * Thread scheduler specific section. + * fields int he thread structure that are specific to this scheduler. */ -struct td_sched { /* really kse */ - TAILQ_ENTRY(kse) ke_procq; /* (j/z) Run queue. */ - int ke_flags; /* (j) KEF_* flags. */ - struct thread *ke_thread; /* (*) Active associated thread. */ - fixpt_t ke_pctcpu; /* (j) %cpu during p_swtime. */ - u_char ke_rqindex; /* (j) Run queue index. */ +struct td_sched { + TAILQ_ENTRY(td_sched) ts_procq; /* (j/z) Run queue. */ + int ts_flags; /* (j) TSF_* flags. */ + struct thread *ts_thread; /* (*) Active associated thread. */ + fixpt_t ts_pctcpu; /* (j) %cpu during p_swtime. */ + u_char ts_rqindex; /* (j) Run queue index. */ enum { - KES_THREAD = 0x0, /* slaved to thread state */ - KES_ONRUNQ - } ke_state; /* (j) thread sched specific status. */ - int ke_slptime; - int ke_slice; - struct runq *ke_runq; - u_char ke_cpu; /* CPU that we have affinity for. */ + TSS_THREAD = 0x0, /* slaved to thread state */ + TSS_ONRUNQ + } ts_state; /* (j) thread sched specific status. */ + int ts_slptime; + int ts_slice; + struct runq *ts_runq; + u_char ts_cpu; /* CPU that we have affinity for. */ /* The following variables are only used for pctcpu calculation */ - int ke_ltick; /* Last tick that we were running on */ - int ke_ftick; /* First tick that we were running on */ - int ke_ticks; /* Tick count */ + int ts_ltick; /* Last tick that we were running on */ + int ts_ftick; /* First tick that we were running on */ + int ts_ticks; /* Tick count */ /* originally from kg_sched */ int skg_slptime; /* Number of ticks we vol. slept */ int skg_runtime; /* Number of ticks we were running */ }; -#define td_kse td_sched -#define ke_assign ke_procq.tqe_next -/* flags kept in ke_flags */ -#define KEF_ASSIGNED 0x0001 /* Thread is being migrated. */ -#define KEF_BOUND 0x0002 /* Thread can not migrate. */ -#define KEF_XFERABLE 0x0004 /* Thread was added as transferable. */ -#define KEF_HOLD 0x0008 /* Thread is temporarily bound. */ -#define KEF_REMOVED 0x0010 /* Thread was removed while ASSIGNED */ -#define KEF_INTERNAL 0x0020 /* Thread added due to migration. */ -#define KEF_PREEMPTED 0x0040 /* Thread was preempted */ -#define KEF_DIDRUN 0x02000 /* Thread actually ran. */ -#define KEF_EXIT 0x04000 /* Thread is being killed. */ - -static struct kse kse0; +#define ts_assign ts_procq.tqe_next +/* flags kept in ts_flags */ +#define TSF_ASSIGNED 0x0001 /* Thread is being migrated. */ +#define TSF_BOUND 0x0002 /* Thread can not migrate. */ +#define TSF_XFERABLE 0x0004 /* Thread was added as transferable. */ +#define TSF_HOLD 0x0008 /* Thread is temporarily bound. */ +#define TSF_REMOVED 0x0010 /* Thread was removed while ASSIGNED */ +#define TSF_INTERNAL 0x0020 /* Thread added due to migration. */ +#define TSF_PREEMPTED 0x0040 /* Thread was preempted */ +#define TSF_DIDRUN 0x02000 /* Thread actually ran. */ +#define TSF_EXIT 0x04000 /* Thread is being killed. */ + +static struct td_sched td_sched0; /* * The priority is primarily determined by the interactivity score. Thus, we @@ -191,9 +188,9 @@ static struct kse kse0; */ #define SCHED_INTERACTIVE(td) \ (sched_interact_score(td) < SCHED_INTERACT_THRESH) -#define SCHED_CURR(td, ke) \ - ((ke->ke_thread->td_flags & TDF_BORROWING) || \ - (ke->ke_flags & KEF_PREEMPTED) || SCHED_INTERACTIVE(td)) +#define SCHED_CURR(td, ts) \ + ((ts->ts_thread->td_flags & TDF_BORROWING) || \ + (ts->ts_flags & TSF_PREEMPTED) || SCHED_INTERACTIVE(td)) /* * Cpu percentage computation macros and defines. @@ -206,22 +203,22 @@ static struct kse kse0; #define SCHED_CPU_TICKS (hz * SCHED_CPU_TIME) /* - * kseq - per processor runqs and statistics. + * tdq - per processor runqs and statistics. */ -struct kseq { +struct tdq { struct runq ksq_idle; /* Queue of IDLE threads. */ struct runq ksq_timeshare[2]; /* Run queues for !IDLE. */ struct runq *ksq_next; /* Next timeshare queue. */ struct runq *ksq_curr; /* Current queue. */ int ksq_load_timeshare; /* Load for timeshare. */ int ksq_load; /* Aggregate load. */ - short ksq_nice[SCHED_PRI_NRESV]; /* KSEs in each nice bin. */ + short ksq_nice[SCHED_PRI_NRESV]; /* threadss in each nice bin. */ short ksq_nicemin; /* Least nice. */ #ifdef SMP int ksq_transferable; - LIST_ENTRY(kseq) ksq_siblings; /* Next in kseq group. */ - struct kseq_group *ksq_group; /* Our processor group. */ - volatile struct kse *ksq_assigned; /* assigned by another CPU. */ + LIST_ENTRY(tdq) ksq_siblings; /* Next in tdq group. */ + struct tdq_group *ksq_group; /* Our processor group. */ + volatile struct td_sched *ksq_assigned; /* assigned by another CPU. */ #else int ksq_sysload; /* For loadavg, !ITHD load. */ #endif @@ -229,21 +226,21 @@ struct kseq { #ifdef SMP /* - * kseq groups are groups of processors which can cheaply share threads. When + * tdq groups are groups of processors which can cheaply share threads. When * one processor in the group goes idle it will check the runqs of the other * processors in its group prior to halting and waiting for an interrupt. * These groups are suitable for SMT (Symetric Multi-Threading) and not NUMA. * In a numa environment we'd want an idle bitmap per group and a two tiered * load balancer. */ -struct kseq_group { - int ksg_cpus; /* Count of CPUs in this kseq group. */ +struct tdq_group { + int ksg_cpus; /* Count of CPUs in this tdq group. */ cpumask_t ksg_cpumask; /* Mask of cpus in this group. */ cpumask_t ksg_idlemask; /* Idle cpus in this group. */ cpumask_t ksg_mask; /* Bit mask for first cpu. */ int ksg_load; /* Total load of this group. */ int ksg_transferable; /* Transferable load of this group. */ - LIST_HEAD(, kseq) ksg_members; /* Linked list of all members. */ + LIST_HEAD(, tdq) ksg_members; /* Linked list of all members. */ }; #endif @@ -251,185 +248,185 @@ struct kseq_group { * One kse queue per processor. */ #ifdef SMP -static cpumask_t kseq_idle; +static cpumask_t tdq_idle; static int ksg_maxid; -static struct kseq kseq_cpu[MAXCPU]; -static struct kseq_group kseq_groups[MAXCPU]; +static struct tdq tdq_cpu[MAXCPU]; +static struct tdq_group tdq_groups[MAXCPU]; static int bal_tick; static int gbal_tick; static int balance_groups; -#define KSEQ_SELF() (&kseq_cpu[PCPU_GET(cpuid)]) -#define KSEQ_CPU(x) (&kseq_cpu[(x)]) -#define KSEQ_ID(x) ((x) - kseq_cpu) -#define KSEQ_GROUP(x) (&kseq_groups[(x)]) +#define TDQ_SELF() (&tdq_cpu[PCPU_GET(cpuid)]) +#define TDQ_CPU(x) (&tdq_cpu[(x)]) +#define TDQ_ID(x) ((x) - tdq_cpu) +#define TDQ_GROUP(x) (&tdq_groups[(x)]) #else /* !SMP */ -static struct kseq kseq_cpu; +static struct tdq tdq_cpu; -#define KSEQ_SELF() (&kseq_cpu) -#define KSEQ_CPU(x) (&kseq_cpu) +#define TDQ_SELF() (&tdq_cpu) +#define TDQ_CPU(x) (&tdq_cpu) #endif -static struct kse *sched_choose(void); /* XXX Should be thread * */ -static void sched_slice(struct kse *); +static struct td_sched *sched_choose(void); /* XXX Should be thread * */ +static void sched_slice(struct td_sched *); static void sched_priority(struct thread *); static void sched_thread_priority(struct thread *, u_char); static int sched_interact_score(struct thread *); static void sched_interact_update(struct thread *); static void sched_interact_fork(struct thread *); -static void sched_pctcpu_update(struct kse *); +static void sched_pctcpu_update(struct td_sched *); /* Operations on per processor queues */ -static struct kse * kseq_choose(struct kseq *); -static void kseq_setup(struct kseq *); -static void kseq_load_add(struct kseq *, struct kse *); -static void kseq_load_rem(struct kseq *, struct kse *); -static __inline void kseq_runq_add(struct kseq *, struct kse *, int); -static __inline void kseq_runq_rem(struct kseq *, struct kse *); -static void kseq_nice_add(struct kseq *, int); -static void kseq_nice_rem(struct kseq *, int); -void kseq_print(int cpu); +static struct td_sched * tdq_choose(struct tdq *); +static void tdq_setup(struct tdq *); +static void tdq_load_add(struct tdq *, struct td_sched *); +static void tdq_load_rem(struct tdq *, struct td_sched *); +static __inline void tdq_runq_add(struct tdq *, struct td_sched *, int); +static __inline void tdq_runq_rem(struct tdq *, struct td_sched *); +static void tdq_nice_add(struct tdq *, int); +static void tdq_nice_rem(struct tdq *, int); +void tdq_print(int cpu); #ifdef SMP -static int kseq_transfer(struct kseq *, struct kse *, int); -static struct kse *runq_steal(struct runq *); +static int tdq_transfer(struct tdq *, struct td_sched *, int); +static struct td_sched *runq_steal(struct runq *); static void sched_balance(void); static void sched_balance_groups(void); -static void sched_balance_group(struct kseq_group *); -static void sched_balance_pair(struct kseq *, struct kseq *); -static void kseq_move(struct kseq *, int); -static int kseq_idled(struct kseq *); -static void kseq_notify(struct kse *, int); -static void kseq_assign(struct kseq *); -static struct kse *kseq_steal(struct kseq *, int); -#define KSE_CAN_MIGRATE(ke) \ - ((ke)->ke_thread->td_pinned == 0 && ((ke)->ke_flags & KEF_BOUND) == 0) +static void sched_balance_group(struct tdq_group *); +static void sched_balance_pair(struct tdq *, struct tdq *); +static void tdq_move(struct tdq *, int); +static int tdq_idled(struct tdq *); +static void tdq_notify(struct td_sched *, int); +static void tdq_assign(struct tdq *); +static struct td_sched *tdq_steal(struct tdq *, int); +#define THREAD_CAN_MIGRATE(ts) \ + ((ts)->ts_thread->td_pinned == 0 && ((ts)->ts_flags & TSF_BOUND) == 0) #endif void -kseq_print(int cpu) +tdq_print(int cpu) { - struct kseq *kseq; + struct tdq *tdq; int i; - kseq = KSEQ_CPU(cpu); + tdq = TDQ_CPU(cpu); - printf("kseq:\n"); - printf("\tload: %d\n", kseq->ksq_load); - printf("\tload TIMESHARE: %d\n", kseq->ksq_load_timeshare); + printf("tdq:\n"); + printf("\tload: %d\n", tdq->ksq_load); + printf("\tload TIMESHARE: %d\n", tdq->ksq_load_timeshare); #ifdef SMP - printf("\tload transferable: %d\n", kseq->ksq_transferable); + printf("\tload transferable: %d\n", tdq->ksq_transferable); #endif - printf("\tnicemin:\t%d\n", kseq->ksq_nicemin); + printf("\tnicemin:\t%d\n", tdq->ksq_nicemin); printf("\tnice counts:\n"); for (i = 0; i < SCHED_PRI_NRESV; i++) - if (kseq->ksq_nice[i]) + if (tdq->ksq_nice[i]) printf("\t\t%d = %d\n", - i - SCHED_PRI_NHALF, kseq->ksq_nice[i]); + i - SCHED_PRI_NHALF, tdq->ksq_nice[i]); } static __inline void -kseq_runq_add(struct kseq *kseq, struct kse *ke, int flags) +tdq_runq_add(struct tdq *tdq, struct td_sched *ts, int flags) { #ifdef SMP - if (KSE_CAN_MIGRATE(ke)) { - kseq->ksq_transferable++; - kseq->ksq_group->ksg_transferable++; - ke->ke_flags |= KEF_XFERABLE; + if (THREAD_CAN_MIGRATE(ts)) { + tdq->ksq_transferable++; + tdq->ksq_group->ksg_transferable++; + ts->ts_flags |= TSF_XFERABLE; } #endif - if (ke->ke_flags & KEF_PREEMPTED) + if (ts->ts_flags & TSF_PREEMPTED) flags |= SRQ_PREEMPTED; - runq_add(ke->ke_runq, ke, flags); + runq_add(ts->ts_runq, ts, flags); } static __inline void -kseq_runq_rem(struct kseq *kseq, struct kse *ke) +tdq_runq_rem(struct tdq *tdq, struct td_sched *ts) { #ifdef SMP - if (ke->ke_flags & KEF_XFERABLE) { - kseq->ksq_transferable--; - kseq->ksq_group->ksg_transferable--; - ke->ke_flags &= ~KEF_XFERABLE; + if (ts->ts_flags & TSF_XFERABLE) { + tdq->ksq_transferable--; + tdq->ksq_group->ksg_transferable--; + ts->ts_flags &= ~TSF_XFERABLE; } #endif - runq_remove(ke->ke_runq, ke); + runq_remove(ts->ts_runq, ts); } static void -kseq_load_add(struct kseq *kseq, struct kse *ke) +tdq_load_add(struct tdq *tdq, struct td_sched *ts) { int class; mtx_assert(&sched_lock, MA_OWNED); - class = PRI_BASE(ke->ke_thread->td_pri_class); + class = PRI_BASE(ts->ts_thread->td_pri_class); if (class == PRI_TIMESHARE) - kseq->ksq_load_timeshare++; - kseq->ksq_load++; - CTR1(KTR_SCHED, "load: %d", kseq->ksq_load); - if (class != PRI_ITHD && (ke->ke_thread->td_proc->p_flag & P_NOLOAD) == 0) + tdq->ksq_load_timeshare++; + tdq->ksq_load++; + CTR1(KTR_SCHED, "load: %d", tdq->ksq_load); + if (class != PRI_ITHD && (ts->ts_thread->td_proc->p_flag & P_NOLOAD) == 0) #ifdef SMP - kseq->ksq_group->ksg_load++; + tdq->ksq_group->ksg_load++; #else - kseq->ksq_sysload++; + tdq->ksq_sysload++; #endif - if (ke->ke_thread->td_pri_class == PRI_TIMESHARE) - kseq_nice_add(kseq, ke->ke_thread->td_proc->p_nice); + if (ts->ts_thread->td_pri_class == PRI_TIMESHARE) + tdq_nice_add(tdq, ts->ts_thread->td_proc->p_nice); } static void -kseq_load_rem(struct kseq *kseq, struct kse *ke) +tdq_load_rem(struct tdq *tdq, struct td_sched *ts) { int class; mtx_assert(&sched_lock, MA_OWNED); - class = PRI_BASE(ke->ke_thread->td_pri_class); + class = PRI_BASE(ts->ts_thread->td_pri_class); if (class == PRI_TIMESHARE) - kseq->ksq_load_timeshare--; - if (class != PRI_ITHD && (ke->ke_thread->td_proc->p_flag & P_NOLOAD) == 0) + tdq->ksq_load_timeshare--; + if (class != PRI_ITHD && (ts->ts_thread->td_proc->p_flag & P_NOLOAD) == 0) #ifdef SMP - kseq->ksq_group->ksg_load--; + tdq->ksq_group->ksg_load--; #else - kseq->ksq_sysload--; + tdq->ksq_sysload--; #endif - kseq->ksq_load--; - CTR1(KTR_SCHED, "load: %d", kseq->ksq_load); - ke->ke_runq = NULL; - if (ke->ke_thread->td_pri_class == PRI_TIMESHARE) - kseq_nice_rem(kseq, ke->ke_thread->td_proc->p_nice); + tdq->ksq_load--; + CTR1(KTR_SCHED, "load: %d", tdq->ksq_load); + ts->ts_runq = NULL; + if (ts->ts_thread->td_pri_class == PRI_TIMESHARE) + tdq_nice_rem(tdq, ts->ts_thread->td_proc->p_nice); } static void -kseq_nice_add(struct kseq *kseq, int nice) +tdq_nice_add(struct tdq *tdq, int nice) { mtx_assert(&sched_lock, MA_OWNED); /* Normalize to zero. */ - kseq->ksq_nice[nice + SCHED_PRI_NHALF]++; - if (nice < kseq->ksq_nicemin || kseq->ksq_load_timeshare == 1) - kseq->ksq_nicemin = nice; + tdq->ksq_nice[nice + SCHED_PRI_NHALF]++; + if (nice < tdq->ksq_nicemin || tdq->ksq_load_timeshare == 1) + tdq->ksq_nicemin = nice; } static void -kseq_nice_rem(struct kseq *kseq, int nice) +tdq_nice_rem(struct tdq *tdq, int nice) { int n; mtx_assert(&sched_lock, MA_OWNED); /* Normalize to zero. */ n = nice + SCHED_PRI_NHALF; - kseq->ksq_nice[n]--; - KASSERT(kseq->ksq_nice[n] >= 0, ("Negative nice count.")); + tdq->ksq_nice[n]--; + KASSERT(tdq->ksq_nice[n] >= 0, ("Negative nice count.")); /* * If this wasn't the smallest nice value or there are more in * this bucket we can just return. Otherwise we have to recalculate * the smallest nice. */ - if (nice != kseq->ksq_nicemin || - kseq->ksq_nice[n] != 0 || - kseq->ksq_load_timeshare == 0) + if (nice != tdq->ksq_nicemin || + tdq->ksq_nice[n] != 0 || + tdq->ksq_load_timeshare == 0) return; for (; n < SCHED_PRI_NRESV; n++) - if (kseq->ksq_nice[n]) { - kseq->ksq_nicemin = n - SCHED_PRI_NHALF; + if (tdq->ksq_nice[n]) { + tdq->ksq_nicemin = n - SCHED_PRI_NHALF; return; } } @@ -454,9 +451,9 @@ kseq_nice_rem(struct kseq *kseq, int nice) static void sched_balance(void) { - struct kseq_group *high; - struct kseq_group *low; - struct kseq_group *ksg; + struct tdq_group *high; + struct tdq_group *low; + struct tdq_group *ksg; int cnt; int i; @@ -466,7 +463,7 @@ sched_balance(void) low = high = NULL; i = random() % (ksg_maxid + 1); for (cnt = 0; cnt <= ksg_maxid; cnt++) { - ksg = KSEQ_GROUP(i); + ksg = TDQ_GROUP(i); /* * Find the CPU with the highest load that has some * threads to transfer. @@ -493,34 +490,34 @@ sched_balance_groups(void) mtx_assert(&sched_lock, MA_OWNED); if (smp_started) for (i = 0; i <= ksg_maxid; i++) - sched_balance_group(KSEQ_GROUP(i)); + sched_balance_group(TDQ_GROUP(i)); } static void -sched_balance_group(struct kseq_group *ksg) +sched_balance_group(struct tdq_group *ksg) { - struct kseq *kseq; - struct kseq *high; - struct kseq *low; + struct tdq *tdq; + struct tdq *high; + struct tdq *low; int load; if (ksg->ksg_transferable == 0) return; low = NULL; high = NULL; - LIST_FOREACH(kseq, &ksg->ksg_members, ksq_siblings) { - load = kseq->ksq_load; + LIST_FOREACH(tdq, &ksg->ksg_members, ksq_siblings) { + load = tdq->ksq_load; if (high == NULL || load > high->ksq_load) - high = kseq; + high = tdq; if (low == NULL || load < low->ksq_load) - low = kseq; + low = tdq; } if (high != NULL && low != NULL && high != low) sched_balance_pair(high, low); } static void -sched_balance_pair(struct kseq *high, struct kseq *low) +sched_balance_pair(struct tdq *high, struct tdq *low) { int transferable; int high_load; @@ -531,7 +528,7 @@ sched_balance_pair(struct kseq *high, struct kseq *low) /* * If we're transfering within a group we have to use this specific - * kseq's transferable count, otherwise we can steal from other members + * tdq's transferable count, otherwise we can steal from other members * of the group. */ if (high->ksq_group == low->ksq_group) { @@ -555,135 +552,135 @@ sched_balance_pair(struct kseq *high, struct kseq *low) move++; move = min(move, transferable); for (i = 0; i < move; i++) - kseq_move(high, KSEQ_ID(low)); + tdq_move(high, TDQ_ID(low)); return; } static void -kseq_move(struct kseq *from, int cpu) +tdq_move(struct tdq *from, int cpu) { - struct kseq *kseq; - struct kseq *to; - struct kse *ke; - - kseq = from; - to = KSEQ_CPU(cpu); - ke = kseq_steal(kseq, 1); - if (ke == NULL) { - struct kseq_group *ksg; - - ksg = kseq->ksq_group; - LIST_FOREACH(kseq, &ksg->ksg_members, ksq_siblings) { - if (kseq == from || kseq->ksq_transferable == 0) + struct tdq *tdq; + struct tdq *to; + struct td_sched *ts; + + tdq = from; + to = TDQ_CPU(cpu); + ts = tdq_steal(tdq, 1); + if (ts == NULL) { + struct tdq_group *ksg; + + ksg = tdq->ksq_group; + LIST_FOREACH(tdq, &ksg->ksg_members, ksq_siblings) { + if (tdq == from || tdq->ksq_transferable == 0) continue; - ke = kseq_steal(kseq, 1); + ts = tdq_steal(tdq, 1); break; } - if (ke == NULL) - panic("kseq_move: No KSEs available with a " + if (ts == NULL) + panic("tdq_move: No threads available with a " "transferable count of %d\n", ksg->ksg_transferable); } - if (kseq == to) + if (tdq == to) return; - ke->ke_state = KES_THREAD; - kseq_runq_rem(kseq, ke); - kseq_load_rem(kseq, ke); - kseq_notify(ke, cpu); + ts->ts_state = TSS_THREAD; + tdq_runq_rem(tdq, ts); + tdq_load_rem(tdq, ts); + tdq_notify(ts, cpu); } static int -kseq_idled(struct kseq *kseq) +tdq_idled(struct tdq *tdq) { - struct kseq_group *ksg; - struct kseq *steal; - struct kse *ke; + struct tdq_group *ksg; + struct tdq *steal; + struct td_sched *ts; - ksg = kseq->ksq_group; + ksg = tdq->ksq_group; /* * If we're in a cpu group, try and steal kses from another cpu in * the group before idling. */ if (ksg->ksg_cpus > 1 && ksg->ksg_transferable) { LIST_FOREACH(steal, &ksg->ksg_members, ksq_siblings) { - if (steal == kseq || steal->ksq_transferable == 0) + if (steal == tdq || steal->ksq_transferable == 0) continue; - ke = kseq_steal(steal, 0); - if (ke == NULL) + ts = tdq_steal(steal, 0); + if (ts == NULL) continue; - ke->ke_state = KES_THREAD; - kseq_runq_rem(steal, ke); - kseq_load_rem(steal, ke); - ke->ke_cpu = PCPU_GET(cpuid); - ke->ke_flags |= KEF_INTERNAL | KEF_HOLD; - sched_add(ke->ke_thread, SRQ_YIELDING); + ts->ts_state = TSS_THREAD; + tdq_runq_rem(steal, ts); + tdq_load_rem(steal, ts); + ts->ts_cpu = PCPU_GET(cpuid); + ts->ts_flags |= TSF_INTERNAL | TSF_HOLD; + sched_add(ts->ts_thread, SRQ_YIELDING); return (0); } } /* * We only set the idled bit when all of the cpus in the group are - * idle. Otherwise we could get into a situation where a KSE bounces + * idle. Otherwise we could get into a situation where a thread bounces * back and forth between two idle cores on seperate physical CPUs. */ ksg->ksg_idlemask |= PCPU_GET(cpumask); if (ksg->ksg_idlemask != ksg->ksg_cpumask) return (1); - atomic_set_int(&kseq_idle, ksg->ksg_mask); + atomic_set_int(&tdq_idle, ksg->ksg_mask); return (1); } static void -kseq_assign(struct kseq *kseq) +tdq_assign(struct tdq *tdq) { - struct kse *nke; - struct kse *ke; + struct td_sched *nts; + struct td_sched *ts; do { - *(volatile struct kse **)&ke = kseq->ksq_assigned; - } while(!atomic_cmpset_ptr((volatile uintptr_t *)&kseq->ksq_assigned, - (uintptr_t)ke, (uintptr_t)NULL)); - for (; ke != NULL; ke = nke) { - nke = ke->ke_assign; - kseq->ksq_group->ksg_load--; - kseq->ksq_load--; - ke->ke_flags &= ~KEF_ASSIGNED; - if (ke->ke_flags & KEF_REMOVED) { - ke->ke_flags &= ~KEF_REMOVED; + *(volatile struct td_sched **)&ts = tdq->ksq_assigned; + } while(!atomic_cmpset_ptr((volatile uintptr_t *)&tdq->ksq_assigned, + (uintptr_t)ts, (uintptr_t)NULL)); + for (; ts != NULL; ts = nts) { + nts = ts->ts_assign; + tdq->ksq_group->ksg_load--; + tdq->ksq_load--; + ts->ts_flags &= ~TSF_ASSIGNED; + if (ts->ts_flags & TSF_REMOVED) { + ts->ts_flags &= ~TSF_REMOVED; continue; } - ke->ke_flags |= KEF_INTERNAL | KEF_HOLD; - sched_add(ke->ke_thread, SRQ_YIELDING); + ts->ts_flags |= TSF_INTERNAL | TSF_HOLD; + sched_add(ts->ts_thread, SRQ_YIELDING); } } static void -kseq_notify(struct kse *ke, int cpu) +tdq_notify(struct td_sched *ts, int cpu) { - struct kseq *kseq; + struct tdq *tdq; struct thread *td; struct pcpu *pcpu; int class; int prio; - kseq = KSEQ_CPU(cpu); + tdq = TDQ_CPU(cpu); /* XXX */ - class = PRI_BASE(ke->ke_thread->td_pri_class); + class = PRI_BASE(ts->ts_thread->td_pri_class); if ((class == PRI_TIMESHARE || class == PRI_REALTIME) && - (kseq_idle & kseq->ksq_group->ksg_mask)) - atomic_clear_int(&kseq_idle, kseq->ksq_group->ksg_mask); - kseq->ksq_group->ksg_load++; - kseq->ksq_load++; - ke->ke_cpu = cpu; - ke->ke_flags |= KEF_ASSIGNED; - prio = ke->ke_thread->td_priority; + (tdq_idle & tdq->ksq_group->ksg_mask)) + atomic_clear_int(&tdq_idle, tdq->ksq_group->ksg_mask); + tdq->ksq_group->ksg_load++; + tdq->ksq_load++; + ts->ts_cpu = cpu; + ts->ts_flags |= TSF_ASSIGNED; + prio = ts->ts_thread->td_priority; /* - * Place a KSE on another cpu's queue and force a resched. + * Place a thread on another cpu's queue and force a resched. */ do { - *(volatile struct kse **)&ke->ke_assign = kseq->ksq_assigned; - } while(!atomic_cmpset_ptr((volatile uintptr_t *)&kseq->ksq_assigned, - (uintptr_t)ke->ke_assign, (uintptr_t)ke)); + *(volatile struct td_sched **)&ts->ts_assign = tdq->ksq_assigned; + } while(!atomic_cmpset_ptr((volatile uintptr_t *)&tdq->ksq_assigned, + (uintptr_t)ts->ts_assign, (uintptr_t)ts)); /* * Without sched_lock we could lose a race where we set NEEDRESCHED * on a thread that is switched out before the IPI is delivered. This @@ -692,19 +689,19 @@ kseq_notify(struct kse *ke, int cpu) */ pcpu = pcpu_find(cpu); td = pcpu->pc_curthread; - if (ke->ke_thread->td_priority < td->td_priority || + if (ts->ts_thread->td_priority < td->td_priority || td == pcpu->pc_idlethread) { td->td_flags |= TDF_NEEDRESCHED; ipi_selected(1 << cpu, IPI_AST); } } -static struct kse * +static struct td_sched * runq_steal(struct runq *rq) { struct rqhead *rqh; struct rqbits *rqb; - struct kse *ke; + struct td_sched *ts; int word; int bit; @@ -717,39 +714,39 @@ runq_steal(struct runq *rq) if ((rqb->rqb_bits[word] & (1ul << bit)) == 0) continue; rqh = &rq->rq_queues[bit + (word << RQB_L2BPW)]; - TAILQ_FOREACH(ke, rqh, ke_procq) { - if (KSE_CAN_MIGRATE(ke)) - return (ke); + TAILQ_FOREACH(ts, rqh, ts_procq) { + if (THREAD_CAN_MIGRATE(ts)) + return (ts); } } } return (NULL); } -static struct kse * -kseq_steal(struct kseq *kseq, int stealidle) +static struct td_sched * +tdq_steal(struct tdq *tdq, int stealidle) { - struct kse *ke; + struct td_sched *ts; /* * Steal from next first to try to get a non-interactive task that * may not have run for a while. */ - if ((ke = runq_steal(kseq->ksq_next)) != NULL) - return (ke); - if ((ke = runq_steal(kseq->ksq_curr)) != NULL) - return (ke); + if ((ts = runq_steal(tdq->ksq_next)) != NULL) + return (ts); + if ((ts = runq_steal(tdq->ksq_curr)) != NULL) + return (ts); if (stealidle) - return (runq_steal(&kseq->ksq_idle)); + return (runq_steal(&tdq->ksq_idle)); return (NULL); } int -kseq_transfer(struct kseq *kseq, struct kse *ke, int class) +tdq_transfer(struct tdq *tdq, struct td_sched *ts, int class) { - struct kseq_group *nksg; - struct kseq_group *ksg; - struct kseq *old; + struct tdq_group *nksg; + struct tdq_group *ksg; + struct tdq *old; int cpu; int idx; @@ -767,16 +764,16 @@ kseq_transfer(struct kseq *kseq, struct kse *ke, int class) * some CPUs may idle. Too low and there will be excess migration * and context switches. */ - old = KSEQ_CPU(ke->ke_cpu); + old = TDQ_CPU(ts->ts_cpu); nksg = old->ksq_group; - ksg = kseq->ksq_group; - if (kseq_idle) { - if (kseq_idle & nksg->ksg_mask) { + ksg = tdq->ksq_group; + if (tdq_idle) { + if (tdq_idle & nksg->ksg_mask) { cpu = ffs(nksg->ksg_idlemask); if (cpu) { CTR2(KTR_SCHED, - "kseq_transfer: %p found old cpu %X " - "in idlemask.", ke, cpu); + "tdq_transfer: %p found old cpu %X " + "in idlemask.", ts, cpu); goto migrate; } } @@ -784,30 +781,30 @@ kseq_transfer(struct kseq *kseq, struct kse *ke, int class) * Multiple cpus could find this bit simultaneously * but the race shouldn't be terrible. */ - cpu = ffs(kseq_idle); + cpu = ffs(tdq_idle); if (cpu) { - CTR2(KTR_SCHED, "kseq_transfer: %p found %X " - "in idlemask.", ke, cpu); + CTR2(KTR_SCHED, "tdq_transfer: %p found %X " + "in idlemask.", ts, cpu); goto migrate; } } idx = 0; #if 0 - if (old->ksq_load < kseq->ksq_load) { - cpu = ke->ke_cpu + 1; - CTR2(KTR_SCHED, "kseq_transfer: %p old cpu %X " - "load less than ours.", ke, cpu); + if (old->ksq_load < tdq->ksq_load) { + cpu = ts->ts_cpu + 1; + CTR2(KTR_SCHED, "tdq_transfer: %p old cpu %X " + "load less than ours.", ts, cpu); goto migrate; } /* * No new CPU was found, look for one with less load. */ for (idx = 0; idx <= ksg_maxid; idx++) { - nksg = KSEQ_GROUP(idx); + nksg = TDQ_GROUP(idx); if (nksg->ksg_load /*+ (nksg->ksg_cpus * 2)*/ < ksg->ksg_load) { cpu = ffs(nksg->ksg_cpumask); - CTR2(KTR_SCHED, "kseq_transfer: %p cpu %X load less " - "than ours.", ke, cpu); + CTR2(KTR_SCHED, "tdq_transfer: %p cpu %X load less " + "than ours.", ts, cpu); goto migrate; } } @@ -819,8 +816,8 @@ kseq_transfer(struct kseq *kseq, struct kse *ke, int class) if (ksg->ksg_idlemask) { cpu = ffs(ksg->ksg_idlemask); if (cpu) { - CTR2(KTR_SCHED, "kseq_transfer: %p cpu %X idle in " - "group.", ke, cpu); + CTR2(KTR_SCHED, "tdq_transfer: %p cpu %X idle in " + "group.", ts, cpu); goto migrate; } } @@ -830,8 +827,8 @@ migrate: * Now that we've found an idle CPU, migrate the thread. */ cpu--; - ke->ke_runq = NULL; - kseq_notify(ke, cpu); + ts->ts_runq = NULL; + tdq_notify(ts, cpu); return (1); } @@ -842,61 +839,61 @@ migrate: * Pick the highest priority task we have and return it. */ -static struct kse * -kseq_choose(struct kseq *kseq) +static struct td_sched * +tdq_choose(struct tdq *tdq) { struct runq *swap; - struct kse *ke; + struct td_sched *ts; int nice; mtx_assert(&sched_lock, MA_OWNED); swap = NULL; for (;;) { - ke = runq_choose(kseq->ksq_curr); - if (ke == NULL) { + ts = runq_choose(tdq->ksq_curr); + if (ts == NULL) { /* * We already swapped once and didn't get anywhere. */ if (swap) break; - swap = kseq->ksq_curr; - kseq->ksq_curr = kseq->ksq_next; - kseq->ksq_next = swap; + swap = tdq->ksq_curr; + tdq->ksq_curr = tdq->ksq_next; + tdq->ksq_next = swap; continue; } /* - * If we encounter a slice of 0 the kse is in a - * TIMESHARE kse group and its nice was too far out + * If we encounter a slice of 0 the td_sched is in a + * TIMESHARE td_sched group and its nice was too far out * of the range that receives slices. */ - nice = ke->ke_thread->td_proc->p_nice + (0 - kseq->ksq_nicemin); + nice = ts->ts_thread->td_proc->p_nice + (0 - tdq->ksq_nicemin); #if 0 - if (ke->ke_slice == 0 || (nice > SCHED_SLICE_NTHRESH && - ke->ke_thread->td_proc->p_nice != 0)) { - runq_remove(ke->ke_runq, ke); - sched_slice(ke); - ke->ke_runq = kseq->ksq_next; - runq_add(ke->ke_runq, ke, 0); + if (ts->ts_slice == 0 || (nice > SCHED_SLICE_NTHRESH && + ts->ts_thread->td_proc->p_nice != 0)) { + runq_remove(ts->ts_runq, ts); + sched_slice(ts); + ts->ts_runq = tdq->ksq_next; + runq_add(ts->ts_runq, ts, 0); continue; } #endif - return (ke); + return (ts); } - return (runq_choose(&kseq->ksq_idle)); + return (runq_choose(&tdq->ksq_idle)); } static void -kseq_setup(struct kseq *kseq) +tdq_setup(struct tdq *tdq) { - runq_init(&kseq->ksq_timeshare[0]); - runq_init(&kseq->ksq_timeshare[1]); - runq_init(&kseq->ksq_idle); - kseq->ksq_curr = &kseq->ksq_timeshare[0]; - kseq->ksq_next = &kseq->ksq_timeshare[1]; - kseq->ksq_load = 0; - kseq->ksq_load_timeshare = 0; + runq_init(&tdq->ksq_timeshare[0]); + runq_init(&tdq->ksq_timeshare[1]); + runq_init(&tdq->ksq_idle); + tdq->ksq_curr = &tdq->ksq_timeshare[0]; + tdq->ksq_next = &tdq->ksq_timeshare[1]; + tdq->ksq_load = 0; + tdq->ksq_load_timeshare = 0; } static void @@ -917,27 +914,27 @@ sched_setup(void *dummy) #ifdef SMP balance_groups = 0; /* - * Initialize the kseqs. + * Initialize the tdqs. */ for (i = 0; i < MAXCPU; i++) { - struct kseq *ksq; + struct tdq *ksq; - ksq = &kseq_cpu[i]; + ksq = &tdq_cpu[i]; ksq->ksq_assigned = NULL; - kseq_setup(&kseq_cpu[i]); + tdq_setup(&tdq_cpu[i]); } if (smp_topology == NULL) { - struct kseq_group *ksg; - struct kseq *ksq; + struct tdq_group *ksg; + struct tdq *ksq; int cpus; for (cpus = 0, i = 0; i < MAXCPU; i++) { if (CPU_ABSENT(i)) continue; - ksq = &kseq_cpu[i]; - ksg = &kseq_groups[cpus]; + ksq = &tdq_cpu[i]; + ksg = &tdq_groups[cpus]; /* - * Setup a kseq group with one member. + * Setup a tdq group with one member. */ ksq->ksq_transferable = 0; ksq->ksq_group = ksg; @@ -952,13 +949,13 @@ sched_setup(void *dummy) } ksg_maxid = cpus - 1; } else { - struct kseq_group *ksg; + struct tdq_group *ksg; struct cpu_group *cg; int j; for (i = 0; i < smp_topology->ct_count; i++) { cg = &smp_topology->ct_group[i]; - ksg = &kseq_groups[i]; + ksg = &tdq_groups[i]; /* * Initialize the group. */ @@ -975,10 +972,10 @@ sched_setup(void *dummy) if ((cg->cg_mask & (1 << j)) != 0) { if (ksg->ksg_mask == 0) ksg->ksg_mask = 1 << j; - kseq_cpu[j].ksq_transferable = 0; - kseq_cpu[j].ksq_group = ksg; + tdq_cpu[j].ksq_transferable = 0; + tdq_cpu[j].ksq_group = ksg; LIST_INSERT_HEAD(&ksg->ksg_members, - &kseq_cpu[j], ksq_siblings); + &tdq_cpu[j], ksq_siblings); } } if (ksg->ksg_cpus > 1) @@ -994,10 +991,10 @@ sched_setup(void *dummy) if (balance_groups) gbal_tick = ticks + (hz / 2); #else - kseq_setup(KSEQ_SELF()); + tdq_setup(TDQ_SELF()); #endif mtx_lock_spin(&sched_lock); - kseq_load_add(KSEQ_SELF(), &kse0); + tdq_load_add(TDQ_SELF(), &td_sched0); mtx_unlock_spin(&sched_lock); } @@ -1042,71 +1039,67 @@ sched_priority(struct thread *td) else if (pri < PRI_MIN_TIMESHARE) pri = PRI_MIN_TIMESHARE; -#ifdef KSE - sched_user_prio(kg, pri); -#else sched_user_prio(td, pri); -#endif return; } /* - * Calculate a time slice based on the properties of the kseg and the runq - * that we're on. This is only for PRI_TIMESHARE threads. + * Calculate a time slice based on the properties of the process + * and the runq that we're on. This is only for PRI_TIMESHARE threads. */ static void -sched_slice(struct kse *ke) +sched_slice(struct td_sched *ts) { - struct kseq *kseq; + struct tdq *tdq; struct thread *td; - td = ke->ke_thread; - kseq = KSEQ_CPU(ke->ke_cpu); + td = ts->ts_thread; + tdq = TDQ_CPU(ts->ts_cpu); if (td->td_flags & TDF_BORROWING) { - ke->ke_slice = SCHED_SLICE_MIN; + ts->ts_slice = SCHED_SLICE_MIN; return; } /* * Rationale: - * KSEs in interactive ksegs get a minimal slice so that we + * Threads in interactive procs get a minimal slice so that we * quickly notice if it abuses its advantage. * - * KSEs in non-interactive ksegs are assigned a slice that is - * based on the ksegs nice value relative to the least nice kseg + * Threads in non-interactive procs are assigned a slice that is + * based on the procs nice value relative to the least nice procs * on the run queue for this cpu. * - * If the KSE is less nice than all others it gets the maximum - * slice and other KSEs will adjust their slice relative to + * If the thread is less nice than all others it gets the maximum + * slice and other threads will adjust their slice relative to * this when they first expire. * * There is 20 point window that starts relative to the least - * nice kse on the run queue. Slice size is determined by - * the kse distance from the last nice thread. + * nice td_sched on the run queue. Slice size is determined by + * the td_sched distance from the last nice thread. * - * If the kse is outside of the window it will get no slice + * If the td_sched is outside of the window it will get no slice * and will be reevaluated each time it is selected on the - * run queue. The exception to this is nice 0 ksegs when + * run queue. The exception to this is nice 0 procs when * a nice -20 is running. They are always granted a minimum * slice. */ if (!SCHED_INTERACTIVE(td)) { int nice; - nice = td->td_proc->p_nice + (0 - kseq->ksq_nicemin); - if (kseq->ksq_load_timeshare == 0 || - td->td_proc->p_nice < kseq->ksq_nicemin) - ke->ke_slice = SCHED_SLICE_MAX; + nice = td->td_proc->p_nice + (0 - tdq->ksq_nicemin); + if (tdq->ksq_load_timeshare == 0 || + td->td_proc->p_nice < tdq->ksq_nicemin) + ts->ts_slice = SCHED_SLICE_MAX; else if (nice <= SCHED_SLICE_NTHRESH) - ke->ke_slice = SCHED_SLICE_NICE(nice); + ts->ts_slice = SCHED_SLICE_NICE(nice); else if (td->td_proc->p_nice == 0) - ke->ke_slice = SCHED_SLICE_MIN; + ts->ts_slice = SCHED_SLICE_MIN; else - ke->ke_slice = SCHED_SLICE_MIN; /* 0 */ + ts->ts_slice = SCHED_SLICE_MIN; /* 0 */ } else - ke->ke_slice = SCHED_SLICE_INTERACTIVE; + ts->ts_slice = SCHED_SLICE_INTERACTIVE; return; } @@ -1187,9 +1180,9 @@ schedinit(void) * Set up the scheduler specific parts of proc0. */ proc0.p_sched = NULL; /* XXX */ - thread0.td_sched = &kse0; - kse0.ke_thread = &thread0; - kse0.ke_state = KES_THREAD; + thread0.td_sched = &td_sched0; + td_sched0.ts_thread = &thread0; + td_sched0.ts_state = TSS_THREAD; } /* @@ -1204,35 +1197,35 @@ sched_rr_interval(void) } static void -sched_pctcpu_update(struct kse *ke) +sched_pctcpu_update(struct td_sched *ts) { /* * Adjust counters and watermark for pctcpu calc. */ - if (ke->ke_ltick > ticks - SCHED_CPU_TICKS) { + if (ts->ts_ltick > ticks - SCHED_CPU_TICKS) { /* * Shift the tick count out so that the divide doesn't * round away our results. */ - ke->ke_ticks <<= 10; - ke->ke_ticks = (ke->ke_ticks / (ticks - ke->ke_ftick)) * + ts->ts_ticks <<= 10; + ts->ts_ticks = (ts->ts_ticks / (ticks - ts->ts_ftick)) * SCHED_CPU_TICKS; - ke->ke_ticks >>= 10; + ts->ts_ticks >>= 10; } else - ke->ke_ticks = 0; - ke->ke_ltick = ticks; - ke->ke_ftick = ke->ke_ltick - SCHED_CPU_TICKS; + ts->ts_ticks = 0; + ts->ts_ltick = ticks; + ts->ts_ftick = ts->ts_ltick - SCHED_CPU_TICKS; } void sched_thread_priority(struct thread *td, u_char prio) { - struct kse *ke; + struct td_sched *ts; CTR6(KTR_SCHED, "sched_prio: %p(%s) prio %d newprio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, prio, curthread, curthread->td_proc->p_comm); - ke = td->td_kse; + ts = td->td_sched; mtx_assert(&sched_lock, MA_OWNED); if (td->td_priority == prio) return; @@ -1243,21 +1236,21 @@ sched_thread_priority(struct thread *td, u_char prio) * queue. We still call adjustrunqueue below in case kse * needs to fix things up. */ - if (prio < td->td_priority && ke->ke_runq != NULL && - (ke->ke_flags & KEF_ASSIGNED) == 0 && - ke->ke_runq != KSEQ_CPU(ke->ke_cpu)->ksq_curr) { - runq_remove(ke->ke_runq, ke); - ke->ke_runq = KSEQ_CPU(ke->ke_cpu)->ksq_curr; - runq_add(ke->ke_runq, ke, 0); + if (prio < td->td_priority && ts->ts_runq != NULL && + (ts->ts_flags & TSF_ASSIGNED) == 0 && + ts->ts_runq != TDQ_CPU(ts->ts_cpu)->ksq_curr) { + runq_remove(ts->ts_runq, ts); + ts->ts_runq = TDQ_CPU(ts->ts_cpu)->ksq_curr; + runq_add(ts->ts_runq, ts, 0); } /* - * Hold this kse on this cpu so that sched_prio() doesn't + * Hold this td_sched on this cpu so that sched_prio() doesn't * cause excessive migration. We only want migration to * happen as the result of a wakeup. */ - ke->ke_flags |= KEF_HOLD; + ts->ts_flags |= TSF_HOLD; adjustrunqueue(td, prio); - ke->ke_flags &= ~KEF_HOLD; + ts->ts_flags &= ~TSF_HOLD; } else td->td_priority = prio; } @@ -1327,39 +1320,14 @@ sched_prio(struct thread *td, u_char prio) } void -#ifdef KSE -sched_user_prio(struct ksegrp *kg, u_char prio) -#else sched_user_prio(struct thread *td, u_char prio) -#endif { -#ifdef KSE - struct thread *td; -#endif u_char oldprio; -#ifdef KSE - kg->kg_base_user_pri = prio; - - /* XXXKSE only for 1:1 */ - - td = TAILQ_FIRST(&kg->kg_threads); - if (td == NULL) { - kg->kg_user_pri = prio; - return; - } - - if (td->td_flags & TDF_UBORROWING && kg->kg_user_pri <= prio) - return; - - oldprio = kg->kg_user_pri; - kg->kg_user_pri = prio; -#else td->td_base_user_pri = prio; oldprio = td->td_user_pri; td->td_user_pri = prio; -#endif if (TD_ON_UPILOCK(td) && oldprio != prio) umtx_pi_adjust(td, oldprio); @@ -1372,13 +1340,8 @@ sched_lend_user_prio(struct thread *td, u_char prio) td->td_flags |= TDF_UBORROWING; -#ifdef KSE - oldprio = td->td_ksegrp->kg_user_pri; - td->td_ksegrp->kg_user_pri = prio; -#else oldprio = td->td_user_pri; td->td_user_pri = prio; -#endif if (TD_ON_UPILOCK(td) && oldprio != prio) umtx_pi_adjust(td, oldprio); @@ -1387,23 +1350,12 @@ sched_lend_user_prio(struct thread *td, u_char prio) void sched_unlend_user_prio(struct thread *td, u_char prio) { -#ifdef KSE - struct ksegrp *kg = td->td_ksegrp; -#endif u_char base_pri; -#ifdef KSE - base_pri = kg->kg_base_user_pri; -#else base_pri = td->td_base_user_pri; -#endif if (prio >= base_pri) { td->td_flags &= ~TDF_UBORROWING; -#ifdef KSE - sched_user_prio(kg, base_pri); -#else sched_user_prio(td, base_pri); -#endif } else sched_lend_user_prio(td, prio); } @@ -1411,13 +1363,13 @@ sched_unlend_user_prio(struct thread *td, u_char prio) void sched_switch(struct thread *td, struct thread *newtd, int flags) { - struct kseq *ksq; - struct kse *ke; + struct tdq *ksq; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); - ke = td->td_kse; - ksq = KSEQ_SELF(); + ts = td->td_sched; + ksq = TDQ_SELF(); td->td_lastcpu = td->td_oncpu; td->td_oncpu = NOCPU; @@ -1425,24 +1377,24 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) td->td_owepreempt = 0; /* - * If the KSE has been assigned it may be in the process of switching + * If the thread has been assigned it may be in the process of switching * to the new cpu. This is the case in sched_bind(). */ if (td == PCPU_GET(idlethread)) { TD_SET_CAN_RUN(td); - } else if ((ke->ke_flags & KEF_ASSIGNED) == 0) { + } else if ((ts->ts_flags & TSF_ASSIGNED) == 0) { /* We are ending our run so make our slot available again */ - kseq_load_rem(ksq, ke); + tdq_load_rem(ksq, ts); if (TD_IS_RUNNING(td)) { /* * Don't allow the thread to migrate * from a preemption. */ - ke->ke_flags |= KEF_HOLD; + ts->ts_flags |= TSF_HOLD; setrunqueue(td, (flags & SW_PREEMPT) ? SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED : SRQ_OURSELF|SRQ_YIELDING); - ke->ke_flags &= ~KEF_HOLD; + ts->ts_flags &= ~TSF_HOLD; } } if (newtd != NULL) { @@ -1450,10 +1402,10 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) * If we bring in a thread account for it as if it had been * added to the run queue and then chosen. */ - newtd->td_kse->ke_flags |= KEF_DIDRUN; - newtd->td_kse->ke_runq = ksq->ksq_curr; + newtd->td_sched->ts_flags |= TSF_DIDRUN; + newtd->td_sched->ts_runq = ksq->ksq_curr; TD_SET_RUNNING(newtd); - kseq_load_add(KSEQ_SELF(), newtd->td_kse); + tdq_load_add(TDQ_SELF(), newtd->td_sched); } else newtd = choosethread(); if (td != newtd) { @@ -1477,23 +1429,23 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) void sched_nice(struct proc *p, int nice) { - struct kse *ke; + struct td_sched *ts; struct thread *td; - struct kseq *kseq; + struct tdq *tdq; PROC_LOCK_ASSERT(p, MA_OWNED); mtx_assert(&sched_lock, MA_OWNED); /* - * We need to adjust the nice counts for running KSEs. + * We need to adjust the nice counts for running threads. */ FOREACH_THREAD_IN_PROC(p, td) { if (td->td_pri_class == PRI_TIMESHARE) { - ke = td->td_kse; - if (ke->ke_runq == NULL) + ts = td->td_sched; + if (ts->ts_runq == NULL) continue; - kseq = KSEQ_CPU(ke->ke_cpu); - kseq_nice_rem(kseq, p->p_nice); - kseq_nice_add(kseq, nice); + tdq = TDQ_CPU(ts->ts_cpu); + tdq_nice_rem(tdq, p->p_nice); + tdq_nice_add(tdq, nice); } } p->p_nice = nice; @@ -1508,7 +1460,7 @@ sched_sleep(struct thread *td) { mtx_assert(&sched_lock, MA_OWNED); - td->td_kse->ke_slptime = ticks; + td->td_sched->ts_slptime = ticks; } void @@ -1517,13 +1469,13 @@ sched_wakeup(struct thread *td) mtx_assert(&sched_lock, MA_OWNED); /* - * Let the kseg know how long we slept for. This is because process - * interactivity behavior is modeled in the kseg. + * Let the procs know how long we slept for. This is because process + * interactivity behavior is modeled in the procs. */ - if (td->td_kse->ke_slptime) { + if (td->td_sched->ts_slptime) { int hzticks; - hzticks = (ticks - td->td_kse->ke_slptime) << 10; + hzticks = (ticks - td->td_sched->ts_slptime) << 10; if (hzticks >= SCHED_SLP_RUN_MAX) { td->td_sched->skg_slptime = SCHED_SLP_RUN_MAX; td->td_sched->skg_runtime = 1; @@ -1532,8 +1484,8 @@ sched_wakeup(struct thread *td) sched_interact_update(td); } sched_priority(td); - sched_slice(td->td_kse); - td->td_kse->ke_slptime = 0; + sched_slice(td->td_sched); + td->td_sched->ts_slptime = 0; } setrunqueue(td, SRQ_BORING); } @@ -1545,10 +1497,15 @@ sched_wakeup(struct thread *td) void sched_fork(struct thread *td, struct thread *child) { - struct kse *ke; - struct kse *ke2; - mtx_assert(&sched_lock, MA_OWNED); + sched_fork_thread(td, child); +} + +void +sched_fork_thread(struct thread *td, struct thread *child) +{ + struct td_sched *ts; + struct td_sched *ts2; child->td_sched->skg_slptime = td->td_sched->skg_slptime; child->td_sched->skg_runtime = td->td_sched->skg_runtime; @@ -1560,23 +1517,23 @@ sched_fork(struct thread *td, struct thread *child) sched_newthread(child); - ke = td->td_kse; - ke2 = child->td_kse; - ke2->ke_slice = 1; /* Attempt to quickly learn interactivity. */ - ke2->ke_cpu = ke->ke_cpu; - ke2->ke_runq = NULL; + ts = td->td_sched; + ts2 = child->td_sched; + ts2->ts_slice = 1; /* Attempt to quickly learn interactivity. */ + ts2->ts_cpu = ts->ts_cpu; + ts2->ts_runq = NULL; /* Grab our parents cpu estimation information. */ - ke2->ke_ticks = ke->ke_ticks; - ke2->ke_ltick = ke->ke_ltick; - ke2->ke_ftick = ke->ke_ftick; + ts2->ts_ticks = ts->ts_ticks; + ts2->ts_ltick = ts->ts_ltick; + ts2->ts_ftick = ts->ts_ftick; } void sched_class(struct thread *td, int class) { - struct kseq *kseq; - struct kse *ke; + struct tdq *tdq; + struct td_sched *ts; int nclass; int oclass; @@ -1586,36 +1543,36 @@ sched_class(struct thread *td, int class) nclass = PRI_BASE(class); oclass = PRI_BASE(td->td_pri_class); - ke = td->td_kse; - if ((ke->ke_state != KES_ONRUNQ && - ke->ke_state != KES_THREAD) || ke->ke_runq == NULL) - continue; - kseq = KSEQ_CPU(ke->ke_cpu); + ts = td->td_sched; + if (!((ts->ts_state != TSS_ONRUNQ && + ts->ts_state != TSS_THREAD) || ts->ts_runq == NULL)) { + tdq = TDQ_CPU(ts->ts_cpu); #ifdef SMP - /* - * On SMP if we're on the RUNQ we must adjust the transferable - * count because could be changing to or from an interrupt - * class. - */ - if (ke->ke_state == KES_ONRUNQ) { - if (KSE_CAN_MIGRATE(ke)) { - kseq->ksq_transferable--; - kseq->ksq_group->ksg_transferable--; - } - if (KSE_CAN_MIGRATE(ke)) { - kseq->ksq_transferable++; - kseq->ksq_group->ksg_transferable++; + /* + * On SMP if we're on the RUNQ we must adjust the transferable + * count because could be changing to or from an interrupt + * class. + */ + if (ts->ts_state == TSS_ONRUNQ) { + if (THREAD_CAN_MIGRATE(ts)) { + tdq->ksq_transferable--; + tdq->ksq_group->ksg_transferable--; + } + if (THREAD_CAN_MIGRATE(ts)) { + tdq->ksq_transferable++; + tdq->ksq_group->ksg_transferable++; + } } - } #endif - if (oclass == PRI_TIMESHARE) { - kseq->ksq_load_timeshare--; - kseq_nice_rem(kseq, td->td_proc->p_nice); - } - if (nclass == PRI_TIMESHARE) { - kseq->ksq_load_timeshare++; - kseq_nice_add(kseq, td->td_proc->p_nice); + if (oclass == PRI_TIMESHARE) { + tdq->ksq_load_timeshare--; + tdq_nice_rem(tdq, td->td_proc->p_nice); + } + if (nclass == PRI_TIMESHARE) { + tdq->ksq_load_timeshare++; + tdq_nice_add(tdq, td->td_proc->p_nice); + } } td->td_pri_class = class; @@ -1637,17 +1594,44 @@ sched_exit(struct proc *p, struct thread *childtd) parent->td_sched->skg_runtime += childtd->td_sched->skg_runtime; sched_interact_update(parent); - kseq_load_rem(KSEQ_CPU(childtd->td_kse->ke_cpu), childtd->td_kse); + tdq_load_rem(TDQ_CPU(childtd->td_sched->ts_cpu), childtd->td_sched); +} + +void +sched_exit_thread(struct thread *td, struct thread *childtd) +{ +} + +void +sched_userret(struct thread *td) +{ + /* + * XXX we cheat slightly on the locking here to avoid locking in + * the usual case. Setting td_priority here is essentially an + * incomplete workaround for not setting it properly elsewhere. + * Now that some interrupt handlers are threads, not setting it + * properly elsewhere can clobber it in the window between setting + * it here and returning to user mode, so don't waste time setting + * it perfectly here. + */ + KASSERT((td->td_flags & TDF_BORROWING) == 0, + ("thread with borrowed priority returning to userland")); + if (td->td_priority != td->td_user_pri) { + mtx_lock_spin(&sched_lock); + td->td_priority = td->td_user_pri; + td->td_base_pri = td->td_user_pri; + mtx_unlock_spin(&sched_lock); + } } void sched_clock(struct thread *td) { - struct kseq *kseq; - struct kse *ke; + struct tdq *tdq; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); - kseq = KSEQ_SELF(); + tdq = TDQ_SELF(); #ifdef SMP if (ticks >= bal_tick) sched_balance(); @@ -1657,18 +1641,18 @@ sched_clock(struct thread *td) * We could have been assigned a non real-time thread without an * IPI. */ - if (kseq->ksq_assigned) - kseq_assign(kseq); /* Potentially sets NEEDRESCHED */ + if (tdq->ksq_assigned) + tdq_assign(tdq); /* Potentially sets NEEDRESCHED */ #endif - ke = td->td_kse; + ts = td->td_sched; /* Adjust ticks for pctcpu */ - ke->ke_ticks++; - ke->ke_ltick = ticks; + ts->ts_ticks++; + ts->ts_ltick = ticks; /* Go up to one second beyond our max and then trim back down */ - if (ke->ke_ftick + SCHED_CPU_TICKS + hz < ke->ke_ltick) - sched_pctcpu_update(ke); + if (ts->ts_ftick + SCHED_CPU_TICKS + hz < ts->ts_ltick) + sched_pctcpu_update(ts); if (td->td_flags & TDF_IDLETD) return; @@ -1687,76 +1671,76 @@ sched_clock(struct thread *td) /* * We used up one time slice. */ - if (--ke->ke_slice > 0) + if (--ts->ts_slice > 0) return; /* * We're out of time, recompute priorities and requeue. */ - kseq_load_rem(kseq, ke); + tdq_load_rem(tdq, ts); sched_priority(td); - sched_slice(ke); - if (SCHED_CURR(td, ke)) - ke->ke_runq = kseq->ksq_curr; + sched_slice(ts); + if (SCHED_CURR(td, ts)) + ts->ts_runq = tdq->ksq_curr; else - ke->ke_runq = kseq->ksq_next; - kseq_load_add(kseq, ke); + ts->ts_runq = tdq->ksq_next; + tdq_load_add(tdq, ts); td->td_flags |= TDF_NEEDRESCHED; } int sched_runnable(void) { - struct kseq *kseq; + struct tdq *tdq; int load; load = 1; - kseq = KSEQ_SELF(); + tdq = TDQ_SELF(); #ifdef SMP - if (kseq->ksq_assigned) { + if (tdq->ksq_assigned) { mtx_lock_spin(&sched_lock); - kseq_assign(kseq); + tdq_assign(tdq); mtx_unlock_spin(&sched_lock); } #endif if ((curthread->td_flags & TDF_IDLETD) != 0) { - if (kseq->ksq_load > 0) + if (tdq->ksq_load > 0) goto out; } else - if (kseq->ksq_load - 1 > 0) + if (tdq->ksq_load - 1 > 0) goto out; load = 0; out: return (load); } -struct kse * +struct td_sched * sched_choose(void) { - struct kseq *kseq; - struct kse *ke; + struct tdq *tdq; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); - kseq = KSEQ_SELF(); + tdq = TDQ_SELF(); #ifdef SMP restart: - if (kseq->ksq_assigned) - kseq_assign(kseq); + if (tdq->ksq_assigned) + tdq_assign(tdq); #endif - ke = kseq_choose(kseq); - if (ke) { + ts = tdq_choose(tdq); + if (ts) { #ifdef SMP - if (ke->ke_thread->td_pri_class == PRI_IDLE) - if (kseq_idled(kseq) == 0) + if (ts->ts_thread->td_pri_class == PRI_IDLE) + if (tdq_idled(tdq) == 0) goto restart; #endif - kseq_runq_rem(kseq, ke); - ke->ke_state = KES_THREAD; - ke->ke_flags &= ~KEF_PREEMPTED; - return (ke); + tdq_runq_rem(tdq, ts); + ts->ts_state = TSS_THREAD; + ts->ts_flags &= ~TSF_PREEMPTED; + return (ts); } #ifdef SMP - if (kseq_idled(kseq) == 0) + if (tdq_idled(tdq) == 0) goto restart; #endif return (NULL); @@ -1765,8 +1749,8 @@ restart: void sched_add(struct thread *td, int flags) { - struct kseq *kseq; - struct kse *ke; + struct tdq *tdq; + struct td_sched *ts; int preemptive; int canmigrate; int class; @@ -1775,60 +1759,60 @@ sched_add(struct thread *td, int flags) td, td->td_proc->p_comm, td->td_priority, curthread, curthread->td_proc->p_comm); mtx_assert(&sched_lock, MA_OWNED); - ke = td->td_kse; + ts = td->td_sched; canmigrate = 1; preemptive = !(flags & SRQ_YIELDING); class = PRI_BASE(td->td_pri_class); - kseq = KSEQ_SELF(); - ke->ke_flags &= ~KEF_INTERNAL; + tdq = TDQ_SELF(); + ts->ts_flags &= ~TSF_INTERNAL; #ifdef SMP - if (ke->ke_flags & KEF_ASSIGNED) { - if (ke->ke_flags & KEF_REMOVED) - ke->ke_flags &= ~KEF_REMOVED; + if (ts->ts_flags & TSF_ASSIGNED) { + if (ts->ts_flags & TSF_REMOVED) + ts->ts_flags &= ~TSF_REMOVED; return; } - canmigrate = KSE_CAN_MIGRATE(ke); + canmigrate = THREAD_CAN_MIGRATE(ts); /* * Don't migrate running threads here. Force the long term balancer * to do it. */ - if (ke->ke_flags & KEF_HOLD) { - ke->ke_flags &= ~KEF_HOLD; + if (ts->ts_flags & TSF_HOLD) { + ts->ts_flags &= ~TSF_HOLD; canmigrate = 0; } #endif - KASSERT(ke->ke_state != KES_ONRUNQ, - ("sched_add: kse %p (%s) already in run queue", ke, + KASSERT(ts->ts_state != TSS_ONRUNQ, + ("sched_add: thread %p (%s) already in run queue", td, td->td_proc->p_comm)); KASSERT(td->td_proc->p_sflag & PS_INMEM, ("sched_add: process swapped out")); - KASSERT(ke->ke_runq == NULL, - ("sched_add: KSE %p is still assigned to a run queue", ke)); + KASSERT(ts->ts_runq == NULL, + ("sched_add: thread %p is still assigned to a run queue", td)); if (flags & SRQ_PREEMPTED) - ke->ke_flags |= KEF_PREEMPTED; + ts->ts_flags |= TSF_PREEMPTED; switch (class) { case PRI_ITHD: case PRI_REALTIME: - ke->ke_runq = kseq->ksq_curr; - ke->ke_slice = SCHED_SLICE_MAX; + ts->ts_runq = tdq->ksq_curr; + ts->ts_slice = SCHED_SLICE_MAX; if (canmigrate) - ke->ke_cpu = PCPU_GET(cpuid); + ts->ts_cpu = PCPU_GET(cpuid); break; case PRI_TIMESHARE: - if (SCHED_CURR(td, ke)) - ke->ke_runq = kseq->ksq_curr; + if (SCHED_CURR(td, ts)) + ts->ts_runq = tdq->ksq_curr; else - ke->ke_runq = kseq->ksq_next; + ts->ts_runq = tdq->ksq_next; break; case PRI_IDLE: /* * This is for priority prop. */ - if (ke->ke_thread->td_priority < PRI_MIN_IDLE) - ke->ke_runq = kseq->ksq_curr; + if (ts->ts_thread->td_priority < PRI_MIN_IDLE) + ts->ts_runq = tdq->ksq_curr; else - ke->ke_runq = &kseq->ksq_idle; - ke->ke_slice = SCHED_SLICE_MIN; + ts->ts_runq = &tdq->ksq_idle; + ts->ts_slice = SCHED_SLICE_MIN; break; default: panic("Unknown pri class."); @@ -1838,9 +1822,9 @@ sched_add(struct thread *td, int flags) /* * If this thread is pinned or bound, notify the target cpu. */ - if (!canmigrate && ke->ke_cpu != PCPU_GET(cpuid) ) { - ke->ke_runq = NULL; - kseq_notify(ke, ke->ke_cpu); + if (!canmigrate && ts->ts_cpu != PCPU_GET(cpuid) ) { + ts->ts_runq = NULL; + tdq_notify(ts, ts->ts_cpu); return; } /* @@ -1848,72 +1832,72 @@ sched_add(struct thread *td, int flags) * the global bitmap. If not, see if we should transfer this thread. */ if ((class == PRI_TIMESHARE || class == PRI_REALTIME) && - (kseq->ksq_group->ksg_idlemask & PCPU_GET(cpumask)) != 0) { + (tdq->ksq_group->ksg_idlemask & PCPU_GET(cpumask)) != 0) { /* * Check to see if our group is unidling, and if so, remove it * from the global idle mask. */ - if (kseq->ksq_group->ksg_idlemask == - kseq->ksq_group->ksg_cpumask) - atomic_clear_int(&kseq_idle, kseq->ksq_group->ksg_mask); + if (tdq->ksq_group->ksg_idlemask == + tdq->ksq_group->ksg_cpumask) + atomic_clear_int(&tdq_idle, tdq->ksq_group->ksg_mask); /* * Now remove ourselves from the group specific idle mask. */ - kseq->ksq_group->ksg_idlemask &= ~PCPU_GET(cpumask); - } else if (canmigrate && kseq->ksq_load > 1 && class != PRI_ITHD) - if (kseq_transfer(kseq, ke, class)) + tdq->ksq_group->ksg_idlemask &= ~PCPU_GET(cpumask); + } else if (canmigrate && tdq->ksq_load > 1 && class != PRI_ITHD) + if (tdq_transfer(tdq, ts, class)) return; - ke->ke_cpu = PCPU_GET(cpuid); + ts->ts_cpu = PCPU_GET(cpuid); #endif if (td->td_priority < curthread->td_priority && - ke->ke_runq == kseq->ksq_curr) + ts->ts_runq == tdq->ksq_curr) curthread->td_flags |= TDF_NEEDRESCHED; if (preemptive && maybe_preempt(td)) return; - ke->ke_state = KES_ONRUNQ; + ts->ts_state = TSS_ONRUNQ; - kseq_runq_add(kseq, ke, flags); - kseq_load_add(kseq, ke); + tdq_runq_add(tdq, ts, flags); + tdq_load_add(tdq, ts); } void sched_rem(struct thread *td) { - struct kseq *kseq; - struct kse *ke; + struct tdq *tdq; + struct td_sched *ts; CTR5(KTR_SCHED, "sched_rem: %p(%s) prio %d by %p(%s)", td, td->td_proc->p_comm, td->td_priority, curthread, curthread->td_proc->p_comm); mtx_assert(&sched_lock, MA_OWNED); - ke = td->td_kse; - ke->ke_flags &= ~KEF_PREEMPTED; - if (ke->ke_flags & KEF_ASSIGNED) { - ke->ke_flags |= KEF_REMOVED; + ts = td->td_sched; + ts->ts_flags &= ~TSF_PREEMPTED; + if (ts->ts_flags & TSF_ASSIGNED) { + ts->ts_flags |= TSF_REMOVED; return; } - KASSERT((ke->ke_state == KES_ONRUNQ), - ("sched_rem: KSE not on run queue")); + KASSERT((ts->ts_state == TSS_ONRUNQ), + ("sched_rem: thread not on run queue")); - ke->ke_state = KES_THREAD; - kseq = KSEQ_CPU(ke->ke_cpu); - kseq_runq_rem(kseq, ke); - kseq_load_rem(kseq, ke); + ts->ts_state = TSS_THREAD; + tdq = TDQ_CPU(ts->ts_cpu); + tdq_runq_rem(tdq, ts); + tdq_load_rem(tdq, ts); } fixpt_t sched_pctcpu(struct thread *td) { fixpt_t pctcpu; - struct kse *ke; + struct td_sched *ts; pctcpu = 0; - ke = td->td_kse; - if (ke == NULL) + ts = td->td_sched; + if (ts == NULL) return (0); mtx_lock_spin(&sched_lock); - if (ke->ke_ticks) { + if (ts->ts_ticks) { int rtick; /* @@ -1921,15 +1905,15 @@ sched_pctcpu(struct thread *td) * this causes the cpu usage to decay away too quickly due to * rounding errors. */ - if (ke->ke_ftick + SCHED_CPU_TICKS < ke->ke_ltick || - ke->ke_ltick < (ticks - (hz / 2))) - sched_pctcpu_update(ke); + if (ts->ts_ftick + SCHED_CPU_TICKS < ts->ts_ltick || + ts->ts_ltick < (ticks - (hz / 2))) + sched_pctcpu_update(ts); /* How many rtick per second ? */ - rtick = min(ke->ke_ticks / SCHED_CPU_TIME, SCHED_CPU_TICKS); + rtick = min(ts->ts_ticks / SCHED_CPU_TIME, SCHED_CPU_TICKS); pctcpu = (FSCALE * ((FSCALE * rtick)/realstathz)) >> FSHIFT; } - td->td_proc->p_swtime = ke->ke_ltick - ke->ke_ftick; + td->td_proc->p_swtime = ts->ts_ltick - ts->ts_ftick; mtx_unlock_spin(&sched_lock); return (pctcpu); @@ -1938,18 +1922,18 @@ sched_pctcpu(struct thread *td) void sched_bind(struct thread *td, int cpu) { - struct kse *ke; + struct td_sched *ts; mtx_assert(&sched_lock, MA_OWNED); - ke = td->td_kse; - ke->ke_flags |= KEF_BOUND; + ts = td->td_sched; + ts->ts_flags |= TSF_BOUND; #ifdef SMP if (PCPU_GET(cpuid) == cpu) return; /* sched_rem without the runq_remove */ - ke->ke_state = KES_THREAD; - kseq_load_rem(KSEQ_CPU(ke->ke_cpu), ke); - kseq_notify(ke, cpu); + ts->ts_state = TSS_THREAD; + tdq_load_rem(TDQ_CPU(ts->ts_cpu), ts); + tdq_notify(ts, cpu); /* When we return from mi_switch we'll be on the correct cpu. */ mi_switch(SW_VOL, NULL); #endif @@ -1959,30 +1943,21 @@ void sched_unbind(struct thread *td) { mtx_assert(&sched_lock, MA_OWNED); - td->td_kse->ke_flags &= ~KEF_BOUND; + td->td_sched->ts_flags &= ~TSF_BOUND; } int sched_is_bound(struct thread *td) { mtx_assert(&sched_lock, MA_OWNED); - return (td->td_kse->ke_flags & KEF_BOUND); + return (td->td_sched->ts_flags & TSF_BOUND); } void sched_relinquish(struct thread *td) { -#ifdef KSE - struct ksegrp *kg; - - kg = td->td_ksegrp; -#endif mtx_lock_spin(&sched_lock); -#ifdef KSE - if (kg->kg_pri_class == PRI_TIMESHARE) -#else if (td->td_pri_class == PRI_TIMESHARE) -#endif sched_prio(td, PRI_MAX_TIMESHARE); mi_switch(SW_VOL, NULL); mtx_unlock_spin(&sched_lock); @@ -1997,10 +1972,10 @@ sched_load(void) total = 0; for (i = 0; i <= ksg_maxid; i++) - total += KSEQ_GROUP(i)->ksg_load; + total += TDQ_GROUP(i)->ksg_load; return (total); #else - return (KSEQ_SELF()->ksq_sysload); + return (TDQ_SELF()->ksq_sysload); #endif } diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index a6eca02..5e7446c 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -149,9 +149,6 @@ ast(struct trapframe *framep) { struct thread *td; struct proc *p; -#ifdef KSE - struct ksegrp *kg; -#endif struct rlimit rlim; int sflag; int flags; @@ -163,9 +160,6 @@ ast(struct trapframe *framep) td = curthread; p = td->td_proc; -#ifdef KSE - kg = td->td_ksegrp; -#endif CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, p->p_pid, p->p_comm); @@ -204,7 +198,7 @@ ast(struct trapframe *framep) /* * XXXKSE While the fact that we owe a user profiling - * tick is stored per KSE in this code, the statistics + * tick is stored per thread in this code, the statistics * themselves are still stored per process. * This should probably change, by which I mean that * possibly the location of both might change. @@ -264,11 +258,7 @@ ast(struct trapframe *framep) ktrcsw(1, 1); #endif mtx_lock_spin(&sched_lock); -#ifdef KSE - sched_prio(td, kg->kg_user_pri); -#else sched_prio(td, td->td_user_pri); -#endif mi_switch(SW_INVOL, NULL); mtx_unlock_spin(&sched_lock); #ifdef KTRACE diff --git a/sys/kern/tty.c b/sys/kern/tty.c index bd7cf8d..5e7c596 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -2578,18 +2578,8 @@ ttyinfo(struct tty *tp) if (proc_compare(pick, p)) pick = p; - td = FIRST_THREAD_IN_PROC(pick); /* XXXKSE */ -#if 0 - KASSERT(td != NULL, ("ttyinfo: no thread")); -#else - if (td == NULL) { - mtx_unlock_spin(&sched_lock); - PGRP_UNLOCK(tp->t_pgrp); - ttyprintf(tp, "foreground process without thread\n"); - tp->t_rocount = 0; - return; - } -#endif + /*^T can only show state for 1 thread. just pick the first. */ + td = FIRST_THREAD_IN_PROC(pick); stateprefix = ""; if (TD_IS_RUNNING(td)) state = "running"; @@ -2669,11 +2659,7 @@ proc_compare(struct proc *p1, struct proc *p2) { int esta, estb; -#ifdef KSE - struct ksegrp *kg; -#else struct thread *td; -#endif mtx_assert(&sched_lock, MA_OWNED); if (p1 == NULL) return (1); @@ -2694,19 +2680,10 @@ proc_compare(struct proc *p1, struct proc *p2) * tie - favor one with highest recent cpu utilization */ esta = estb = 0; -#ifdef KSE - FOREACH_KSEGRP_IN_PROC(p1,kg) { - esta += kg->kg_estcpu; - } - FOREACH_KSEGRP_IN_PROC(p2,kg) { - estb += kg->kg_estcpu; - } -#else FOREACH_THREAD_IN_PROC(p1, td) esta += td->td_estcpu; FOREACH_THREAD_IN_PROC(p2, td) estb += td->td_estcpu; -#endif if (estb > esta) return (1); if (esta > estb) |