summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libkvm/kvm_proc.c9
-rw-r--r--sys/alpha/alpha/machdep.c2
-rw-r--r--sys/amd64/amd64/machdep.c2
-rw-r--r--sys/arm/sa11x0/assabet_machdep.c2
-rw-r--r--sys/conf/files3
-rw-r--r--sys/ddb/db_ps.c8
-rw-r--r--sys/i386/i386/machdep.c2
-rw-r--r--sys/ia64/ia64/machdep.c2
-rw-r--r--sys/kern/init_main.c29
-rw-r--r--sys/kern/kern_exec.c8
-rw-r--r--sys/kern/kern_exit.c19
-rw-r--r--sys/kern/kern_fork.c13
-rw-r--r--sys/kern/kern_intr.c1
-rw-r--r--sys/kern/kern_kse.c93
-rw-r--r--sys/kern/kern_proc.c38
-rw-r--r--sys/kern/kern_switch.c281
-rw-r--r--sys/kern/kern_synch.c6
-rw-r--r--sys/kern/kern_thr.c157
-rw-r--r--sys/kern/kern_thread.c394
-rw-r--r--sys/kern/sched_4bsd.c179
-rw-r--r--sys/kern/sched_ule.c271
-rw-r--r--sys/pc98/i386/machdep.c2
-rw-r--r--sys/pc98/pc98/machdep.c2
-rw-r--r--sys/powerpc/aim/machdep.c2
-rw-r--r--sys/powerpc/powerpc/machdep.c2
-rw-r--r--sys/sparc64/sparc64/machdep.c2
-rw-r--r--sys/sys/proc.h114
-rw-r--r--sys/sys/sched.h23
28 files changed, 811 insertions, 855 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 661a17ce0073..41aed4b89988 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -104,7 +104,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
struct pstats pstats;
struct ucred ucred;
struct thread mtd;
- struct kse mke;
+ /*struct kse mke;*/
struct ksegrp mkg;
struct proc proc;
struct proc pproc;
@@ -137,6 +137,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
TAILQ_FIRST(&proc.p_ksegrps));
return (-1);
}
+#if 0
if (KREAD(kd,
(u_long)TAILQ_FIRST(&mkg.kg_kseq), &mke)) {
_kvm_err(kd, kd->program,
@@ -144,6 +145,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
TAILQ_FIRST(&mkg.kg_kseq));
return (-1);
}
+#endif
}
}
if (KREAD(kd, (u_long)proc.p_ucred, &ucred) == 0) {
@@ -386,9 +388,14 @@ nopgrp:
kp->ki_pri.pri_user = mkg.kg_user_pri;
kp->ki_estcpu = mkg.kg_estcpu;
+#if 0
/* Stuff from the kse */
kp->ki_pctcpu = mke.ke_pctcpu;
kp->ki_rqindex = mke.ke_rqindex;
+#else
+ kp->ki_pctcpu = 0;
+ kp->ki_rqindex = 0;
+#endif
} else {
kp->ki_tdflags = -1;
/* All the rest are 0 for now */
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index ead24d39762f..693d139468d0 100644
--- a/sys/alpha/alpha/machdep.c
+++ b/sys/alpha/alpha/machdep.c
@@ -846,7 +846,7 @@ alpha_init(pfn, ptb, bim, bip, biv)
}
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
/*
* Init mapping for u page(s) for proc 0
*/
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index ded77f27b21e..c2bebe068189 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1116,7 +1116,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
preload_bootstrap_relocate(KERNBASE);
diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c
index a293bc780d97..776244074567 100644
--- a/sys/arm/sa11x0/assabet_machdep.c
+++ b/sys/arm/sa11x0/assabet_machdep.c
@@ -370,7 +370,7 @@ initarm(void *arg, void *arg2)
/* Set stack for exception handlers */
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
proc0.p_uarea = (struct user *) proc0_uarea.pv_va;
thread0.td_kstack = kernelstack.pv_va;
thread0.td_pcb = (struct pcb *)
diff --git a/sys/conf/files b/sys/conf/files
index 2d675b081bd5..cea8f8813382 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1086,7 +1086,6 @@ kern/kern_fork.c standard
kern/kern_idle.c standard
kern/kern_intr.c standard
kern/kern_jail.c standard
-kern/kern_thr.c standard
kern/kern_kse.c standard
kern/kern_kthread.c standard
kern/kern_ktr.c optional ktr
@@ -1110,12 +1109,12 @@ kern/kern_sema.c standard
kern/kern_shutdown.c standard
kern/kern_sig.c standard
kern/kern_subr.c standard
-kern/kern_switch.c standard
kern/kern_sx.c standard
kern/kern_synch.c standard
kern/kern_syscalls.c standard
kern/kern_sysctl.c standard
kern/kern_tc.c standard
+kern/kern_thr.c standard
kern/kern_thread.c standard
kern/kern_time.c standard
kern/kern_timeout.c standard
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index 47d4c7dc6e0b..58200598b507 100644
--- a/sys/ddb/db_ps.c
+++ b/sys/ddb/db_ps.c
@@ -100,7 +100,7 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
p->p_ucred != NULL ? p->p_ucred->cr_ruid : 0, pp->p_pid,
p->p_pgrp != NULL ? p->p_pgrp->pg_id : 0, p->p_flag,
state);
- if (p->p_flag & P_SA)
+ if (p->p_flag & P_HADTHREADS)
db_printf("(threaded) %s\n", p->p_comm);
FOREACH_THREAD_IN_PROC(p, td) {
dumpthread(p, td);
@@ -120,7 +120,7 @@ static void
dumpthread(volatile struct proc *p, volatile struct thread *td)
{
- if (p->p_flag & P_SA)
+ if (p->p_flag & P_HADTHREADS)
db_printf( " thread %p ksegrp %p ", td, td->td_ksegrp);
if (TD_ON_SLEEPQ(td))
db_printf("[SLPQ %s %p]", td->td_wmesg, (void *)td->td_wchan);
@@ -159,9 +159,11 @@ dumpthread(volatile struct proc *p, volatile struct thread *td)
default:
db_printf("[UNK: %#x]", td->td_state);
}
- if (p->p_flag & P_SA) {
+ if (p->p_flag & P_HADTHREADS) {
+#ifdef KEF_DIDRUN
if (td->td_kse)
db_printf("[kse %p]", td->td_kse);
+#endif
db_printf("\n");
} else
db_printf(" %s\n", p->p_comm);
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 0bcb6cfa5dff..ae4dc22d0ab6 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -1952,7 +1952,7 @@ init386(first)
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
metadata_missing = 0;
if (bootinfo.bi_modulep) {
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index 497bd91ed92d..29f8f1b018b8 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -724,7 +724,7 @@ ia64_init(void)
msgbufp = (struct msgbuf *)pmap_steal_memory(MSGBUF_SIZE);
msgbufinit(msgbufp, MSGBUF_SIZE);
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
/*
* Init mapping for u page(s) for proc 0
*/
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index cb39a82a6329..6acb6b01252f 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -90,7 +90,6 @@ static struct session session0;
static struct pgrp pgrp0;
struct proc proc0;
struct thread thread0;
-struct kse kse0;
struct ksegrp ksegrp0;
static struct filedesc0 filedesc0;
struct vmspace vmspace0;
@@ -320,31 +319,29 @@ proc0_init(void *dummy __unused)
register unsigned i;
struct thread *td;
struct ksegrp *kg;
- struct kse *ke;
GIANT_REQUIRED;
p = &proc0;
td = &thread0;
- ke = &kse0;
kg = &ksegrp0;
- ke->ke_sched = kse0_sched;
- kg->kg_sched = ksegrp0_sched;
- p->p_sched = proc0_sched;
- td->td_sched = thread0_sched;
-
/*
* Initialize magic number.
*/
p->p_magic = P_MAGIC;
/*
- * Initialize thread, process and pgrp structures.
+ * Initialize thread, process and ksegrp structures.
*/
- procinit();
- threadinit();
+ 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.
+ */
+ schedinit(); /* scheduler gets its house in order */
+ /*
* Initialize sleep queue hash table
*/
sleepinit();
@@ -371,13 +368,6 @@ proc0_init(void *dummy __unused)
session0.s_leader = p;
p->p_sysent = &null_sysvec;
-
- /*
- * proc_linkup was already done in init_i386() or alphainit() etc.
- * because the earlier code needed to follow td->td_proc. Otherwise
- * I would have done it here.. maybe this means this should be
- * done earlier too.
- */
p->p_flag = P_SYSTEM;
p->p_sflag = PS_INMEM;
p->p_state = PRS_NORMAL;
@@ -388,10 +378,7 @@ proc0_init(void *dummy __unused)
kg->kg_user_pri = PUSER;
td->td_priority = PVM;
td->td_base_pri = PUSER;
- td->td_kse = ke; /* XXXKSE */
td->td_oncpu = 0;
- ke->ke_state = KES_THREAD;
- ke->ke_thread = td;
p->p_peers = 0;
p->p_leader = p;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 34c75714d7ba..1a79f48a3273 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -254,7 +254,7 @@ kern_execve(td, fname, argv, envv, mac_p)
PROC_LOCK(p);
KASSERT((p->p_flag & P_INEXEC) == 0,
("%s(): process already has P_INEXEC flag", __func__));
- if (p->p_flag & P_SA || p->p_numthreads > 1) {
+ if (p->p_flag & P_HADTHREADS) {
if (thread_single(SINGLE_EXIT)) {
PROC_UNLOCK(p);
mtx_unlock(&Giant);
@@ -262,12 +262,8 @@ kern_execve(td, fname, argv, envv, mac_p)
}
/*
* If we get here all other threads are dead,
- * so unset the associated flags and lose KSE mode.
+ * and threading mode has been turned off
*/
- p->p_flag &= ~P_SA;
- td->td_mailbox = NULL;
- td->td_pflags &= ~TDP_SA;
- thread_single_end();
}
p->p_flag |= P_INEXEC;
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 96e9cf22d9ad..747fb3b68d47 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -134,7 +134,7 @@ exit1(struct thread *td, int rv)
* MUST abort all other threads before proceeding past here.
*/
PROC_LOCK(p);
- if (p->p_flag & P_SA || p->p_numthreads > 1) {
+ if (p->p_flag & P_HADTHREADS) {
retry:
/*
* First check if some other thread got here before us..
@@ -164,13 +164,8 @@ retry:
goto retry;
/*
* All other activity in this process is now stopped.
- * Remove excess KSEs and KSEGRPS. XXXKSE (when we have them)
- * ...
- * Turn off threading support.
+ * Threading support has been turned off.
*/
- p->p_flag &= ~P_SA;
- td->td_pflags &= ~TDP_SA;
- thread_single_end(); /* Don't need this any more. */
}
p->p_flag |= P_WEXIT;
@@ -385,16 +380,6 @@ retry:
lim_free(plim);
/*
- * Release this thread's reference to the ucred. The actual proc
- * reference will stay around until the proc is harvested by
- * wait(). At this point the ucred is immutable (no other threads
- * from this proc are around that can change it) so we leave the
- * per-thread ucred pointer intact in case it is needed although
- * in theory nothing should be using it at this point.
- */
- crfree(td->td_ucred);
-
- /*
* Remove proc from allproc queue and pidhash chain.
* Place onto zombproc. Unlink from parent's child list.
*/
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index b5459d8651aa..eeef44428e72 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -203,7 +203,6 @@ fork1(td, flags, pages, procp)
struct filedesc *fd;
struct filedesc_to_leader *fdtol;
struct thread *td2;
- struct kse *ke2;
struct ksegrp *kg2;
struct sigacts *newsigacts;
int error;
@@ -466,7 +465,6 @@ again:
*/
td2 = FIRST_THREAD_IN_PROC(p2);
kg2 = FIRST_KSEGRP_IN_PROC(p2);
- ke2 = FIRST_KSE_IN_KSEGRP(kg2);
/* Allocate and switch to an alternate kstack if specified. */
if (pages != 0)
@@ -479,8 +477,6 @@ again:
bzero(&p2->p_startzero,
(unsigned) RANGEOF(struct proc, p_startzero, p_endzero));
- bzero(&ke2->ke_startzero,
- (unsigned) RANGEOF(struct kse, ke_startzero, ke_endzero));
bzero(&td2->td_startzero,
(unsigned) RANGEOF(struct thread, td_startzero, td_endzero));
bzero(&kg2->kg_startzero,
@@ -496,11 +492,6 @@ again:
td2->td_sigstk = td->td_sigstk;
- /* Set up the thread as an active thread (as if runnable). */
- ke2->ke_state = KES_THREAD;
- ke2->ke_thread = td2;
- td2->td_kse = ke2;
-
/*
* Duplicate sub-structures as needed.
* Increase reference counts on shared objects.
@@ -515,7 +506,7 @@ again:
* Allow the scheduler to adjust the priority of the child and
* parent while we hold the sched_lock.
*/
- sched_fork(td, p2);
+ sched_fork(td, td2);
mtx_unlock_spin(&sched_lock);
p2->p_ucred = crhold(td->td_ucred);
@@ -792,7 +783,7 @@ fork_exit(callout, arg, frame)
mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
cpu_critical_fork_exit();
CTR4(KTR_PROC, "fork_exit: new thread %p (kse %p, pid %d, %s)",
- td, td->td_kse, p->p_pid, p->p_comm);
+ td, td->td_sched, p->p_pid, p->p_comm);
/*
* Processes normally resume in mi_switch() after being
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index ca7c206fc90d..9d8af711aff5 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -444,6 +444,7 @@ swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler,
}
return (ithread_add_handler(ithd, name, handler, arg,
(pri * RQ_PPQ) + PI_SOFT, flags, cookiep));
+ /* XXKSE.. think of a better way to get separate queues */
}
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index 7eca37a1b8f9..4a89665b7b96 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -68,12 +68,6 @@ TAILQ_HEAD(, kse_upcall) zombie_upcalls =
static int thread_update_usr_ticks(struct thread *td);
static void thread_alloc_spare(struct thread *td);
-/* move to proc.h */
-extern void kse_purge(struct proc *p, struct thread *td);
-extern void kse_purge_group(struct thread *td);
-void kseinit(void);
-void kse_GC(void);
-
struct kse_upcall *
upcall_alloc(void)
{
@@ -277,7 +271,6 @@ kse_exit(struct thread *td, struct kse_exit_args *uap)
{
struct proc *p;
struct ksegrp *kg;
- struct kse *ke;
struct kse_upcall *ku, *ku2;
int error, count;
@@ -330,22 +323,38 @@ kse_exit(struct thread *td, struct kse_exit_args *uap)
psignal(p, SIGSEGV);
mtx_lock_spin(&sched_lock);
upcall_remove(td);
- ke = td->td_kse;
- if (p->p_numthreads == 1) {
- kse_purge(p, td);
- p->p_flag &= ~P_SA;
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
- } else {
- if (kg->kg_numthreads == 1) { /* Shutdown a group */
- kse_purge_group(td);
- ke->ke_flags |= KEF_EXIT;
- }
+ 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
+ * resource leak otherwise.
+ * This is an A[PB]I issue.. what SHOULD we do?
+ * One possibility is to return to the user. It may not cope well.
+ * The other possibility would be to let the process exit.
+ */
+ p->p_flag &= ~(P_SA|P_HADTHREADS);
+ sched_set_concurrency(td->td_ksegrp, 1);
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+#if 1
return (0);
+#else
+ exit1(td, 0);
+#endif
}
/*
@@ -489,6 +498,10 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
/*
* No new KSEG: 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
+ * a mailbox..
*/
/* struct kse_create_args {
struct kse_mailbox *mbx;
@@ -497,7 +510,6 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
int
kse_create(struct thread *td, struct kse_create_args *uap)
{
- struct kse *newke;
struct ksegrp *newkg;
struct ksegrp *kg;
struct proc *p;
@@ -510,6 +522,13 @@ kse_create(struct thread *td, struct kse_create_args *uap)
if ((err = copyin(uap->mbx, &mbx, sizeof(mbx))))
return (err);
+ /*
+ * Processes using the other threading model can't
+ * suddenly start calling this one
+ */
+ if ((p->p_flag & (P_SA|P_HADTHREADS)) == P_HADTHREADS)
+ return (EINVAL);
+
ncpus = mp_ncpus;
if (virtual_cpu != 0)
ncpus = virtual_cpu;
@@ -531,7 +550,7 @@ kse_create(struct thread *td, struct kse_create_args *uap)
PROC_LOCK(p);
if (!(p->p_flag & P_SA)) {
first = 1;
- p->p_flag |= P_SA;
+ p->p_flag |= P_SA|P_HADTHREADS;
}
PROC_UNLOCK(p);
/*
@@ -612,17 +631,7 @@ kse_create(struct thread *td, struct kse_create_args *uap)
* an upcall when blocked. This simulates pthread system
* scope thread behaviour.
*/
- while (newkg->kg_kses < ncpus) {
- newke = kse_alloc();
- bzero(&newke->ke_startzero, RANGEOF(struct kse,
- ke_startzero, ke_endzero));
- mtx_lock_spin(&sched_lock);
- kse_link(newke, newkg);
- sched_fork_kse(td, newke);
- /* Add engine */
- kse_reassign(newke);
- mtx_unlock_spin(&sched_lock);
- }
+ sched_set_concurrency(newkg, ncpus);
}
/*
* Even bound LWPs get a mailbox and an upcall to hold it.
@@ -981,7 +990,8 @@ error:
/*
* This function is intended to be used to initialize a spare thread
* for upcall. Initialize thread's large data area outside sched_lock
- * for thread_schedule_upcall().
+ * for thread_schedule_upcall(). The crhold is also here to get it out
+ * from the schedlock as it has a mutex op itself.
*/
void
thread_alloc_spare(struct thread *td)
@@ -1037,7 +1047,6 @@ thread_schedule_upcall(struct thread *td, struct kse_upcall *ku)
td2->td_upcall = ku;
td2->td_flags = 0;
td2->td_pflags = TDP_SA|TDP_UPCALLING;
- td2->td_kse = NULL;
td2->td_state = TDS_CAN_RUN;
td2->td_inhibitors = 0;
SIGFILLSET(td2->td_sigmask);
@@ -1075,9 +1084,9 @@ thread_signal_add(struct thread *td, int sig)
PROC_LOCK(p);
mtx_lock(&ps->ps_mtx);
}
-
-void
-thread_switchout(struct thread *td)
+#include "opt_sched.h"
+struct thread *
+thread_switchout(struct thread *td, int flags, struct thread *nextthread)
{
struct kse_upcall *ku;
struct thread *td2;
@@ -1113,8 +1122,20 @@ thread_switchout(struct thread *td)
td->td_upcall = NULL;
td->td_pflags &= ~TDP_CAN_UNBIND;
td2 = thread_schedule_upcall(td, ku);
+#ifdef SCHED_4BSD
+ if (flags & SW_INVOL || nextthread) {
+ setrunqueue(td2, SRQ_YIELDING);
+ } else {
+ /* Keep up with reality.. we have one extra thread
+ * in the picture.. and it's 'running'.
+ */
+ return td2;
+ }
+#else
setrunqueue(td2, SRQ_YIELDING);
+#endif
}
+ return (nextthread);
}
/*
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index b1445438877a..3f1280129c0c 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -100,8 +100,6 @@ int uarea_pages = UAREA_PAGES;
SYSCTL_INT(_kern, OID_AUTO, kstack_pages, CTLFLAG_RD, &kstack_pages, 0, "");
SYSCTL_INT(_kern, OID_AUTO, uarea_pages, CTLFLAG_RD, &uarea_pages, 0, "");
-#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
-
CTASSERT(sizeof(struct kinfo_proc) == KINFO_PROC_SIZE);
/*
@@ -145,19 +143,20 @@ proc_dtor(void *mem, int size, void *arg)
{
struct proc *p;
struct thread *td;
+#ifdef INVARIANTS
struct ksegrp *kg;
- struct kse *ke;
+#endif
/* INVARIANTS checks go here */
p = (struct proc *)mem;
+ td = FIRST_THREAD_IN_PROC(p);
+#ifdef INVARIANTS
KASSERT((p->p_numthreads == 1),
("bad number of threads in exiting process"));
- td = FIRST_THREAD_IN_PROC(p);
KASSERT((td != NULL), ("proc_dtor: bad thread pointer"));
kg = FIRST_KSEGRP_IN_PROC(p);
KASSERT((kg != NULL), ("proc_dtor: bad kg pointer"));
- ke = FIRST_KSE_IN_KSEGRP(kg);
- KASSERT((ke != NULL), ("proc_dtor: bad ke pointer"));
+#endif
/* Dispose of an alternate kstack, if it exists.
* XXX What if there are more than one thread in the proc?
@@ -166,14 +165,6 @@ proc_dtor(void *mem, int size, void *arg)
*/
if (((p->p_flag & P_KTHREAD) != 0) && (td->td_altkstack != 0))
vm_thread_dispose_altkstack(td);
-
- /*
- * We want to make sure we know the initial linkages.
- * so for now tear them down and remake them.
- * This is probably un-needed as we can probably rely
- * on the state coming in here from wait4().
- */
- proc_linkup(p, kg, ke, td);
}
/*
@@ -185,17 +176,16 @@ proc_init(void *mem, int size, int flags)
struct proc *p;
struct thread *td;
struct ksegrp *kg;
- struct kse *ke;
p = (struct proc *)mem;
p->p_sched = (struct p_sched *)&p[1];
vm_proc_new(p);
td = thread_alloc();
- ke = kse_alloc();
kg = ksegrp_alloc();
- proc_linkup(p, kg, ke, td);
bzero(&p->p_mtx, sizeof(struct mtx));
mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
+ proc_linkup(p, kg, td);
+ sched_newproc(p, kg, td);
return (0);
}
@@ -208,7 +198,6 @@ proc_fini(void *mem, int size)
struct proc *p;
struct thread *td;
struct ksegrp *kg;
- struct kse *ke;
p = (struct proc *)mem;
KASSERT((p->p_numthreads == 1),
@@ -217,12 +206,10 @@ proc_fini(void *mem, int size)
KASSERT((td != NULL), ("proc_fini: bad thread pointer"));
kg = FIRST_KSEGRP_IN_PROC(p);
KASSERT((kg != NULL), ("proc_fini: bad kg pointer"));
- ke = FIRST_KSE_IN_KSEGRP(kg);
- KASSERT((ke != NULL), ("proc_fini: bad ke pointer"));
vm_proc_dispose(p);
+ sched_destroyproc(p);
thread_free(td);
ksegrp_free(kg);
- kse_free(ke);
mtx_destroy(&p->p_mtx);
}
@@ -635,7 +622,6 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp)
{
struct proc *p;
struct thread *td0;
- struct kse *ke;
struct ksegrp *kg;
struct tty *tp;
struct session *sp;
@@ -756,7 +742,6 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp)
}
kg = td->td_ksegrp;
- ke = td->td_kse;
/* things in the KSE GROUP */
kp->ki_estcpu = kg->kg_estcpu;
@@ -777,11 +762,8 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp)
kp->ki_kstack = (void *)td->td_kstack;
kp->ki_pctcpu = sched_pctcpu(td);
- /* Things in the kse */
- if (ke)
- kp->ki_rqindex = ke->ke_rqindex;
- else
- kp->ki_rqindex = 0;
+ /* We can't get this anymore but ps etc never used it anyway. */
+ kp->ki_rqindex = 0;
} else {
kp->ki_stat = SZOMB;
diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c
index 9c45ce6696ac..eeed120d995d 100644
--- a/sys/kern/kern_switch.c
+++ b/sys/kern/kern_switch.c
@@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$");
#include "opt_sched.h"
+#ifndef KERN_SWITCH_INCLUDE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kdb.h>
@@ -100,6 +101,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/sched.h>
+#else /* KERN_SWITCH_INCLUDE */
#if defined(SMP) && (defined(__i386__) || defined(__amd64__))
#include <sys/smp.h>
#endif
@@ -116,6 +118,8 @@ __FBSDID("$FreeBSD$");
CTASSERT((RQB_BPW * RQB_LEN) == RQ_NQS);
+#define td_kse td_sched
+
/************************************************************************
* Functions that manipulate runnability from a thread perspective. *
************************************************************************/
@@ -149,7 +153,7 @@ retry:
td = ke->ke_thread;
KASSERT((td->td_kse == ke), ("kse/thread mismatch"));
kg = ke->ke_ksegrp;
- if (td->td_proc->p_flag & P_SA) {
+ if (td->td_proc->p_flag & P_HADTHREADS) {
if (kg->kg_last_assigned == td) {
kg->kg_last_assigned = TAILQ_PREV(td,
threadqueue, td_runq);
@@ -183,51 +187,41 @@ retry:
}
/*
- * Given a surplus KSE, either assign a new runable thread to it
- * (and put it in the run queue) or put it in the ksegrp's idle KSE list.
- * Assumes that the original thread is not runnable.
+ * 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) (commented out)
*/
-void
-kse_reassign(struct kse *ke)
+static void
+slot_fill(struct ksegrp *kg)
{
- struct ksegrp *kg;
struct thread *td;
- struct thread *original;
mtx_assert(&sched_lock, MA_OWNED);
- original = ke->ke_thread;
- KASSERT(original == NULL || TD_IS_INHIBITED(original),
- ("reassigning KSE with runnable thread"));
- kg = ke->ke_ksegrp;
- if (original)
- original->td_kse = NULL;
-
- /*
- * 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);
+ 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, assign it the kse, otherwise idle the kse.
- */
- if (td) {
- kg->kg_last_assigned = td;
- td->td_kse = ke;
- ke->ke_thread = td;
- CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p", ke, td);
- sched_add(td, SRQ_BORING);
- return;
+ /*
+ * If we found one, send it to the system scheduler.
+ */
+ if (td) {
+ kg->kg_last_assigned = td;
+ kg->kg_avail_opennings--;
+ sched_add(td, SRQ_BORING);
+ CTR2(KTR_RUNQ, "slot_fill: td%p -> kg%p", td, kg);
+ } else {
+ /* no threads to use up the slots. quit now */
+ break;
+ }
}
-
- ke->ke_state = KES_IDLE;
- ke->ke_thread = NULL;
- TAILQ_INSERT_TAIL(&kg->kg_iq, ke, ke_kgrlist);
- kg->kg_idle_kses++;
- CTR1(KTR_RUNQ, "kse_reassign: ke%p on idle queue", ke);
- return;
}
#if 0
@@ -253,16 +247,17 @@ remrunqueue(struct thread *td)
/*
* If it is not a threaded process, take the shortcut.
*/
- if ((td->td_proc->p_flag & P_SA) == 0) {
+ if ((td->td_proc->p_flag & P_HADTHREADS) == 0) {
/* Bring its kse with it, leave the thread attached */
sched_rem(td);
+ kg->kg_avail_opennings++;
ke->ke_state = KES_THREAD;
return;
}
td3 = TAILQ_PREV(td, threadqueue, td_runq);
TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
kg->kg_runnable--;
- if (ke) {
+ if (ke->ke_state == KES_ONRUNQ) {
/*
* This thread has been assigned to a KSE.
* We need to dissociate it and try assign the
@@ -270,12 +265,13 @@ remrunqueue(struct thread *td)
* see if we need to move the KSE in the run queues.
*/
sched_rem(td);
+ kg->kg_avail_opennings++;
ke->ke_state = KES_THREAD;
td2 = kg->kg_last_assigned;
KASSERT((td2 != NULL), ("last assigned has wrong value"));
if (td2 == td)
kg->kg_last_assigned = td3;
- kse_reassign(ke);
+ slot_fill(kg);
}
}
#endif
@@ -297,7 +293,7 @@ adjustrunqueue( struct thread *td, int newpri)
/*
* If it is not a threaded process, take the shortcut.
*/
- if ((td->td_proc->p_flag & P_SA) == 0) {
+ if ((td->td_proc->p_flag & P_HADTHREADS) == 0) {
/* We only care about the kse in the run queue. */
td->td_priority = newpri;
if (ke->ke_rqindex != (newpri / RQ_PPQ)) {
@@ -310,77 +306,67 @@ adjustrunqueue( struct thread *td, int newpri)
/* It is a threaded process */
kg = td->td_ksegrp;
TD_SET_CAN_RUN(td);
- if (ke) {
+ if (ke->ke_state == KES_ONRUNQ) {
if (kg->kg_last_assigned == td) {
kg->kg_last_assigned =
TAILQ_PREV(td, threadqueue, td_runq);
}
sched_rem(td);
+ kg->kg_avail_opennings++;
}
TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
kg->kg_runnable--;
td->td_priority = newpri;
setrunqueue(td, SRQ_BORING);
}
-
+int limitcount;
void
setrunqueue(struct thread *td, int flags)
{
- struct kse *ke;
struct ksegrp *kg;
struct thread *td2;
struct thread *tda;
int count;
- CTR4(KTR_RUNQ, "setrunqueue: td:%p ke:%p kg:%p pid:%d",
- td, td->td_kse, td->td_ksegrp, td->td_proc->p_pid);
+ CTR3(KTR_RUNQ, "setrunqueue: td:%p kg:%p pid:%d",
+ td, td->td_ksegrp, td->td_proc->p_pid);
mtx_assert(&sched_lock, MA_OWNED);
KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)),
("setrunqueue: bad thread state"));
TD_SET_RUNQ(td);
kg = td->td_ksegrp;
- if ((td->td_proc->p_flag & P_SA) == 0) {
+ 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 < 100) {
+ limitcount++;
+ printf("pid %d: bad slot count (%d)\n",
+ td->td_proc->p_pid, kg->kg_avail_opennings);
+
+ }
+ kg->kg_avail_opennings = 1;
+ }
+ kg->kg_avail_opennings--;
sched_add(td, flags);
return;
}
tda = kg->kg_last_assigned;
- if ((ke = td->td_kse) == NULL) {
- if (kg->kg_idle_kses) {
- /*
- * There is a free one so it's ours for the asking..
- */
- ke = TAILQ_FIRST(&kg->kg_iq);
- CTR2(KTR_RUNQ, "setrunqueue: kg:%p: Use free ke:%p",
- kg, ke);
- TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
- ke->ke_state = KES_THREAD;
- kg->kg_idle_kses--;
- } else if (tda && (tda->td_priority > td->td_priority)) {
- /*
- * None free, but there is one we can commandeer.
- */
- ke = tda->td_kse;
- CTR3(KTR_RUNQ,
- "setrunqueue: kg:%p: take ke:%p from td: %p",
- kg, ke, tda);
- sched_rem(tda);
- tda->td_kse = NULL;
- ke->ke_thread = NULL;
- tda = kg->kg_last_assigned =
- TAILQ_PREV(tda, threadqueue, td_runq);
- }
- } else {
- /*
- * Temporarily disassociate so it looks like the other cases.
+ if ((kg->kg_avail_opennings <= 0) &&
+ (tda && (tda->td_priority > td->td_priority))) {
+ /*
+ * None free, but there is one we can commandeer.
*/
- ke->ke_thread = NULL;
- td->td_kse = NULL;
+ 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);
+ kg->kg_avail_opennings++;
}
/*
@@ -407,40 +393,30 @@ setrunqueue(struct thread *td, int flags)
}
/*
- * If we have a ke to use, then put it on the run queue and
- * If needed, readjust the last_assigned pointer.
+ * If we have a slot to use, then put the thread on the system
+ * run queue and if needed, readjust the last_assigned pointer.
*/
- if (ke) {
+ if (kg->kg_avail_opennings > 0) {
if (tda == NULL) {
/*
* No pre-existing last assigned so whoever is first
* gets the KSE we brought in.. (maybe us)
*/
td2 = TAILQ_FIRST(&kg->kg_runq);
- KASSERT((td2->td_kse == NULL),
- ("unexpected ke present"));
- td2->td_kse = ke;
- ke->ke_thread = td2;
kg->kg_last_assigned = td2;
} else if (tda->td_priority > td->td_priority) {
- /*
- * It's ours, grab it, but last_assigned is past us
- * so don't change it.
- */
- td->td_kse = ke;
- ke->ke_thread = td;
+ td2 = td;
} else {
/*
* We are past last_assigned, so
- * put the new kse on whatever is next,
+ * gave 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;
- td2->td_kse = ke;
- ke->ke_thread = td2;
}
- sched_add(ke->ke_thread, flags);
+ kg->kg_avail_opennings--;
+ 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);
@@ -692,7 +668,6 @@ runq_check(struct runq *rq)
#if defined(SMP) && defined(SCHED_4BSD)
int runq_fuzz = 1;
-SYSCTL_DECL(_kern_sched);
SYSCTL_INT(_kern_sched, OID_AUTO, runq_fuzz, CTLFLAG_RW, &runq_fuzz, 0, "");
#endif
@@ -766,3 +741,115 @@ runq_remove(struct runq *rq, struct kse *ke)
}
}
+/****** functions that are temporarily here ***********/
+#include <vm/uma.h>
+#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
+extern struct mtx kse_zombie_lock;
+
+/*
+ * Allocate scheduler specific per-process resources.
+ * The thread and ksegrp have already been linked in.
+ * In this case just set the default concurrency value.
+ *
+ * Called from:
+ * proc_init() (UMA init method)
+ */
+void
+sched_newproc(struct proc *p, struct ksegrp *kg, struct thread *td)
+{
+
+ /* This can go in sched_fork */
+ sched_init_concurrency(kg);
+}
+
+/*
+ * Called by the uma process fini routine..
+ * undo anything we may have done in the uma_init method.
+ * Panic if it's not all 1:1:1:1
+ * Called from:
+ * proc_fini() (UMA method)
+ */
+void
+sched_destroyproc(struct proc *p)
+{
+
+ /* this function slated for destruction */
+ KASSERT((p->p_numthreads == 1), ("Cached proc with > 1 thread "));
+ KASSERT((p->p_numksegrps == 1), ("Cached proc with > 1 ksegrp "));
+}
+
+#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
+/*
+ * thread is being either created or recycled.
+ * Fix up the per-scheduler resources associated with it.
+ * Called from:
+ * sched_fork_thread()
+ * thread_dtor() (*may go away)
+ * thread_init() (*may go away)
+ */
+void
+sched_newthread(struct thread *td)
+{
+ struct td_sched *ke;
+
+ ke = (struct td_sched *) (td + 1);
+ bzero(ke, sizeof(*ke));
+ td->td_sched = ke;
+ ke->ke_thread = td;
+ ke->ke_oncpu = NOCPU;
+ ke->ke_state = KES_THREAD;
+}
+
+/*
+ * 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)
+{
+
+ kg->kg_concurrency = 1;
+ kg->kg_avail_opennings = 1;
+}
+
+/*
+ * Change the concurrency of an existing ksegrp to N
+ * Called from:
+ * kse_create()
+ * kse_exit()
+ * thread_exit()
+ * thread_single()
+ */
+void
+sched_set_concurrency(struct ksegrp *kg, int concurrency)
+{
+
+ /* Handle the case for a declining concurrency */
+ kg->kg_avail_opennings += (concurrency - kg->kg_concurrency);
+ kg->kg_concurrency = concurrency;
+}
+
+/*
+ * Called from thread_exit() for all exiting thread
+ *
+ * Not to be confused with sched_exit_thread()
+ * that is only called from thread_exit() for threads exiting
+ * without the rest of the process exiting because it is also called from
+ * sched_exit() and we wouldn't want to call it twice.
+ * XXX This can probably be fixed.
+ */
+void
+sched_thread_exit(struct thread *td)
+{
+
+ td->td_ksegrp->kg_avail_opennings++;
+ slot_fill(td->td_ksegrp);
+}
+
+#endif /* KERN_SWITCH_INCLUDE */
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index aae9d95e2351..2c97a5b308e9 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -334,13 +334,13 @@ mi_switch(int flags, struct thread *newtd)
PCPU_SET(switchtime, new_switchtime);
PCPU_SET(switchticks, ticks);
CTR4(KTR_PROC, "mi_switch: old thread %p (kse %p, pid %ld, %s)",
- (void *)td, td->td_kse, (long)p->p_pid, p->p_comm);
+ (void *)td, td->td_sched, (long)p->p_pid, p->p_comm);
if (td->td_proc->p_flag & P_SA)
- thread_switchout(td);
+ newtd = thread_switchout(td, flags, newtd);
sched_switch(td, newtd);
CTR4(KTR_PROC, "mi_switch: new thread %p (kse %p, pid %ld, %s)",
- (void *)td, td->td_kse, (long)p->p_pid, p->p_comm);
+ (void *)td, td->td_sched, (long)p->p_pid, p->p_comm);
/*
* If the last thread was exiting, finish cleaning it up.
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 7be6b6bf697c..e4ec7be15eaa 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
+#include <sys/smp.h>
#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -43,74 +44,13 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
+extern int max_threads_per_proc;
+extern int max_groups_per_proc;
+
/*
* Back end support functions.
*/
-void
-thr_exit1(void)
-{
- struct ksegrp *kg;
- struct thread *td;
- struct kse *ke;
- struct proc *p;
-
- td = curthread;
- p = td->td_proc;
- kg = td->td_ksegrp;
- ke = td->td_kse;
-
- mtx_assert(&sched_lock, MA_OWNED);
- PROC_LOCK_ASSERT(p, MA_OWNED);
- KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
-
- /*
- * Shutting down last thread in the proc. This will actually
- * call exit() in the trampoline when it returns.
- */
- if (p->p_numthreads == 1) {
- PROC_UNLOCK(p);
- return;
- }
-
- /*
- * XXX Undelivered process wide signals should be reposted to the
- * proc.
- */
-
- /* Clean up cpu resources. */
- cpu_thread_exit(td);
-
- /* Unlink the thread from the process and kseg. */
- thread_unlink(td);
-
- ke->ke_state = KES_UNQUEUED;
- ke->ke_thread = NULL;
- kse_unlink(ke);
- sched_exit_kse(TAILQ_NEXT(ke, ke_kglist), td);
-
- /*
- * If we were stopped while waiting for all threads to exit and this
- * is the last thread wakeup the exiting thread.
- */
- if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE)
- if (p->p_numthreads == 1)
- thread_unsuspend_one(p->p_singlethread);
-
- PROC_UNLOCK(p);
- td->td_kse = NULL;
- td->td_state = TDS_INACTIVE;
-#if 0
- td->td_proc = NULL;
-#endif
- td->td_ksegrp = NULL;
- td->td_last_kse = NULL;
- sched_exit_thread(TAILQ_NEXT(td, td_kglist), td);
- thread_stash(td);
-
- cpu_throw(td, choosethread());
-}
-
#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
/*
@@ -120,69 +60,79 @@ int
thr_create(struct thread *td, struct thr_create_args *uap)
/* ucontext_t *ctx, long *id, int flags */
{
- struct kse *ke0;
- struct thread *td0;
+ struct thread *newtd;
ucontext_t ctx;
long id;
int error;
+ struct ksegrp *kg, *newkg;
+ struct proc *p;
+ p = td->td_proc;
+ kg = td->td_ksegrp;
if ((error = copyin(uap->ctx, &ctx, sizeof(ctx))))
return (error);
- /* Initialize our td. */
- td0 = thread_alloc();
-
+ /* Have race condition but it is cheap */
+ if ((p->p_numksegrps >= max_groups_per_proc) ||
+ (p->p_numthreads >= max_threads_per_proc)) {
+ return (EPROCLIM);
+ }
+ /* Initialize our td and new ksegrp.. */
+ newtd = thread_alloc();
+ newkg = ksegrp_alloc();
/*
* Try the copyout as soon as we allocate the td so we don't have to
* tear things down in a failure case below.
*/
- id = td0->td_tid;
+ id = newtd->td_tid;
if ((error = copyout(&id, uap->id, sizeof(long)))) {
- thread_free(td0);
+ ksegrp_free(newkg);
+ thread_free(newtd);
return (error);
}
- bzero(&td0->td_startzero,
- (unsigned)RANGEOF(struct thread, td_startzero, td_endzero));
- bcopy(&td->td_startcopy, &td0->td_startcopy,
+ bzero(&newtd->td_startzero,
+ (unsigned) RANGEOF(struct thread, td_startzero, td_endzero));
+ bcopy(&td->td_startcopy, &newtd->td_startcopy,
(unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy));
- td0->td_proc = td->td_proc;
- PROC_LOCK(td->td_proc);
- td0->td_sigmask = td->td_sigmask;
- PROC_UNLOCK(td->td_proc);
- td0->td_ucred = crhold(td->td_ucred);
+ bzero(&newkg->kg_startzero,
+ (unsigned) RANGEOF(struct ksegrp, kg_startzero, kg_endzero));
+ bcopy(&kg->kg_startcopy, &newkg->kg_startcopy,
+ (unsigned) RANGEOF(struct ksegrp, kg_startcopy, kg_endcopy));
- /* Initialize our kse structure. */
- ke0 = kse_alloc();
- bzero(&ke0->ke_startzero,
- RANGEOF(struct kse, ke_startzero, ke_endzero));
+ newtd->td_proc = td->td_proc;
+ newtd->td_ucred = crhold(td->td_ucred);
/* Set up our machine context. */
- cpu_set_upcall(td0, td);
- error = set_mcontext(td0, &ctx.uc_mcontext);
+ cpu_set_upcall(newtd, td);
+ error = set_mcontext(newtd, &ctx.uc_mcontext);
if (error != 0) {
- kse_free(ke0);
- thread_free(td0);
+ ksegrp_free(newkg);
+ thread_free(newtd);
+ crfree(td->td_ucred);
goto out;
}
/* Link the thread and kse into the ksegrp and make it runnable. */
+ 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);
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+ sched_init_concurrency(newkg);
- thread_link(td0, td->td_ksegrp);
- kse_link(ke0, td->td_ksegrp);
-
- /* Bind this thread and kse together. */
- td0->td_kse = ke0;
- ke0->ke_thread = td0;
-
- sched_fork_kse(td, ke0);
- sched_fork_thread(td, td0);
+ /* let the scheduler know about these things. */
+ mtx_lock_spin(&sched_lock);
+ sched_fork_ksegrp(td, newkg);
+ sched_fork_thread(td, newtd);
- TD_SET_CAN_RUN(td0);
+ TD_SET_CAN_RUN(newtd);
if ((uap->flags & THR_SUSPENDED) == 0)
- setrunqueue(td0, SRQ_BORING);
+ setrunqueue(newtd, SRQ_BORING);
mtx_unlock_spin(&sched_lock);
@@ -216,12 +166,15 @@ thr_exit(struct thread *td, struct thr_exit_args *uap)
mtx_lock_spin(&sched_lock);
/*
- * This unlocks proc and doesn't return unless this is the last
- * thread.
+ * Shutting down last thread in the proc. This will actually
+ * call exit() in the trampoline when it returns.
*/
- thr_exit1();
+ if (p->p_numthreads != 1) {
+ thread_exit();
+ /* NOTREACHED */
+ }
mtx_unlock_spin(&sched_lock);
-
+ PROC_UNLOCK(p);
return (0);
}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 031b67d0bbc6..4aaef434540b 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
* KSEGRP related storage.
*/
static uma_zone_t ksegrp_zone;
-static uma_zone_t kse_zone;
static uma_zone_t thread_zone;
/* DEBUG ONLY */
@@ -63,7 +62,7 @@ int max_threads_per_proc = 1500;
SYSCTL_INT(_kern_threads, OID_AUTO, max_threads_per_proc, CTLFLAG_RW,
&max_threads_per_proc, 0, "Limit on threads per proc");
-int max_groups_per_proc = 500;
+int max_groups_per_proc = 1500;
SYSCTL_INT(_kern_threads, OID_AUTO, max_groups_per_proc, CTLFLAG_RW,
&max_groups_per_proc, 0, "Limit on thread groups per proc");
@@ -76,19 +75,10 @@ int virtual_cpu;
#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
TAILQ_HEAD(, thread) zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads);
-TAILQ_HEAD(, kse) zombie_kses = TAILQ_HEAD_INITIALIZER(zombie_kses);
TAILQ_HEAD(, ksegrp) zombie_ksegrps = TAILQ_HEAD_INITIALIZER(zombie_ksegrps);
struct mtx kse_zombie_lock;
MTX_SYSINIT(kse_zombie_lock, &kse_zombie_lock, "kse zombie lock", MTX_SPIN);
-void kse_purge(struct proc *p, struct thread *td);
-void kse_purge_group(struct thread *td);
-
-/* move to proc.h */
-extern void kseinit(void);
-extern void kse_GC(void);
-
-
static int
sysctl_kse_virtual_cpu(SYSCTL_HANDLER_ARGS)
{
@@ -198,6 +188,7 @@ thread_dtor(void *mem, int size, void *arg)
/* NOTREACHED */
}
#endif
+ sched_newthread(td);
}
/*
@@ -252,6 +243,7 @@ thread_init(void *mem, int size, int flags)
td->td_sleepqueue = sleepq_alloc();
td->td_turnstile = turnstile_alloc();
td->td_sched = (struct td_sched *)&td[1];
+ sched_newthread(td);
return (0);
}
@@ -287,19 +279,6 @@ thread_fini(void *mem, int size)
}
/*
- * Initialize type-stable parts of a kse (when newly created).
- */
-static int
-kse_init(void *mem, int size, int flags)
-{
- struct kse *ke;
-
- ke = (struct kse *)mem;
- ke->ke_sched = (struct ke_sched *)&ke[1];
- return (0);
-}
-
-/*
* Initialize type-stable parts of a ksegrp (when newly created).
*/
static int
@@ -309,46 +288,10 @@ ksegrp_init(void *mem, int size, int flags)
kg = (struct ksegrp *)mem;
kg->kg_sched = (struct kg_sched *)&kg[1];
+ /* sched_newksegrp(kg); */
return (0);
}
-/*
- * KSE is linked into kse group.
- */
-void
-kse_link(struct kse *ke, struct ksegrp *kg)
-{
- struct proc *p = kg->kg_proc;
-
- TAILQ_INSERT_HEAD(&kg->kg_kseq, ke, ke_kglist);
- kg->kg_kses++;
- ke->ke_state = KES_UNQUEUED;
- ke->ke_proc = p;
- ke->ke_ksegrp = kg;
- ke->ke_thread = NULL;
- ke->ke_oncpu = NOCPU;
- ke->ke_flags = 0;
-}
-
-void
-kse_unlink(struct kse *ke)
-{
- struct ksegrp *kg;
-
- mtx_assert(&sched_lock, MA_OWNED);
- kg = ke->ke_ksegrp;
- TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
- if (ke->ke_state == KES_IDLE) {
- TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
- kg->kg_idle_kses--;
- }
- --kg->kg_kses;
- /*
- * Aggregate stats from the KSE
- */
- kse_stash(ke);
-}
-
void
ksegrp_link(struct ksegrp *kg, struct proc *p)
{
@@ -356,8 +299,6 @@ 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_slpq); /* links with td_runq */
- TAILQ_INIT(&kg->kg_kseq); /* all kses in ksegrp */
- TAILQ_INIT(&kg->kg_iq); /* all idle kses in ksegrp */
TAILQ_INIT(&kg->kg_upcalls); /* all upcall structure in ksegrp */
kg->kg_proc = p;
/*
@@ -366,15 +307,16 @@ ksegrp_link(struct ksegrp *kg, struct proc *p)
*/
kg->kg_numthreads = 0;
kg->kg_runnable = 0;
- kg->kg_kses = 0;
- kg->kg_runq_kses = 0; /* XXXKSE change name */
- kg->kg_idle_kses = 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)
{
@@ -382,7 +324,6 @@ ksegrp_unlink(struct ksegrp *kg)
mtx_assert(&sched_lock, MA_OWNED);
KASSERT((kg->kg_numthreads == 0), ("ksegrp_unlink: residual threads"));
- KASSERT((kg->kg_kses == 0), ("ksegrp_unlink: residual kses"));
KASSERT((kg->kg_numupcalls == 0), ("ksegrp_unlink: residual upcalls"));
p = kg->kg_proc;
@@ -391,16 +332,18 @@ ksegrp_unlink(struct ksegrp *kg)
/*
* Aggregate stats from the KSE
*/
- ksegrp_stash(kg);
}
/*
* For a newly created process,
* link up all the structures and its initial threads etc.
+ * called from:
+ * {arch}/{arch}/machdep.c ia64_init(), init386() etc.
+ * proc_dtor() (should go away)
+ * proc_init()
*/
void
-proc_linkup(struct proc *p, struct ksegrp *kg,
- struct kse *ke, struct thread *td)
+proc_linkup(struct proc *p, struct ksegrp *kg, struct thread *td)
{
TAILQ_INIT(&p->p_ksegrps); /* all ksegrps in proc */
@@ -410,7 +353,6 @@ proc_linkup(struct proc *p, struct ksegrp *kg,
p->p_numthreads = 0;
ksegrp_link(kg, p);
- kse_link(ke, kg);
thread_link(td, kg);
}
@@ -429,10 +371,7 @@ threadinit(void)
ksegrp_zone = uma_zcreate("KSEGRP", sched_sizeof_ksegrp(),
NULL, NULL, ksegrp_init, NULL,
UMA_ALIGN_CACHE, 0);
- kse_zone = uma_zcreate("KSE", sched_sizeof_kse(),
- NULL, NULL, kse_init, NULL,
- UMA_ALIGN_CACHE, 0);
- kseinit();
+ kseinit(); /* set up kse specific stuff e.g. upcall zone*/
}
/*
@@ -447,17 +386,6 @@ thread_stash(struct thread *td)
}
/*
- * Stash an embarasingly extra kse into the zombie kse queue.
- */
-void
-kse_stash(struct kse *ke)
-{
- mtx_lock_spin(&kse_zombie_lock);
- TAILQ_INSERT_HEAD(&zombie_kses, ke, ke_procq);
- mtx_unlock_spin(&kse_zombie_lock);
-}
-
-/*
* Stash an embarasingly extra ksegrp into the zombie ksegrp queue.
*/
void
@@ -475,7 +403,6 @@ void
thread_reap(void)
{
struct thread *td_first, *td_next;
- struct kse *ke_first, *ke_next;
struct ksegrp *kg_first, * kg_next;
/*
@@ -483,16 +410,12 @@ thread_reap(void)
* we really don't care about the next instant..
*/
if ((!TAILQ_EMPTY(&zombie_threads))
- || (!TAILQ_EMPTY(&zombie_kses))
|| (!TAILQ_EMPTY(&zombie_ksegrps))) {
mtx_lock_spin(&kse_zombie_lock);
td_first = TAILQ_FIRST(&zombie_threads);
- ke_first = TAILQ_FIRST(&zombie_kses);
kg_first = TAILQ_FIRST(&zombie_ksegrps);
if (td_first)
TAILQ_INIT(&zombie_threads);
- if (ke_first)
- TAILQ_INIT(&zombie_kses);
if (kg_first)
TAILQ_INIT(&zombie_ksegrps);
mtx_unlock_spin(&kse_zombie_lock);
@@ -503,18 +426,17 @@ thread_reap(void)
thread_free(td_first);
td_first = td_next;
}
- while (ke_first) {
- ke_next = TAILQ_NEXT(ke_first, ke_procq);
- kse_free(ke_first);
- ke_first = ke_next;
- }
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();
}
- kse_GC();
}
/*
@@ -527,15 +449,6 @@ ksegrp_alloc(void)
}
/*
- * Allocate a kse.
- */
-struct kse *
-kse_alloc(void)
-{
- return (uma_zalloc(kse_zone, M_WAITOK));
-}
-
-/*
* Allocate a thread.
*/
struct thread *
@@ -555,15 +468,6 @@ ksegrp_free(struct ksegrp *td)
}
/*
- * Deallocate a kse.
- */
-void
-kse_free(struct kse *td)
-{
- uma_zfree(kse_zone, td);
-}
-
-/*
* Deallocate a thread.
*/
void
@@ -594,92 +498,150 @@ thread_free(struct thread *td)
* Of course in the end, they end up coming here through exit1
* anyhow.. After fixing 'thr' to play by the rules we should be able
* to merge these two functions together.
+ *
+ * called from:
+ * exit1()
+ * kse_exit()
+ * thr_exit()
+ * thread_user_enter()
+ * thread_userret()
+ * thread_suspend_check()
*/
void
thread_exit(void)
{
struct thread *td;
- struct kse *ke;
struct proc *p;
struct ksegrp *kg;
td = curthread;
kg = td->td_ksegrp;
p = td->td_proc;
- ke = td->td_kse;
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"));
- KASSERT(ke != NULL, ("thread exiting without a kse"));
KASSERT(kg != NULL, ("thread exiting without a kse group"));
- PROC_LOCK_ASSERT(p, MA_OWNED);
CTR3(KTR_PROC, "thread_exit: thread %p (pid %ld, %s)", td,
(long)p->p_pid, p->p_comm);
- mtx_assert(&Giant, MA_NOTOWNED);
if (td->td_standin != NULL) {
+ /*
+ * Note that we don't need to free the cred here as it
+ * is done in thread_reap().
+ */
thread_stash(td->td_standin);
td->td_standin = NULL;
}
+ /*
+ * drop FPU & debug register state storage, or any other
+ * architecture specific resources that
+ * would not be on a new untouched process.
+ */
cpu_thread_exit(td); /* XXXSMP */
/*
+ * The thread is exiting. scheduler can release its stuff
+ * and collect stats etc.
+ */
+ sched_thread_exit(td);
+
+ /*
* The last thread is left attached to the process
* So that the whole bundle gets recycled. Skip
- * all this stuff.
+ * all this stuff if we never had threads.
+ * EXIT clears all sign of other threads when
+ * it goes to single threading, so the last thread always
+ * takes the short path.
*/
- if (p->p_numthreads > 1) {
- thread_unlink(td);
- if (p->p_maxthrwaits)
- wakeup(&p->p_numthreads);
- /*
- * The test below is NOT true if we are the
- * sole exiting thread. P_STOPPED_SNGL is unset
- * in exit1() after it is the only survivor.
- */
- if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
- if (p->p_numthreads == p->p_suspcount) {
- thread_unsuspend_one(p->p_singlethread);
+ if (p->p_flag & P_HADTHREADS) {
+ if (p->p_numthreads > 1) {
+ thread_unlink(td);
+
+ /* XXX first arg not used in 4BSD or ULE */
+ sched_exit_thread(FIRST_THREAD_IN_PROC(p), td);
+
+ /*
+ * as we are exiting there is room for another
+ * to be created.
+ */
+ if (p->p_maxthrwaits)
+ wakeup(&p->p_numthreads);
+
+ /*
+ * The test below is NOT true if we are the
+ * sole exiting thread. P_STOPPED_SNGL is unset
+ * in exit1() after it is the only survivor.
+ */
+ if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
+ if (p->p_numthreads == p->p_suspcount) {
+ thread_unsuspend_one(p->p_singlethread);
+ }
}
- }
- /*
- * Because each upcall structure has an owner thread,
- * owner thread exits only when process is in exiting
- * state, so upcall to userland is no longer needed,
- * deleting upcall structure is safe here.
- * So when all threads in a group is exited, all upcalls
- * in the group should be automatically freed.
- */
- if (td->td_upcall)
+ /*
+ * Because each upcall structure has an owner thread,
+ * owner thread exits only when process is in exiting
+ * state, so upcall to userland is no longer needed,
+ * deleting upcall structure is safe here.
+ * So when all threads in a group is exited, all upcalls
+ * in the group should be automatically freed.
+ * XXXKSE This is a KSE thing and should be exported
+ * there somehow.
+ */
upcall_remove(td);
- sched_exit_thread(FIRST_THREAD_IN_PROC(p), td);
- sched_exit_kse(FIRST_KSE_IN_PROC(p), td);
- ke->ke_state = KES_UNQUEUED;
- ke->ke_thread = NULL;
- /*
- * Decide what to do with the KSE attached to this thread.
- */
- if (ke->ke_flags & KEF_EXIT) {
- kse_unlink(ke);
- if (kg->kg_kses == 0) {
+ /*
+ * 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);
}
+ PROC_UNLOCK(p);
+ td->td_ksegrp = NULL;
+ PCPU_SET(deadthread, td);
+ } else {
+ /*
+ * The last thread is exiting.. but not through exit()
+ * what should we do?
+ * Theoretically this can't happen
+ * exit1() - clears threading flags before coming here
+ * kse_exit() - treats last thread specially
+ * thr_exit() - treats last thread specially
+ * thread_user_enter() - only if more exist
+ * thread_userret() - only if more exist
+ * thread_suspend_check() - only if more exist
+ */
+ panic ("thread_exit: Last thread exiting on its own");
}
- else
- kse_reassign(ke);
- PROC_UNLOCK(p);
- td->td_kse = NULL;
-#if 0
- td->td_proc = NULL;
-#endif
- td->td_ksegrp = NULL;
- td->td_last_kse = NULL;
- PCPU_SET(deadthread, td);
} else {
+ /*
+ * non threaded process comes here.
+ * This includes an EX threaded process that is coming
+ * here via exit1(). (exit1 dethreads the proc first).
+ */
PROC_UNLOCK(p);
}
td->td_state = TDS_INACTIVE;
@@ -703,10 +665,13 @@ thread_wait(struct proc *p)
KASSERT((p->p_numksegrps == 1), ("Multiple ksegrps in wait1()"));
FOREACH_THREAD_IN_PROC(p, td) {
if (td->td_standin != NULL) {
+ crfree(td->td_ucred);
+ td->td_ucred = NULL;
thread_free(td->td_standin);
td->td_standin = NULL;
}
cpu_thread_clean(td);
+ crfree(td->td_ucred);
}
thread_reap(); /* check for zombie threads etc. */
}
@@ -718,6 +683,10 @@ thread_wait(struct proc *p)
*
* Note that we do not link to the proc's ucred here.
* The thread is linked as if running but no KSE assigned.
+ * Called from:
+ * proc_linkup()
+ * thread_schedule_upcall()
+ * thr_create()
*/
void
thread_link(struct thread *td, struct ksegrp *kg)
@@ -728,10 +697,8 @@ thread_link(struct thread *td, struct ksegrp *kg)
td->td_state = TDS_INACTIVE;
td->td_proc = p;
td->td_ksegrp = kg;
- td->td_last_kse = NULL;
td->td_flags = 0;
td->td_kflags = 0;
- td->td_kse = NULL;
LIST_INIT(&td->td_contested);
callout_init(&td->td_slpcallout, CALLOUT_MPSAFE);
@@ -741,6 +708,10 @@ thread_link(struct thread *td, struct ksegrp *kg)
kg->kg_numthreads++;
}
+/*
+ * Called from:
+ * thread_exit()
+ */
void
thread_unlink(struct thread *td)
{
@@ -753,73 +724,7 @@ thread_unlink(struct thread *td)
TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
kg->kg_numthreads--;
/* could clear a few other things here */
-}
-
-/*
- * Purge a ksegrp resource. When a ksegrp is preparing to
- * exit, it calls this function.
- */
-void
-kse_purge_group(struct thread *td)
-{
- struct ksegrp *kg;
- struct kse *ke;
-
- kg = td->td_ksegrp;
- KASSERT(kg->kg_numthreads == 1, ("%s: bad thread number", __func__));
- while ((ke = TAILQ_FIRST(&kg->kg_iq)) != NULL) {
- KASSERT(ke->ke_state == KES_IDLE,
- ("%s: wrong idle KSE state", __func__));
- kse_unlink(ke);
- }
- KASSERT((kg->kg_kses == 1),
- ("%s: ksegrp still has %d KSEs", __func__, kg->kg_kses));
- KASSERT((kg->kg_numupcalls == 0),
- ("%s: ksegrp still has %d upcall datas",
- __func__, kg->kg_numupcalls));
-}
-
-/*
- * Purge a process's KSE resource. When a process is preparing to
- * exit, it calls kse_purge to release any extra KSE resources in
- * the process.
- */
-void
-kse_purge(struct proc *p, struct thread *td)
-{
- struct ksegrp *kg;
- struct kse *ke;
-
- KASSERT(p->p_numthreads == 1, ("bad thread number"));
- while ((kg = TAILQ_FIRST(&p->p_ksegrps)) != NULL) {
- TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp);
- p->p_numksegrps--;
- /*
- * There is no ownership for KSE, after all threads
- * in the group exited, it is possible that some KSEs
- * were left in idle queue, gc them now.
- */
- while ((ke = TAILQ_FIRST(&kg->kg_iq)) != NULL) {
- KASSERT(ke->ke_state == KES_IDLE,
- ("%s: wrong idle KSE state", __func__));
- TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
- kg->kg_idle_kses--;
- TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
- kg->kg_kses--;
- kse_stash(ke);
- }
- KASSERT(((kg->kg_kses == 0) && (kg != td->td_ksegrp)) ||
- ((kg->kg_kses == 1) && (kg == td->td_ksegrp)),
- ("ksegrp has wrong kg_kses: %d", kg->kg_kses));
- KASSERT((kg->kg_numupcalls == 0),
- ("%s: ksegrp still has %d upcall datas",
- __func__, kg->kg_numupcalls));
-
- if (kg != td->td_ksegrp)
- ksegrp_stash(kg);
- }
- TAILQ_INSERT_HEAD(&p->p_ksegrps, td->td_ksegrp, kg_ksegrp);
- p->p_numksegrps++;
+ /* Must NOT clear links to proc and ksegrp! */
}
/*
@@ -849,7 +754,7 @@ thread_single(int force_exit)
PROC_LOCK_ASSERT(p, MA_OWNED);
KASSERT((td != NULL), ("curthread is NULL"));
- if ((p->p_flag & P_SA) == 0 && p->p_numthreads == 1)
+ if ((p->p_flag & P_HADTHREADS) == 0)
return (0);
/* Is someone already single threading? */
@@ -924,11 +829,17 @@ thread_single(int force_exit)
remaining = p->p_numthreads - p->p_suspcount;
}
if (force_exit == SINGLE_EXIT) {
- if (td->td_upcall)
- upcall_remove(td);
- kse_purge(p, td);
+ upcall_remove(td);
+ p->p_flag &= ~(P_SA|P_HADTHREADS);
+ td->td_mailbox = NULL;
+ td->td_pflags &= ~TDP_SA;
+ p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT);
+ p->p_singlethread = NULL;
+ sched_set_concurrency(td->td_ksegrp, 1);
+ mtx_unlock_spin(&sched_lock);
+ } else {
+ mtx_unlock_spin(&sched_lock);
}
- mtx_unlock_spin(&sched_lock);
return (0);
}
@@ -1000,10 +911,7 @@ thread_suspend_check(int return_instead)
* Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
*/
if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
- if (p->p_flag & P_SA)
- thread_exit();
- else
- thr_exit1();
+ thread_exit();
}
/*
@@ -1084,6 +992,10 @@ thread_unsuspend(struct proc *p)
}
}
+/*
+ * End the single threading mode..
+ * Part of this is duplicated in thread-single in the SINGLE_EXIT case.
+ */
void
thread_single_end(void)
{
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 44e34a55f87a..2b1ff3633b69 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#define kse td_sched
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -64,29 +66,69 @@ __FBSDID("$FreeBSD$");
#endif
#define NICE_WEIGHT 1 /* Priorities per nice level. */
-struct ke_sched {
- int ske_cpticks; /* (j) Ticks of cpu time. */
- struct runq *ske_runq; /* runq the kse is currently on */
+/*
+ * The schedulable entity that can be given a context to run.
+ * A process may have several of these. Probably one per processor
+ * but posibly a few more. In this universe they are grouped
+ * with a KSEG that contains the priority and niceness
+ * for the group.
+ */
+struct kse {
+ TAILQ_ENTRY(kse) ke_kglist; /* (*) Queue of KSEs in ke_ksegrp. */
+ TAILQ_ENTRY(kse) ke_kgrlist; /* (*) Queue of KSEs in this state. */
+ TAILQ_ENTRY(kse) ke_procq; /* (j/z) Run queue. */
+ struct thread *ke_thread; /* (*) Active associated thread. */
+ fixpt_t ke_pctcpu; /* (j) %cpu during p_swtime. */
+ u_char ke_oncpu; /* (j) Which cpu we are on. */
+ char ke_rqindex; /* (j) Run queue index. */
+ enum {
+ KES_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 */
+ int ke_pinned; /* nested count of pinned to a cpu */
};
-#define ke_runq ke_sched->ske_runq
-#define ke_cpticks ke_sched->ske_cpticks
-#define KEF_BOUND KEF_SCHED1
+
+#define ke_proc ke_thread->td_proc
+#define ke_ksegrp ke_thread->td_ksegrp
+
+#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_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)
+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. */
+ int skg_runq_kses; /* (j) Num KSEs on runq. */
+};
+#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 kg_runq_kses kg_sched->skg_runq_kses
+
/*
* 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)
-static struct ke_sched ke_sched;
+ ((ke)->ke_pinned == 0 && ((ke)->ke_flags & KEF_BOUND) == 0)
-struct ke_sched *kse0_sched = &ke_sched;
-struct kg_sched *ksegrp0_sched = NULL;
-struct p_sched *proc0_sched = NULL;
-struct td_sched *thread0_sched = NULL;
+static struct kse kse0;
+static struct kg_sched kg_sched0;
static int sched_tdcnt; /* Total runnable threads in the system. */
static int sched_quantum; /* Roundrobin scheduling quantum in ticks. */
@@ -94,6 +136,9 @@ static int sched_quantum; /* Roundrobin scheduling quantum in ticks. */
static struct callout roundrobin_callout;
+static void slot_fill(struct ksegrp *kg);
+static struct kse *sched_choose(void); /* XXX Should be thread * */
+
static void setup_runqs(void);
static void roundrobin(void *arg);
static void schedcpu(void);
@@ -213,7 +258,7 @@ maybe_resched(struct thread *td)
{
mtx_assert(&sched_lock, MA_OWNED);
- if (td->td_priority < curthread->td_priority && curthread->td_kse)
+ if (td->td_priority < curthread->td_priority)
curthread->td_flags |= TDF_NEEDRESCHED;
}
@@ -353,7 +398,8 @@ schedcpu(void)
p->p_swtime++;
FOREACH_KSEGRP_IN_PROC(p, kg) {
awake = 0;
- FOREACH_KSE_IN_GROUP(kg, ke) {
+ FOREACH_THREAD_IN_GROUP(kg, td) {
+ ke = td->td_kse;
/*
* Increment sleep time (if sleeping). We
* ignore overflow, as above.
@@ -366,7 +412,7 @@ schedcpu(void)
awake = 1;
ke->ke_flags &= ~KEF_DIDRUN;
} else if ((ke->ke_state == KES_THREAD) &&
- (TD_IS_RUNNING(ke->ke_thread))) {
+ (TD_IS_RUNNING(td))) {
awake = 1;
/* Do not clear KEF_DIDRUN */
} else if (ke->ke_flags & KEF_DIDRUN) {
@@ -517,6 +563,28 @@ sched_setup(void *dummy)
}
/* External interfaces start here */
+/*
+ * Very early in the boot some setup of scheduler-specific
+ * parts of proc0 and of soem scheduler resources needs to be done.
+ * Called from:
+ * proc0_init()
+ */
+void
+schedinit(void)
+{
+ /*
+ * Set up the scheduler specific parts of proc0.
+ */
+ proc0.p_sched = NULL; /* XXX */
+ ksegrp0.kg_sched = &kg_sched0;
+ thread0.td_sched = &kse0;
+ kse0.ke_thread = &thread0;
+ kse0.ke_oncpu = NOCPU; /* wrong.. can we use PCPU(cpuid) yet? */
+ kse0.ke_state = KES_THREAD;
+ kg_sched0.skg_concurrency = 1;
+ kg_sched0.skg_avail_opennings = 0; /* we are already running */
+}
+
int
sched_runnable(void)
{
@@ -579,17 +647,11 @@ sched_clock(struct thread *td)
void
sched_exit(struct proc *p, struct thread *td)
{
- sched_exit_kse(FIRST_KSE_IN_PROC(p), td);
sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), td);
sched_exit_thread(FIRST_THREAD_IN_PROC(p), td);
}
void
-sched_exit_kse(struct kse *ke, struct thread *child)
-{
-}
-
-void
sched_exit_ksegrp(struct ksegrp *kg, struct thread *childtd)
{
@@ -605,17 +667,10 @@ sched_exit_thread(struct thread *td, struct thread *child)
}
void
-sched_fork(struct thread *td, struct proc *p1)
-{
- sched_fork_kse(td, FIRST_KSE_IN_PROC(p1));
- sched_fork_ksegrp(td, FIRST_KSEGRP_IN_PROC(p1));
- sched_fork_thread(td, FIRST_THREAD_IN_PROC(p1));
-}
-
-void
-sched_fork_kse(struct thread *td, struct kse *child)
+sched_fork(struct thread *td, struct thread *childtd)
{
- child->ke_cpticks = 0;
+ sched_fork_ksegrp(td, childtd->td_ksegrp);
+ sched_fork_thread(td, childtd);
}
void
@@ -626,8 +681,9 @@ sched_fork_ksegrp(struct thread *td, struct ksegrp *child)
}
void
-sched_fork_thread(struct thread *td, struct thread *child)
+sched_fork_thread(struct thread *td, struct thread *childtd)
{
+ sched_newthread(childtd);
}
void
@@ -687,14 +743,21 @@ sched_switch(struct thread *td, struct thread *newtd)
p = td->td_proc;
mtx_assert(&sched_lock, MA_OWNED);
- KASSERT((ke->ke_state == KES_THREAD), ("sched_switch: kse state?"));
if ((p->p_flag & P_NOLOAD) == 0)
sched_tdcnt--;
if (newtd != NULL && (newtd->td_proc->p_flag & P_NOLOAD) == 0)
sched_tdcnt++;
+ /*
+ * The thread we are about to run needs to be counted as if it had been
+ * added to the run queue and selected.
+ */
+ if (newtd) {
+ newtd->td_ksegrp->kg_avail_opennings--;
+ newtd->td_kse->ke_flags |= KEF_DIDRUN;
+ TD_SET_RUNNING(newtd);
+ }
td->td_lastcpu = td->td_oncpu;
- td->td_last_kse = ke;
td->td_flags &= ~TDF_NEEDRESCHED;
td->td_pflags &= ~TDP_OWEPREEMPT;
td->td_oncpu = NOCPU;
@@ -706,16 +769,19 @@ sched_switch(struct thread *td, struct thread *newtd)
*/
if (td == PCPU_GET(idlethread))
TD_SET_CAN_RUN(td);
- else if (TD_IS_RUNNING(td)) {
- /* Put us back on the run queue (kse and all). */
- setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING);
- } else if (p->p_flag & P_SA) {
- /*
- * We will not be on the run queue. So we must be
- * sleeping or similar. As it's available,
- * someone else can use the KSE if they need it.
- */
- kse_reassign(ke);
+ else {
+ td->td_ksegrp->kg_avail_opennings++;
+ if (TD_IS_RUNNING(td)) {
+ /* Put us back on the run queue (kse and all). */
+ setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING);
+ } 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.
+ */
+ slot_fill(td->td_ksegrp);
+ }
}
if (newtd == NULL)
newtd = choosethread();
@@ -750,7 +816,7 @@ forward_wakeup(int cpunum)
mtx_assert(&sched_lock, MA_OWNED);
- CTR0(KTR_SMP, "forward_wakeup()");
+ CTR0(KTR_RUNQ, "forward_wakeup()");
if ((!forward_wakeup_enabled) ||
(forward_wakeup_use_mask == 0 && forward_wakeup_use_loop == 0))
@@ -838,9 +904,6 @@ sched_add(struct thread *td, int flags)
ke = td->td_kse;
mtx_assert(&sched_lock, MA_OWNED);
- KASSERT((ke->ke_thread != NULL), ("sched_add: No thread on KSE"));
- KASSERT((ke->ke_thread->td_kse != NULL),
- ("sched_add: No KSE on thread"));
KASSERT(ke->ke_state != KES_ONRUNQ,
("sched_add: kse %p (%s) already in run queue", ke,
ke->ke_proc->p_comm));
@@ -974,10 +1037,6 @@ sched_choose(void)
ke->ke_state = KES_THREAD;
ke->ke_ksegrp->kg_runq_kses--;
- KASSERT((ke->ke_thread != NULL),
- ("sched_choose: No thread on KSE"));
- KASSERT((ke->ke_thread->td_kse != NULL),
- ("sched_choose: No KSE on thread"));
KASSERT(ke->ke_proc->p_sflag & PS_INMEM,
("sched_choose: process swapped out"));
}
@@ -1042,14 +1101,9 @@ sched_load(void)
}
int
-sched_sizeof_kse(void)
-{
- return (sizeof(struct kse) + sizeof(struct ke_sched));
-}
-int
sched_sizeof_ksegrp(void)
{
- return (sizeof(struct ksegrp));
+ return (sizeof(struct ksegrp) + sizeof(struct kg_sched));
}
int
sched_sizeof_proc(void)
@@ -1059,7 +1113,7 @@ sched_sizeof_proc(void)
int
sched_sizeof_thread(void)
{
- return (sizeof(struct thread));
+ return (sizeof(struct thread) + sizeof(struct kse));
}
fixpt_t
@@ -1068,10 +1122,9 @@ sched_pctcpu(struct thread *td)
struct kse *ke;
ke = td->td_kse;
- if (ke == NULL)
- ke = td->td_last_kse;
- if (ke)
- return (ke->ke_pctcpu);
+ return (ke->ke_pctcpu);
return (0);
}
+#define KERN_SWITCH_INCLUDE 1
+#include "kern/kern_switch.c"
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index e235c1f9b752..52349c518652 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$");
#include <opt_sched.h>
+#define kse td_sched
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kdb.h>
@@ -90,53 +92,82 @@ SYSINIT(preempt_warning, SI_SUB_COPYRIGHT, SI_ORDER_ANY, printf_caddr_t,
#endif
/*
+ * The schedulable entity that can be given a context to run.
+ * A process may have several of these. Probably one per processor
+ * but posibly a few more. In this universe they are grouped
+ * with a KSEG that contains the priority and niceness
+ * for the group.
+ */
+struct kse {
+ TAILQ_ENTRY(kse) ke_kglist; /* (*) Queue of threads in ke_ksegrp. */
+ TAILQ_ENTRY(kse) ke_kgrlist; /* (*) Queue of threads in this state.*/
+ 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_oncpu; /* (j) Which cpu we are on. */
+ char ke_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_pinned;
+ int ke_slice;
+ struct runq *ke_runq;
+ u_char ke_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 */
+
+};
+
+
+#define td_kse td_sched
+#define td_slptime td_kse->ke_slptime
+#define ke_proc ke_thread->td_proc
+#define ke_ksegrp ke_thread->td_ksegrp
+
+/* flags kept in ke_flags */
+#define KEF_SCHED0 0x00001 /* For scheduler-specific use. */
+#define KEF_SCHED1 0x00002 /* For scheduler-specific use. */
+#define KEF_SCHED2 0x00004 /* For scheduler-specific use. */
+#define KEF_SCHED3 0x00008 /* For scheduler-specific use. */
+#define KEF_DIDRUN 0x02000 /* Thread actually ran. */
+#define KEF_EXIT 0x04000 /* Thread is being killed. */
+
+/*
* These datastructures are allocated within their parent datastructure but
* are scheduler specific.
*/
-struct ke_sched {
- int ske_slice;
- struct runq *ske_runq;
- /* The following variables are only used for pctcpu calculation */
- int ske_ltick; /* Last tick that we were running on */
- int ske_ftick; /* First tick that we were running on */
- int ske_ticks; /* Tick count */
- /* CPU that we have affinity for. */
- u_char ske_cpu;
-};
-#define ke_slice ke_sched->ske_slice
-#define ke_runq ke_sched->ske_runq
-#define ke_ltick ke_sched->ske_ltick
-#define ke_ftick ke_sched->ske_ftick
-#define ke_ticks ke_sched->ske_ticks
-#define ke_cpu ke_sched->ske_cpu
#define ke_assign ke_procq.tqe_next
-#define KEF_ASSIGNED KEF_SCHED0 /* KSE is being migrated. */
-#define KEF_BOUND KEF_SCHED1 /* KSE can not migrate. */
-#define KEF_XFERABLE KEF_SCHED2 /* KSE was added as transferable. */
-#define KEF_HOLD KEF_SCHED3 /* KSE is temporarily bound. */
+#define KEF_ASSIGNED KEF_SCHED0 /* Thread is being migrated. */
+#define KEF_BOUND KEF_SCHED1 /* Thread can not migrate. */
+#define KEF_XFERABLE KEF_SCHED2 /* Thread was added as transferable. */
+#define KEF_HOLD KEF_SCHED3 /* Thread is temporarily bound. */
struct kg_sched {
+ struct thread *skg_last_assigned; /* (j) Last thread assigned to */
+ /* the system scheduler */
int skg_slptime; /* Number of ticks we vol. slept */
int skg_runtime; /* Number of ticks we were running */
+ int skg_avail_opennings; /* (j) Num unfilled slots in group.*/
+ int skg_concurrency; /* (j) Num threads requested in group.*/
+ int skg_runq_threads; /* (j) Num KSEs on runq. */
};
-#define kg_slptime kg_sched->skg_slptime
-#define kg_runtime kg_sched->skg_runtime
-
-struct td_sched {
- int std_slptime;
-};
-#define td_slptime td_sched->std_slptime
+#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 kg_runq_threads kg_sched->skg_runq_threads
+#define kg_runtime kg_sched->skg_runtime
+#define kg_slptime kg_sched->skg_slptime
-struct td_sched td_sched;
-struct ke_sched ke_sched;
-struct kg_sched kg_sched;
-struct ke_sched *kse0_sched = &ke_sched;
-struct kg_sched *ksegrp0_sched = &kg_sched;
-struct p_sched *proc0_sched = NULL;
-struct td_sched *thread0_sched = &td_sched;
+static struct kse kse0;
+static struct kg_sched kg_sched0;
/*
* The priority is primarily determined by the interactivity score. Thus, we
@@ -191,7 +222,7 @@ struct td_sched *thread0_sched = &td_sched;
(SCHED_SLICE_MAX - SCHED_SLICE_SCALE((nice), SCHED_SLICE_NTHRESH))
/*
- * This macro determines whether or not the kse belongs on the current or
+ * This macro determines whether or not the thread belongs on the current or
* next run queue.
*/
#define SCHED_INTERACTIVE(kg) \
@@ -274,6 +305,8 @@ static struct kseq kseq_cpu;
#define KSEQ_CPU(x) (&kseq_cpu)
#endif
+static void slot_fill(struct ksegrp *kg);
+static struct kse *sched_choose(void); /* XXX Should be thread * */
static void sched_add_internal(struct thread *td, int preemptive);
static void sched_slice(struct kse *ke);
static void sched_priority(struct ksegrp *kg);
@@ -1106,6 +1139,28 @@ sched_interact_score(struct ksegrp *kg)
}
/*
+ * Very early in the boot some setup of scheduler-specific
+ * parts of proc0 and of soem scheduler resources needs to be done.
+ * Called from:
+ * proc0_init()
+ */
+void
+schedinit(void)
+{
+ /*
+ * Set up the scheduler specific parts of proc0.
+ */
+ ksegrp0.kg_sched = &kg_sched0;
+ proc0.p_sched = NULL; /* XXX */
+ thread0.td_kse = &kse0;
+ kse0.ke_thread = &thread0;
+ kse0.ke_oncpu = NOCPU; /* wrong.. can we use PCPU(cpuid) yet? */
+ kse0.ke_state = KES_THREAD;
+ kg_sched0.skg_concurrency = 1;
+ kg_sched0.skg_avail_opennings = 0; /* we are already running */
+}
+
+/*
* This is only somewhat accurate since given many processes of the same
* priority they will switch when their slices run out, which will be
* at most SCHED_SLICE_MAX.
@@ -1178,37 +1233,50 @@ sched_switch(struct thread *td, struct thread *newtd)
ke = td->td_kse;
- td->td_last_kse = ke;
td->td_lastcpu = td->td_oncpu;
td->td_oncpu = NOCPU;
td->td_flags &= ~TDF_NEEDRESCHED;
td->td_pflags &= ~TDP_OWEPREEMPT;
/*
+ * If we bring in a thread,
+ * then account for it as if it had been added to the run queue and then chosen.
+ */
+ if (newtd) {
+ newtd->td_ksegrp->kg_avail_opennings--;
+ newtd->td_kse->ke_flags |= KEF_DIDRUN;
+ TD_SET_RUNNING(newtd);
+ }
+ /*
* If the KSE has been assigned it may be in the process of switching
* to the new cpu. This is the case in sched_bind().
*/
if ((ke->ke_flags & KEF_ASSIGNED) == 0) {
if (td == PCPU_GET(idlethread)) {
TD_SET_CAN_RUN(td);
- } else if (TD_IS_RUNNING(td)) {
- kseq_load_rem(KSEQ_CPU(ke->ke_cpu), ke);
- /*
- * Don't allow the kse to migrate from a preemption.
- */
- ke->ke_flags |= KEF_HOLD;
- setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING);
} else {
- if (ke->ke_runq) {
+ /* We are ending our run so make our slot available again */
+ td->td_ksegrp->kg_avail_opennings++;
+ if (TD_IS_RUNNING(td)) {
kseq_load_rem(KSEQ_CPU(ke->ke_cpu), ke);
- } else if ((td->td_flags & TDF_IDLETD) == 0)
- kdb_backtrace();
- /*
- * We will not be on the run queue. So we must be
- * sleeping or similar.
- */
- if (td->td_proc->p_flag & P_SA)
- kse_reassign(ke);
+ /*
+ * Don't allow the thread to migrate
+ * from a preemption.
+ */
+ ke->ke_flags |= KEF_HOLD;
+ setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING);
+ } else {
+ if (ke->ke_runq) {
+ kseq_load_rem(KSEQ_CPU(ke->ke_cpu), ke);
+ } else if ((td->td_flags & TDF_IDLETD) == 0)
+ kdb_backtrace();
+ /*
+ * We will not be on the run queue.
+ * So we must be sleeping or similar.
+ */
+ if (td->td_proc->p_flag & P_HADTHREADS)
+ slot_fill(td->td_ksegrp);
+ }
}
}
if (newtd != NULL)
@@ -1237,7 +1305,8 @@ sched_nice(struct proc *p, int nice)
*/
FOREACH_KSEGRP_IN_PROC(p, kg) {
if (kg->kg_pri_class == PRI_TIMESHARE) {
- FOREACH_KSE_IN_GROUP(kg, ke) {
+ FOREACH_THREAD_IN_GROUP(kg, td) {
+ ke = td->td_kse;
if (ke->ke_runq == NULL)
continue;
kseq = KSEQ_CPU(ke->ke_cpu);
@@ -1262,8 +1331,8 @@ sched_sleep(struct thread *td)
td->td_slptime = ticks;
td->td_base_pri = td->td_priority;
- CTR2(KTR_ULE, "sleep kse %p (tick: %d)",
- td->td_kse, td->td_slptime);
+ CTR2(KTR_ULE, "sleep thread %p (tick: %d)",
+ td, td->td_slptime);
}
void
@@ -1289,10 +1358,8 @@ sched_wakeup(struct thread *td)
sched_interact_update(kg);
}
sched_priority(kg);
- if (td->td_kse)
- sched_slice(td->td_kse);
- CTR2(KTR_ULE, "wakeup kse %p (%d ticks)",
- td->td_kse, hzticks);
+ sched_slice(td->td_kse);
+ CTR2(KTR_ULE, "wakeup thread %p (%d ticks)", td, hzticks);
td->td_slptime = 0;
}
setrunqueue(td, SRQ_BORING);
@@ -1303,37 +1370,20 @@ sched_wakeup(struct thread *td)
* priority.
*/
void
-sched_fork(struct thread *td, struct proc *p1)
+sched_fork(struct thread *td, struct thread *childtd)
{
mtx_assert(&sched_lock, MA_OWNED);
- p1->p_nice = td->td_proc->p_nice;
- sched_fork_ksegrp(td, FIRST_KSEGRP_IN_PROC(p1));
- sched_fork_kse(td, FIRST_KSE_IN_PROC(p1));
- sched_fork_thread(td, FIRST_THREAD_IN_PROC(p1));
-}
-
-void
-sched_fork_kse(struct thread *td, struct kse *child)
-{
- struct kse *ke = td->td_kse;
-
- child->ke_slice = 1; /* Attempt to quickly learn interactivity. */
- child->ke_cpu = ke->ke_cpu;
- child->ke_runq = NULL;
-
- /* Grab our parents cpu estimation information. */
- child->ke_ticks = ke->ke_ticks;
- child->ke_ltick = ke->ke_ltick;
- child->ke_ftick = ke->ke_ftick;
+ sched_fork_ksegrp(td, childtd->td_ksegrp);
+ sched_fork_thread(td, childtd);
}
void
sched_fork_ksegrp(struct thread *td, struct ksegrp *child)
{
struct ksegrp *kg = td->td_ksegrp;
- PROC_LOCK_ASSERT(child->kg_proc, MA_OWNED);
+ mtx_assert(&sched_lock, MA_OWNED);
child->kg_slptime = kg->kg_slptime;
child->kg_runtime = kg->kg_runtime;
@@ -1350,6 +1400,20 @@ sched_fork_ksegrp(struct thread *td, struct ksegrp *child)
void
sched_fork_thread(struct thread *td, struct thread *child)
{
+ struct kse *ke;
+ struct kse *ke2;
+
+ 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;
+
+ /* Grab our parents cpu estimation information. */
+ ke2->ke_ticks = ke->ke_ticks;
+ ke2->ke_ltick = ke->ke_ltick;
+ ke2->ke_ftick = ke->ke_ftick;
}
void
@@ -1357,6 +1421,7 @@ sched_class(struct ksegrp *kg, int class)
{
struct kseq *kseq;
struct kse *ke;
+ struct thread *td;
int nclass;
int oclass;
@@ -1366,7 +1431,8 @@ sched_class(struct ksegrp *kg, int class)
nclass = PRI_BASE(class);
oclass = PRI_BASE(kg->kg_pri_class);
- FOREACH_KSE_IN_GROUP(kg, ke) {
+ FOREACH_THREAD_IN_GROUP(kg, td) {
+ ke = td->td_kse;
if (ke->ke_state != KES_ONRUNQ &&
ke->ke_state != KES_THREAD)
continue;
@@ -1404,19 +1470,15 @@ sched_class(struct ksegrp *kg, int class)
/*
* Return some of the child's priority and interactivity to the parent.
+ * Avoid using sched_exit_thread to avoid having to decide which
+ * thread in the parent gets the honour since it isn't used.
*/
void
-sched_exit(struct proc *p, struct thread *td)
+sched_exit(struct proc *p, struct thread *childtd)
{
mtx_assert(&sched_lock, MA_OWNED);
- sched_exit_kse(FIRST_KSE_IN_PROC(p), td);
- sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), td);
-}
-
-void
-sched_exit_kse(struct kse *ke, struct thread *td)
-{
- kseq_load_rem(KSEQ_CPU(td->td_kse->ke_cpu), td->td_kse);
+ sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), childtd);
+ kseq_load_rem(KSEQ_CPU(childtd->td_kse->ke_cpu), childtd->td_kse);
}
void
@@ -1428,8 +1490,9 @@ sched_exit_ksegrp(struct ksegrp *kg, struct thread *td)
}
void
-sched_exit_thread(struct thread *td, struct thread *child)
+sched_exit_thread(struct thread *td, struct thread *childtd)
{
+ kseq_load_rem(KSEQ_CPU(childtd->td_kse->ke_cpu), childtd->td_kse);
}
void
@@ -1483,8 +1546,8 @@ sched_clock(struct thread *td)
if (td->td_flags & TDF_IDLETD)
return;
- CTR4(KTR_ULE, "Tick kse %p (slice: %d, slptime: %d, runtime: %d)",
- ke, ke->ke_slice, kg->kg_slptime >> 10, kg->kg_runtime >> 10);
+ CTR4(KTR_ULE, "Tick thread %p (slice: %d, slptime: %d, runtime: %d)",
+ td, ke->ke_slice, kg->kg_slptime >> 10, kg->kg_runtime >> 10);
/*
* We only do slicing code for TIMESHARE ksegrps.
*/
@@ -1581,8 +1644,8 @@ restart:
ke->ke_state = KES_THREAD;
if (ke->ke_ksegrp->kg_pri_class == PRI_TIMESHARE) {
- CTR4(KTR_ULE, "Run kse %p from %p (slice: %d, pri: %d)",
- ke, ke->ke_runq, ke->ke_slice,
+ CTR4(KTR_ULE, "Run thread %p from %p (slice: %d, pri: %d)",
+ ke->ke_thread, ke->ke_runq, ke->ke_slice,
ke->ke_thread->td_priority);
}
return (ke);
@@ -1627,10 +1690,6 @@ sched_add_internal(struct thread *td, int preemptive)
if (ke->ke_flags & KEF_ASSIGNED)
return;
kseq = KSEQ_SELF();
- KASSERT((ke->ke_thread != NULL),
- ("sched_add: No thread on KSE"));
- KASSERT((ke->ke_thread->td_kse != NULL),
- ("sched_add: No KSE on thread"));
KASSERT(ke->ke_state != KES_ONRUNQ,
("sched_add: kse %p (%s) already in run queue", ke,
ke->ke_proc->p_comm));
@@ -1715,7 +1774,7 @@ sched_add_internal(struct thread *td, int preemptive)
curthread->td_flags |= TDF_NEEDRESCHED;
if (preemptive && maybe_preempt(td))
return;
- ke->ke_ksegrp->kg_runq_kses++;
+ ke->ke_ksegrp->kg_runq_threads++;
ke->ke_state = KES_ONRUNQ;
kseq_runq_add(kseq, ke);
@@ -1742,7 +1801,7 @@ sched_rem(struct thread *td)
("sched_rem: KSE not on run queue"));
ke->ke_state = KES_THREAD;
- ke->ke_ksegrp->kg_runq_kses--;
+ ke->ke_ksegrp->kg_runq_threads--;
kseq = KSEQ_CPU(ke->ke_cpu);
kseq_runq_rem(kseq, ke);
kseq_load_rem(kseq, ke);
@@ -1795,7 +1854,7 @@ sched_bind(struct thread *td, int cpu)
return;
/* sched_rem without the runq_remove */
ke->ke_state = KES_THREAD;
- ke->ke_ksegrp->kg_runq_kses--;
+ ke->ke_ksegrp->kg_runq_threads--;
kseq_load_rem(KSEQ_CPU(ke->ke_cpu), ke);
kseq_notify(ke, cpu);
/* When we return from mi_switch we'll be on the correct cpu. */
@@ -1827,12 +1886,6 @@ sched_load(void)
}
int
-sched_sizeof_kse(void)
-{
- return (sizeof(struct kse) + sizeof(struct ke_sched));
-}
-
-int
sched_sizeof_ksegrp(void)
{
return (sizeof(struct ksegrp) + sizeof(struct kg_sched));
@@ -1849,3 +1902,5 @@ sched_sizeof_thread(void)
{
return (sizeof(struct thread) + sizeof(struct td_sched));
}
+#define KERN_SWITCH_INCLUDE 1
+#include "kern/kern_switch.c"
diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c
index d73e44391190..20cbd716384e 100644
--- a/sys/pc98/i386/machdep.c
+++ b/sys/pc98/i386/machdep.c
@@ -2011,7 +2011,7 @@ init386(first)
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
#ifdef PC98
/*
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index d73e44391190..20cbd716384e 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -2011,7 +2011,7 @@ init386(first)
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
#ifdef PC98
/*
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 1a1e6617f44b..2f0d3c41ea0a 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -279,7 +279,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
/*
* Start initializing proc0 and thread0.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
proc0.p_uarea = (struct user *)uarea0;
proc0.p_stats = &proc0.p_uarea->u_stats;
thread0.td_frame = &frame0;
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
index 1a1e6617f44b..2f0d3c41ea0a 100644
--- a/sys/powerpc/powerpc/machdep.c
+++ b/sys/powerpc/powerpc/machdep.c
@@ -279,7 +279,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
/*
* Start initializing proc0 and thread0.
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
proc0.p_uarea = (struct user *)uarea0;
proc0.p_stats = &proc0.p_uarea->u_stats;
thread0.td_frame = &frame0;
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 2cfa3d15e70c..582930dfca1b 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -342,7 +342,7 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
/*
* Initialize proc0 stuff (p_contested needs to be done early).
*/
- proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
+ proc_linkup(&proc0, &ksegrp0, &thread0);
proc0.p_md.md_sigtramp = NULL;
proc0.p_md.md_utrap = NULL;
proc0.p_uarea = (struct user *)uarea0;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 893add0376a3..57e180c95a07 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -142,14 +142,13 @@ struct pargs {
* q - td_contested lock
* r - p_peers lock
* x - created at fork, only changes during single threading in exec
- * z - zombie threads/kse/ksegroup lock
+ * z - zombie threads/ksegroup lock
*
* If the locking key specifies two identifiers (for example, p_pptr) then
* either lock is sufficient for read access, but both locks must be held
* for write access.
*/
struct ithd;
-struct ke_sched;
struct kg_sched;
struct nlminfo;
struct p_sched;
@@ -159,7 +158,7 @@ struct trapframe;
struct turnstile;
/*
- * Here we define the four structures used for process information.
+ * Here we define the three structures used for process information.
*
* The first is the thread. It might be thought of as a "Kernel
* Schedulable Entity Context".
@@ -171,16 +170,16 @@ struct turnstile;
* load balancing. Each of these is associated with a kernel stack
* and a pcb.
*
- * It is important to remember that a particular thread structure only
- * exists as long as the system call or kernel entrance (e.g. by pagefault)
+ * It is important to remember that a particular thread structure may only
+ * exist as long as the system call or kernel entrance (e.g. by pagefault)
* which it is currently executing. It should therefore NEVER be referenced
* by pointers in long lived structures that live longer than a single
* request. If several threads complete their work at the same time,
* they will all rewind their stacks to the user boundary, report their
* completion state, and all but one will be freed. That last one will
* be kept to provide a kernel stack and pcb for the NEXT syscall or kernel
- * entrance. (basically to save freeing and then re-allocating it) The KSE
- * keeps a cached thread available to allow it to quickly
+ * entrance. (basically to save freeing and then re-allocating it) The existing
+ * thread keeps a cached spare thread available to allow it to quickly
* get one when it needs a new one. There is also a system
* cache of free threads. Threads have priority and partake in priority
* inheritance schemes.
@@ -188,23 +187,9 @@ struct turnstile;
struct thread;
/*
- * The second structure is the Kernel Schedulable Entity. (KSE)
- * It represents the ability to take a slot in the scheduler queue.
- * As long as this is scheduled, it could continue to run any threads that
- * are assigned to the KSEGRP (see later) until either it runs out
- * of runnable threads of high enough priority, or CPU.
- * It runs on one CPU and is assigned a quantum of time. When a thread is
- * blocked, The KSE continues to run and will search for another thread
- * in a runnable state amongst those it has. It May decide to return to user
- * mode with a new 'empty' thread if there are no runnable threads.
- * Threads are temporarily associated with a KSE for scheduling reasons.
- */
-struct kse;
-
-/*
* The KSEGRP is allocated resources across a number of CPUs.
* (Including a number of CPUxQUANTA. It parcels these QUANTA up among
- * its KSEs, each of which should be running in a different CPU.
+ * its threads, each of which should be running in a different CPU.
* BASE priority and total available quanta are properties of a KSEGRP.
* Multiple KSEGRPs in a single process compete against each other
* for total quanta in the same way that a forked child competes against
@@ -227,8 +212,8 @@ struct proc;
With a single run queue used by all processors:
RUNQ: --->KSE---KSE--... SLEEPQ:[]---THREAD---THREAD---THREAD
- | / []---THREAD
- KSEG---THREAD--THREAD--THREAD []
+ \ \ []---THREAD
+ KSEG---THREAD--THREAD--THREAD []
[]---THREAD---THREAD
(processors run THREADs from the KSEG until they are exhausted or
@@ -271,8 +256,6 @@ struct thread {
int td_flags; /* (j) TDF_* flags. */
int td_inhibitors; /* (j) Why can not run. */
int td_pflags; /* (k) Private thread (TDP_*) flags. */
- struct kse *td_last_kse; /* (j) Previous value of td_kse. */
- struct kse *td_kse; /* (j) Current KSE if any. */
int td_dupfd; /* (k) Ret value from fdopen. XXX */
void *td_wchan; /* (j) Sleep address. */
const char *td_wmesg; /* (j) Reason for sleep. */
@@ -368,10 +351,10 @@ struct thread {
#define TDF_DBSUSPEND 0x00200000 /* Thread is suspended by debugger */
#define TDF_UNUSED22 0x00400000 /* --available -- */
#define TDF_UNUSED23 0x00800000 /* --available -- */
-#define TDF_SCHED1 0x01000000 /* Reserved for scheduler private use */
-#define TDF_SCHED2 0x02000000 /* Reserved for scheduler private use */
-#define TDF_SCHED3 0x04000000 /* Reserved for scheduler private use */
-#define TDF_SCHED4 0x08000000 /* Reserved for scheduler private use */
+#define TDF_SCHED0 0x01000000 /* Reserved for scheduler private use */
+#define TDF_SCHED1 0x02000000 /* Reserved for scheduler private use */
+#define TDF_SCHED2 0x04000000 /* Reserved for scheduler private use */
+#define TDF_SCHED3 0x08000000 /* Reserved for scheduler private use */
/*
* "Private" flags kept in td_pflags:
@@ -455,45 +438,6 @@ struct thread {
#define TD_SET_CAN_RUN(td) (td)->td_state = TDS_CAN_RUN
/*
- * The schedulable entity that can be given a context to run.
- * A process may have several of these. Probably one per processor
- * but posibly a few more. In this universe they are grouped
- * with a KSEG that contains the priority and niceness
- * for the group.
- */
-struct kse {
- struct proc *ke_proc; /* (*) Associated process. */
- struct ksegrp *ke_ksegrp; /* (*) Associated KSEG. */
- TAILQ_ENTRY(kse) ke_kglist; /* (*) Queue of KSEs in ke_ksegrp. */
- TAILQ_ENTRY(kse) ke_kgrlist; /* (*) Queue of KSEs in this state. */
- TAILQ_ENTRY(kse) ke_procq; /* (j/z) Run queue. */
-
-#define ke_startzero ke_flags
- 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_oncpu; /* (j) Which cpu we are on. */
- char ke_rqindex; /* (j) Run queue index. */
- enum {
- KES_UNUSED = 0x0,
- KES_IDLE,
- KES_ONRUNQ,
- KES_UNQUEUED, /* in transit */
- KES_THREAD /* slaved to thread state */
- } ke_state; /* (j) KSE status. */
-#define ke_endzero ke_sched
- struct ke_sched *ke_sched; /* (*) Scheduler-specific data. */
-};
-
-/* flags kept in ke_flags */
-#define KEF_SCHED0 0x00001 /* For scheduler-specific use. */
-#define KEF_SCHED1 0x00002 /* For scheduler-specific use. */
-#define KEF_SCHED2 0X00004 /* For scheduler-specific use. */
-#define KEF_SCHED3 0x00008 /* For scheduler-specific use. */
-#define KEF_DIDRUN 0x02000 /* KSE actually ran. */
-#define KEF_EXIT 0x04000 /* KSE is being killed. */
-
-/*
* The upcall management structure.
* The upcall is used when returning to userland. If a thread does not have
* an upcall on return to userland the thread exports its context and exits.
@@ -520,8 +464,6 @@ struct kse_upcall {
struct ksegrp {
struct proc *kg_proc; /* (*) Process that contains this KSEG. */
TAILQ_ENTRY(ksegrp) kg_ksegrp; /* (*) Queue of KSEGs in kg_proc. */
- TAILQ_HEAD(, kse) kg_kseq; /* (ke_kglist) All KSEs. */
- TAILQ_HEAD(, kse) kg_iq; /* (ke_kgrlist) All idle KSEs. */
TAILQ_HEAD(, thread) kg_threads;/* (td_kglist) All threads. */
TAILQ_HEAD(, thread) kg_runq; /* (td_runq) waiting RUNNABLE threads */
TAILQ_HEAD(, thread) kg_slpq; /* (td_runq) NONRUNNABLE threads. */
@@ -529,10 +471,7 @@ struct ksegrp {
#define kg_startzero kg_estcpu
u_int kg_estcpu; /* (j) Sum of the same field in KSEs. */
u_int kg_slptime; /* (j) How long completely blocked. */
- struct thread *kg_last_assigned; /* (j) Last thread assigned to a KSE. */
int kg_runnable; /* (j) Num runnable threads on queue. */
- int kg_runq_kses; /* (j) Num KSEs on runq. */
- int kg_idle_kses; /* (j) Num KSEs on iq. */
int kg_numupcalls; /* (j) Num upcalls. */
int kg_upsleeps; /* (c) Num threads in kse_release(). */
struct kse_thr_mailbox *kg_completed; /* (c) Completed thread mboxes. */
@@ -545,14 +484,12 @@ struct ksegrp {
u_char kg_user_pri; /* (j) User pri from estcpu and nice. */
#define kg_endcopy kg_numthreads
int kg_numthreads; /* (j) Num threads in total. */
- int kg_kses; /* (j) Num KSEs in group. */
- int kg_concurrency; /* (j) Num KSEs requested in group. */
struct kg_sched *kg_sched; /* (*) Scheduler-specific data. */
};
/*
* The old fashionned process. May have multiple threads, KSEGRPs
- * and KSEs. Starts off with a single embedded KSEGRP, KSE and THREAD.
+ * and KSEs. Starts off with a single embedded KSEGRP and THREAD.
*/
struct proc {
LIST_ENTRY(proc) p_list; /* (d) List of all processes. */
@@ -562,7 +499,7 @@ struct proc {
struct ucred *p_ucred; /* (c) Process owner's identity. */
struct filedesc *p_fd; /* (b) Ptr to open files structure. */
struct filedesc_to_leader *p_fdtol; /* (b) Ptr to tracking node */
- /* Accumulated stats for all KSEs? */
+ /* Accumulated stats for all threads? */
struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */
struct plimit *p_limit; /* (c) Process limits. */
struct vm_object *p_upages_obj; /* (a) Upages object. */
@@ -575,7 +512,7 @@ struct proc {
int p_sflag; /* (j) PS_* flags. */
enum {
PRS_NEW = 0, /* In creation */
- PRS_NORMAL, /* KSEs can be run. */
+ PRS_NORMAL, /* threads can be run. */
PRS_ZOMBIE
} p_state; /* (j/c) S* process status. */
pid_t p_pid; /* (b) Process identifier. */
@@ -742,8 +679,6 @@ MALLOC_DECLARE(M_ZOMBIE);
TAILQ_FOREACH((kg), &(p)->p_ksegrps, kg_ksegrp)
#define FOREACH_THREAD_IN_GROUP(kg, td) \
TAILQ_FOREACH((td), &(kg)->kg_threads, td_kglist)
-#define FOREACH_KSE_IN_GROUP(kg, ke) \
- TAILQ_FOREACH((ke), &(kg)->kg_kseq, ke_kglist)
#define FOREACH_UPCALL_IN_GROUP(kg, ku) \
TAILQ_FOREACH((ku), &(kg)->kg_upcalls, ku_link)
#define FOREACH_THREAD_IN_PROC(p, td) \
@@ -752,8 +687,6 @@ MALLOC_DECLARE(M_ZOMBIE);
/* XXXKSE the lines below should probably only be used in 1:1 code */
#define FIRST_THREAD_IN_PROC(p) TAILQ_FIRST(&(p)->p_threads)
#define FIRST_KSEGRP_IN_PROC(p) TAILQ_FIRST(&(p)->p_ksegrps)
-#define FIRST_KSE_IN_KSEGRP(kg) TAILQ_FIRST(&(kg)->kg_kseq)
-#define FIRST_KSE_IN_PROC(p) FIRST_KSE_IN_KSEGRP(FIRST_KSEGRP_IN_PROC(p))
/*
* We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t,
@@ -855,7 +788,6 @@ extern struct mtx ppeers_lock;
extern struct proc proc0; /* Process slot for swapper. */
extern struct thread thread0; /* Primary thread in proc0. */
extern struct ksegrp ksegrp0; /* Primary ksegrp in proc0. */
-extern struct kse kse0; /* Primary kse in proc0. */
extern struct vmspace vmspace0; /* VM space for proc0. */
extern int hogticks; /* Limit on kernel cpu hogs. */
extern int nprocs, maxproc; /* Current and max number of procs. */
@@ -905,8 +837,7 @@ void pargs_free(struct pargs *pa);
void pargs_hold(struct pargs *pa);
void procinit(void);
void threadinit(void);
-void proc_linkup(struct proc *p, struct ksegrp *kg,
- struct kse *ke, struct thread *td);
+void proc_linkup(struct proc *p, struct ksegrp *kg, struct thread *td);
void proc_reparent(struct proc *child, struct proc *newparent);
int securelevel_ge(struct ucred *cr, int level);
int securelevel_gt(struct ucred *cr, int level);
@@ -932,9 +863,8 @@ void cpu_set_fork_handler(struct thread *, void (*)(void *), void *);
struct ksegrp *ksegrp_alloc(void);
void ksegrp_free(struct ksegrp *kg);
void ksegrp_stash(struct ksegrp *kg);
-struct kse *kse_alloc(void);
-void kse_free(struct kse *ke);
-void kse_stash(struct kse *ke);
+void kse_GC(void);
+void kseinit(void);
void cpu_set_upcall(struct thread *td, struct thread *td0);
void cpu_set_upcall_kse(struct thread *td, struct kse_upcall *ku);
void cpu_thread_clean(struct thread *);
@@ -943,9 +873,6 @@ void cpu_thread_setup(struct thread *td);
void cpu_thread_siginfo(int sig, u_long code, siginfo_t *si);
void cpu_thread_swapin(struct thread *);
void cpu_thread_swapout(struct thread *);
-void kse_reassign(struct kse *ke);
-void kse_link(struct kse *ke, struct ksegrp *kg);
-void kse_unlink(struct kse *ke);
void ksegrp_link(struct ksegrp *kg, struct proc *p);
void ksegrp_unlink(struct ksegrp *kg);
void thread_signal_add(struct thread *td, int sig);
@@ -978,7 +905,8 @@ void upcall_remove(struct thread *td);
void upcall_stash(struct kse_upcall *ke);
void thread_sanity_check(struct thread *td, char *);
void thread_stopped(struct proc *p);
-void thread_switchout(struct thread *td);
+struct thread *thread_switchout(struct thread *td, int flags,
+ struct thread *newtd);
void thread_continued(struct proc *p);
void thr_exit1(void);
#endif /* _KERNEL */
diff --git a/sys/sys/sched.h b/sys/sys/sched.h
index ae453c7608c3..472af52cc47d 100644
--- a/sys/sys/sched.h
+++ b/sys/sys/sched.h
@@ -46,7 +46,7 @@ int sched_runnable(void);
* Proc related scheduling hooks.
*/
void sched_exit(struct proc *p, struct thread *childtd);
-void sched_fork(struct thread *td, struct proc *child);
+void sched_fork(struct thread *td, struct thread *childtd);
/*
* KSE Groups contain scheduling priority information. They record the
@@ -74,7 +74,6 @@ void sched_wakeup(struct thread *td);
* Threads are moved on and off of run queues
*/
void sched_add(struct thread *td, int flags);
-struct kse *sched_choose(void); /* XXX Should be thread * */
void sched_clock(struct thread *td);
void sched_rem(struct thread *td);
@@ -87,26 +86,15 @@ static __inline void sched_pin(void);
void sched_unbind(struct thread *td);
static __inline void sched_unpin(void);
-/*
- * These interfaces will eventually be removed.
- */
-void sched_exit_kse(struct kse *ke, struct thread *childtd);
-void sched_fork_kse(struct thread *td, struct kse *child);
/*
* These procedures tell the process data structure allocation code how
* many bytes to actually allocate.
*/
-int sched_sizeof_kse(void);
int sched_sizeof_ksegrp(void);
int sched_sizeof_proc(void);
int sched_sizeof_thread(void);
-extern struct ke_sched *kse0_sched;
-extern struct kg_sched *ksegrp0_sched;
-extern struct p_sched *proc0_sched;
-extern struct td_sched *thread0_sched;
-
static __inline void
sched_pin(void)
{
@@ -119,4 +107,13 @@ sched_unpin(void)
curthread->td_pinned--;
}
+/* temporarily here */
+void schedinit(void);
+void sched_destroyproc(struct proc *p);
+void sched_init_concurrency(struct ksegrp *kg);
+void sched_set_concurrency(struct ksegrp *kg, int cuncurrency);
+void sched_schedinit(void);
+void sched_newproc(struct proc *p, struct ksegrp *kg, struct thread *td);
+void sched_thread_exit(struct thread *td);
+void sched_newthread(struct thread *td);
#endif /* !_SYS_SCHED_H_ */