xref: /freebsd/sys/kern/kern_thread.c (revision 696058c3c557ad790e659e93aedf0f69ba41a1ff)
144990b8cSJulian Elischer /*
244990b8cSJulian Elischer  * Copyright (C) 2001 Julian Elischer <julian@freebsd.org>.
344990b8cSJulian Elischer  *  All rights reserved.
444990b8cSJulian Elischer  *
544990b8cSJulian Elischer  * Redistribution and use in source and binary forms, with or without
644990b8cSJulian Elischer  * modification, are permitted provided that the following conditions
744990b8cSJulian Elischer  * are met:
844990b8cSJulian Elischer  * 1. Redistributions of source code must retain the above copyright
944990b8cSJulian Elischer  *    notice(s), this list of conditions and the following disclaimer as
1044990b8cSJulian Elischer  *    the first lines of this file unmodified other than the possible
1144990b8cSJulian Elischer  *    addition of one or more copyright notices.
1244990b8cSJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
1344990b8cSJulian Elischer  *    notice(s), this list of conditions and the following disclaimer in the
1444990b8cSJulian Elischer  *    documentation and/or other materials provided with the distribution.
1544990b8cSJulian Elischer  *
1644990b8cSJulian Elischer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
1744990b8cSJulian Elischer  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1844990b8cSJulian Elischer  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1944990b8cSJulian Elischer  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2044990b8cSJulian Elischer  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2144990b8cSJulian Elischer  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2244990b8cSJulian Elischer  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2344990b8cSJulian Elischer  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2444990b8cSJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2544990b8cSJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2644990b8cSJulian Elischer  * DAMAGE.
2744990b8cSJulian Elischer  *
2844990b8cSJulian Elischer  * $FreeBSD$
2944990b8cSJulian Elischer  */
3044990b8cSJulian Elischer 
3144990b8cSJulian Elischer #include <sys/param.h>
3244990b8cSJulian Elischer #include <sys/systm.h>
3344990b8cSJulian Elischer #include <sys/kernel.h>
3444990b8cSJulian Elischer #include <sys/lock.h>
3544990b8cSJulian Elischer #include <sys/malloc.h>
3644990b8cSJulian Elischer #include <sys/mutex.h>
3744990b8cSJulian Elischer #include <sys/proc.h>
38904f1b77SJulian Elischer #include <sys/smp.h>
3944990b8cSJulian Elischer #include <sys/sysctl.h>
405c8329edSJulian Elischer #include <sys/sysproto.h>
4144990b8cSJulian Elischer #include <sys/filedesc.h>
42de028f5aSJeff Roberson #include <sys/sched.h>
4344990b8cSJulian Elischer #include <sys/signalvar.h>
4444990b8cSJulian Elischer #include <sys/sx.h>
45de028f5aSJeff Roberson #include <sys/tty.h>
4644990b8cSJulian Elischer #include <sys/user.h>
4744990b8cSJulian Elischer #include <sys/jail.h>
4844990b8cSJulian Elischer #include <sys/kse.h>
4944990b8cSJulian Elischer #include <sys/ktr.h>
50c76e33b6SJonathan Mini #include <sys/ucontext.h>
5144990b8cSJulian Elischer 
5244990b8cSJulian Elischer #include <vm/vm.h>
5344990b8cSJulian Elischer #include <vm/vm_object.h>
5444990b8cSJulian Elischer #include <vm/pmap.h>
5544990b8cSJulian Elischer #include <vm/uma.h>
5644990b8cSJulian Elischer #include <vm/vm_map.h>
5744990b8cSJulian Elischer 
5802fb42b0SPeter Wemm #include <machine/frame.h>
5902fb42b0SPeter Wemm 
6044990b8cSJulian Elischer /*
614f0db5e0SJulian Elischer  * KSEGRP related storage.
6244990b8cSJulian Elischer  */
634f0db5e0SJulian Elischer static uma_zone_t ksegrp_zone;
644f0db5e0SJulian Elischer static uma_zone_t kse_zone;
6544990b8cSJulian Elischer static uma_zone_t thread_zone;
6644990b8cSJulian Elischer 
674f0db5e0SJulian Elischer /* DEBUG ONLY */
6844990b8cSJulian Elischer SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0, "thread allocation");
69696058c3SJulian Elischer static int thread_debug = 0;
70696058c3SJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, debug, CTLFLAG_RW,
71696058c3SJulian Elischer 	&thread_debug, 0, "thread debug");
72fdc5ecd2SDavid Xu 
73fdc5ecd2SDavid Xu static int max_threads_per_proc = 30;
74fdc5ecd2SDavid Xu SYSCTL_INT(_kern_threads, OID_AUTO, max_threads_per_proc, CTLFLAG_RW,
754f0db5e0SJulian Elischer 	&max_threads_per_proc, 0, "Limit on threads per proc");
764f0db5e0SJulian Elischer 
77fdc5ecd2SDavid Xu static int max_groups_per_proc = 5;
78fdc5ecd2SDavid Xu SYSCTL_INT(_kern_threads, OID_AUTO, max_groups_per_proc, CTLFLAG_RW,
79fdc5ecd2SDavid Xu 	&max_groups_per_proc, 0, "Limit on thread groups per proc");
80fdc5ecd2SDavid Xu 
8144990b8cSJulian Elischer #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
8244990b8cSJulian Elischer 
8344990b8cSJulian Elischer struct threadqueue zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads);
845c8329edSJulian Elischer TAILQ_HEAD(, kse) zombie_kses = TAILQ_HEAD_INITIALIZER(zombie_kses);
855c8329edSJulian Elischer TAILQ_HEAD(, ksegrp) zombie_ksegrps = TAILQ_HEAD_INITIALIZER(zombie_ksegrps);
8644990b8cSJulian Elischer struct mtx zombie_thread_lock;
8744990b8cSJulian Elischer MTX_SYSINIT(zombie_thread_lock, &zombie_thread_lock,
8844990b8cSJulian Elischer     "zombie_thread_lock", MTX_SPIN);
8944990b8cSJulian Elischer 
90696058c3SJulian Elischer static void kse_purge(struct proc *p, struct thread *td);
915c8329edSJulian Elischer 
9244990b8cSJulian Elischer /*
93696058c3SJulian Elischer  * Prepare a thread for use.
9444990b8cSJulian Elischer  */
9544990b8cSJulian Elischer static void
9644990b8cSJulian Elischer thread_ctor(void *mem, int size, void *arg)
9744990b8cSJulian Elischer {
9844990b8cSJulian Elischer 	struct thread	*td;
9944990b8cSJulian Elischer 
10044990b8cSJulian Elischer 	td = (struct thread *)mem;
10171fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
10244990b8cSJulian Elischer 	td->td_flags |= TDF_UNBOUND;
10344990b8cSJulian Elischer }
10444990b8cSJulian Elischer 
10544990b8cSJulian Elischer /*
10644990b8cSJulian Elischer  * Reclaim a thread after use.
10744990b8cSJulian Elischer  */
10844990b8cSJulian Elischer static void
10944990b8cSJulian Elischer thread_dtor(void *mem, int size, void *arg)
11044990b8cSJulian Elischer {
11144990b8cSJulian Elischer 	struct thread	*td;
11244990b8cSJulian Elischer 
11344990b8cSJulian Elischer 	td = (struct thread *)mem;
11444990b8cSJulian Elischer 
11544990b8cSJulian Elischer #ifdef INVARIANTS
11644990b8cSJulian Elischer 	/* Verify that this thread is in a safe state to free. */
11744990b8cSJulian Elischer 	switch (td->td_state) {
11871fad9fdSJulian Elischer 	case TDS_INHIBITED:
11971fad9fdSJulian Elischer 	case TDS_RUNNING:
12071fad9fdSJulian Elischer 	case TDS_CAN_RUN:
12144990b8cSJulian Elischer 	case TDS_RUNQ:
12244990b8cSJulian Elischer 		/*
12344990b8cSJulian Elischer 		 * We must never unlink a thread that is in one of
12444990b8cSJulian Elischer 		 * these states, because it is currently active.
12544990b8cSJulian Elischer 		 */
12644990b8cSJulian Elischer 		panic("bad state for thread unlinking");
12744990b8cSJulian Elischer 		/* NOTREACHED */
12871fad9fdSJulian Elischer 	case TDS_INACTIVE:
12944990b8cSJulian Elischer 		break;
13044990b8cSJulian Elischer 	default:
13144990b8cSJulian Elischer 		panic("bad thread state");
13244990b8cSJulian Elischer 		/* NOTREACHED */
13344990b8cSJulian Elischer 	}
13444990b8cSJulian Elischer #endif
13544990b8cSJulian Elischer }
13644990b8cSJulian Elischer 
13744990b8cSJulian Elischer /*
13844990b8cSJulian Elischer  * Initialize type-stable parts of a thread (when newly created).
13944990b8cSJulian Elischer  */
14044990b8cSJulian Elischer static void
14144990b8cSJulian Elischer thread_init(void *mem, int size)
14244990b8cSJulian Elischer {
14344990b8cSJulian Elischer 	struct thread	*td;
14444990b8cSJulian Elischer 
14544990b8cSJulian Elischer 	td = (struct thread *)mem;
146e6e24ff9SJulian Elischer 	mtx_lock(&Giant);
147316ec49aSScott Long 	pmap_new_thread(td, 0);
148e6e24ff9SJulian Elischer 	mtx_unlock(&Giant);
14944990b8cSJulian Elischer 	cpu_thread_setup(td);
150de028f5aSJeff Roberson 	td->td_sched = (struct td_sched *)&td[1];
15144990b8cSJulian Elischer }
15244990b8cSJulian Elischer 
15344990b8cSJulian Elischer /*
15444990b8cSJulian Elischer  * Tear down type-stable parts of a thread (just before being discarded).
15544990b8cSJulian Elischer  */
15644990b8cSJulian Elischer static void
15744990b8cSJulian Elischer thread_fini(void *mem, int size)
15844990b8cSJulian Elischer {
15944990b8cSJulian Elischer 	struct thread	*td;
16044990b8cSJulian Elischer 
16144990b8cSJulian Elischer 	td = (struct thread *)mem;
16244990b8cSJulian Elischer 	pmap_dispose_thread(td);
16344990b8cSJulian Elischer }
164de028f5aSJeff Roberson /*
165de028f5aSJeff Roberson  * Initialize type-stable parts of a kse (when newly created).
166de028f5aSJeff Roberson  */
167de028f5aSJeff Roberson static void
168de028f5aSJeff Roberson kse_init(void *mem, int size)
169de028f5aSJeff Roberson {
170de028f5aSJeff Roberson 	struct kse	*ke;
171de028f5aSJeff Roberson 
172de028f5aSJeff Roberson 	ke = (struct kse *)mem;
173de028f5aSJeff Roberson 	ke->ke_sched = (struct ke_sched *)&ke[1];
174de028f5aSJeff Roberson }
175de028f5aSJeff Roberson /*
176de028f5aSJeff Roberson  * Initialize type-stable parts of a ksegrp (when newly created).
177de028f5aSJeff Roberson  */
178de028f5aSJeff Roberson static void
179de028f5aSJeff Roberson ksegrp_init(void *mem, int size)
180de028f5aSJeff Roberson {
181de028f5aSJeff Roberson 	struct ksegrp	*kg;
182de028f5aSJeff Roberson 
183de028f5aSJeff Roberson 	kg = (struct ksegrp *)mem;
184de028f5aSJeff Roberson 	kg->kg_sched = (struct kg_sched *)&kg[1];
185de028f5aSJeff Roberson }
18644990b8cSJulian Elischer 
18744990b8cSJulian Elischer /*
1885c8329edSJulian Elischer  * KSE is linked onto the idle queue.
1895c8329edSJulian Elischer  */
1905c8329edSJulian Elischer void
1915c8329edSJulian Elischer kse_link(struct kse *ke, struct ksegrp *kg)
1925c8329edSJulian Elischer {
1935c8329edSJulian Elischer 	struct proc *p = kg->kg_proc;
1945c8329edSJulian Elischer 
1955c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_kseq, ke, ke_kglist);
1965c8329edSJulian Elischer 	kg->kg_kses++;
1975c8329edSJulian Elischer 	ke->ke_state = KES_UNQUEUED;
1985c8329edSJulian Elischer 	ke->ke_proc	= p;
1995c8329edSJulian Elischer 	ke->ke_ksegrp	= kg;
2005c8329edSJulian Elischer 	ke->ke_thread	= NULL;
2015c8329edSJulian Elischer 	ke->ke_oncpu = NOCPU;
2025c8329edSJulian Elischer }
2035c8329edSJulian Elischer 
2045c8329edSJulian Elischer void
2055c8329edSJulian Elischer kse_unlink(struct kse *ke)
2065c8329edSJulian Elischer {
2075c8329edSJulian Elischer 	struct ksegrp *kg;
2085c8329edSJulian Elischer 
2095c8329edSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
2105c8329edSJulian Elischer 	kg = ke->ke_ksegrp;
2115c8329edSJulian Elischer 	if (ke->ke_state == KES_IDLE) {
2125c8329edSJulian Elischer 		kg->kg_idle_kses--;
2135c8329edSJulian Elischer 		TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
2145c8329edSJulian Elischer 	}
2155c8329edSJulian Elischer 
2165c8329edSJulian Elischer 	TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
2175c8329edSJulian Elischer 	if (--kg->kg_kses == 0) {
2185c8329edSJulian Elischer 			ksegrp_unlink(kg);
2195c8329edSJulian Elischer 	}
2205c8329edSJulian Elischer 	/*
2215c8329edSJulian Elischer 	 * Aggregate stats from the KSE
2225c8329edSJulian Elischer 	 */
2235c8329edSJulian Elischer 	kse_stash(ke);
2245c8329edSJulian Elischer }
2255c8329edSJulian Elischer 
2265c8329edSJulian Elischer void
2275c8329edSJulian Elischer ksegrp_link(struct ksegrp *kg, struct proc *p)
2285c8329edSJulian Elischer {
2295c8329edSJulian Elischer 
2305c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_threads);
2315c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_runq);	/* links with td_runq */
2325c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_slpq);	/* links with td_runq */
2335c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_kseq);	/* all kses in ksegrp */
2345c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_iq);		/* idle kses in ksegrp */
2355c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_lq);		/* loan kses in ksegrp */
2365c8329edSJulian Elischer 	kg->kg_proc	= p;
2375c8329edSJulian Elischer /* the following counters are in the -zero- section and may not need clearing */
2385c8329edSJulian Elischer 	kg->kg_numthreads = 0;
2395c8329edSJulian Elischer 	kg->kg_runnable = 0;
2405c8329edSJulian Elischer 	kg->kg_kses = 0;
2415c8329edSJulian Elischer 	kg->kg_idle_kses = 0;
2425c8329edSJulian Elischer 	kg->kg_loan_kses = 0;
2435c8329edSJulian Elischer 	kg->kg_runq_kses = 0; /* XXXKSE change name */
2445c8329edSJulian Elischer /* link it in now that it's consistent */
2455c8329edSJulian Elischer 	p->p_numksegrps++;
2465c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_ksegrps, kg, kg_ksegrp);
2475c8329edSJulian Elischer }
2485c8329edSJulian Elischer 
2495c8329edSJulian Elischer void
2505c8329edSJulian Elischer ksegrp_unlink(struct ksegrp *kg)
2515c8329edSJulian Elischer {
2525c8329edSJulian Elischer 	struct proc *p;
2535c8329edSJulian Elischer 
2545c8329edSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
2555c8329edSJulian Elischer 	p = kg->kg_proc;
2565c8329edSJulian Elischer 	KASSERT(((kg->kg_numthreads == 0) && (kg->kg_kses == 0)),
2575c8329edSJulian Elischer 	    ("kseg_unlink: residual threads or KSEs"));
2585c8329edSJulian Elischer 	TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp);
2595c8329edSJulian Elischer 	p->p_numksegrps--;
2605c8329edSJulian Elischer 	/*
2615c8329edSJulian Elischer 	 * Aggregate stats from the KSE
2625c8329edSJulian Elischer 	 */
2635c8329edSJulian Elischer 	ksegrp_stash(kg);
2645c8329edSJulian Elischer }
2655c8329edSJulian Elischer 
2665c8329edSJulian Elischer /*
2675c8329edSJulian Elischer  * for a newly created process,
2685c8329edSJulian Elischer  * link up a the structure and its initial threads etc.
2695c8329edSJulian Elischer  */
2705c8329edSJulian Elischer void
2715c8329edSJulian Elischer proc_linkup(struct proc *p, struct ksegrp *kg,
2725c8329edSJulian Elischer 			struct kse *ke, struct thread *td)
2735c8329edSJulian Elischer {
2745c8329edSJulian Elischer 
2755c8329edSJulian Elischer 	TAILQ_INIT(&p->p_ksegrps);	     /* all ksegrps in proc */
2765c8329edSJulian Elischer 	TAILQ_INIT(&p->p_threads);	     /* all threads in proc */
2775c8329edSJulian Elischer 	TAILQ_INIT(&p->p_suspended);	     /* Threads suspended */
2785c8329edSJulian Elischer 	p->p_numksegrps = 0;
2795c8329edSJulian Elischer 	p->p_numthreads = 0;
2805c8329edSJulian Elischer 
2815c8329edSJulian Elischer 	ksegrp_link(kg, p);
2825c8329edSJulian Elischer 	kse_link(ke, kg);
2835c8329edSJulian Elischer 	thread_link(td, kg);
2845c8329edSJulian Elischer }
2855c8329edSJulian Elischer 
2865c8329edSJulian Elischer int
2875c8329edSJulian Elischer kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
2885c8329edSJulian Elischer {
28934e80e02SDavid Xu 	struct proc *p;
29034e80e02SDavid Xu 	struct thread *td2;
2915c8329edSJulian Elischer 
292adac9400SDavid Xu 	p = td->td_proc;
293adac9400SDavid Xu 	/* KSE-enabled processes only, please. */
294adac9400SDavid Xu 	if (!(p->p_flag & P_KSES))
295adac9400SDavid Xu 		return (EINVAL);
2968db2431fSDavid Xu 	if (uap->tmbx == NULL)
2978db2431fSDavid Xu 		return (EINVAL);
29834e80e02SDavid Xu 	mtx_lock_spin(&sched_lock);
29934e80e02SDavid Xu 	FOREACH_THREAD_IN_PROC(p, td2) {
30034e80e02SDavid Xu 		if (td2->td_mailbox == uap->tmbx) {
30134e80e02SDavid Xu 			td2->td_flags |= TDF_INTERRUPT;
30234e80e02SDavid Xu 			if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) {
30334e80e02SDavid Xu 				if (td2->td_flags & TDF_CVWAITQ)
30434e80e02SDavid Xu 					cv_abort(td2);
30534e80e02SDavid Xu 				else
30634e80e02SDavid Xu 					abortsleep(td2);
30734e80e02SDavid Xu 			}
30834e80e02SDavid Xu 			mtx_unlock_spin(&sched_lock);
30937fcb8bcSDavid Xu 			td->td_retval[0] = 0;
31037fcb8bcSDavid Xu 			td->td_retval[1] = 0;
3117b290dd0SDavid Xu 			return (0);
31234e80e02SDavid Xu 		}
31334e80e02SDavid Xu 	}
31434e80e02SDavid Xu 	mtx_unlock_spin(&sched_lock);
31534e80e02SDavid Xu 	return (ESRCH);
3165c8329edSJulian Elischer }
3175c8329edSJulian Elischer 
3185c8329edSJulian Elischer int
3195c8329edSJulian Elischer kse_exit(struct thread *td, struct kse_exit_args *uap)
3205c8329edSJulian Elischer {
3215c8329edSJulian Elischer 	struct proc *p;
3225c8329edSJulian Elischer 	struct ksegrp *kg;
3235c8329edSJulian Elischer 
3245c8329edSJulian Elischer 	p = td->td_proc;
3255c8329edSJulian Elischer 	/* KSE-enabled processes only, please. */
3265c8329edSJulian Elischer 	if (!(p->p_flag & P_KSES))
3277b290dd0SDavid Xu 		return (EINVAL);
3285c8329edSJulian Elischer 	/* must be a bound thread */
3295c8329edSJulian Elischer 	if (td->td_flags & TDF_UNBOUND)
3307b290dd0SDavid Xu 		return (EINVAL);
3315c8329edSJulian Elischer 	kg = td->td_ksegrp;
3325c8329edSJulian Elischer 	/* serialize killing kse */
3335c8329edSJulian Elischer 	PROC_LOCK(p);
3345c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
3355c8329edSJulian Elischer 	if ((kg->kg_kses == 1) && (kg->kg_numthreads > 1)) {
3365c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
3375c8329edSJulian Elischer 		PROC_UNLOCK(p);
3385c8329edSJulian Elischer 		return (EDEADLK);
3395c8329edSJulian Elischer 	}
3405c8329edSJulian Elischer 	if ((p->p_numthreads == 1) && (p->p_numksegrps == 1)) {
341696058c3SJulian Elischer 		/* XXXSKE what if >1 KSE? check.... */
3425c8329edSJulian Elischer 		p->p_flag &= ~P_KSES;
3435c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
3445c8329edSJulian Elischer 		PROC_UNLOCK(p);
3455c8329edSJulian Elischer 	} else {
3465c8329edSJulian Elischer 		td->td_kse->ke_flags |= KEF_EXIT;
3475c8329edSJulian Elischer 		thread_exit();
3485c8329edSJulian Elischer 		/* NOTREACHED */
3495c8329edSJulian Elischer 	}
3507b290dd0SDavid Xu 	return (0);
3515c8329edSJulian Elischer }
3525c8329edSJulian Elischer 
353696058c3SJulian Elischer /*
354696058c3SJulian Elischer  * Either returns as an upcall or exits
355696058c3SJulian Elischer  */
3565c8329edSJulian Elischer int
3575c8329edSJulian Elischer kse_release(struct thread * td, struct kse_release_args * uap)
3585c8329edSJulian Elischer {
3595c8329edSJulian Elischer 	struct proc *p;
360696058c3SJulian Elischer 	struct ksegrp *kg;
3615c8329edSJulian Elischer 
3625c8329edSJulian Elischer 	p = td->td_proc;
363696058c3SJulian Elischer 	kg = td->td_ksegrp;
364ca161eb6SDavid Xu 	/*
365ca161eb6SDavid Xu 	 * Must be a bound thread. And kse must have a mailbox ready,
366696058c3SJulian Elischer 	 * if not, the kse can not generate an upcall.
367ca161eb6SDavid Xu 	 */
368696058c3SJulian Elischer 	if (!(p->p_flag & P_KSES) ||
369696058c3SJulian Elischer 	    (td->td_flags & TDF_UNBOUND) ||
370696058c3SJulian Elischer 	    (td->td_kse->ke_mailbox == NULL))
3715c8329edSJulian Elischer 		return (EINVAL);
372696058c3SJulian Elischer 	PROC_LOCK(p);
373696058c3SJulian Elischer 	mtx_lock_spin(&sched_lock);
374696058c3SJulian Elischer 	if (kg->kg_completed == NULL) {
375696058c3SJulian Elischer #if 1       /* temp until signals make new threads */
376696058c3SJulian Elischer 		if (p->p_numthreads == 1) {
377696058c3SJulian Elischer 			/* change OURSELF to become an upcall */
378696058c3SJulian Elischer 			td->td_flags = TDF_UPCALLING;
379696058c3SJulian Elischer 			mtx_unlock_spin(&sched_lock);
380696058c3SJulian Elischer 			PROC_UNLOCK(p);
381696058c3SJulian Elischer 			/*
382696058c3SJulian Elischer 			 * msleep will not call thread_sched_upcall
383696058c3SJulian Elischer 			 * because thread is not UNBOUND.
384696058c3SJulian Elischer 			 */
385696058c3SJulian Elischer 			msleep(p->p_sigacts, NULL,
386696058c3SJulian Elischer 			    PPAUSE | PCATCH, "ksepause", 0);
387696058c3SJulian Elischer 			return (0);
388696058c3SJulian Elischer 		}
389696058c3SJulian Elischer #endif      /* end temp */
390696058c3SJulian Elischer 		thread_exit();
391696058c3SJulian Elischer 	}
392696058c3SJulian Elischer 	/* change OURSELF to become an upcall */
393696058c3SJulian Elischer 	td->td_flags = TDF_UPCALLING;
394696058c3SJulian Elischer 	mtx_unlock_spin(&sched_lock);
395696058c3SJulian Elischer 	PROC_UNLOCK(p);
396696058c3SJulian Elischer 	return (0);
3975c8329edSJulian Elischer }
3985c8329edSJulian Elischer 
3995c8329edSJulian Elischer /* struct kse_wakeup_args {
4005c8329edSJulian Elischer 	struct kse_mailbox *mbx;
4015c8329edSJulian Elischer }; */
4025c8329edSJulian Elischer int
4035c8329edSJulian Elischer kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
4045c8329edSJulian Elischer {
4055c8329edSJulian Elischer 	struct proc *p;
4065c8329edSJulian Elischer 	struct kse *ke, *ke2;
4075c8329edSJulian Elischer 	struct ksegrp *kg;
4085c8329edSJulian Elischer 
4095c8329edSJulian Elischer 	p = td->td_proc;
4105c8329edSJulian Elischer 	/* KSE-enabled processes only, please. */
4115c8329edSJulian Elischer 	if (!(p->p_flag & P_KSES))
4125c8329edSJulian Elischer 		return EINVAL;
4135c8329edSJulian Elischer 	ke = NULL;
4145c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
4155c8329edSJulian Elischer 	if (uap->mbx) {
4165c8329edSJulian Elischer 		FOREACH_KSEGRP_IN_PROC(p, kg) {
4175c8329edSJulian Elischer 			FOREACH_KSE_IN_GROUP(kg, ke2) {
4185c8329edSJulian Elischer 				if (ke2->ke_mailbox != uap->mbx)
4195c8329edSJulian Elischer 					continue;
4205c8329edSJulian Elischer 				if (ke2->ke_state == KES_IDLE) {
4215c8329edSJulian Elischer 					ke = ke2;
4225c8329edSJulian Elischer 					goto found;
4235c8329edSJulian Elischer 				} else {
4245c8329edSJulian Elischer 					mtx_unlock_spin(&sched_lock);
4255c8329edSJulian Elischer 					td->td_retval[0] = 0;
4265c8329edSJulian Elischer 					td->td_retval[1] = 0;
4277b290dd0SDavid Xu 					return (0);
4285c8329edSJulian Elischer 				}
4295c8329edSJulian Elischer 			}
4305c8329edSJulian Elischer 		}
4315c8329edSJulian Elischer 	} else {
4325c8329edSJulian Elischer 		kg = td->td_ksegrp;
4335c8329edSJulian Elischer 		ke = TAILQ_FIRST(&kg->kg_iq);
4345c8329edSJulian Elischer 	}
4355c8329edSJulian Elischer 	if (ke == NULL) {
4365c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
4377b290dd0SDavid Xu 		return (ESRCH);
4385c8329edSJulian Elischer 	}
4395c8329edSJulian Elischer found:
4405c8329edSJulian Elischer 	thread_schedule_upcall(td, ke);
4415c8329edSJulian Elischer 	mtx_unlock_spin(&sched_lock);
4425c8329edSJulian Elischer 	td->td_retval[0] = 0;
4435c8329edSJulian Elischer 	td->td_retval[1] = 0;
4447b290dd0SDavid Xu 	return (0);
4455c8329edSJulian Elischer }
4465c8329edSJulian Elischer 
4475c8329edSJulian Elischer /*
4485c8329edSJulian Elischer  * No new KSEG: first call: use current KSE, don't schedule an upcall
4495c8329edSJulian Elischer  * All other situations, do allocate a new KSE and schedule an upcall on it.
4505c8329edSJulian Elischer  */
4515c8329edSJulian Elischer /* struct kse_create_args {
4525c8329edSJulian Elischer 	struct kse_mailbox *mbx;
4535c8329edSJulian Elischer 	int newgroup;
4545c8329edSJulian Elischer }; */
4555c8329edSJulian Elischer int
4565c8329edSJulian Elischer kse_create(struct thread *td, struct kse_create_args *uap)
4575c8329edSJulian Elischer {
4585c8329edSJulian Elischer 	struct kse *newke;
4595c8329edSJulian Elischer 	struct kse *ke;
4605c8329edSJulian Elischer 	struct ksegrp *newkg;
4615c8329edSJulian Elischer 	struct ksegrp *kg;
4625c8329edSJulian Elischer 	struct proc *p;
4635c8329edSJulian Elischer 	struct kse_mailbox mbx;
4645c8329edSJulian Elischer 	int err;
4655c8329edSJulian Elischer 
4665c8329edSJulian Elischer 	p = td->td_proc;
4675c8329edSJulian Elischer 	if ((err = copyin(uap->mbx, &mbx, sizeof(mbx))))
4685c8329edSJulian Elischer 		return (err);
4695c8329edSJulian Elischer 
4705c8329edSJulian Elischer 	p->p_flag |= P_KSES; /* easier to just set it than to test and set */
4715c8329edSJulian Elischer 	kg = td->td_ksegrp;
4725c8329edSJulian Elischer 	if (uap->newgroup) {
473fdc5ecd2SDavid Xu 		if (p->p_numksegrps >= max_groups_per_proc)
474fdc5ecd2SDavid Xu 			return (EPROCLIM);
4755c8329edSJulian Elischer 		/*
4765c8329edSJulian Elischer 		 * If we want a new KSEGRP it doesn't matter whether
4775c8329edSJulian Elischer 		 * we have already fired up KSE mode before or not.
4785c8329edSJulian Elischer 		 * We put the process in KSE mode and create a new KSEGRP
4795c8329edSJulian Elischer 		 * and KSE. If our KSE has not got a mailbox yet then
4805c8329edSJulian Elischer 		 * that doesn't matter, just leave it that way. It will
4815c8329edSJulian Elischer 		 * ensure that this thread stay BOUND. It's possible
4825c8329edSJulian Elischer 		 * that the call came form a threaded library and the main
4835c8329edSJulian Elischer 		 * program knows nothing of threads.
4845c8329edSJulian Elischer 		 */
4855c8329edSJulian Elischer 		newkg = ksegrp_alloc();
4865c8329edSJulian Elischer 		bzero(&newkg->kg_startzero, RANGEOF(struct ksegrp,
4875c8329edSJulian Elischer 		      kg_startzero, kg_endzero));
4885c8329edSJulian Elischer 		bcopy(&kg->kg_startcopy, &newkg->kg_startcopy,
4895c8329edSJulian Elischer 		      RANGEOF(struct ksegrp, kg_startcopy, kg_endcopy));
4905c8329edSJulian Elischer 		newke = kse_alloc();
4915c8329edSJulian Elischer 	} else {
4925c8329edSJulian Elischer 		/*
4935c8329edSJulian Elischer 		 * Otherwise, if we have already set this KSE
4945c8329edSJulian Elischer 		 * to have a mailbox, we want to make another KSE here,
4955c8329edSJulian Elischer 		 * but only if there are not already the limit, which
4965c8329edSJulian Elischer 		 * is 1 per CPU max.
4975c8329edSJulian Elischer 		 *
4985c8329edSJulian Elischer 		 * If the current KSE doesn't have a mailbox we just use it
4995c8329edSJulian Elischer 		 * and give it one.
5005c8329edSJulian Elischer 		 *
5015c8329edSJulian Elischer 		 * Because we don't like to access
5025c8329edSJulian Elischer 		 * the KSE outside of schedlock if we are UNBOUND,
5035c8329edSJulian Elischer 		 * (because it can change if we are preempted by an interrupt)
5045c8329edSJulian Elischer 		 * we can deduce it as having a mailbox if we are UNBOUND,
5055c8329edSJulian Elischer 		 * and only need to actually look at it if we are BOUND,
5065c8329edSJulian Elischer 		 * which is safe.
5075c8329edSJulian Elischer 		 */
5085c8329edSJulian Elischer 		if ((td->td_flags & TDF_UNBOUND) || td->td_kse->ke_mailbox) {
509696058c3SJulian Elischer 			if (thread_debug == 0) { /* if debugging, allow more */
5105c8329edSJulian Elischer #ifdef SMP
5115c8329edSJulian Elischer 			if (kg->kg_kses > mp_ncpus)
5125c8329edSJulian Elischer #endif
5135c8329edSJulian Elischer 				return (EPROCLIM);
514fdc5ecd2SDavid Xu 			}
5155c8329edSJulian Elischer 			newke = kse_alloc();
5165c8329edSJulian Elischer 		} else {
5175c8329edSJulian Elischer 			newke = NULL;
5185c8329edSJulian Elischer 		}
5195c8329edSJulian Elischer 		newkg = NULL;
5205c8329edSJulian Elischer 	}
5215c8329edSJulian Elischer 	if (newke) {
5225c8329edSJulian Elischer 		bzero(&newke->ke_startzero, RANGEOF(struct kse,
5235c8329edSJulian Elischer 		      ke_startzero, ke_endzero));
5245c8329edSJulian Elischer #if 0
5255c8329edSJulian Elischer 		bcopy(&ke->ke_startcopy, &newke->ke_startcopy,
5265c8329edSJulian Elischer 		      RANGEOF(struct kse, ke_startcopy, ke_endcopy));
5275c8329edSJulian Elischer #endif
5285c8329edSJulian Elischer 		/* For the first call this may not have been set */
5295c8329edSJulian Elischer 		if (td->td_standin == NULL) {
5305c8329edSJulian Elischer 			td->td_standin = thread_alloc();
5315c8329edSJulian Elischer 		}
5325c8329edSJulian Elischer 		mtx_lock_spin(&sched_lock);
533fdc5ecd2SDavid Xu 		if (newkg) {
534fdc5ecd2SDavid Xu 			if (p->p_numksegrps >= max_groups_per_proc) {
535fdc5ecd2SDavid Xu 				mtx_unlock_spin(&sched_lock);
536fdc5ecd2SDavid Xu 				ksegrp_free(newkg);
537fdc5ecd2SDavid Xu 				kse_free(newke);
538fdc5ecd2SDavid Xu 				return (EPROCLIM);
539fdc5ecd2SDavid Xu 			}
5405c8329edSJulian Elischer 			ksegrp_link(newkg, p);
541fdc5ecd2SDavid Xu 		}
5425c8329edSJulian Elischer 		else
5435c8329edSJulian Elischer 			newkg = kg;
5445c8329edSJulian Elischer 		kse_link(newke, newkg);
54572465621SDavid Xu 		if (p->p_sflag & PS_NEEDSIGCHK)
54672465621SDavid Xu 			newke->ke_flags |= KEF_ASTPENDING;
5475c8329edSJulian Elischer 		newke->ke_mailbox = uap->mbx;
5485c8329edSJulian Elischer 		newke->ke_upcall = mbx.km_func;
5495c8329edSJulian Elischer 		bcopy(&mbx.km_stack, &newke->ke_stack, sizeof(stack_t));
5505c8329edSJulian Elischer 		thread_schedule_upcall(td, newke);
5515c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
5525c8329edSJulian Elischer 	} else {
5535c8329edSJulian Elischer 		/*
5545c8329edSJulian Elischer 		 * If we didn't allocate a new KSE then the we are using
5555c8329edSJulian Elischer 		 * the exisiting (BOUND) kse.
5565c8329edSJulian Elischer 		 */
5575c8329edSJulian Elischer 		ke = td->td_kse;
5585c8329edSJulian Elischer 		ke->ke_mailbox = uap->mbx;
5595c8329edSJulian Elischer 		ke->ke_upcall = mbx.km_func;
5605c8329edSJulian Elischer 		bcopy(&mbx.km_stack, &ke->ke_stack, sizeof(stack_t));
5615c8329edSJulian Elischer 	}
5625c8329edSJulian Elischer 	/*
5635c8329edSJulian Elischer 	 * Fill out the KSE-mode specific fields of the new kse.
5645c8329edSJulian Elischer 	 */
5655c8329edSJulian Elischer 
5665c8329edSJulian Elischer 	td->td_retval[0] = 0;
5675c8329edSJulian Elischer 	td->td_retval[1] = 0;
5685c8329edSJulian Elischer 	return (0);
5695c8329edSJulian Elischer }
5705c8329edSJulian Elischer 
5715c8329edSJulian Elischer /*
572c76e33b6SJonathan Mini  * Fill a ucontext_t with a thread's context information.
573c76e33b6SJonathan Mini  *
574c76e33b6SJonathan Mini  * This is an analogue to getcontext(3).
575c76e33b6SJonathan Mini  */
576c76e33b6SJonathan Mini void
577c76e33b6SJonathan Mini thread_getcontext(struct thread *td, ucontext_t *uc)
578c76e33b6SJonathan Mini {
579c76e33b6SJonathan Mini 
580acaa1566SPeter Wemm /*
581acaa1566SPeter Wemm  * XXX this is declared in a MD include file, i386/include/ucontext.h but
582acaa1566SPeter Wemm  * is used in MI code.
583acaa1566SPeter Wemm  */
5841e19df33SPeter Wemm #ifdef __i386__
585c76e33b6SJonathan Mini 	get_mcontext(td, &uc->uc_mcontext);
5861e19df33SPeter Wemm #endif
587c76e33b6SJonathan Mini 	uc->uc_sigmask = td->td_proc->p_sigmask;
588c76e33b6SJonathan Mini }
589c76e33b6SJonathan Mini 
590c76e33b6SJonathan Mini /*
591c76e33b6SJonathan Mini  * Set a thread's context from a ucontext_t.
592c76e33b6SJonathan Mini  *
593c76e33b6SJonathan Mini  * This is an analogue to setcontext(3).
594c76e33b6SJonathan Mini  */
595c76e33b6SJonathan Mini int
596c76e33b6SJonathan Mini thread_setcontext(struct thread *td, ucontext_t *uc)
597c76e33b6SJonathan Mini {
598c76e33b6SJonathan Mini 	int ret;
599c76e33b6SJonathan Mini 
600acaa1566SPeter Wemm /*
601acaa1566SPeter Wemm  * XXX this is declared in a MD include file, i386/include/ucontext.h but
602acaa1566SPeter Wemm  * is used in MI code.
603acaa1566SPeter Wemm  */
6041e19df33SPeter Wemm #ifdef __i386__
605c76e33b6SJonathan Mini 	ret = set_mcontext(td, &uc->uc_mcontext);
6061e19df33SPeter Wemm #else
6071e19df33SPeter Wemm 	ret = ENOSYS;
6081e19df33SPeter Wemm #endif
609c76e33b6SJonathan Mini 	if (ret == 0) {
610c76e33b6SJonathan Mini 		SIG_CANTMASK(uc->uc_sigmask);
611c76e33b6SJonathan Mini 		PROC_LOCK(td->td_proc);
612c76e33b6SJonathan Mini 		td->td_proc->p_sigmask = uc->uc_sigmask;
613c76e33b6SJonathan Mini 		PROC_UNLOCK(td->td_proc);
614c76e33b6SJonathan Mini 	}
615c76e33b6SJonathan Mini 	return (ret);
616c76e33b6SJonathan Mini }
617c76e33b6SJonathan Mini 
618c76e33b6SJonathan Mini /*
61944990b8cSJulian Elischer  * Initialize global thread allocation resources.
62044990b8cSJulian Elischer  */
62144990b8cSJulian Elischer void
62244990b8cSJulian Elischer threadinit(void)
62344990b8cSJulian Elischer {
62444990b8cSJulian Elischer 
625c281972eSPeter Wemm #ifndef __ia64__
626de028f5aSJeff Roberson 	thread_zone = uma_zcreate("THREAD", sched_sizeof_thread(),
62744990b8cSJulian Elischer 	    thread_ctor, thread_dtor, thread_init, thread_fini,
62844990b8cSJulian Elischer 	    UMA_ALIGN_CACHE, 0);
629c281972eSPeter Wemm #else
630c281972eSPeter Wemm 	/*
631c281972eSPeter Wemm 	 * XXX the ia64 kstack allocator is really lame and is at the mercy
632c281972eSPeter Wemm 	 * of contigmallloc().  This hackery is to pre-construct a whole
633c281972eSPeter Wemm 	 * pile of thread structures with associated kernel stacks early
634c281972eSPeter Wemm 	 * in the system startup while contigmalloc() still works. Once we
635c281972eSPeter Wemm 	 * have them, keep them.  Sigh.
636c281972eSPeter Wemm 	 */
637de028f5aSJeff Roberson 	thread_zone = uma_zcreate("THREAD", sched_sizeof_thread(),
638c281972eSPeter Wemm 	    thread_ctor, thread_dtor, thread_init, thread_fini,
639c281972eSPeter Wemm 	    UMA_ALIGN_CACHE, UMA_ZONE_NOFREE);
640c281972eSPeter Wemm 	uma_prealloc(thread_zone, 512);		/* XXX arbitary */
641c281972eSPeter Wemm #endif
642de028f5aSJeff Roberson 	ksegrp_zone = uma_zcreate("KSEGRP", sched_sizeof_ksegrp(),
643de028f5aSJeff Roberson 	    NULL, NULL, ksegrp_init, NULL,
6444f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
645de028f5aSJeff Roberson 	kse_zone = uma_zcreate("KSE", sched_sizeof_kse(),
646de028f5aSJeff Roberson 	    NULL, NULL, kse_init, NULL,
6474f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
64844990b8cSJulian Elischer }
64944990b8cSJulian Elischer 
65044990b8cSJulian Elischer /*
6511faf202eSJulian Elischer  * Stash an embarasingly extra thread into the zombie thread queue.
65244990b8cSJulian Elischer  */
65344990b8cSJulian Elischer void
65444990b8cSJulian Elischer thread_stash(struct thread *td)
65544990b8cSJulian Elischer {
65644990b8cSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
65744990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_threads, td, td_runq);
65844990b8cSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
65944990b8cSJulian Elischer }
66044990b8cSJulian Elischer 
66144990b8cSJulian Elischer /*
6625c8329edSJulian Elischer  * Stash an embarasingly extra kse into the zombie kse queue.
6635c8329edSJulian Elischer  */
6645c8329edSJulian Elischer void
6655c8329edSJulian Elischer kse_stash(struct kse *ke)
6665c8329edSJulian Elischer {
6675c8329edSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
6685c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_kses, ke, ke_procq);
6695c8329edSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
6705c8329edSJulian Elischer }
6715c8329edSJulian Elischer 
6725c8329edSJulian Elischer /*
6735c8329edSJulian Elischer  * Stash an embarasingly extra ksegrp into the zombie ksegrp queue.
6745c8329edSJulian Elischer  */
6755c8329edSJulian Elischer void
6765c8329edSJulian Elischer ksegrp_stash(struct ksegrp *kg)
6775c8329edSJulian Elischer {
6785c8329edSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
6795c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_ksegrps, kg, kg_ksegrp);
6805c8329edSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
6815c8329edSJulian Elischer }
6825c8329edSJulian Elischer 
6835c8329edSJulian Elischer /*
684c76e33b6SJonathan Mini  * Reap zombie threads.
68544990b8cSJulian Elischer  */
68644990b8cSJulian Elischer void
68744990b8cSJulian Elischer thread_reap(void)
68844990b8cSJulian Elischer {
6895c8329edSJulian Elischer 	struct thread *td_first, *td_next;
6905c8329edSJulian Elischer 	struct kse *ke_first, *ke_next;
6915c8329edSJulian Elischer 	struct ksegrp *kg_first, * kg_next;
69244990b8cSJulian Elischer 
69344990b8cSJulian Elischer 	/*
69444990b8cSJulian Elischer 	 * don't even bother to lock if none at this instant
69544990b8cSJulian Elischer 	 * We really don't care about the next instant..
69644990b8cSJulian Elischer 	 */
6975c8329edSJulian Elischer 	if ((!TAILQ_EMPTY(&zombie_threads))
6985c8329edSJulian Elischer 	    || (!TAILQ_EMPTY(&zombie_kses))
6995c8329edSJulian Elischer 	    || (!TAILQ_EMPTY(&zombie_ksegrps))) {
70044990b8cSJulian Elischer 		mtx_lock_spin(&zombie_thread_lock);
7015c8329edSJulian Elischer 		td_first = TAILQ_FIRST(&zombie_threads);
7025c8329edSJulian Elischer 		ke_first = TAILQ_FIRST(&zombie_kses);
7035c8329edSJulian Elischer 		kg_first = TAILQ_FIRST(&zombie_ksegrps);
7045c8329edSJulian Elischer 		if (td_first)
7055c8329edSJulian Elischer 			TAILQ_INIT(&zombie_threads);
7065c8329edSJulian Elischer 		if (ke_first)
7075c8329edSJulian Elischer 			TAILQ_INIT(&zombie_kses);
7085c8329edSJulian Elischer 		if (kg_first)
7095c8329edSJulian Elischer 			TAILQ_INIT(&zombie_ksegrps);
71044990b8cSJulian Elischer 		mtx_unlock_spin(&zombie_thread_lock);
7115c8329edSJulian Elischer 		while (td_first) {
7125c8329edSJulian Elischer 			td_next = TAILQ_NEXT(td_first, td_runq);
7135c8329edSJulian Elischer 			thread_free(td_first);
7145c8329edSJulian Elischer 			td_first = td_next;
71544990b8cSJulian Elischer 		}
7165c8329edSJulian Elischer 		while (ke_first) {
7175c8329edSJulian Elischer 			ke_next = TAILQ_NEXT(ke_first, ke_procq);
7185c8329edSJulian Elischer 			kse_free(ke_first);
7195c8329edSJulian Elischer 			ke_first = ke_next;
7205c8329edSJulian Elischer 		}
7215c8329edSJulian Elischer 		while (kg_first) {
7225c8329edSJulian Elischer 			kg_next = TAILQ_NEXT(kg_first, kg_ksegrp);
7235c8329edSJulian Elischer 			ksegrp_free(kg_first);
7245c8329edSJulian Elischer 			kg_first = kg_next;
7255c8329edSJulian Elischer 		}
72644990b8cSJulian Elischer 	}
72744990b8cSJulian Elischer }
72844990b8cSJulian Elischer 
72944990b8cSJulian Elischer /*
7304f0db5e0SJulian Elischer  * Allocate a ksegrp.
7314f0db5e0SJulian Elischer  */
7324f0db5e0SJulian Elischer struct ksegrp *
7334f0db5e0SJulian Elischer ksegrp_alloc(void)
7344f0db5e0SJulian Elischer {
7354f0db5e0SJulian Elischer 	return (uma_zalloc(ksegrp_zone, M_WAITOK));
7364f0db5e0SJulian Elischer }
7374f0db5e0SJulian Elischer 
7384f0db5e0SJulian Elischer /*
7394f0db5e0SJulian Elischer  * Allocate a kse.
7404f0db5e0SJulian Elischer  */
7414f0db5e0SJulian Elischer struct kse *
7424f0db5e0SJulian Elischer kse_alloc(void)
7434f0db5e0SJulian Elischer {
7444f0db5e0SJulian Elischer 	return (uma_zalloc(kse_zone, M_WAITOK));
7454f0db5e0SJulian Elischer }
7464f0db5e0SJulian Elischer 
7474f0db5e0SJulian Elischer /*
74844990b8cSJulian Elischer  * Allocate a thread.
74944990b8cSJulian Elischer  */
75044990b8cSJulian Elischer struct thread *
75144990b8cSJulian Elischer thread_alloc(void)
75244990b8cSJulian Elischer {
75344990b8cSJulian Elischer 	thread_reap(); /* check if any zombies to get */
75444990b8cSJulian Elischer 	return (uma_zalloc(thread_zone, M_WAITOK));
75544990b8cSJulian Elischer }
75644990b8cSJulian Elischer 
75744990b8cSJulian Elischer /*
7584f0db5e0SJulian Elischer  * Deallocate a ksegrp.
7594f0db5e0SJulian Elischer  */
7604f0db5e0SJulian Elischer void
7614f0db5e0SJulian Elischer ksegrp_free(struct ksegrp *td)
7624f0db5e0SJulian Elischer {
7634f0db5e0SJulian Elischer 	uma_zfree(ksegrp_zone, td);
7644f0db5e0SJulian Elischer }
7654f0db5e0SJulian Elischer 
7664f0db5e0SJulian Elischer /*
7674f0db5e0SJulian Elischer  * Deallocate a kse.
7684f0db5e0SJulian Elischer  */
7694f0db5e0SJulian Elischer void
7704f0db5e0SJulian Elischer kse_free(struct kse *td)
7714f0db5e0SJulian Elischer {
7724f0db5e0SJulian Elischer 	uma_zfree(kse_zone, td);
7734f0db5e0SJulian Elischer }
7744f0db5e0SJulian Elischer 
7754f0db5e0SJulian Elischer /*
77644990b8cSJulian Elischer  * Deallocate a thread.
77744990b8cSJulian Elischer  */
77844990b8cSJulian Elischer void
77944990b8cSJulian Elischer thread_free(struct thread *td)
78044990b8cSJulian Elischer {
781696058c3SJulian Elischer 
782696058c3SJulian Elischer 	cpu_thread_clean(td);
78344990b8cSJulian Elischer 	uma_zfree(thread_zone, td);
78444990b8cSJulian Elischer }
78544990b8cSJulian Elischer 
78644990b8cSJulian Elischer /*
78744990b8cSJulian Elischer  * Store the thread context in the UTS's mailbox.
7883d0586d4SJulian Elischer  * then add the mailbox at the head of a list we are building in user space.
7893d0586d4SJulian Elischer  * The list is anchored in the ksegrp structure.
79044990b8cSJulian Elischer  */
79144990b8cSJulian Elischer int
79244990b8cSJulian Elischer thread_export_context(struct thread *td)
79344990b8cSJulian Elischer {
7940d294460SJuli Mallett 	struct proc *p;
7953d0586d4SJulian Elischer 	struct ksegrp *kg;
7963d0586d4SJulian Elischer 	uintptr_t mbx;
7973d0586d4SJulian Elischer 	void *addr;
79844990b8cSJulian Elischer 	int error;
799c76e33b6SJonathan Mini 	ucontext_t uc;
8008798d4f9SDavid Xu 	uint temp;
80144990b8cSJulian Elischer 
8020d294460SJuli Mallett 	p = td->td_proc;
8030d294460SJuli Mallett 	kg = td->td_ksegrp;
8040d294460SJuli Mallett 
805c76e33b6SJonathan Mini 	/* Export the user/machine context. */
8063d0586d4SJulian Elischer #if 0
8073d0586d4SJulian Elischer 	addr = (caddr_t)td->td_mailbox +
8083d0586d4SJulian Elischer 	    offsetof(struct kse_thr_mailbox, tm_context);
8093d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
8103d0586d4SJulian Elischer 		addr = (void *)(&td->td_mailbox->tm_context);
8113d0586d4SJulian Elischer #endif
8123d0586d4SJulian Elischer 	error = copyin(addr, &uc, sizeof(ucontext_t));
813c76e33b6SJonathan Mini 	if (error == 0) {
814c76e33b6SJonathan Mini 		thread_getcontext(td, &uc);
8153d0586d4SJulian Elischer 		error = copyout(&uc, addr, sizeof(ucontext_t));
81644990b8cSJulian Elischer 
81744990b8cSJulian Elischer 	}
8183d0586d4SJulian Elischer 	if (error) {
8190cd3964fSJulian Elischer 		PROC_LOCK(p);
8200cd3964fSJulian Elischer 		psignal(p, SIGSEGV);
8210cd3964fSJulian Elischer 		PROC_UNLOCK(p);
82244990b8cSJulian Elischer 		return (error);
82344990b8cSJulian Elischer 	}
8243d0586d4SJulian Elischer 	/* get address in latest mbox of list pointer */
8253d0586d4SJulian Elischer #if 0
8263d0586d4SJulian Elischer 	addr = (caddr_t)td->td_mailbox
8273d0586d4SJulian Elischer 	    + offsetof(struct kse_thr_mailbox , tm_next);
8283d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
8293d0586d4SJulian Elischer 	addr = (void *)(&td->td_mailbox->tm_next);
8303d0586d4SJulian Elischer #endif
8313d0586d4SJulian Elischer 	/*
8323d0586d4SJulian Elischer 	 * Put the saved address of the previous first
8333d0586d4SJulian Elischer 	 * entry into this one
8343d0586d4SJulian Elischer 	 */
8353d0586d4SJulian Elischer 	for (;;) {
8363d0586d4SJulian Elischer 		mbx = (uintptr_t)kg->kg_completed;
8373d0586d4SJulian Elischer 		if (suword(addr, mbx)) {
8388798d4f9SDavid Xu 			goto bad;
8393d0586d4SJulian Elischer 		}
8400cd3964fSJulian Elischer 		PROC_LOCK(p);
8413d0586d4SJulian Elischer 		if (mbx == (uintptr_t)kg->kg_completed) {
8423d0586d4SJulian Elischer 			kg->kg_completed = td->td_mailbox;
8430cd3964fSJulian Elischer 			PROC_UNLOCK(p);
8443d0586d4SJulian Elischer 			break;
8453d0586d4SJulian Elischer 		}
8460cd3964fSJulian Elischer 		PROC_UNLOCK(p);
8473d0586d4SJulian Elischer 	}
8488798d4f9SDavid Xu 	addr = (caddr_t)td->td_mailbox
8498798d4f9SDavid Xu 		 + offsetof(struct kse_thr_mailbox, tm_sticks);
8508798d4f9SDavid Xu 	temp = fuword(addr) + td->td_usticks;
8518798d4f9SDavid Xu 	if (suword(addr, temp))
8528798d4f9SDavid Xu 		goto bad;
8533d0586d4SJulian Elischer 	return (0);
8548798d4f9SDavid Xu 
8558798d4f9SDavid Xu bad:
8568798d4f9SDavid Xu 	PROC_LOCK(p);
8578798d4f9SDavid Xu 	psignal(p, SIGSEGV);
8588798d4f9SDavid Xu 	PROC_UNLOCK(p);
8598798d4f9SDavid Xu 	return (EFAULT);
8603d0586d4SJulian Elischer }
86144990b8cSJulian Elischer 
8623d0586d4SJulian Elischer /*
8633d0586d4SJulian Elischer  * Take the list of completed mailboxes for this KSEGRP and put them on this
8643d0586d4SJulian Elischer  * KSE's mailbox as it's the next one going up.
8653d0586d4SJulian Elischer  */
8663d0586d4SJulian Elischer static int
8673d0586d4SJulian Elischer thread_link_mboxes(struct ksegrp *kg, struct kse *ke)
8683d0586d4SJulian Elischer {
8690cd3964fSJulian Elischer 	struct proc *p = kg->kg_proc;
8703d0586d4SJulian Elischer 	void *addr;
8713d0586d4SJulian Elischer 	uintptr_t mbx;
8723d0586d4SJulian Elischer 
8733d0586d4SJulian Elischer #if 0
8743d0586d4SJulian Elischer 	addr = (caddr_t)ke->ke_mailbox
8753d0586d4SJulian Elischer 	    + offsetof(struct kse_mailbox, km_completed);
8763d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
8773d0586d4SJulian Elischer 		addr = (void *)(&ke->ke_mailbox->km_completed);
8783d0586d4SJulian Elischer #endif
8793d0586d4SJulian Elischer 	for (;;) {
8803d0586d4SJulian Elischer 		mbx = (uintptr_t)kg->kg_completed;
8813d0586d4SJulian Elischer 		if (suword(addr, mbx)) {
8820cd3964fSJulian Elischer 			PROC_LOCK(p);
8830cd3964fSJulian Elischer 			psignal(p, SIGSEGV);
8840cd3964fSJulian Elischer 			PROC_UNLOCK(p);
8853d0586d4SJulian Elischer 			return (EFAULT);
8863d0586d4SJulian Elischer 		}
8873d0586d4SJulian Elischer 		/* XXXKSE could use atomic CMPXCH here */
8880cd3964fSJulian Elischer 		PROC_LOCK(p);
8893d0586d4SJulian Elischer 		if (mbx == (uintptr_t)kg->kg_completed) {
8903d0586d4SJulian Elischer 			kg->kg_completed = NULL;
8910cd3964fSJulian Elischer 			PROC_UNLOCK(p);
8923d0586d4SJulian Elischer 			break;
8933d0586d4SJulian Elischer 		}
8940cd3964fSJulian Elischer 		PROC_UNLOCK(p);
8953d0586d4SJulian Elischer 	}
8963d0586d4SJulian Elischer 	return (0);
8973d0586d4SJulian Elischer }
89844990b8cSJulian Elischer 
89944990b8cSJulian Elischer /*
9008798d4f9SDavid Xu  * This function should be called at statclock interrupt time
9018798d4f9SDavid Xu  */
9028798d4f9SDavid Xu int
9038798d4f9SDavid Xu thread_add_ticks_intr(int user, uint ticks)
9048798d4f9SDavid Xu {
9058798d4f9SDavid Xu 	struct thread *td = curthread;
9068798d4f9SDavid Xu 	struct kse *ke = td->td_kse;
9078798d4f9SDavid Xu 
9088798d4f9SDavid Xu 	if (ke->ke_mailbox == NULL)
9098798d4f9SDavid Xu 		return -1;
9108798d4f9SDavid Xu 	if (user) {
9118798d4f9SDavid Xu 		/* Current always do via ast() */
9128798d4f9SDavid Xu 		ke->ke_flags |= KEF_ASTPENDING;
9138798d4f9SDavid Xu 		ke->ke_uuticks += ticks;
9148798d4f9SDavid Xu 	} else {
9158798d4f9SDavid Xu 		if (td->td_mailbox != NULL)
9168798d4f9SDavid Xu 			td->td_usticks += ticks;
9178798d4f9SDavid Xu 		else
9188798d4f9SDavid Xu 			ke->ke_usticks += ticks;
9198798d4f9SDavid Xu 	}
9208798d4f9SDavid Xu 	return 0;
9218798d4f9SDavid Xu }
9228798d4f9SDavid Xu 
9238798d4f9SDavid Xu static int
9248798d4f9SDavid Xu thread_update_uticks(void)
9258798d4f9SDavid Xu {
9268798d4f9SDavid Xu 	struct thread *td = curthread;
9278798d4f9SDavid Xu 	struct proc *p = td->td_proc;
9288798d4f9SDavid Xu 	struct kse *ke = td->td_kse;
9298798d4f9SDavid Xu 	struct kse_thr_mailbox *tmbx;
9308798d4f9SDavid Xu 	caddr_t addr;
9318798d4f9SDavid Xu 	uint uticks, sticks;
9328798d4f9SDavid Xu 
9338798d4f9SDavid Xu 	KASSERT(!(td->td_flags & TDF_UNBOUND), ("thread not bound."));
9348798d4f9SDavid Xu 
9358798d4f9SDavid Xu 	if (ke->ke_mailbox == NULL)
9368798d4f9SDavid Xu 		return 0;
9378798d4f9SDavid Xu 
9388798d4f9SDavid Xu 	uticks = ke->ke_uuticks;
9398798d4f9SDavid Xu 	ke->ke_uuticks = 0;
9408798d4f9SDavid Xu 	sticks = ke->ke_usticks;
9418798d4f9SDavid Xu 	ke->ke_usticks = 0;
9428798d4f9SDavid Xu 	tmbx = (void *)fuword((caddr_t)ke->ke_mailbox
9438798d4f9SDavid Xu 			+ offsetof(struct kse_mailbox, km_curthread));
9448798d4f9SDavid Xu 	if ((tmbx == NULL) || (tmbx == (void *)-1))
9458798d4f9SDavid Xu 		return 0;
9468798d4f9SDavid Xu 	if (uticks) {
9478798d4f9SDavid Xu 		addr = (caddr_t)tmbx + offsetof(struct kse_thr_mailbox, tm_uticks);
9488798d4f9SDavid Xu 		uticks += fuword(addr);
9498798d4f9SDavid Xu 		if (suword(addr, uticks))
9508798d4f9SDavid Xu 			goto bad;
9518798d4f9SDavid Xu 	}
9528798d4f9SDavid Xu 	if (sticks) {
9538798d4f9SDavid Xu 		addr = (caddr_t)tmbx + offsetof(struct kse_thr_mailbox, tm_sticks);
9548798d4f9SDavid Xu 		sticks += fuword(addr);
9558798d4f9SDavid Xu 		if (suword(addr, sticks))
9568798d4f9SDavid Xu 			goto bad;
9578798d4f9SDavid Xu 	}
9588798d4f9SDavid Xu 	return 0;
9598798d4f9SDavid Xu bad:
9608798d4f9SDavid Xu 	PROC_LOCK(p);
9618798d4f9SDavid Xu 	psignal(p, SIGSEGV);
9628798d4f9SDavid Xu 	PROC_UNLOCK(p);
9638798d4f9SDavid Xu 	return -1;
9648798d4f9SDavid Xu }
9658798d4f9SDavid Xu 
9668798d4f9SDavid Xu /*
96744990b8cSJulian Elischer  * Discard the current thread and exit from its context.
96844990b8cSJulian Elischer  *
96944990b8cSJulian Elischer  * Because we can't free a thread while we're operating under its context,
970696058c3SJulian Elischer  * push the current thread into our CPU's deadthread holder. This means
971696058c3SJulian Elischer  * we needn't worry about someone else grabbing our context before we
972696058c3SJulian Elischer  * do a cpu_throw().
97344990b8cSJulian Elischer  */
97444990b8cSJulian Elischer void
97544990b8cSJulian Elischer thread_exit(void)
97644990b8cSJulian Elischer {
97744990b8cSJulian Elischer 	struct thread *td;
97844990b8cSJulian Elischer 	struct kse *ke;
97944990b8cSJulian Elischer 	struct proc *p;
98044990b8cSJulian Elischer 	struct ksegrp	*kg;
98144990b8cSJulian Elischer 
98244990b8cSJulian Elischer 	td = curthread;
98344990b8cSJulian Elischer 	kg = td->td_ksegrp;
98444990b8cSJulian Elischer 	p = td->td_proc;
98544990b8cSJulian Elischer 	ke = td->td_kse;
98644990b8cSJulian Elischer 
98744990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
98888151aa3SJulian Elischer 	KASSERT(p != NULL, ("thread exiting without a process"));
98988151aa3SJulian Elischer 	KASSERT(ke != NULL, ("thread exiting without a kse"));
99088151aa3SJulian Elischer 	KASSERT(kg != NULL, ("thread exiting without a kse group"));
99144990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
99244990b8cSJulian Elischer 	CTR1(KTR_PROC, "thread_exit: thread %p", td);
99344990b8cSJulian Elischer 	KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
99444990b8cSJulian Elischer 
99548bfcdddSJulian Elischer 	if (td->td_standin != NULL) {
99648bfcdddSJulian Elischer 		thread_stash(td->td_standin);
99748bfcdddSJulian Elischer 		td->td_standin = NULL;
99848bfcdddSJulian Elischer 	}
99948bfcdddSJulian Elischer 
100044990b8cSJulian Elischer 	cpu_thread_exit(td);	/* XXXSMP */
100144990b8cSJulian Elischer 
10021faf202eSJulian Elischer 	/*
10031faf202eSJulian Elischer 	 * The last thread is left attached to the process
10041faf202eSJulian Elischer 	 * So that the whole bundle gets recycled. Skip
10051faf202eSJulian Elischer 	 * all this stuff.
10061faf202eSJulian Elischer 	 */
10071faf202eSJulian Elischer 	if (p->p_numthreads > 1) {
10085c8329edSJulian Elischer 		/*
10095c8329edSJulian Elischer 		 * Unlink this thread from its proc and the kseg.
10105c8329edSJulian Elischer 		 * In keeping with the other structs we probably should
10115c8329edSJulian Elischer 		 * have a thread_unlink() that does some of this but it
10125c8329edSJulian Elischer 		 * would only be called from here (I think) so it would
10135c8329edSJulian Elischer 		 * be a waste. (might be useful for proc_fini() as well.)
10145c8329edSJulian Elischer  		 */
101544990b8cSJulian Elischer 		TAILQ_REMOVE(&p->p_threads, td, td_plist);
101644990b8cSJulian Elischer 		p->p_numthreads--;
101744990b8cSJulian Elischer 		TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
101844990b8cSJulian Elischer 		kg->kg_numthreads--;
101944990b8cSJulian Elischer 		/*
102044990b8cSJulian Elischer 		 * The test below is NOT true if we are the
10211faf202eSJulian Elischer 		 * sole exiting thread. P_STOPPED_SNGL is unset
102244990b8cSJulian Elischer 		 * in exit1() after it is the only survivor.
102344990b8cSJulian Elischer 		 */
10241279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
102544990b8cSJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
102671fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
102744990b8cSJulian Elischer 			}
102844990b8cSJulian Elischer 		}
102948bfcdddSJulian Elischer 
103048bfcdddSJulian Elischer 		/* Reassign this thread's KSE. */
103148bfcdddSJulian Elischer 		ke->ke_thread = NULL;
103248bfcdddSJulian Elischer 		td->td_kse = NULL;
103348bfcdddSJulian Elischer 		ke->ke_state = KES_UNQUEUED;
10345c8329edSJulian Elischer 		KASSERT((ke->ke_bound != td),
10355c8329edSJulian Elischer 		    ("thread_exit: entered with ke_bound set"));
103648bfcdddSJulian Elischer 
103748bfcdddSJulian Elischer 		/*
1038696058c3SJulian Elischer 		 * decide what to do with the KSE attached to this thread.
103948bfcdddSJulian Elischer 		 */
10405c8329edSJulian Elischer 		if (ke->ke_flags & KEF_EXIT) {
10415c8329edSJulian Elischer 			kse_unlink(ke);
10425c8329edSJulian Elischer 		} else {
10435c8329edSJulian Elischer 			kse_reassign(ke);
10445c8329edSJulian Elischer 		}
10455c8329edSJulian Elischer 		PROC_UNLOCK(p);
10465c8329edSJulian Elischer 		td->td_state	= TDS_INACTIVE;
10475c8329edSJulian Elischer 		td->td_proc	= NULL;
10485c8329edSJulian Elischer 		td->td_ksegrp	= NULL;
10495c8329edSJulian Elischer 		td->td_last_kse	= NULL;
1050696058c3SJulian Elischer 		PCPU_SET(deadthread, td);
10511faf202eSJulian Elischer 	} else {
10521faf202eSJulian Elischer 		PROC_UNLOCK(p);
10531faf202eSJulian Elischer 	}
105444990b8cSJulian Elischer 	cpu_throw();
105544990b8cSJulian Elischer 	/* NOTREACHED */
105644990b8cSJulian Elischer }
105744990b8cSJulian Elischer 
105844990b8cSJulian Elischer /*
1059696058c3SJulian Elischer  * Do any thread specific cleanups that may be needed in wait()
1060696058c3SJulian Elischer  * called with Giant held, proc and schedlock not held.
1061696058c3SJulian Elischer  */
1062696058c3SJulian Elischer void
1063696058c3SJulian Elischer thread_wait(struct proc *p)
1064696058c3SJulian Elischer {
1065696058c3SJulian Elischer 	struct thread *td;
1066696058c3SJulian Elischer 
1067696058c3SJulian Elischer 	KASSERT((p->p_numthreads == 1), ("Muliple threads in wait1()"));
1068696058c3SJulian Elischer 	KASSERT((p->p_numksegrps == 1), ("Muliple ksegrps in wait1()"));
1069696058c3SJulian Elischer 	FOREACH_THREAD_IN_PROC(p, td) {
1070696058c3SJulian Elischer 		if (td->td_standin != NULL) {
1071696058c3SJulian Elischer 			thread_free(td->td_standin);
1072696058c3SJulian Elischer 			td->td_standin = NULL;
1073696058c3SJulian Elischer 		}
1074696058c3SJulian Elischer 		cpu_thread_clean(td);
1075696058c3SJulian Elischer 	}
1076696058c3SJulian Elischer 	thread_reap();	/* check for zombie threads etc. */
1077696058c3SJulian Elischer }
1078696058c3SJulian Elischer 
1079696058c3SJulian Elischer /*
108044990b8cSJulian Elischer  * Link a thread to a process.
10811faf202eSJulian Elischer  * set up anything that needs to be initialized for it to
10821faf202eSJulian Elischer  * be used by the process.
108344990b8cSJulian Elischer  *
108444990b8cSJulian Elischer  * Note that we do not link to the proc's ucred here.
108544990b8cSJulian Elischer  * The thread is linked as if running but no KSE assigned.
108644990b8cSJulian Elischer  */
108744990b8cSJulian Elischer void
108844990b8cSJulian Elischer thread_link(struct thread *td, struct ksegrp *kg)
108944990b8cSJulian Elischer {
109044990b8cSJulian Elischer 	struct proc *p;
109144990b8cSJulian Elischer 
109244990b8cSJulian Elischer 	p = kg->kg_proc;
109371fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
109444990b8cSJulian Elischer 	td->td_proc	= p;
109544990b8cSJulian Elischer 	td->td_ksegrp	= kg;
109644990b8cSJulian Elischer 	td->td_last_kse	= NULL;
109744990b8cSJulian Elischer 
10981faf202eSJulian Elischer 	LIST_INIT(&td->td_contested);
10991faf202eSJulian Elischer 	callout_init(&td->td_slpcallout, 1);
110044990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist);
110144990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist);
110244990b8cSJulian Elischer 	p->p_numthreads++;
110344990b8cSJulian Elischer 	kg->kg_numthreads++;
110444990b8cSJulian Elischer 	td->td_kse	= NULL;
110544990b8cSJulian Elischer }
110644990b8cSJulian Elischer 
11075c8329edSJulian Elischer void
11085c8329edSJulian Elischer kse_purge(struct proc *p, struct thread *td)
11095c8329edSJulian Elischer {
11105c8329edSJulian Elischer 	struct kse *ke;
11115c8329edSJulian Elischer 	struct ksegrp *kg;
11125c8329edSJulian Elischer 
11135c8329edSJulian Elischer  	KASSERT(p->p_numthreads == 1, ("bad thread number"));
11145c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
11155c8329edSJulian Elischer 	while ((kg = TAILQ_FIRST(&p->p_ksegrps)) != NULL) {
11165c8329edSJulian Elischer 		while ((ke = TAILQ_FIRST(&kg->kg_iq)) != NULL) {
11175c8329edSJulian Elischer 			TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
11185c8329edSJulian Elischer 			kg->kg_idle_kses--;
11195c8329edSJulian Elischer 			TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
11205c8329edSJulian Elischer 			kg->kg_kses--;
11215c8329edSJulian Elischer    			kse_stash(ke);
11225c8329edSJulian Elischer 		}
11235c8329edSJulian Elischer 		TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp);
11245c8329edSJulian Elischer 		p->p_numksegrps--;
11255c8329edSJulian Elischer 		KASSERT(((kg->kg_kses == 0) && (kg != td->td_ksegrp)) ||
11265c8329edSJulian Elischer 		    ((kg->kg_kses == 1) && (kg == td->td_ksegrp)),
11275c8329edSJulian Elischer 			("wrong kg_kses"));
11285c8329edSJulian Elischer 		if (kg != td->td_ksegrp) {
11295c8329edSJulian Elischer 			ksegrp_stash(kg);
11305c8329edSJulian Elischer 		}
11315c8329edSJulian Elischer 	}
11325c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_ksegrps, td->td_ksegrp, kg_ksegrp);
11335c8329edSJulian Elischer 	p->p_numksegrps++;
11345c8329edSJulian Elischer 	mtx_unlock_spin(&sched_lock);
11355c8329edSJulian Elischer }
11365c8329edSJulian Elischer 
11375c8329edSJulian Elischer 
113844990b8cSJulian Elischer /*
1139c76e33b6SJonathan Mini  * Create a thread and schedule it for upcall on the KSE given.
114044990b8cSJulian Elischer  */
114144990b8cSJulian Elischer struct thread *
114244990b8cSJulian Elischer thread_schedule_upcall(struct thread *td, struct kse *ke)
114344990b8cSJulian Elischer {
114444990b8cSJulian Elischer 	struct thread *td2;
11450cf60970SDavid Xu 	struct ksegrp *kg;
114648bfcdddSJulian Elischer 	int newkse;
114744990b8cSJulian Elischer 
114844990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
114948bfcdddSJulian Elischer 	newkse = (ke != td->td_kse);
115048bfcdddSJulian Elischer 
115148bfcdddSJulian Elischer 	/*
115248bfcdddSJulian Elischer 	 * If the kse is already owned by another thread then we can't
115348bfcdddSJulian Elischer 	 * schedule an upcall because the other thread must be BOUND
115448bfcdddSJulian Elischer 	 * which means it is not in a position to take an upcall.
115548bfcdddSJulian Elischer 	 * We must be borrowing the KSE to allow us to complete some in-kernel
115648bfcdddSJulian Elischer 	 * work. When we complete, the Bound thread will have teh chance to
115748bfcdddSJulian Elischer 	 * complete. This thread will sleep as planned. Hopefully there will
115848bfcdddSJulian Elischer 	 * eventually be un unbound thread that can be converted to an
115948bfcdddSJulian Elischer 	 * upcall to report the completion of this thread.
116048bfcdddSJulian Elischer 	 */
116148bfcdddSJulian Elischer 	if (ke->ke_bound && ((ke->ke_bound->td_flags & TDF_UNBOUND) == 0)) {
116248bfcdddSJulian Elischer 		return (NULL);
116348bfcdddSJulian Elischer 	}
116448bfcdddSJulian Elischer 	KASSERT((ke->ke_bound == NULL), ("kse already bound"));
116548bfcdddSJulian Elischer 
11660cf60970SDavid Xu 	if (ke->ke_state == KES_IDLE) {
11670cf60970SDavid Xu 		kg = ke->ke_ksegrp;
11680cf60970SDavid Xu 		TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
11690cf60970SDavid Xu 		kg->kg_idle_kses--;
11700cf60970SDavid Xu 		ke->ke_state = KES_UNQUEUED;
11710cf60970SDavid Xu 	}
117248bfcdddSJulian Elischer 	if ((td2 = td->td_standin) != NULL) {
117348bfcdddSJulian Elischer 		td->td_standin = NULL;
117444990b8cSJulian Elischer 	} else {
117548bfcdddSJulian Elischer 		if (newkse)
117648bfcdddSJulian Elischer 			panic("no reserve thread when called with a new kse");
117748bfcdddSJulian Elischer 		/*
117848bfcdddSJulian Elischer 		 * If called from (e.g.) sleep and we do not have
117948bfcdddSJulian Elischer 		 * a reserve thread, then we've used it, so do not
118048bfcdddSJulian Elischer 		 * create an upcall.
118148bfcdddSJulian Elischer 		 */
118248bfcdddSJulian Elischer 		return (NULL);
118344990b8cSJulian Elischer 	}
118444990b8cSJulian Elischer 	CTR3(KTR_PROC, "thread_schedule_upcall: thread %p (pid %d, %s)",
118548bfcdddSJulian Elischer 	     td2, td->td_proc->p_pid, td->td_proc->p_comm);
1186c0698d32SJulian Elischer 	bzero(&td2->td_startzero,
11871faf202eSJulian Elischer 	    (unsigned)RANGEOF(struct thread, td_startzero, td_endzero));
11881faf202eSJulian Elischer 	bcopy(&td->td_startcopy, &td2->td_startcopy,
11891faf202eSJulian Elischer 	    (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy));
119044990b8cSJulian Elischer 	thread_link(td2, ke->ke_ksegrp);
1191c76e33b6SJonathan Mini 	cpu_set_upcall(td2, td->td_pcb);
119248bfcdddSJulian Elischer 
1193c76e33b6SJonathan Mini 	/*
119448bfcdddSJulian Elischer 	 * XXXKSE do we really need this? (default values for the
119548bfcdddSJulian Elischer 	 * frame).
119648bfcdddSJulian Elischer 	 */
119748bfcdddSJulian Elischer 	bcopy(td->td_frame, td2->td_frame, sizeof(struct trapframe));
119848bfcdddSJulian Elischer 
119948bfcdddSJulian Elischer 	/*
120048bfcdddSJulian Elischer 	 * Bind the new thread to the KSE,
120148bfcdddSJulian Elischer 	 * and if it's our KSE, lend it back to ourself
120248bfcdddSJulian Elischer 	 * so we can continue running.
1203c76e33b6SJonathan Mini 	 */
120444990b8cSJulian Elischer 	td2->td_ucred = crhold(td->td_ucred);
120548bfcdddSJulian Elischer 	td2->td_flags = TDF_UPCALLING; /* note: BOUND */
120648bfcdddSJulian Elischer 	td2->td_kse = ke;
120748bfcdddSJulian Elischer 	td2->td_state = TDS_CAN_RUN;
120848bfcdddSJulian Elischer 	td2->td_inhibitors = 0;
120948bfcdddSJulian Elischer 	/*
121048bfcdddSJulian Elischer 	 * If called from msleep(), we are working on the current
121148bfcdddSJulian Elischer 	 * KSE so fake that we borrowed it. If called from
121248bfcdddSJulian Elischer 	 * kse_create(), don't, as we have a new kse too.
121348bfcdddSJulian Elischer 	 */
121448bfcdddSJulian Elischer 	if (!newkse) {
121548bfcdddSJulian Elischer 		/*
121648bfcdddSJulian Elischer 		 * This thread will be scheduled when the current thread
121748bfcdddSJulian Elischer 		 * blocks, exits or tries to enter userspace, (which ever
121848bfcdddSJulian Elischer 		 * happens first). When that happens the KSe will "revert"
121948bfcdddSJulian Elischer 		 * to this thread in a BOUND manner. Since we are called
122048bfcdddSJulian Elischer 		 * from msleep() this is going to be "very soon" in nearly
122148bfcdddSJulian Elischer 		 * all cases.
122248bfcdddSJulian Elischer 		 */
122348bfcdddSJulian Elischer 		ke->ke_bound = td2;
122448bfcdddSJulian Elischer 		TD_SET_LOAN(td2);
122548bfcdddSJulian Elischer 	} else {
122648bfcdddSJulian Elischer 		ke->ke_bound = NULL;
122748bfcdddSJulian Elischer 		ke->ke_thread = td2;
12280cf60970SDavid Xu 		ke->ke_state = KES_THREAD;
122944990b8cSJulian Elischer 		setrunqueue(td2);
123048bfcdddSJulian Elischer 	}
123148bfcdddSJulian Elischer 	return (td2);	/* bogus.. should be a void function */
123244990b8cSJulian Elischer }
123344990b8cSJulian Elischer 
123444990b8cSJulian Elischer /*
1235c76e33b6SJonathan Mini  * Schedule an upcall to notify a KSE process recieved signals.
123644990b8cSJulian Elischer  *
1237c76e33b6SJonathan Mini  * XXX - Modifying a sigset_t like this is totally bogus.
123844990b8cSJulian Elischer  */
1239c76e33b6SJonathan Mini struct thread *
1240c76e33b6SJonathan Mini signal_upcall(struct proc *p, int sig)
1241c76e33b6SJonathan Mini {
1242c76e33b6SJonathan Mini 	struct thread *td, *td2;
1243c76e33b6SJonathan Mini 	struct kse *ke;
1244c76e33b6SJonathan Mini 	sigset_t ss;
1245c76e33b6SJonathan Mini 	int error;
1246c76e33b6SJonathan Mini 
1247c76e33b6SJonathan Mini 	PROC_LOCK_ASSERT(p, MA_OWNED);
124848bfcdddSJulian Elischer return (NULL);
1249c76e33b6SJonathan Mini 
1250c76e33b6SJonathan Mini 	td = FIRST_THREAD_IN_PROC(p);
1251c76e33b6SJonathan Mini 	ke = td->td_kse;
1252c76e33b6SJonathan Mini 	PROC_UNLOCK(p);
1253c76e33b6SJonathan Mini 	error = copyin(&ke->ke_mailbox->km_sigscaught, &ss, sizeof(sigset_t));
1254c76e33b6SJonathan Mini 	PROC_LOCK(p);
1255c76e33b6SJonathan Mini 	if (error)
1256c76e33b6SJonathan Mini 		return (NULL);
1257c76e33b6SJonathan Mini 	SIGADDSET(ss, sig);
1258c76e33b6SJonathan Mini 	PROC_UNLOCK(p);
1259c76e33b6SJonathan Mini 	error = copyout(&ss, &ke->ke_mailbox->km_sigscaught, sizeof(sigset_t));
1260c76e33b6SJonathan Mini 	PROC_LOCK(p);
1261c76e33b6SJonathan Mini 	if (error)
1262c76e33b6SJonathan Mini 		return (NULL);
126348bfcdddSJulian Elischer 	if (td->td_standin == NULL)
126448bfcdddSJulian Elischer 		td->td_standin = thread_alloc();
1265c76e33b6SJonathan Mini 	mtx_lock_spin(&sched_lock);
126648bfcdddSJulian Elischer 	td2 = thread_schedule_upcall(td, ke); /* Bogus JRE */
1267c76e33b6SJonathan Mini 	mtx_unlock_spin(&sched_lock);
1268c76e33b6SJonathan Mini 	return (td2);
1269c76e33b6SJonathan Mini }
1270c76e33b6SJonathan Mini 
1271c76e33b6SJonathan Mini /*
12721434d3feSJulian Elischer  * setup done on the thread when it enters the kernel.
12731434d3feSJulian Elischer  * XXXKSE Presently only for syscalls but eventually all kernel entries.
12741434d3feSJulian Elischer  */
12751434d3feSJulian Elischer void
12761434d3feSJulian Elischer thread_user_enter(struct proc *p, struct thread *td)
12771434d3feSJulian Elischer {
12781434d3feSJulian Elischer 	struct kse *ke;
12791434d3feSJulian Elischer 
12801434d3feSJulian Elischer 	/*
12811434d3feSJulian Elischer 	 * First check that we shouldn't just abort.
12821434d3feSJulian Elischer 	 * But check if we are the single thread first!
12831434d3feSJulian Elischer 	 * XXX p_singlethread not locked, but should be safe.
12841434d3feSJulian Elischer 	 */
12851434d3feSJulian Elischer 	if ((p->p_flag & P_WEXIT) && (p->p_singlethread != td)) {
12861434d3feSJulian Elischer 		PROC_LOCK(p);
12871434d3feSJulian Elischer 		mtx_lock_spin(&sched_lock);
12881434d3feSJulian Elischer 		thread_exit();
12891434d3feSJulian Elischer 		/* NOTREACHED */
12901434d3feSJulian Elischer 	}
12911434d3feSJulian Elischer 
12921434d3feSJulian Elischer 	/*
12931434d3feSJulian Elischer 	 * If we are doing a syscall in a KSE environment,
12941434d3feSJulian Elischer 	 * note where our mailbox is. There is always the
12951434d3feSJulian Elischer 	 * possibility that we could do this lazily (in sleep()),
12961434d3feSJulian Elischer 	 * but for now do it every time.
12971434d3feSJulian Elischer 	 */
12984c40dcd4SDavid Xu 	ke = td->td_kse;
1299de4723f6SJulian Elischer 	if (ke->ke_mailbox != NULL) {
13001434d3feSJulian Elischer #if 0
13011434d3feSJulian Elischer 		td->td_mailbox = (void *)fuword((caddr_t)ke->ke_mailbox
13021434d3feSJulian Elischer 		    + offsetof(struct kse_mailbox, km_curthread));
13031434d3feSJulian Elischer #else /* if user pointer arithmetic is ok in the kernel */
13041434d3feSJulian Elischer 		td->td_mailbox =
13051434d3feSJulian Elischer 		    (void *)fuword( (void *)&ke->ke_mailbox->km_curthread);
13061434d3feSJulian Elischer #endif
13071434d3feSJulian Elischer 		if ((td->td_mailbox == NULL) ||
13088798d4f9SDavid Xu 		    (td->td_mailbox == (void *)-1)) {
13091434d3feSJulian Elischer 			td->td_mailbox = NULL;	/* single thread it.. */
13108798d4f9SDavid Xu 			mtx_lock_spin(&sched_lock);
13111434d3feSJulian Elischer 			td->td_flags &= ~TDF_UNBOUND;
13128798d4f9SDavid Xu 			mtx_unlock_spin(&sched_lock);
13138798d4f9SDavid Xu 		} else {
13148798d4f9SDavid Xu 			/*
13158798d4f9SDavid Xu 			 * when thread limit reached, act like that the thread
13168798d4f9SDavid Xu 			 * has already done an upcall.
13178798d4f9SDavid Xu 			 */
13188798d4f9SDavid Xu 		    	if (p->p_numthreads > max_threads_per_proc) {
13198798d4f9SDavid Xu 				if (td->td_standin != NULL)
13208798d4f9SDavid Xu 					thread_stash(td->td_standin);
13218798d4f9SDavid Xu 				td->td_standin = NULL;
13221434d3feSJulian Elischer 			} else {
13231434d3feSJulian Elischer 				if (td->td_standin == NULL)
13241434d3feSJulian Elischer 					td->td_standin = thread_alloc();
13258798d4f9SDavid Xu 			}
13268798d4f9SDavid Xu 			mtx_lock_spin(&sched_lock);
13271434d3feSJulian Elischer 			td->td_flags |= TDF_UNBOUND;
13288798d4f9SDavid Xu 			mtx_unlock_spin(&sched_lock);
13298798d4f9SDavid Xu 			td->td_usticks = 0;
13301434d3feSJulian Elischer 		}
13311434d3feSJulian Elischer 	}
13321434d3feSJulian Elischer }
13331434d3feSJulian Elischer 
13341434d3feSJulian Elischer /*
1335c76e33b6SJonathan Mini  * The extra work we go through if we are a threaded process when we
1336c76e33b6SJonathan Mini  * return to userland.
1337c76e33b6SJonathan Mini  *
1338c76e33b6SJonathan Mini  * If we are a KSE process and returning to user mode, check for
1339c76e33b6SJonathan Mini  * extra work to do before we return (e.g. for more syscalls
1340c76e33b6SJonathan Mini  * to complete first).  If we were in a critical section, we should
1341c76e33b6SJonathan Mini  * just return to let it finish. Same if we were in the UTS (in
1342c76e33b6SJonathan Mini  * which case the mailbox's context's busy indicator will be set).
1343c76e33b6SJonathan Mini  * The only traps we suport will have set the mailbox.
1344c76e33b6SJonathan Mini  * We will clear it here.
134544990b8cSJulian Elischer  */
1346c76e33b6SJonathan Mini int
1347253fdd5bSJulian Elischer thread_userret(struct thread *td, struct trapframe *frame)
1348c76e33b6SJonathan Mini {
1349c76e33b6SJonathan Mini 	int error;
13503d0586d4SJulian Elischer 	int unbound;
13513d0586d4SJulian Elischer 	struct kse *ke;
135248bfcdddSJulian Elischer 	struct ksegrp *kg;
135348bfcdddSJulian Elischer 	struct thread *td2;
135448bfcdddSJulian Elischer 	struct proc *p;
1355bfd83250SDavid Xu 	struct timespec ts;
1356c76e33b6SJonathan Mini 
135748bfcdddSJulian Elischer 	error = 0;
135848bfcdddSJulian Elischer 
135948bfcdddSJulian Elischer 	unbound = td->td_flags & TDF_UNBOUND;
136048bfcdddSJulian Elischer 
136148bfcdddSJulian Elischer 	kg = td->td_ksegrp;
136248bfcdddSJulian Elischer 	p = td->td_proc;
136348bfcdddSJulian Elischer 
136448bfcdddSJulian Elischer 	/*
136548bfcdddSJulian Elischer 	 * Originally bound threads never upcall but they may
136648bfcdddSJulian Elischer 	 * loan out their KSE at this point.
136748bfcdddSJulian Elischer 	 * Upcalls imply bound.. They also may want to do some Philantropy.
136848bfcdddSJulian Elischer 	 * Unbound threads on the other hand either yield to other work
136948bfcdddSJulian Elischer 	 * or transform into an upcall.
137048bfcdddSJulian Elischer 	 * (having saved their context to user space in both cases)
137148bfcdddSJulian Elischer 	 */
137248bfcdddSJulian Elischer 	if (unbound) {
137348bfcdddSJulian Elischer 		/*
137448bfcdddSJulian Elischer 		 * We are an unbound thread, looking to return to
137548bfcdddSJulian Elischer 		 * user space.
137648bfcdddSJulian Elischer 		 * THere are several possibilities:
137748bfcdddSJulian Elischer 		 * 1) we are using a borrowed KSE. save state and exit.
137848bfcdddSJulian Elischer 		 *    kse_reassign() will recycle the kse as needed,
137948bfcdddSJulian Elischer 		 * 2) we are not.. save state, and then convert ourself
138048bfcdddSJulian Elischer 		 *    to be an upcall, bound to the KSE.
138148bfcdddSJulian Elischer 		 *    if there are others that need the kse,
138248bfcdddSJulian Elischer 		 *    give them a chance by doing an mi_switch().
138348bfcdddSJulian Elischer 		 *    Because we are bound, control will eventually return
138448bfcdddSJulian Elischer 		 *    to us here.
138548bfcdddSJulian Elischer 		 * ***
138648bfcdddSJulian Elischer 		 * Save the thread's context, and link it
138748bfcdddSJulian Elischer 		 * into the KSEGRP's list of completed threads.
138848bfcdddSJulian Elischer 		 */
138948bfcdddSJulian Elischer 		error = thread_export_context(td);
139048bfcdddSJulian Elischer 		td->td_mailbox = NULL;
13918798d4f9SDavid Xu 		td->td_usticks = 0;
139248bfcdddSJulian Elischer 		if (error) {
139348bfcdddSJulian Elischer 			/*
139448bfcdddSJulian Elischer 			 * If we are not running on a borrowed KSE, then
139548bfcdddSJulian Elischer 			 * failing to do the KSE operation just defaults
139648bfcdddSJulian Elischer 			 * back to synchonous operation, so just return from
139748bfcdddSJulian Elischer 			 * the syscall. If it IS borrowed, there is nothing
139848bfcdddSJulian Elischer 			 * we can do. We just lose that context. We
139948bfcdddSJulian Elischer 			 * probably should note this somewhere and send
140048bfcdddSJulian Elischer 			 * the process a signal.
140148bfcdddSJulian Elischer 			 */
14029eb1fdeaSJulian Elischer 			PROC_LOCK(td->td_proc);
140348bfcdddSJulian Elischer 			psignal(td->td_proc, SIGSEGV);
14049eb1fdeaSJulian Elischer 			mtx_lock_spin(&sched_lock);
140548bfcdddSJulian Elischer 			if (td->td_kse->ke_bound == NULL) {
140648bfcdddSJulian Elischer 				td->td_flags &= ~TDF_UNBOUND;
140748bfcdddSJulian Elischer 				PROC_UNLOCK(td->td_proc);
140848bfcdddSJulian Elischer 				mtx_unlock_spin(&sched_lock);
14098798d4f9SDavid Xu 				thread_update_uticks();
141048bfcdddSJulian Elischer 				return (error);	/* go sync */
141148bfcdddSJulian Elischer 			}
14129eb1fdeaSJulian Elischer 			thread_exit();
14139eb1fdeaSJulian Elischer 		}
14149eb1fdeaSJulian Elischer 
1415c76e33b6SJonathan Mini 		/*
141648bfcdddSJulian Elischer 		 * if the KSE is owned and we are borrowing it,
141748bfcdddSJulian Elischer 		 * don't make an upcall, just exit so that the owner
141848bfcdddSJulian Elischer 		 * can get its KSE if it wants it.
141948bfcdddSJulian Elischer 		 * Our context is already safely stored for later
142048bfcdddSJulian Elischer 		 * use by the UTS.
142148bfcdddSJulian Elischer 		 */
142248bfcdddSJulian Elischer 		PROC_LOCK(p);
142348bfcdddSJulian Elischer 		mtx_lock_spin(&sched_lock);
142448bfcdddSJulian Elischer 		if (td->td_kse->ke_bound) {
142548bfcdddSJulian Elischer 			thread_exit();
142648bfcdddSJulian Elischer 		}
142748bfcdddSJulian Elischer 		PROC_UNLOCK(p);
142848bfcdddSJulian Elischer 
142948bfcdddSJulian Elischer 		/*
143048bfcdddSJulian Elischer 		 * Turn ourself into a bound upcall.
143148bfcdddSJulian Elischer 		 * We will rely on kse_reassign()
143248bfcdddSJulian Elischer 		 * to make us run at a later time.
143348bfcdddSJulian Elischer 		 * We should look just like a sheduled upcall
143448bfcdddSJulian Elischer 		 * from msleep() or cv_wait().
143548bfcdddSJulian Elischer 		 */
143648bfcdddSJulian Elischer 		td->td_flags &= ~TDF_UNBOUND;
143748bfcdddSJulian Elischer 		td->td_flags |= TDF_UPCALLING;
143848bfcdddSJulian Elischer 		/* Only get here if we have become an upcall */
143948bfcdddSJulian Elischer 
144048bfcdddSJulian Elischer 	} else {
144148bfcdddSJulian Elischer 		mtx_lock_spin(&sched_lock);
144248bfcdddSJulian Elischer 	}
144348bfcdddSJulian Elischer 	/*
144448bfcdddSJulian Elischer 	 * We ARE going back to userland with this KSE.
144548bfcdddSJulian Elischer 	 * Check for threads that need to borrow it.
144648bfcdddSJulian Elischer 	 * Optimisation: don't call mi_switch if no-one wants the KSE.
144748bfcdddSJulian Elischer 	 * Any other thread that comes ready after this missed the boat.
1448c76e33b6SJonathan Mini 	 */
14493d0586d4SJulian Elischer 	ke = td->td_kse;
145048bfcdddSJulian Elischer 	if ((td2 = kg->kg_last_assigned))
145148bfcdddSJulian Elischer 		td2 = TAILQ_NEXT(td2, td_runq);
145248bfcdddSJulian Elischer 	else
145348bfcdddSJulian Elischer 		td2 = TAILQ_FIRST(&kg->kg_runq);
145448bfcdddSJulian Elischer 	if (td2)  {
1455c76e33b6SJonathan Mini 		/*
145648bfcdddSJulian Elischer 		 * force a switch to more urgent 'in kernel'
145748bfcdddSJulian Elischer 		 * work. Control will return to this thread
145848bfcdddSJulian Elischer 		 * when there is no more work to do.
145948bfcdddSJulian Elischer 		 * kse_reassign() will do tha for us.
1460c76e33b6SJonathan Mini 		 */
146148bfcdddSJulian Elischer 		TD_SET_LOAN(td);
146248bfcdddSJulian Elischer 		ke->ke_bound = td;
146348bfcdddSJulian Elischer 		ke->ke_thread = NULL;
1464696058c3SJulian Elischer 		p->p_stats->p_ru.ru_nvcsw++;
146548bfcdddSJulian Elischer 		mi_switch(); /* kse_reassign() will (re)find td2 */
146648bfcdddSJulian Elischer 	}
146748bfcdddSJulian Elischer 	mtx_unlock_spin(&sched_lock);
146848bfcdddSJulian Elischer 
146948bfcdddSJulian Elischer 	/*
147048bfcdddSJulian Elischer 	 * Optimisation:
147148bfcdddSJulian Elischer 	 * Ensure that we have a spare thread available,
147248bfcdddSJulian Elischer 	 * for when we re-enter the kernel.
147348bfcdddSJulian Elischer 	 */
147448bfcdddSJulian Elischer 	if (td->td_standin == NULL) {
147548bfcdddSJulian Elischer 		td->td_standin = thread_alloc();
147648bfcdddSJulian Elischer 	}
147748bfcdddSJulian Elischer 
14788798d4f9SDavid Xu 	thread_update_uticks();
147948bfcdddSJulian Elischer 	/*
148048bfcdddSJulian Elischer 	 * To get here, we know there is no other need for our
148148bfcdddSJulian Elischer 	 * KSE so we can proceed. If not upcalling, go back to
148248bfcdddSJulian Elischer 	 * userspace. If we are, get the upcall set up.
148348bfcdddSJulian Elischer 	 */
148448bfcdddSJulian Elischer 	if ((td->td_flags & TDF_UPCALLING) == 0)
1485c76e33b6SJonathan Mini 		return (0);
148648bfcdddSJulian Elischer 
1487c76e33b6SJonathan Mini 	/*
148848bfcdddSJulian Elischer 	 * We must be an upcall to get this far.
148944990b8cSJulian Elischer 	 * There is no more work to do and we are going to ride
14903d0586d4SJulian Elischer 	 * this thead/KSE up to userland as an upcall.
149148bfcdddSJulian Elischer 	 * Do the last parts of the setup needed for the upcall.
149244990b8cSJulian Elischer 	 */
1493c76e33b6SJonathan Mini 	CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)",
1494ed32df81SJulian Elischer 	    td, td->td_proc->p_pid, td->td_proc->p_comm);
1495c76e33b6SJonathan Mini 
1496c76e33b6SJonathan Mini 	/*
1497c76e33b6SJonathan Mini 	 * Set user context to the UTS.
1498696058c3SJulian Elischer 	 * Will use Giant in cpu_thread_clean() because it uses
1499696058c3SJulian Elischer 	 * kmem_free(kernel_map, ...)
1500c76e33b6SJonathan Mini 	 */
15013d0586d4SJulian Elischer 	cpu_set_upcall_kse(td, ke);
15023d0586d4SJulian Elischer 
1503c76e33b6SJonathan Mini 	/*
15043d0586d4SJulian Elischer 	 * Put any completed mailboxes on this KSE's list.
1505c76e33b6SJonathan Mini 	 */
150648bfcdddSJulian Elischer 	error = thread_link_mboxes(kg, ke);
15073d0586d4SJulian Elischer 	if (error)
15083d0586d4SJulian Elischer 		goto bad;
1509c76e33b6SJonathan Mini 
1510c76e33b6SJonathan Mini 	/*
1511c76e33b6SJonathan Mini 	 * Set state and mailbox.
151248bfcdddSJulian Elischer 	 * From now on we are just a bound outgoing process.
151348bfcdddSJulian Elischer 	 * **Problem** userret is often called several times.
151448bfcdddSJulian Elischer 	 * it would be nice if this all happenned only on the first time
151548bfcdddSJulian Elischer 	 * through. (the scan for extra work etc.)
1516c76e33b6SJonathan Mini 	 */
151734e80e02SDavid Xu 	mtx_lock_spin(&sched_lock);
1518c76e33b6SJonathan Mini 	td->td_flags &= ~TDF_UPCALLING;
151934e80e02SDavid Xu 	mtx_unlock_spin(&sched_lock);
15203d0586d4SJulian Elischer #if 0
15213d0586d4SJulian Elischer 	error = suword((caddr_t)ke->ke_mailbox +
152248bfcdddSJulian Elischer 	    offsetof(struct kse_mailbox, km_curthread), 0);
15233d0586d4SJulian Elischer #else	/* if user pointer arithmetic is ok in the kernel */
15243d0586d4SJulian Elischer 	error = suword((caddr_t)&ke->ke_mailbox->km_curthread, 0);
15253d0586d4SJulian Elischer #endif
1526bfd83250SDavid Xu 	ke->ke_uuticks = ke->ke_usticks = 0;
1527bfd83250SDavid Xu 	if (!error) {
1528bfd83250SDavid Xu 		nanotime(&ts);
1529bfd83250SDavid Xu 		if (copyout(&ts, (caddr_t)&ke->ke_mailbox->km_timeofday,
1530bfd83250SDavid Xu 		    sizeof(ts))) {
1531bfd83250SDavid Xu 			goto bad;
1532bfd83250SDavid Xu 		}
1533bfd83250SDavid Xu 	}
153448bfcdddSJulian Elischer 	return (0);
153548bfcdddSJulian Elischer 
15363d0586d4SJulian Elischer bad:
15373d0586d4SJulian Elischer 	/*
15383d0586d4SJulian Elischer 	 * Things are going to be so screwed we should just kill the process.
15393d0586d4SJulian Elischer  	 * how do we do that?
15403d0586d4SJulian Elischer 	 */
154148bfcdddSJulian Elischer 	PROC_LOCK(td->td_proc);
154248bfcdddSJulian Elischer 	psignal(td->td_proc, SIGSEGV);
154348bfcdddSJulian Elischer 	PROC_UNLOCK(td->td_proc);
154448bfcdddSJulian Elischer 	return (error);	/* go sync */
154544990b8cSJulian Elischer }
154644990b8cSJulian Elischer 
154744990b8cSJulian Elischer /*
154844990b8cSJulian Elischer  * Enforce single-threading.
154944990b8cSJulian Elischer  *
155044990b8cSJulian Elischer  * Returns 1 if the caller must abort (another thread is waiting to
155144990b8cSJulian Elischer  * exit the process or similar). Process is locked!
155244990b8cSJulian Elischer  * Returns 0 when you are successfully the only thread running.
155344990b8cSJulian Elischer  * A process has successfully single threaded in the suspend mode when
155444990b8cSJulian Elischer  * There are no threads in user mode. Threads in the kernel must be
155544990b8cSJulian Elischer  * allowed to continue until they get to the user boundary. They may even
155644990b8cSJulian Elischer  * copy out their return values and data before suspending. They may however be
155744990b8cSJulian Elischer  * accellerated in reaching the user boundary as we will wake up
155844990b8cSJulian Elischer  * any sleeping threads that are interruptable. (PCATCH).
155944990b8cSJulian Elischer  */
156044990b8cSJulian Elischer int
156144990b8cSJulian Elischer thread_single(int force_exit)
156244990b8cSJulian Elischer {
156344990b8cSJulian Elischer 	struct thread *td;
156444990b8cSJulian Elischer 	struct thread *td2;
156544990b8cSJulian Elischer 	struct proc *p;
156644990b8cSJulian Elischer 
156744990b8cSJulian Elischer 	td = curthread;
156844990b8cSJulian Elischer 	p = td->td_proc;
1569696058c3SJulian Elischer 	mtx_assert(&Giant, MA_OWNED);
157044990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
157144990b8cSJulian Elischer 	KASSERT((td != NULL), ("curthread is NULL"));
157244990b8cSJulian Elischer 
157344990b8cSJulian Elischer 	if ((p->p_flag & P_KSES) == 0)
157444990b8cSJulian Elischer 		return (0);
157544990b8cSJulian Elischer 
1576e3b9bf71SJulian Elischer 	/* Is someone already single threading? */
1577e3b9bf71SJulian Elischer 	if (p->p_singlethread)
157844990b8cSJulian Elischer 		return (1);
157944990b8cSJulian Elischer 
15801279572aSDavid Xu 	if (force_exit == SINGLE_EXIT)
158144990b8cSJulian Elischer 		p->p_flag |= P_SINGLE_EXIT;
158244990b8cSJulian Elischer 	else
158344990b8cSJulian Elischer 		p->p_flag &= ~P_SINGLE_EXIT;
15841279572aSDavid Xu 	p->p_flag |= P_STOPPED_SINGLE;
158544990b8cSJulian Elischer 	p->p_singlethread = td;
15869d102777SJulian Elischer 	/* XXXKSE Which lock protects the below values? */
158744990b8cSJulian Elischer 	while ((p->p_numthreads - p->p_suspcount) != 1) {
158871fad9fdSJulian Elischer 		mtx_lock_spin(&sched_lock);
158944990b8cSJulian Elischer 		FOREACH_THREAD_IN_PROC(p, td2) {
159044990b8cSJulian Elischer 			if (td2 == td)
159144990b8cSJulian Elischer 				continue;
159271fad9fdSJulian Elischer 			if (TD_IS_INHIBITED(td2)) {
15931279572aSDavid Xu 				if (force_exit == SINGLE_EXIT) {
15949d102777SJulian Elischer 					if (TD_IS_SUSPENDED(td2)) {
159571fad9fdSJulian Elischer 						thread_unsuspend_one(td2);
159671fad9fdSJulian Elischer 					}
159733862f40SDavid Xu 					if (TD_ON_SLEEPQ(td2) &&
159833862f40SDavid Xu 					    (td2->td_flags & TDF_SINTR)) {
1599e3b9bf71SJulian Elischer 						if (td2->td_flags & TDF_CVWAITQ)
160033862f40SDavid Xu 							cv_abort(td2);
1601e3b9bf71SJulian Elischer 						else
160233862f40SDavid Xu 							abortsleep(td2);
160371fad9fdSJulian Elischer 					}
16049d102777SJulian Elischer 				} else {
16059d102777SJulian Elischer 					if (TD_IS_SUSPENDED(td2))
16069d102777SJulian Elischer 						continue;
16079d102777SJulian Elischer 					/* maybe other inhibitted states too? */
160856a6a23eSDavid Xu 					if (TD_IS_SLEEPING(td2))
16099d102777SJulian Elischer 						thread_suspend_one(td2);
161044990b8cSJulian Elischer 				}
161144990b8cSJulian Elischer 			}
16129d102777SJulian Elischer 		}
16139d102777SJulian Elischer 		/*
16149d102777SJulian Elischer 		 * Maybe we suspended some threads.. was it enough?
16159d102777SJulian Elischer 		 */
16169d102777SJulian Elischer 		if ((p->p_numthreads - p->p_suspcount) == 1) {
16179d102777SJulian Elischer 			mtx_unlock_spin(&sched_lock);
16189d102777SJulian Elischer 			break;
16199d102777SJulian Elischer 		}
16209d102777SJulian Elischer 
162144990b8cSJulian Elischer 		/*
162244990b8cSJulian Elischer 		 * Wake us up when everyone else has suspended.
1623e3b9bf71SJulian Elischer 		 * In the mean time we suspend as well.
162444990b8cSJulian Elischer 		 */
162571fad9fdSJulian Elischer 		thread_suspend_one(td);
162644990b8cSJulian Elischer 		mtx_unlock(&Giant);
162744990b8cSJulian Elischer 		PROC_UNLOCK(p);
1628696058c3SJulian Elischer 		p->p_stats->p_ru.ru_nvcsw++;
162944990b8cSJulian Elischer 		mi_switch();
163044990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
163144990b8cSJulian Elischer 		mtx_lock(&Giant);
163244990b8cSJulian Elischer 		PROC_LOCK(p);
163344990b8cSJulian Elischer 	}
16345c8329edSJulian Elischer 	if (force_exit == SINGLE_EXIT)
16355c8329edSJulian Elischer 		kse_purge(p, td);
163644990b8cSJulian Elischer 	return (0);
163744990b8cSJulian Elischer }
163844990b8cSJulian Elischer 
163944990b8cSJulian Elischer /*
164044990b8cSJulian Elischer  * Called in from locations that can safely check to see
164144990b8cSJulian Elischer  * whether we have to suspend or at least throttle for a
164244990b8cSJulian Elischer  * single-thread event (e.g. fork).
164344990b8cSJulian Elischer  *
164444990b8cSJulian Elischer  * Such locations include userret().
164544990b8cSJulian Elischer  * If the "return_instead" argument is non zero, the thread must be able to
164644990b8cSJulian Elischer  * accept 0 (caller may continue), or 1 (caller must abort) as a result.
164744990b8cSJulian Elischer  *
164844990b8cSJulian Elischer  * The 'return_instead' argument tells the function if it may do a
164944990b8cSJulian Elischer  * thread_exit() or suspend, or whether the caller must abort and back
165044990b8cSJulian Elischer  * out instead.
165144990b8cSJulian Elischer  *
165244990b8cSJulian Elischer  * If the thread that set the single_threading request has set the
165344990b8cSJulian Elischer  * P_SINGLE_EXIT bit in the process flags then this call will never return
165444990b8cSJulian Elischer  * if 'return_instead' is false, but will exit.
165544990b8cSJulian Elischer  *
165644990b8cSJulian Elischer  * P_SINGLE_EXIT | return_instead == 0| return_instead != 0
165744990b8cSJulian Elischer  *---------------+--------------------+---------------------
165844990b8cSJulian Elischer  *       0       | returns 0          |   returns 0 or 1
165944990b8cSJulian Elischer  *               | when ST ends       |   immediatly
166044990b8cSJulian Elischer  *---------------+--------------------+---------------------
166144990b8cSJulian Elischer  *       1       | thread exits       |   returns 1
166244990b8cSJulian Elischer  *               |                    |  immediatly
166344990b8cSJulian Elischer  * 0 = thread_exit() or suspension ok,
166444990b8cSJulian Elischer  * other = return error instead of stopping the thread.
166544990b8cSJulian Elischer  *
166644990b8cSJulian Elischer  * While a full suspension is under effect, even a single threading
166744990b8cSJulian Elischer  * thread would be suspended if it made this call (but it shouldn't).
166844990b8cSJulian Elischer  * This call should only be made from places where
166944990b8cSJulian Elischer  * thread_exit() would be safe as that may be the outcome unless
167044990b8cSJulian Elischer  * return_instead is set.
167144990b8cSJulian Elischer  */
167244990b8cSJulian Elischer int
167344990b8cSJulian Elischer thread_suspend_check(int return_instead)
167444990b8cSJulian Elischer {
1675ecafb24bSJuli Mallett 	struct thread *td;
1676ecafb24bSJuli Mallett 	struct proc *p;
16775c8329edSJulian Elischer 	struct kse *ke;
16785c8329edSJulian Elischer 	struct ksegrp *kg;
167944990b8cSJulian Elischer 
168044990b8cSJulian Elischer 	td = curthread;
168144990b8cSJulian Elischer 	p = td->td_proc;
16825c8329edSJulian Elischer 	kg = td->td_ksegrp;
168344990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
168444990b8cSJulian Elischer 	while (P_SHOULDSTOP(p)) {
16851279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
168644990b8cSJulian Elischer 			KASSERT(p->p_singlethread != NULL,
168744990b8cSJulian Elischer 			    ("singlethread not set"));
168844990b8cSJulian Elischer 			/*
1689e3b9bf71SJulian Elischer 			 * The only suspension in action is a
1690e3b9bf71SJulian Elischer 			 * single-threading. Single threader need not stop.
1691b6d5995eSJulian Elischer 			 * XXX Should be safe to access unlocked
1692b6d5995eSJulian Elischer 			 * as it can only be set to be true by us.
169344990b8cSJulian Elischer 			 */
1694e3b9bf71SJulian Elischer 			if (p->p_singlethread == td)
169544990b8cSJulian Elischer 				return (0);	/* Exempt from stopping. */
169644990b8cSJulian Elischer 		}
1697e3b9bf71SJulian Elischer 		if (return_instead)
169844990b8cSJulian Elischer 			return (1);
169944990b8cSJulian Elischer 
170044990b8cSJulian Elischer 		/*
170144990b8cSJulian Elischer 		 * If the process is waiting for us to exit,
170244990b8cSJulian Elischer 		 * this thread should just suicide.
17031279572aSDavid Xu 		 * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
170444990b8cSJulian Elischer 		 */
170544990b8cSJulian Elischer 		if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
170644990b8cSJulian Elischer 			mtx_lock_spin(&sched_lock);
170744990b8cSJulian Elischer 			while (mtx_owned(&Giant))
170844990b8cSJulian Elischer 				mtx_unlock(&Giant);
17095c8329edSJulian Elischer 			/*
17105c8329edSJulian Elischer 			 * free extra kses and ksegrps, we needn't worry
17115c8329edSJulian Elischer 			 * about if current thread is in same ksegrp as
17125c8329edSJulian Elischer 			 * p_singlethread and last kse in the group
17135c8329edSJulian Elischer 			 * could be killed, this is protected by kg_numthreads,
17145c8329edSJulian Elischer 			 * in this case, we deduce that kg_numthreads must > 1.
17155c8329edSJulian Elischer 			 */
17165c8329edSJulian Elischer 			ke = td->td_kse;
17175c8329edSJulian Elischer 			if (ke->ke_bound == NULL &&
17185c8329edSJulian Elischer 			    ((kg->kg_kses != 1) || (kg->kg_numthreads == 1)))
17195c8329edSJulian Elischer 				ke->ke_flags |= KEF_EXIT;
172044990b8cSJulian Elischer 			thread_exit();
172144990b8cSJulian Elischer 		}
172244990b8cSJulian Elischer 
172344990b8cSJulian Elischer 		/*
172444990b8cSJulian Elischer 		 * When a thread suspends, it just
172544990b8cSJulian Elischer 		 * moves to the processes's suspend queue
172644990b8cSJulian Elischer 		 * and stays there.
172744990b8cSJulian Elischer 		 *
172844990b8cSJulian Elischer 		 * XXXKSE if TDF_BOUND is true
172944990b8cSJulian Elischer 		 * it will not release it's KSE which might
173044990b8cSJulian Elischer 		 * lead to deadlock if there are not enough KSEs
173144990b8cSJulian Elischer 		 * to complete all waiting threads.
173244990b8cSJulian Elischer 		 * Maybe be able to 'lend' it out again.
173344990b8cSJulian Elischer 		 * (lent kse's can not go back to userland?)
173444990b8cSJulian Elischer 		 * and can only be lent in STOPPED state.
173544990b8cSJulian Elischer 		 */
1736721e5910SJulian Elischer 		mtx_lock_spin(&sched_lock);
17371279572aSDavid Xu 		if ((p->p_flag & P_STOPPED_SIG) &&
1738721e5910SJulian Elischer 		    (p->p_suspcount+1 == p->p_numthreads)) {
1739721e5910SJulian Elischer 			mtx_unlock_spin(&sched_lock);
1740721e5910SJulian Elischer 			PROC_LOCK(p->p_pptr);
1741721e5910SJulian Elischer 			if ((p->p_pptr->p_procsig->ps_flag &
1742721e5910SJulian Elischer 				PS_NOCLDSTOP) == 0) {
1743721e5910SJulian Elischer 				psignal(p->p_pptr, SIGCHLD);
1744721e5910SJulian Elischer 			}
1745721e5910SJulian Elischer 			PROC_UNLOCK(p->p_pptr);
17469b0e281bSJulian Elischer 			mtx_lock_spin(&sched_lock);
1747721e5910SJulian Elischer 		}
174844990b8cSJulian Elischer 		mtx_assert(&Giant, MA_NOTOWNED);
174971fad9fdSJulian Elischer 		thread_suspend_one(td);
175044990b8cSJulian Elischer 		PROC_UNLOCK(p);
17511279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
1752cf19bf91SJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
175371fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
1754cf19bf91SJulian Elischer 			}
1755cf19bf91SJulian Elischer 		}
175620568366SJulian Elischer 		p->p_stats->p_ru.ru_nivcsw++;
175744990b8cSJulian Elischer 		mi_switch();
175844990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
175944990b8cSJulian Elischer 		PROC_LOCK(p);
176044990b8cSJulian Elischer 	}
176144990b8cSJulian Elischer 	return (0);
176244990b8cSJulian Elischer }
176344990b8cSJulian Elischer 
176435c32a76SDavid Xu void
176535c32a76SDavid Xu thread_suspend_one(struct thread *td)
176635c32a76SDavid Xu {
176735c32a76SDavid Xu 	struct proc *p = td->td_proc;
176835c32a76SDavid Xu 
176935c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
177035c32a76SDavid Xu 	p->p_suspcount++;
177171fad9fdSJulian Elischer 	TD_SET_SUSPENDED(td);
177235c32a76SDavid Xu 	TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
177371fad9fdSJulian Elischer 	/*
177471fad9fdSJulian Elischer 	 * Hack: If we are suspending but are on the sleep queue
177571fad9fdSJulian Elischer 	 * then we are in msleep or the cv equivalent. We
177671fad9fdSJulian Elischer 	 * want to look like we have two Inhibitors.
17779d102777SJulian Elischer 	 * May already be set.. doesn't matter.
177871fad9fdSJulian Elischer 	 */
177971fad9fdSJulian Elischer 	if (TD_ON_SLEEPQ(td))
178071fad9fdSJulian Elischer 		TD_SET_SLEEPING(td);
178135c32a76SDavid Xu }
178235c32a76SDavid Xu 
178335c32a76SDavid Xu void
178435c32a76SDavid Xu thread_unsuspend_one(struct thread *td)
178535c32a76SDavid Xu {
178635c32a76SDavid Xu 	struct proc *p = td->td_proc;
178735c32a76SDavid Xu 
178835c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
178935c32a76SDavid Xu 	TAILQ_REMOVE(&p->p_suspended, td, td_runq);
179071fad9fdSJulian Elischer 	TD_CLR_SUSPENDED(td);
179135c32a76SDavid Xu 	p->p_suspcount--;
179271fad9fdSJulian Elischer 	setrunnable(td);
179335c32a76SDavid Xu }
179435c32a76SDavid Xu 
179544990b8cSJulian Elischer /*
179644990b8cSJulian Elischer  * Allow all threads blocked by single threading to continue running.
179744990b8cSJulian Elischer  */
179844990b8cSJulian Elischer void
179944990b8cSJulian Elischer thread_unsuspend(struct proc *p)
180044990b8cSJulian Elischer {
180144990b8cSJulian Elischer 	struct thread *td;
180244990b8cSJulian Elischer 
1803b6d5995eSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
180444990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
180544990b8cSJulian Elischer 	if (!P_SHOULDSTOP(p)) {
180644990b8cSJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
180735c32a76SDavid Xu 			thread_unsuspend_one(td);
180844990b8cSJulian Elischer 		}
18091279572aSDavid Xu 	} else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) &&
181044990b8cSJulian Elischer 	    (p->p_numthreads == p->p_suspcount)) {
181144990b8cSJulian Elischer 		/*
181244990b8cSJulian Elischer 		 * Stopping everything also did the job for the single
181344990b8cSJulian Elischer 		 * threading request. Now we've downgraded to single-threaded,
181444990b8cSJulian Elischer 		 * let it continue.
181544990b8cSJulian Elischer 		 */
181635c32a76SDavid Xu 		thread_unsuspend_one(p->p_singlethread);
181744990b8cSJulian Elischer 	}
181844990b8cSJulian Elischer }
181944990b8cSJulian Elischer 
182044990b8cSJulian Elischer void
182144990b8cSJulian Elischer thread_single_end(void)
182244990b8cSJulian Elischer {
182344990b8cSJulian Elischer 	struct thread *td;
182444990b8cSJulian Elischer 	struct proc *p;
182544990b8cSJulian Elischer 
182644990b8cSJulian Elischer 	td = curthread;
182744990b8cSJulian Elischer 	p = td->td_proc;
182844990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
18291279572aSDavid Xu 	p->p_flag &= ~P_STOPPED_SINGLE;
183044990b8cSJulian Elischer 	p->p_singlethread = NULL;
183149539972SJulian Elischer 	/*
183249539972SJulian Elischer 	 * If there are other threads they mey now run,
183349539972SJulian Elischer 	 * unless of course there is a blanket 'stop order'
183449539972SJulian Elischer 	 * on the process. The single threader must be allowed
183549539972SJulian Elischer 	 * to continue however as this is a bad place to stop.
183649539972SJulian Elischer 	 */
183749539972SJulian Elischer 	if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
183849539972SJulian Elischer 		mtx_lock_spin(&sched_lock);
183949539972SJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
184071fad9fdSJulian Elischer 			thread_unsuspend_one(td);
184144990b8cSJulian Elischer 		}
184249539972SJulian Elischer 		mtx_unlock_spin(&sched_lock);
184349539972SJulian Elischer 	}
184449539972SJulian Elischer }
184549539972SJulian Elischer 
184644990b8cSJulian Elischer 
1847