xref: /freebsd/sys/kern/kern_thread.c (revision 5c8329ed6c59b996347929db73bff3cbec1306e1)
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>
3844990b8cSJulian Elischer #include <sys/sysctl.h>
395c8329edSJulian Elischer #include <sys/sysproto.h>
4044990b8cSJulian Elischer #include <sys/filedesc.h>
4144990b8cSJulian Elischer #include <sys/tty.h>
4244990b8cSJulian Elischer #include <sys/signalvar.h>
4344990b8cSJulian Elischer #include <sys/sx.h>
4444990b8cSJulian Elischer #include <sys/user.h>
4544990b8cSJulian Elischer #include <sys/jail.h>
4644990b8cSJulian Elischer #include <sys/kse.h>
4744990b8cSJulian Elischer #include <sys/ktr.h>
48c76e33b6SJonathan Mini #include <sys/ucontext.h>
4944990b8cSJulian Elischer 
5044990b8cSJulian Elischer #include <vm/vm.h>
5144990b8cSJulian Elischer #include <vm/vm_object.h>
5244990b8cSJulian Elischer #include <vm/pmap.h>
5344990b8cSJulian Elischer #include <vm/uma.h>
5444990b8cSJulian Elischer #include <vm/vm_map.h>
5544990b8cSJulian Elischer 
5602fb42b0SPeter Wemm #include <machine/frame.h>
5702fb42b0SPeter Wemm 
5844990b8cSJulian Elischer /*
594f0db5e0SJulian Elischer  * KSEGRP related storage.
6044990b8cSJulian Elischer  */
614f0db5e0SJulian Elischer static uma_zone_t ksegrp_zone;
624f0db5e0SJulian Elischer static uma_zone_t kse_zone;
6344990b8cSJulian Elischer static uma_zone_t thread_zone;
6444990b8cSJulian Elischer 
654f0db5e0SJulian Elischer /* DEBUG ONLY */
6644990b8cSJulian Elischer SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0, "thread allocation");
6744990b8cSJulian Elischer static int oiks_debug = 1;	/* 0 disable, 1 printf, 2 enter debugger */
6844990b8cSJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, oiks, CTLFLAG_RW,
6944990b8cSJulian Elischer 	&oiks_debug, 0, "OIKS thread debug");
7044990b8cSJulian Elischer 
7148bfcdddSJulian Elischer static int max_threads_per_proc = 10;
724f0db5e0SJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, max_per_proc, CTLFLAG_RW,
734f0db5e0SJulian Elischer 	&max_threads_per_proc, 0, "Limit on threads per proc");
744f0db5e0SJulian Elischer 
7544990b8cSJulian Elischer #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
7644990b8cSJulian Elischer 
7744990b8cSJulian Elischer struct threadqueue zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads);
785c8329edSJulian Elischer TAILQ_HEAD(, kse) zombie_kses = TAILQ_HEAD_INITIALIZER(zombie_kses);
795c8329edSJulian Elischer TAILQ_HEAD(, ksegrp) zombie_ksegrps = TAILQ_HEAD_INITIALIZER(zombie_ksegrps);
8044990b8cSJulian Elischer struct mtx zombie_thread_lock;
8144990b8cSJulian Elischer MTX_SYSINIT(zombie_thread_lock, &zombie_thread_lock,
8244990b8cSJulian Elischer     "zombie_thread_lock", MTX_SPIN);
8344990b8cSJulian Elischer 
845c8329edSJulian Elischer 
855c8329edSJulian Elischer 
865c8329edSJulian Elischer void kse_purge(struct proc *p, struct thread *td);
8744990b8cSJulian Elischer /*
8844990b8cSJulian Elischer  * Pepare a thread for use.
8944990b8cSJulian Elischer  */
9044990b8cSJulian Elischer static void
9144990b8cSJulian Elischer thread_ctor(void *mem, int size, void *arg)
9244990b8cSJulian Elischer {
9344990b8cSJulian Elischer 	struct thread	*td;
9444990b8cSJulian Elischer 
9544990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
96b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
9744990b8cSJulian Elischer 
9844990b8cSJulian Elischer 	td = (struct thread *)mem;
9971fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
10044990b8cSJulian Elischer 	td->td_flags |= TDF_UNBOUND;
10144990b8cSJulian Elischer }
10244990b8cSJulian Elischer 
10344990b8cSJulian Elischer /*
10444990b8cSJulian Elischer  * Reclaim a thread after use.
10544990b8cSJulian Elischer  */
10644990b8cSJulian Elischer static void
10744990b8cSJulian Elischer thread_dtor(void *mem, int size, void *arg)
10844990b8cSJulian Elischer {
10944990b8cSJulian Elischer 	struct thread	*td;
11044990b8cSJulian Elischer 
11144990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
112b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
11344990b8cSJulian Elischer 
11444990b8cSJulian Elischer 	td = (struct thread *)mem;
11544990b8cSJulian Elischer 
11644990b8cSJulian Elischer #ifdef INVARIANTS
11744990b8cSJulian Elischer 	/* Verify that this thread is in a safe state to free. */
11844990b8cSJulian Elischer 	switch (td->td_state) {
11971fad9fdSJulian Elischer 	case TDS_INHIBITED:
12071fad9fdSJulian Elischer 	case TDS_RUNNING:
12171fad9fdSJulian Elischer 	case TDS_CAN_RUN:
12244990b8cSJulian Elischer 	case TDS_RUNQ:
12344990b8cSJulian Elischer 		/*
12444990b8cSJulian Elischer 		 * We must never unlink a thread that is in one of
12544990b8cSJulian Elischer 		 * these states, because it is currently active.
12644990b8cSJulian Elischer 		 */
12744990b8cSJulian Elischer 		panic("bad state for thread unlinking");
12844990b8cSJulian Elischer 		/* NOTREACHED */
12971fad9fdSJulian Elischer 	case TDS_INACTIVE:
13044990b8cSJulian Elischer 		break;
13144990b8cSJulian Elischer 	default:
13244990b8cSJulian Elischer 		panic("bad thread state");
13344990b8cSJulian Elischer 		/* NOTREACHED */
13444990b8cSJulian Elischer 	}
13544990b8cSJulian Elischer #endif
13644990b8cSJulian Elischer }
13744990b8cSJulian Elischer 
13844990b8cSJulian Elischer /*
13944990b8cSJulian Elischer  * Initialize type-stable parts of a thread (when newly created).
14044990b8cSJulian Elischer  */
14144990b8cSJulian Elischer static void
14244990b8cSJulian Elischer thread_init(void *mem, int size)
14344990b8cSJulian Elischer {
14444990b8cSJulian Elischer 	struct thread	*td;
14544990b8cSJulian Elischer 
14644990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
147b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
14844990b8cSJulian Elischer 
14944990b8cSJulian Elischer 	td = (struct thread *)mem;
150e6e24ff9SJulian Elischer 	mtx_lock(&Giant);
151316ec49aSScott Long 	pmap_new_thread(td, 0);
152e6e24ff9SJulian Elischer 	mtx_unlock(&Giant);
15344990b8cSJulian Elischer 	cpu_thread_setup(td);
15444990b8cSJulian Elischer }
15544990b8cSJulian Elischer 
15644990b8cSJulian Elischer /*
15744990b8cSJulian Elischer  * Tear down type-stable parts of a thread (just before being discarded).
15844990b8cSJulian Elischer  */
15944990b8cSJulian Elischer static void
16044990b8cSJulian Elischer thread_fini(void *mem, int size)
16144990b8cSJulian Elischer {
16244990b8cSJulian Elischer 	struct thread	*td;
16344990b8cSJulian Elischer 
16444990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
165b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
16644990b8cSJulian Elischer 
16744990b8cSJulian Elischer 	td = (struct thread *)mem;
16844990b8cSJulian Elischer 	pmap_dispose_thread(td);
16944990b8cSJulian Elischer }
17044990b8cSJulian Elischer 
17144990b8cSJulian Elischer /*
1725c8329edSJulian Elischer  * KSE is linked onto the idle queue.
1735c8329edSJulian Elischer  */
1745c8329edSJulian Elischer void
1755c8329edSJulian Elischer kse_link(struct kse *ke, struct ksegrp *kg)
1765c8329edSJulian Elischer {
1775c8329edSJulian Elischer 	struct proc *p = kg->kg_proc;
1785c8329edSJulian Elischer 
1795c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_kseq, ke, ke_kglist);
1805c8329edSJulian Elischer 	kg->kg_kses++;
1815c8329edSJulian Elischer 	ke->ke_state = KES_UNQUEUED;
1825c8329edSJulian Elischer 	ke->ke_proc	= p;
1835c8329edSJulian Elischer 	ke->ke_ksegrp	= kg;
1845c8329edSJulian Elischer 	ke->ke_thread	= NULL;
1855c8329edSJulian Elischer 	ke->ke_oncpu = NOCPU;
1865c8329edSJulian Elischer }
1875c8329edSJulian Elischer 
1885c8329edSJulian Elischer void
1895c8329edSJulian Elischer kse_unlink(struct kse *ke)
1905c8329edSJulian Elischer {
1915c8329edSJulian Elischer 	struct ksegrp *kg;
1925c8329edSJulian Elischer 
1935c8329edSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
1945c8329edSJulian Elischer 	kg = ke->ke_ksegrp;
1955c8329edSJulian Elischer 	if (ke->ke_state == KES_IDLE) {
1965c8329edSJulian Elischer 		kg->kg_idle_kses--;
1975c8329edSJulian Elischer 		TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
1985c8329edSJulian Elischer 	}
1995c8329edSJulian Elischer 
2005c8329edSJulian Elischer 	TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
2015c8329edSJulian Elischer 	if (--kg->kg_kses == 0) {
2025c8329edSJulian Elischer 			ksegrp_unlink(kg);
2035c8329edSJulian Elischer 	}
2045c8329edSJulian Elischer 	/*
2055c8329edSJulian Elischer 	 * Aggregate stats from the KSE
2065c8329edSJulian Elischer 	 */
2075c8329edSJulian Elischer 	kse_stash(ke);
2085c8329edSJulian Elischer }
2095c8329edSJulian Elischer 
2105c8329edSJulian Elischer void
2115c8329edSJulian Elischer ksegrp_link(struct ksegrp *kg, struct proc *p)
2125c8329edSJulian Elischer {
2135c8329edSJulian Elischer 
2145c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_threads);
2155c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_runq);	/* links with td_runq */
2165c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_slpq);	/* links with td_runq */
2175c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_kseq);	/* all kses in ksegrp */
2185c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_iq);		/* idle kses in ksegrp */
2195c8329edSJulian Elischer 	TAILQ_INIT(&kg->kg_lq);		/* loan kses in ksegrp */
2205c8329edSJulian Elischer 	kg->kg_proc	= p;
2215c8329edSJulian Elischer /* the following counters are in the -zero- section and may not need clearing */
2225c8329edSJulian Elischer 	kg->kg_numthreads = 0;
2235c8329edSJulian Elischer 	kg->kg_runnable = 0;
2245c8329edSJulian Elischer 	kg->kg_kses = 0;
2255c8329edSJulian Elischer 	kg->kg_idle_kses = 0;
2265c8329edSJulian Elischer 	kg->kg_loan_kses = 0;
2275c8329edSJulian Elischer 	kg->kg_runq_kses = 0; /* XXXKSE change name */
2285c8329edSJulian Elischer /* link it in now that it's consistent */
2295c8329edSJulian Elischer 	p->p_numksegrps++;
2305c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_ksegrps, kg, kg_ksegrp);
2315c8329edSJulian Elischer }
2325c8329edSJulian Elischer 
2335c8329edSJulian Elischer void
2345c8329edSJulian Elischer ksegrp_unlink(struct ksegrp *kg)
2355c8329edSJulian Elischer {
2365c8329edSJulian Elischer 	struct proc *p;
2375c8329edSJulian Elischer 
2385c8329edSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
2395c8329edSJulian Elischer 	p = kg->kg_proc;
2405c8329edSJulian Elischer 	KASSERT(((kg->kg_numthreads == 0) && (kg->kg_kses == 0)),
2415c8329edSJulian Elischer 	    ("kseg_unlink: residual threads or KSEs"));
2425c8329edSJulian Elischer 	TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp);
2435c8329edSJulian Elischer 	p->p_numksegrps--;
2445c8329edSJulian Elischer 	/*
2455c8329edSJulian Elischer 	 * Aggregate stats from the KSE
2465c8329edSJulian Elischer 	 */
2475c8329edSJulian Elischer 	ksegrp_stash(kg);
2485c8329edSJulian Elischer }
2495c8329edSJulian Elischer 
2505c8329edSJulian Elischer /*
2515c8329edSJulian Elischer  * for a newly created process,
2525c8329edSJulian Elischer  * link up a the structure and its initial threads etc.
2535c8329edSJulian Elischer  */
2545c8329edSJulian Elischer void
2555c8329edSJulian Elischer proc_linkup(struct proc *p, struct ksegrp *kg,
2565c8329edSJulian Elischer 			struct kse *ke, struct thread *td)
2575c8329edSJulian Elischer {
2585c8329edSJulian Elischer 
2595c8329edSJulian Elischer 	TAILQ_INIT(&p->p_ksegrps);	     /* all ksegrps in proc */
2605c8329edSJulian Elischer 	TAILQ_INIT(&p->p_threads);	     /* all threads in proc */
2615c8329edSJulian Elischer 	TAILQ_INIT(&p->p_suspended);	     /* Threads suspended */
2625c8329edSJulian Elischer 	p->p_numksegrps = 0;
2635c8329edSJulian Elischer 	p->p_numthreads = 0;
2645c8329edSJulian Elischer 
2655c8329edSJulian Elischer 	ksegrp_link(kg, p);
2665c8329edSJulian Elischer 	kse_link(ke, kg);
2675c8329edSJulian Elischer 	thread_link(td, kg);
2685c8329edSJulian Elischer }
2695c8329edSJulian Elischer 
2705c8329edSJulian Elischer int
2715c8329edSJulian Elischer kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
2725c8329edSJulian Elischer {
2735c8329edSJulian Elischer 
2745c8329edSJulian Elischer 	return(ENOSYS);
2755c8329edSJulian Elischer }
2765c8329edSJulian Elischer 
2775c8329edSJulian Elischer int
2785c8329edSJulian Elischer kse_exit(struct thread *td, struct kse_exit_args *uap)
2795c8329edSJulian Elischer {
2805c8329edSJulian Elischer 	struct proc *p;
2815c8329edSJulian Elischer 	struct ksegrp *kg;
2825c8329edSJulian Elischer 
2835c8329edSJulian Elischer 	p = td->td_proc;
2845c8329edSJulian Elischer 	/* KSE-enabled processes only, please. */
2855c8329edSJulian Elischer 	if (!(p->p_flag & P_KSES))
2865c8329edSJulian Elischer 		return EINVAL;
2875c8329edSJulian Elischer 	/* must be a bound thread */
2885c8329edSJulian Elischer 	if (td->td_flags & TDF_UNBOUND)
2895c8329edSJulian Elischer 		return EINVAL;
2905c8329edSJulian Elischer 	kg = td->td_ksegrp;
2915c8329edSJulian Elischer 	/* serialize killing kse */
2925c8329edSJulian Elischer 	PROC_LOCK(p);
2935c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
2945c8329edSJulian Elischer 	if ((kg->kg_kses == 1) && (kg->kg_numthreads > 1)) {
2955c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
2965c8329edSJulian Elischer 		PROC_UNLOCK(p);
2975c8329edSJulian Elischer 		return (EDEADLK);
2985c8329edSJulian Elischer 	}
2995c8329edSJulian Elischer 	if ((p->p_numthreads == 1) && (p->p_numksegrps == 1)) {
3005c8329edSJulian Elischer 		p->p_flag &= ~P_KSES;
3015c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
3025c8329edSJulian Elischer 		PROC_UNLOCK(p);
3035c8329edSJulian Elischer 	} else {
3045c8329edSJulian Elischer 		while (mtx_owned(&Giant))
3055c8329edSJulian Elischer 			mtx_unlock(&Giant);
3065c8329edSJulian Elischer 		td->td_kse->ke_flags |= KEF_EXIT;
3075c8329edSJulian Elischer 		thread_exit();
3085c8329edSJulian Elischer 		/* NOTREACHED */
3095c8329edSJulian Elischer 	}
3105c8329edSJulian Elischer 	return 0;
3115c8329edSJulian Elischer }
3125c8329edSJulian Elischer 
3135c8329edSJulian Elischer int
3145c8329edSJulian Elischer kse_release(struct thread *td, struct kse_release_args *uap)
3155c8329edSJulian Elischer {
3165c8329edSJulian Elischer 	struct proc *p;
3175c8329edSJulian Elischer 
3185c8329edSJulian Elischer 	p = td->td_proc;
3195c8329edSJulian Elischer 	/* KSE-enabled processes only, please. */
3205c8329edSJulian Elischer 	if (p->p_flag & P_KSES) {
3215c8329edSJulian Elischer 		PROC_LOCK(p);
3225c8329edSJulian Elischer 		mtx_lock_spin(&sched_lock);
3235c8329edSJulian Elischer 		thread_exit();
3245c8329edSJulian Elischer 		/* NOTREACHED */
3255c8329edSJulian Elischer 	}
3265c8329edSJulian Elischer 	return (EINVAL);
3275c8329edSJulian Elischer }
3285c8329edSJulian Elischer 
3295c8329edSJulian Elischer /* struct kse_wakeup_args {
3305c8329edSJulian Elischer 	struct kse_mailbox *mbx;
3315c8329edSJulian Elischer }; */
3325c8329edSJulian Elischer int
3335c8329edSJulian Elischer kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
3345c8329edSJulian Elischer {
3355c8329edSJulian Elischer 	struct proc *p;
3365c8329edSJulian Elischer 	struct kse *ke, *ke2;
3375c8329edSJulian Elischer 	struct ksegrp *kg;
3385c8329edSJulian Elischer 
3395c8329edSJulian Elischer 	p = td->td_proc;
3405c8329edSJulian Elischer 	/* KSE-enabled processes only, please. */
3415c8329edSJulian Elischer 	if (!(p->p_flag & P_KSES))
3425c8329edSJulian Elischer 		return EINVAL;
3435c8329edSJulian Elischer 	if (td->td_standin == NULL)
3445c8329edSJulian Elischer 		td->td_standin = thread_alloc();
3455c8329edSJulian Elischer 	ke = NULL;
3465c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
3475c8329edSJulian Elischer 	if (uap->mbx) {
3485c8329edSJulian Elischer 		FOREACH_KSEGRP_IN_PROC(p, kg) {
3495c8329edSJulian Elischer 			FOREACH_KSE_IN_GROUP(kg, ke2) {
3505c8329edSJulian Elischer 				if (ke2->ke_mailbox != uap->mbx)
3515c8329edSJulian Elischer 					continue;
3525c8329edSJulian Elischer 				if (ke2->ke_state == KES_IDLE) {
3535c8329edSJulian Elischer 					ke = ke2;
3545c8329edSJulian Elischer 					goto found;
3555c8329edSJulian Elischer 				} else {
3565c8329edSJulian Elischer 					mtx_unlock_spin(&sched_lock);
3575c8329edSJulian Elischer 					td->td_retval[0] = 0;
3585c8329edSJulian Elischer 					td->td_retval[1] = 0;
3595c8329edSJulian Elischer 					return 0;
3605c8329edSJulian Elischer 				}
3615c8329edSJulian Elischer 			}
3625c8329edSJulian Elischer 		}
3635c8329edSJulian Elischer 	} else {
3645c8329edSJulian Elischer 		kg = td->td_ksegrp;
3655c8329edSJulian Elischer 		ke = TAILQ_FIRST(&kg->kg_iq);
3665c8329edSJulian Elischer 	}
3675c8329edSJulian Elischer 	if (ke == NULL) {
3685c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
3695c8329edSJulian Elischer 		return ESRCH;
3705c8329edSJulian Elischer 	}
3715c8329edSJulian Elischer found:
3725c8329edSJulian Elischer 	thread_schedule_upcall(td, ke);
3735c8329edSJulian Elischer 	mtx_unlock_spin(&sched_lock);
3745c8329edSJulian Elischer 	td->td_retval[0] = 0;
3755c8329edSJulian Elischer 	td->td_retval[1] = 0;
3765c8329edSJulian Elischer 	return 0;
3775c8329edSJulian Elischer }
3785c8329edSJulian Elischer 
3795c8329edSJulian Elischer /*
3805c8329edSJulian Elischer  * No new KSEG: first call: use current KSE, don't schedule an upcall
3815c8329edSJulian Elischer  * All other situations, do allocate a new KSE and schedule an upcall on it.
3825c8329edSJulian Elischer  */
3835c8329edSJulian Elischer /* struct kse_create_args {
3845c8329edSJulian Elischer 	struct kse_mailbox *mbx;
3855c8329edSJulian Elischer 	int newgroup;
3865c8329edSJulian Elischer }; */
3875c8329edSJulian Elischer int
3885c8329edSJulian Elischer kse_create(struct thread *td, struct kse_create_args *uap)
3895c8329edSJulian Elischer {
3905c8329edSJulian Elischer 	struct kse *newke;
3915c8329edSJulian Elischer 	struct kse *ke;
3925c8329edSJulian Elischer 	struct ksegrp *newkg;
3935c8329edSJulian Elischer 	struct ksegrp *kg;
3945c8329edSJulian Elischer 	struct proc *p;
3955c8329edSJulian Elischer 	struct kse_mailbox mbx;
3965c8329edSJulian Elischer 	int err;
3975c8329edSJulian Elischer 
3985c8329edSJulian Elischer 	p = td->td_proc;
3995c8329edSJulian Elischer 	if ((err = copyin(uap->mbx, &mbx, sizeof(mbx))))
4005c8329edSJulian Elischer 		return (err);
4015c8329edSJulian Elischer 
4025c8329edSJulian Elischer 	p->p_flag |= P_KSES; /* easier to just set it than to test and set */
4035c8329edSJulian Elischer 	kg = td->td_ksegrp;
4045c8329edSJulian Elischer 	if (uap->newgroup) {
4055c8329edSJulian Elischer 		/*
4065c8329edSJulian Elischer 		 * If we want a new KSEGRP it doesn't matter whether
4075c8329edSJulian Elischer 		 * we have already fired up KSE mode before or not.
4085c8329edSJulian Elischer 		 * We put the process in KSE mode and create a new KSEGRP
4095c8329edSJulian Elischer 		 * and KSE. If our KSE has not got a mailbox yet then
4105c8329edSJulian Elischer 		 * that doesn't matter, just leave it that way. It will
4115c8329edSJulian Elischer 		 * ensure that this thread stay BOUND. It's possible
4125c8329edSJulian Elischer 		 * that the call came form a threaded library and the main
4135c8329edSJulian Elischer 		 * program knows nothing of threads.
4145c8329edSJulian Elischer 		 */
4155c8329edSJulian Elischer 		newkg = ksegrp_alloc();
4165c8329edSJulian Elischer 		bzero(&newkg->kg_startzero, RANGEOF(struct ksegrp,
4175c8329edSJulian Elischer 		      kg_startzero, kg_endzero));
4185c8329edSJulian Elischer 		bcopy(&kg->kg_startcopy, &newkg->kg_startcopy,
4195c8329edSJulian Elischer 		      RANGEOF(struct ksegrp, kg_startcopy, kg_endcopy));
4205c8329edSJulian Elischer 		newke = kse_alloc();
4215c8329edSJulian Elischer 	} else {
4225c8329edSJulian Elischer 		/*
4235c8329edSJulian Elischer 		 * Otherwise, if we have already set this KSE
4245c8329edSJulian Elischer 		 * to have a mailbox, we want to make another KSE here,
4255c8329edSJulian Elischer 		 * but only if there are not already the limit, which
4265c8329edSJulian Elischer 		 * is 1 per CPU max.
4275c8329edSJulian Elischer 		 *
4285c8329edSJulian Elischer 		 * If the current KSE doesn't have a mailbox we just use it
4295c8329edSJulian Elischer 		 * and give it one.
4305c8329edSJulian Elischer 		 *
4315c8329edSJulian Elischer 		 * Because we don't like to access
4325c8329edSJulian Elischer 		 * the KSE outside of schedlock if we are UNBOUND,
4335c8329edSJulian Elischer 		 * (because it can change if we are preempted by an interrupt)
4345c8329edSJulian Elischer 		 * we can deduce it as having a mailbox if we are UNBOUND,
4355c8329edSJulian Elischer 		 * and only need to actually look at it if we are BOUND,
4365c8329edSJulian Elischer 		 * which is safe.
4375c8329edSJulian Elischer 		 */
4385c8329edSJulian Elischer 		if ((td->td_flags & TDF_UNBOUND) || td->td_kse->ke_mailbox) {
4395c8329edSJulian Elischer #if 0  /* while debugging */
4405c8329edSJulian Elischer #ifdef SMP
4415c8329edSJulian Elischer 			if (kg->kg_kses > mp_ncpus)
4425c8329edSJulian Elischer #endif
4435c8329edSJulian Elischer 				return (EPROCLIM);
4445c8329edSJulian Elischer #endif
4455c8329edSJulian Elischer 			newke = kse_alloc();
4465c8329edSJulian Elischer 		} else {
4475c8329edSJulian Elischer 			newke = NULL;
4485c8329edSJulian Elischer 		}
4495c8329edSJulian Elischer 		newkg = NULL;
4505c8329edSJulian Elischer 	}
4515c8329edSJulian Elischer 	if (newke) {
4525c8329edSJulian Elischer 		bzero(&newke->ke_startzero, RANGEOF(struct kse,
4535c8329edSJulian Elischer 		      ke_startzero, ke_endzero));
4545c8329edSJulian Elischer #if 0
4555c8329edSJulian Elischer 		bcopy(&ke->ke_startcopy, &newke->ke_startcopy,
4565c8329edSJulian Elischer 		      RANGEOF(struct kse, ke_startcopy, ke_endcopy));
4575c8329edSJulian Elischer #endif
4585c8329edSJulian Elischer 		PROC_LOCK(p);
4595c8329edSJulian Elischer 		if (SIGPENDING(p))
4605c8329edSJulian Elischer 			newke->ke_flags |= KEF_ASTPENDING;
4615c8329edSJulian Elischer 		PROC_UNLOCK(p);
4625c8329edSJulian Elischer 		/* For the first call this may not have been set */
4635c8329edSJulian Elischer 		if (td->td_standin == NULL) {
4645c8329edSJulian Elischer 			td->td_standin = thread_alloc();
4655c8329edSJulian Elischer 		}
4665c8329edSJulian Elischer 		mtx_lock_spin(&sched_lock);
4675c8329edSJulian Elischer 		if (newkg)
4685c8329edSJulian Elischer 			ksegrp_link(newkg, p);
4695c8329edSJulian Elischer 		else
4705c8329edSJulian Elischer 			newkg = kg;
4715c8329edSJulian Elischer 		kse_link(newke, newkg);
4725c8329edSJulian Elischer 		newke->ke_mailbox = uap->mbx;
4735c8329edSJulian Elischer 		newke->ke_upcall = mbx.km_func;
4745c8329edSJulian Elischer 		bcopy(&mbx.km_stack, &newke->ke_stack, sizeof(stack_t));
4755c8329edSJulian Elischer 		thread_schedule_upcall(td, newke);
4765c8329edSJulian Elischer 		mtx_unlock_spin(&sched_lock);
4775c8329edSJulian Elischer 	} else {
4785c8329edSJulian Elischer 		/*
4795c8329edSJulian Elischer 		 * If we didn't allocate a new KSE then the we are using
4805c8329edSJulian Elischer 		 * the exisiting (BOUND) kse.
4815c8329edSJulian Elischer 		 */
4825c8329edSJulian Elischer 		ke = td->td_kse;
4835c8329edSJulian Elischer 		ke->ke_mailbox = uap->mbx;
4845c8329edSJulian Elischer 		ke->ke_upcall = mbx.km_func;
4855c8329edSJulian Elischer 		bcopy(&mbx.km_stack, &ke->ke_stack, sizeof(stack_t));
4865c8329edSJulian Elischer 	}
4875c8329edSJulian Elischer 	/*
4885c8329edSJulian Elischer 	 * Fill out the KSE-mode specific fields of the new kse.
4895c8329edSJulian Elischer 	 */
4905c8329edSJulian Elischer 
4915c8329edSJulian Elischer 	td->td_retval[0] = 0;
4925c8329edSJulian Elischer 	td->td_retval[1] = 0;
4935c8329edSJulian Elischer 	return (0);
4945c8329edSJulian Elischer }
4955c8329edSJulian Elischer 
4965c8329edSJulian Elischer /*
497c76e33b6SJonathan Mini  * Fill a ucontext_t with a thread's context information.
498c76e33b6SJonathan Mini  *
499c76e33b6SJonathan Mini  * This is an analogue to getcontext(3).
500c76e33b6SJonathan Mini  */
501c76e33b6SJonathan Mini void
502c76e33b6SJonathan Mini thread_getcontext(struct thread *td, ucontext_t *uc)
503c76e33b6SJonathan Mini {
504c76e33b6SJonathan Mini 
505acaa1566SPeter Wemm /*
506acaa1566SPeter Wemm  * XXX this is declared in a MD include file, i386/include/ucontext.h but
507acaa1566SPeter Wemm  * is used in MI code.
508acaa1566SPeter Wemm  */
5091e19df33SPeter Wemm #ifdef __i386__
510c76e33b6SJonathan Mini 	get_mcontext(td, &uc->uc_mcontext);
5111e19df33SPeter Wemm #endif
512c76e33b6SJonathan Mini 	uc->uc_sigmask = td->td_proc->p_sigmask;
513c76e33b6SJonathan Mini }
514c76e33b6SJonathan Mini 
515c76e33b6SJonathan Mini /*
516c76e33b6SJonathan Mini  * Set a thread's context from a ucontext_t.
517c76e33b6SJonathan Mini  *
518c76e33b6SJonathan Mini  * This is an analogue to setcontext(3).
519c76e33b6SJonathan Mini  */
520c76e33b6SJonathan Mini int
521c76e33b6SJonathan Mini thread_setcontext(struct thread *td, ucontext_t *uc)
522c76e33b6SJonathan Mini {
523c76e33b6SJonathan Mini 	int ret;
524c76e33b6SJonathan Mini 
525acaa1566SPeter Wemm /*
526acaa1566SPeter Wemm  * XXX this is declared in a MD include file, i386/include/ucontext.h but
527acaa1566SPeter Wemm  * is used in MI code.
528acaa1566SPeter Wemm  */
5291e19df33SPeter Wemm #ifdef __i386__
530c76e33b6SJonathan Mini 	ret = set_mcontext(td, &uc->uc_mcontext);
5311e19df33SPeter Wemm #else
5321e19df33SPeter Wemm 	ret = ENOSYS;
5331e19df33SPeter Wemm #endif
534c76e33b6SJonathan Mini 	if (ret == 0) {
535c76e33b6SJonathan Mini 		SIG_CANTMASK(uc->uc_sigmask);
536c76e33b6SJonathan Mini 		PROC_LOCK(td->td_proc);
537c76e33b6SJonathan Mini 		td->td_proc->p_sigmask = uc->uc_sigmask;
538c76e33b6SJonathan Mini 		PROC_UNLOCK(td->td_proc);
539c76e33b6SJonathan Mini 	}
540c76e33b6SJonathan Mini 	return (ret);
541c76e33b6SJonathan Mini }
542c76e33b6SJonathan Mini 
543c76e33b6SJonathan Mini /*
54444990b8cSJulian Elischer  * Initialize global thread allocation resources.
54544990b8cSJulian Elischer  */
54644990b8cSJulian Elischer void
54744990b8cSJulian Elischer threadinit(void)
54844990b8cSJulian Elischer {
54944990b8cSJulian Elischer 
550c281972eSPeter Wemm #ifndef __ia64__
55144990b8cSJulian Elischer 	thread_zone = uma_zcreate("THREAD", sizeof (struct thread),
55244990b8cSJulian Elischer 	    thread_ctor, thread_dtor, thread_init, thread_fini,
55344990b8cSJulian Elischer 	    UMA_ALIGN_CACHE, 0);
554c281972eSPeter Wemm #else
555c281972eSPeter Wemm 	/*
556c281972eSPeter Wemm 	 * XXX the ia64 kstack allocator is really lame and is at the mercy
557c281972eSPeter Wemm 	 * of contigmallloc().  This hackery is to pre-construct a whole
558c281972eSPeter Wemm 	 * pile of thread structures with associated kernel stacks early
559c281972eSPeter Wemm 	 * in the system startup while contigmalloc() still works. Once we
560c281972eSPeter Wemm 	 * have them, keep them.  Sigh.
561c281972eSPeter Wemm 	 */
562c281972eSPeter Wemm 	thread_zone = uma_zcreate("THREAD", sizeof (struct thread),
563c281972eSPeter Wemm 	    thread_ctor, thread_dtor, thread_init, thread_fini,
564c281972eSPeter Wemm 	    UMA_ALIGN_CACHE, UMA_ZONE_NOFREE);
565c281972eSPeter Wemm 	uma_prealloc(thread_zone, 512);		/* XXX arbitary */
566c281972eSPeter Wemm #endif
5674f0db5e0SJulian Elischer 	ksegrp_zone = uma_zcreate("KSEGRP", sizeof (struct ksegrp),
5684f0db5e0SJulian Elischer 	    NULL, NULL, NULL, NULL,
5694f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
5704f0db5e0SJulian Elischer 	kse_zone = uma_zcreate("KSE", sizeof (struct kse),
5714f0db5e0SJulian Elischer 	    NULL, NULL, NULL, NULL,
5724f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
57344990b8cSJulian Elischer }
57444990b8cSJulian Elischer 
57544990b8cSJulian Elischer /*
5761faf202eSJulian Elischer  * Stash an embarasingly extra thread into the zombie thread queue.
57744990b8cSJulian Elischer  */
57844990b8cSJulian Elischer void
57944990b8cSJulian Elischer thread_stash(struct thread *td)
58044990b8cSJulian Elischer {
58144990b8cSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
58244990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_threads, td, td_runq);
58344990b8cSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
58444990b8cSJulian Elischer }
58544990b8cSJulian Elischer 
58644990b8cSJulian Elischer /*
5875c8329edSJulian Elischer  * Stash an embarasingly extra kse into the zombie kse queue.
5885c8329edSJulian Elischer  */
5895c8329edSJulian Elischer void
5905c8329edSJulian Elischer kse_stash(struct kse *ke)
5915c8329edSJulian Elischer {
5925c8329edSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
5935c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_kses, ke, ke_procq);
5945c8329edSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
5955c8329edSJulian Elischer }
5965c8329edSJulian Elischer 
5975c8329edSJulian Elischer /*
5985c8329edSJulian Elischer  * Stash an embarasingly extra ksegrp into the zombie ksegrp queue.
5995c8329edSJulian Elischer  */
6005c8329edSJulian Elischer void
6015c8329edSJulian Elischer ksegrp_stash(struct ksegrp *kg)
6025c8329edSJulian Elischer {
6035c8329edSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
6045c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_ksegrps, kg, kg_ksegrp);
6055c8329edSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
6065c8329edSJulian Elischer }
6075c8329edSJulian Elischer 
6085c8329edSJulian Elischer /*
609c76e33b6SJonathan Mini  * Reap zombie threads.
61044990b8cSJulian Elischer  */
61144990b8cSJulian Elischer void
61244990b8cSJulian Elischer thread_reap(void)
61344990b8cSJulian Elischer {
6145c8329edSJulian Elischer 	struct thread *td_first, *td_next;
6155c8329edSJulian Elischer 	struct kse *ke_first, *ke_next;
6165c8329edSJulian Elischer 	struct ksegrp *kg_first, * kg_next;
61744990b8cSJulian Elischer 
61844990b8cSJulian Elischer 	/*
61944990b8cSJulian Elischer 	 * don't even bother to lock if none at this instant
62044990b8cSJulian Elischer 	 * We really don't care about the next instant..
62144990b8cSJulian Elischer 	 */
6225c8329edSJulian Elischer 	if ((!TAILQ_EMPTY(&zombie_threads))
6235c8329edSJulian Elischer 	    || (!TAILQ_EMPTY(&zombie_kses))
6245c8329edSJulian Elischer 	    || (!TAILQ_EMPTY(&zombie_ksegrps))) {
62544990b8cSJulian Elischer 		mtx_lock_spin(&zombie_thread_lock);
6265c8329edSJulian Elischer 		td_first = TAILQ_FIRST(&zombie_threads);
6275c8329edSJulian Elischer 		ke_first = TAILQ_FIRST(&zombie_kses);
6285c8329edSJulian Elischer 		kg_first = TAILQ_FIRST(&zombie_ksegrps);
6295c8329edSJulian Elischer 		if (td_first)
6305c8329edSJulian Elischer 			TAILQ_INIT(&zombie_threads);
6315c8329edSJulian Elischer 		if (ke_first)
6325c8329edSJulian Elischer 			TAILQ_INIT(&zombie_kses);
6335c8329edSJulian Elischer 		if (kg_first)
6345c8329edSJulian Elischer 			TAILQ_INIT(&zombie_ksegrps);
63544990b8cSJulian Elischer 		mtx_unlock_spin(&zombie_thread_lock);
6365c8329edSJulian Elischer 		while (td_first) {
6375c8329edSJulian Elischer 			td_next = TAILQ_NEXT(td_first, td_runq);
6385c8329edSJulian Elischer 			thread_free(td_first);
6395c8329edSJulian Elischer 			td_first = td_next;
64044990b8cSJulian Elischer 		}
6415c8329edSJulian Elischer 		while (ke_first) {
6425c8329edSJulian Elischer 			ke_next = TAILQ_NEXT(ke_first, ke_procq);
6435c8329edSJulian Elischer 			kse_free(ke_first);
6445c8329edSJulian Elischer 			ke_first = ke_next;
6455c8329edSJulian Elischer 		}
6465c8329edSJulian Elischer 		while (kg_first) {
6475c8329edSJulian Elischer 			kg_next = TAILQ_NEXT(kg_first, kg_ksegrp);
6485c8329edSJulian Elischer 			ksegrp_free(kg_first);
6495c8329edSJulian Elischer 			kg_first = kg_next;
6505c8329edSJulian Elischer 		}
65144990b8cSJulian Elischer 	}
65244990b8cSJulian Elischer }
65344990b8cSJulian Elischer 
65444990b8cSJulian Elischer /*
6554f0db5e0SJulian Elischer  * Allocate a ksegrp.
6564f0db5e0SJulian Elischer  */
6574f0db5e0SJulian Elischer struct ksegrp *
6584f0db5e0SJulian Elischer ksegrp_alloc(void)
6594f0db5e0SJulian Elischer {
6604f0db5e0SJulian Elischer 	return (uma_zalloc(ksegrp_zone, M_WAITOK));
6614f0db5e0SJulian Elischer }
6624f0db5e0SJulian Elischer 
6634f0db5e0SJulian Elischer /*
6644f0db5e0SJulian Elischer  * Allocate a kse.
6654f0db5e0SJulian Elischer  */
6664f0db5e0SJulian Elischer struct kse *
6674f0db5e0SJulian Elischer kse_alloc(void)
6684f0db5e0SJulian Elischer {
6694f0db5e0SJulian Elischer 	return (uma_zalloc(kse_zone, M_WAITOK));
6704f0db5e0SJulian Elischer }
6714f0db5e0SJulian Elischer 
6724f0db5e0SJulian Elischer /*
67344990b8cSJulian Elischer  * Allocate a thread.
67444990b8cSJulian Elischer  */
67544990b8cSJulian Elischer struct thread *
67644990b8cSJulian Elischer thread_alloc(void)
67744990b8cSJulian Elischer {
67844990b8cSJulian Elischer 	thread_reap(); /* check if any zombies to get */
67944990b8cSJulian Elischer 	return (uma_zalloc(thread_zone, M_WAITOK));
68044990b8cSJulian Elischer }
68144990b8cSJulian Elischer 
68244990b8cSJulian Elischer /*
6834f0db5e0SJulian Elischer  * Deallocate a ksegrp.
6844f0db5e0SJulian Elischer  */
6854f0db5e0SJulian Elischer void
6864f0db5e0SJulian Elischer ksegrp_free(struct ksegrp *td)
6874f0db5e0SJulian Elischer {
6884f0db5e0SJulian Elischer 	uma_zfree(ksegrp_zone, td);
6894f0db5e0SJulian Elischer }
6904f0db5e0SJulian Elischer 
6914f0db5e0SJulian Elischer /*
6924f0db5e0SJulian Elischer  * Deallocate a kse.
6934f0db5e0SJulian Elischer  */
6944f0db5e0SJulian Elischer void
6954f0db5e0SJulian Elischer kse_free(struct kse *td)
6964f0db5e0SJulian Elischer {
6974f0db5e0SJulian Elischer 	uma_zfree(kse_zone, td);
6984f0db5e0SJulian Elischer }
6994f0db5e0SJulian Elischer 
7004f0db5e0SJulian Elischer /*
70144990b8cSJulian Elischer  * Deallocate a thread.
70244990b8cSJulian Elischer  */
70344990b8cSJulian Elischer void
70444990b8cSJulian Elischer thread_free(struct thread *td)
70544990b8cSJulian Elischer {
70644990b8cSJulian Elischer 	uma_zfree(thread_zone, td);
70744990b8cSJulian Elischer }
70844990b8cSJulian Elischer 
70944990b8cSJulian Elischer /*
71044990b8cSJulian Elischer  * Store the thread context in the UTS's mailbox.
7113d0586d4SJulian Elischer  * then add the mailbox at the head of a list we are building in user space.
7123d0586d4SJulian Elischer  * The list is anchored in the ksegrp structure.
71344990b8cSJulian Elischer  */
71444990b8cSJulian Elischer int
71544990b8cSJulian Elischer thread_export_context(struct thread *td)
71644990b8cSJulian Elischer {
7170d294460SJuli Mallett 	struct proc *p;
7183d0586d4SJulian Elischer 	struct ksegrp *kg;
7193d0586d4SJulian Elischer 	uintptr_t mbx;
7203d0586d4SJulian Elischer 	void *addr;
72144990b8cSJulian Elischer 	int error;
722c76e33b6SJonathan Mini 	ucontext_t uc;
72344990b8cSJulian Elischer 
7240d294460SJuli Mallett 	p = td->td_proc;
7250d294460SJuli Mallett 	kg = td->td_ksegrp;
7260d294460SJuli Mallett 
727c76e33b6SJonathan Mini 	/* Export the user/machine context. */
7283d0586d4SJulian Elischer #if 0
7293d0586d4SJulian Elischer 	addr = (caddr_t)td->td_mailbox +
7303d0586d4SJulian Elischer 	    offsetof(struct kse_thr_mailbox, tm_context);
7313d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
7323d0586d4SJulian Elischer 		addr = (void *)(&td->td_mailbox->tm_context);
7333d0586d4SJulian Elischer #endif
7343d0586d4SJulian Elischer 	error = copyin(addr, &uc, sizeof(ucontext_t));
735c76e33b6SJonathan Mini 	if (error == 0) {
736c76e33b6SJonathan Mini 		thread_getcontext(td, &uc);
7373d0586d4SJulian Elischer 		error = copyout(&uc, addr, sizeof(ucontext_t));
73844990b8cSJulian Elischer 
73944990b8cSJulian Elischer 	}
7403d0586d4SJulian Elischer 	if (error) {
7410cd3964fSJulian Elischer 		PROC_LOCK(p);
7420cd3964fSJulian Elischer 		psignal(p, SIGSEGV);
7430cd3964fSJulian Elischer 		PROC_UNLOCK(p);
74444990b8cSJulian Elischer 		return (error);
74544990b8cSJulian Elischer 	}
7463d0586d4SJulian Elischer 	/* get address in latest mbox of list pointer */
7473d0586d4SJulian Elischer #if 0
7483d0586d4SJulian Elischer 	addr = (caddr_t)td->td_mailbox
7493d0586d4SJulian Elischer 	    + offsetof(struct kse_thr_mailbox , tm_next);
7503d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
7513d0586d4SJulian Elischer 	addr = (void *)(&td->td_mailbox->tm_next);
7523d0586d4SJulian Elischer #endif
7533d0586d4SJulian Elischer 	/*
7543d0586d4SJulian Elischer 	 * Put the saved address of the previous first
7553d0586d4SJulian Elischer 	 * entry into this one
7563d0586d4SJulian Elischer 	 */
7573d0586d4SJulian Elischer 	for (;;) {
7583d0586d4SJulian Elischer 		mbx = (uintptr_t)kg->kg_completed;
7593d0586d4SJulian Elischer 		if (suword(addr, mbx)) {
7600cd3964fSJulian Elischer 			PROC_LOCK(p);
7610cd3964fSJulian Elischer 			psignal(p, SIGSEGV);
7620cd3964fSJulian Elischer 			PROC_UNLOCK(p);
7633d0586d4SJulian Elischer 			return (EFAULT);
7643d0586d4SJulian Elischer 		}
7650cd3964fSJulian Elischer 		PROC_LOCK(p);
7663d0586d4SJulian Elischer 		if (mbx == (uintptr_t)kg->kg_completed) {
7673d0586d4SJulian Elischer 			kg->kg_completed = td->td_mailbox;
7680cd3964fSJulian Elischer 			PROC_UNLOCK(p);
7693d0586d4SJulian Elischer 			break;
7703d0586d4SJulian Elischer 		}
7710cd3964fSJulian Elischer 		PROC_UNLOCK(p);
7723d0586d4SJulian Elischer 	}
7733d0586d4SJulian Elischer 	return (0);
7743d0586d4SJulian Elischer }
77544990b8cSJulian Elischer 
7763d0586d4SJulian Elischer /*
7773d0586d4SJulian Elischer  * Take the list of completed mailboxes for this KSEGRP and put them on this
7783d0586d4SJulian Elischer  * KSE's mailbox as it's the next one going up.
7793d0586d4SJulian Elischer  */
7803d0586d4SJulian Elischer static int
7813d0586d4SJulian Elischer thread_link_mboxes(struct ksegrp *kg, struct kse *ke)
7823d0586d4SJulian Elischer {
7830cd3964fSJulian Elischer 	struct proc *p = kg->kg_proc;
7843d0586d4SJulian Elischer 	void *addr;
7853d0586d4SJulian Elischer 	uintptr_t mbx;
7863d0586d4SJulian Elischer 
7873d0586d4SJulian Elischer #if 0
7883d0586d4SJulian Elischer 	addr = (caddr_t)ke->ke_mailbox
7893d0586d4SJulian Elischer 	    + offsetof(struct kse_mailbox, km_completed);
7903d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */
7913d0586d4SJulian Elischer 		addr = (void *)(&ke->ke_mailbox->km_completed);
7923d0586d4SJulian Elischer #endif
7933d0586d4SJulian Elischer 	for (;;) {
7943d0586d4SJulian Elischer 		mbx = (uintptr_t)kg->kg_completed;
7953d0586d4SJulian Elischer 		if (suword(addr, mbx)) {
7960cd3964fSJulian Elischer 			PROC_LOCK(p);
7970cd3964fSJulian Elischer 			psignal(p, SIGSEGV);
7980cd3964fSJulian Elischer 			PROC_UNLOCK(p);
7993d0586d4SJulian Elischer 			return (EFAULT);
8003d0586d4SJulian Elischer 		}
8013d0586d4SJulian Elischer 		/* XXXKSE could use atomic CMPXCH here */
8020cd3964fSJulian Elischer 		PROC_LOCK(p);
8033d0586d4SJulian Elischer 		if (mbx == (uintptr_t)kg->kg_completed) {
8043d0586d4SJulian Elischer 			kg->kg_completed = NULL;
8050cd3964fSJulian Elischer 			PROC_UNLOCK(p);
8063d0586d4SJulian Elischer 			break;
8073d0586d4SJulian Elischer 		}
8080cd3964fSJulian Elischer 		PROC_UNLOCK(p);
8093d0586d4SJulian Elischer 	}
8103d0586d4SJulian Elischer 	return (0);
8113d0586d4SJulian Elischer }
81244990b8cSJulian Elischer 
81344990b8cSJulian Elischer /*
81444990b8cSJulian Elischer  * Discard the current thread and exit from its context.
81544990b8cSJulian Elischer  *
81644990b8cSJulian Elischer  * Because we can't free a thread while we're operating under its context,
81744990b8cSJulian Elischer  * push the current thread into our KSE's ke_tdspare slot, freeing the
81844990b8cSJulian Elischer  * thread that might be there currently. Because we know that only this
81944990b8cSJulian Elischer  * processor will run our KSE, we needn't worry about someone else grabbing
82044990b8cSJulian Elischer  * our context before we do a cpu_throw.
82144990b8cSJulian Elischer  */
82244990b8cSJulian Elischer void
82344990b8cSJulian Elischer thread_exit(void)
82444990b8cSJulian Elischer {
82544990b8cSJulian Elischer 	struct thread *td;
82644990b8cSJulian Elischer 	struct kse *ke;
82744990b8cSJulian Elischer 	struct proc *p;
82844990b8cSJulian Elischer 	struct ksegrp	*kg;
82944990b8cSJulian Elischer 
83044990b8cSJulian Elischer 	td = curthread;
83144990b8cSJulian Elischer 	kg = td->td_ksegrp;
83244990b8cSJulian Elischer 	p = td->td_proc;
83344990b8cSJulian Elischer 	ke = td->td_kse;
83444990b8cSJulian Elischer 
83544990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
83688151aa3SJulian Elischer 	KASSERT(p != NULL, ("thread exiting without a process"));
83788151aa3SJulian Elischer 	KASSERT(ke != NULL, ("thread exiting without a kse"));
83888151aa3SJulian Elischer 	KASSERT(kg != NULL, ("thread exiting without a kse group"));
83944990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
84044990b8cSJulian Elischer 	CTR1(KTR_PROC, "thread_exit: thread %p", td);
84144990b8cSJulian Elischer 	KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
84244990b8cSJulian Elischer 
84344990b8cSJulian Elischer 	if (ke->ke_tdspare != NULL) {
84471fad9fdSJulian Elischer 		thread_stash(ke->ke_tdspare);
84544990b8cSJulian Elischer 		ke->ke_tdspare = NULL;
84644990b8cSJulian Elischer 	}
84748bfcdddSJulian Elischer 	if (td->td_standin != NULL) {
84848bfcdddSJulian Elischer 		thread_stash(td->td_standin);
84948bfcdddSJulian Elischer 		td->td_standin = NULL;
85048bfcdddSJulian Elischer 	}
85148bfcdddSJulian Elischer 
85244990b8cSJulian Elischer 	cpu_thread_exit(td);	/* XXXSMP */
85344990b8cSJulian Elischer 
8541faf202eSJulian Elischer 	/*
8551faf202eSJulian Elischer 	 * The last thread is left attached to the process
8561faf202eSJulian Elischer 	 * So that the whole bundle gets recycled. Skip
8571faf202eSJulian Elischer 	 * all this stuff.
8581faf202eSJulian Elischer 	 */
8591faf202eSJulian Elischer 	if (p->p_numthreads > 1) {
8605c8329edSJulian Elischer 		/*
8615c8329edSJulian Elischer 		 * Unlink this thread from its proc and the kseg.
8625c8329edSJulian Elischer 		 * In keeping with the other structs we probably should
8635c8329edSJulian Elischer 		 * have a thread_unlink() that does some of this but it
8645c8329edSJulian Elischer 		 * would only be called from here (I think) so it would
8655c8329edSJulian Elischer 		 * be a waste. (might be useful for proc_fini() as well.)
8665c8329edSJulian Elischer  		 */
86744990b8cSJulian Elischer 		TAILQ_REMOVE(&p->p_threads, td, td_plist);
86844990b8cSJulian Elischer 		p->p_numthreads--;
86944990b8cSJulian Elischer 		TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
87044990b8cSJulian Elischer 		kg->kg_numthreads--;
87144990b8cSJulian Elischer 		/*
87244990b8cSJulian Elischer 		 * The test below is NOT true if we are the
8731faf202eSJulian Elischer 		 * sole exiting thread. P_STOPPED_SNGL is unset
87444990b8cSJulian Elischer 		 * in exit1() after it is the only survivor.
87544990b8cSJulian Elischer 		 */
8761279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
87744990b8cSJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
87871fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
87944990b8cSJulian Elischer 			}
88044990b8cSJulian Elischer 		}
88148bfcdddSJulian Elischer 
88248bfcdddSJulian Elischer 		/* Reassign this thread's KSE. */
88348bfcdddSJulian Elischer 		ke->ke_thread = NULL;
88448bfcdddSJulian Elischer 		td->td_kse = NULL;
88548bfcdddSJulian Elischer 		ke->ke_state = KES_UNQUEUED;
8865c8329edSJulian Elischer 		KASSERT((ke->ke_bound != td),
8875c8329edSJulian Elischer 		    ("thread_exit: entered with ke_bound set"));
88848bfcdddSJulian Elischer 
88948bfcdddSJulian Elischer 		/*
8905c8329edSJulian Elischer 		 * The reason for all this hoopla is
8915c8329edSJulian Elischer 		 * an attempt to stop our thread stack from being freed
8925c8329edSJulian Elischer 		 * until AFTER we have stopped running on it.
8935c8329edSJulian Elischer 		 * Since we are under schedlock, almost any method where
8945c8329edSJulian Elischer 		 * it is eventually freed by someone else is probably ok.
8955c8329edSJulian Elischer 		 * (Especially if they do it under schedlock). We could
8965c8329edSJulian Elischer 		 * almost free it here if we could be certain that
8975c8329edSJulian Elischer 		 * the uma code wouldn't pull it apart immediatly,
8985c8329edSJulian Elischer 		 * but unfortunatly we can not guarantee that.
89948bfcdddSJulian Elischer 		 *
9005c8329edSJulian Elischer 		 * For threads that are exiting and NOT killing their
9015c8329edSJulian Elischer 		 * KSEs we can just stash it in the KSE, however
9025c8329edSJulian Elischer 		 * in the case where the KSE is also being deallocated,
9035c8329edSJulian Elischer 		 * we need to store it somewhere else. It turns out that
9045c8329edSJulian Elischer 		 * we will never free the last KSE, so there is always one
9055c8329edSJulian Elischer 		 * other KSE available. We might as well just choose one
9065c8329edSJulian Elischer 		 * and stash it there. Being under schedlock should make that
9075c8329edSJulian Elischer 		 * safe.
9085c8329edSJulian Elischer 		 *
9095c8329edSJulian Elischer 		 * In borrower threads, we can stash it in the lender
9105c8329edSJulian Elischer 		 * Where it won't be needed until this thread is long gone.
9115c8329edSJulian Elischer 		 * Borrower threads can't kill their KSE anyhow, so even
9125c8329edSJulian Elischer 		 * the KSE would be a safe place for them. It is not
9135c8329edSJulian Elischer 		 * necessary to have a KSE (or KSEGRP) at all beyond this
9145c8329edSJulian Elischer 		 * point, while we are under the protection of schedlock.
9155c8329edSJulian Elischer 		 *
9165c8329edSJulian Elischer 		 * Either give the KSE to another thread to use (or make
9175c8329edSJulian Elischer 		 * it idle), or free it entirely, possibly along with its
9185c8329edSJulian Elischer 		 * ksegrp if it's the last one.
91948bfcdddSJulian Elischer 		 */
9205c8329edSJulian Elischer 		if (ke->ke_flags & KEF_EXIT) {
9215c8329edSJulian Elischer 			kse_unlink(ke);
9225c8329edSJulian Elischer 			/*
9235c8329edSJulian Elischer 			 * Designate another KSE to hold our thread.
9245c8329edSJulian Elischer 			 * Safe as long as we abide by whatever lock
9255c8329edSJulian Elischer 			 * we control it with.. The other KSE will not
9265c8329edSJulian Elischer 			 * be able to run it until we release the schelock,
9275c8329edSJulian Elischer 			 * but we need to be careful about it deciding to
9285c8329edSJulian Elischer 			 * write to the stack before then. Luckily
9295c8329edSJulian Elischer 			 * I believe that while another thread's
9305c8329edSJulian Elischer 			 * standin thread can be used in this way, the
9315c8329edSJulian Elischer 			 * spare thread for the KSE cannot be used without
9325c8329edSJulian Elischer 			 * holding schedlock at least once.
9335c8329edSJulian Elischer 			 */
9345c8329edSJulian Elischer 			ke =  FIRST_KSE_IN_PROC(p);
9355c8329edSJulian Elischer 		} else {
9365c8329edSJulian Elischer 			kse_reassign(ke);
9375c8329edSJulian Elischer 		}
93848bfcdddSJulian Elischer 		if (ke->ke_bound) {
9395c8329edSJulian Elischer 			/*
9405c8329edSJulian Elischer 			 * WE are a borrower..
9415c8329edSJulian Elischer 			 * stash our thread with the owner.
9425c8329edSJulian Elischer 			 */
94348bfcdddSJulian Elischer 			if (ke->ke_bound->td_standin) {
94448bfcdddSJulian Elischer 				thread_stash(ke->ke_bound->td_standin);
94548bfcdddSJulian Elischer 			}
94648bfcdddSJulian Elischer 			ke->ke_bound->td_standin = td;
94748bfcdddSJulian Elischer 		} else {
9485c8329edSJulian Elischer 			if (ke->ke_tdspare != NULL) {
9495c8329edSJulian Elischer 				thread_stash(ke->ke_tdspare);
9505c8329edSJulian Elischer 				ke->ke_tdspare = NULL;
9515c8329edSJulian Elischer 			}
95244990b8cSJulian Elischer 			ke->ke_tdspare = td;
95348bfcdddSJulian Elischer 		}
9545c8329edSJulian Elischer 		PROC_UNLOCK(p);
9555c8329edSJulian Elischer 		td->td_state	= TDS_INACTIVE;
9565c8329edSJulian Elischer 		td->td_proc	= NULL;
9575c8329edSJulian Elischer 		td->td_ksegrp	= NULL;
9585c8329edSJulian Elischer 		td->td_last_kse	= NULL;
9591faf202eSJulian Elischer 	} else {
9601faf202eSJulian Elischer 		PROC_UNLOCK(p);
9611faf202eSJulian Elischer 	}
9621faf202eSJulian Elischer 
96344990b8cSJulian Elischer 	cpu_throw();
96444990b8cSJulian Elischer 	/* NOTREACHED */
96544990b8cSJulian Elischer }
96644990b8cSJulian Elischer 
96744990b8cSJulian Elischer /*
96844990b8cSJulian Elischer  * Link a thread to a process.
9691faf202eSJulian Elischer  * set up anything that needs to be initialized for it to
9701faf202eSJulian Elischer  * be used by the process.
97144990b8cSJulian Elischer  *
97244990b8cSJulian Elischer  * Note that we do not link to the proc's ucred here.
97344990b8cSJulian Elischer  * The thread is linked as if running but no KSE assigned.
97444990b8cSJulian Elischer  */
97544990b8cSJulian Elischer void
97644990b8cSJulian Elischer thread_link(struct thread *td, struct ksegrp *kg)
97744990b8cSJulian Elischer {
97844990b8cSJulian Elischer 	struct proc *p;
97944990b8cSJulian Elischer 
98044990b8cSJulian Elischer 	p = kg->kg_proc;
98171fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
98244990b8cSJulian Elischer 	td->td_proc	= p;
98344990b8cSJulian Elischer 	td->td_ksegrp	= kg;
98444990b8cSJulian Elischer 	td->td_last_kse	= NULL;
98544990b8cSJulian Elischer 
9861faf202eSJulian Elischer 	LIST_INIT(&td->td_contested);
9871faf202eSJulian Elischer 	callout_init(&td->td_slpcallout, 1);
98844990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist);
98944990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist);
99044990b8cSJulian Elischer 	p->p_numthreads++;
99144990b8cSJulian Elischer 	kg->kg_numthreads++;
9924f0db5e0SJulian Elischer 	if (oiks_debug && p->p_numthreads > max_threads_per_proc) {
99344990b8cSJulian Elischer 		printf("OIKS %d\n", p->p_numthreads);
99444990b8cSJulian Elischer 		if (oiks_debug > 1)
99544990b8cSJulian Elischer 			Debugger("OIKS");
99644990b8cSJulian Elischer 	}
99744990b8cSJulian Elischer 	td->td_kse	= NULL;
99844990b8cSJulian Elischer }
99944990b8cSJulian Elischer 
10005c8329edSJulian Elischer void
10015c8329edSJulian Elischer kse_purge(struct proc *p, struct thread *td)
10025c8329edSJulian Elischer {
10035c8329edSJulian Elischer 	struct kse *ke;
10045c8329edSJulian Elischer 	struct ksegrp *kg;
10055c8329edSJulian Elischer 
10065c8329edSJulian Elischer  	KASSERT(p->p_numthreads == 1, ("bad thread number"));
10075c8329edSJulian Elischer 	mtx_lock_spin(&sched_lock);
10085c8329edSJulian Elischer 	while ((kg = TAILQ_FIRST(&p->p_ksegrps)) != NULL) {
10095c8329edSJulian Elischer 		while ((ke = TAILQ_FIRST(&kg->kg_iq)) != NULL) {
10105c8329edSJulian Elischer 			TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
10115c8329edSJulian Elischer 			kg->kg_idle_kses--;
10125c8329edSJulian Elischer 			TAILQ_REMOVE(&kg->kg_kseq, ke, ke_kglist);
10135c8329edSJulian Elischer 			kg->kg_kses--;
10145c8329edSJulian Elischer 			if (ke->ke_tdspare)
10155c8329edSJulian Elischer 				thread_stash(ke->ke_tdspare);
10165c8329edSJulian Elischer    			kse_stash(ke);
10175c8329edSJulian Elischer 		}
10185c8329edSJulian Elischer 		TAILQ_REMOVE(&p->p_ksegrps, kg, kg_ksegrp);
10195c8329edSJulian Elischer 		p->p_numksegrps--;
10205c8329edSJulian Elischer 		KASSERT(((kg->kg_kses == 0) && (kg != td->td_ksegrp)) ||
10215c8329edSJulian Elischer 		    ((kg->kg_kses == 1) && (kg == td->td_ksegrp)),
10225c8329edSJulian Elischer 			("wrong kg_kses"));
10235c8329edSJulian Elischer 		if (kg != td->td_ksegrp) {
10245c8329edSJulian Elischer 			ksegrp_stash(kg);
10255c8329edSJulian Elischer 		}
10265c8329edSJulian Elischer 	}
10275c8329edSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_ksegrps, td->td_ksegrp, kg_ksegrp);
10285c8329edSJulian Elischer 	p->p_numksegrps++;
10295c8329edSJulian Elischer 	mtx_unlock_spin(&sched_lock);
10305c8329edSJulian Elischer }
10315c8329edSJulian Elischer 
10325c8329edSJulian Elischer 
103344990b8cSJulian Elischer /*
1034c76e33b6SJonathan Mini  * Create a thread and schedule it for upcall on the KSE given.
103544990b8cSJulian Elischer  */
103644990b8cSJulian Elischer struct thread *
103744990b8cSJulian Elischer thread_schedule_upcall(struct thread *td, struct kse *ke)
103844990b8cSJulian Elischer {
103944990b8cSJulian Elischer 	struct thread *td2;
104048bfcdddSJulian Elischer 	int newkse;
104144990b8cSJulian Elischer 
104244990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
104348bfcdddSJulian Elischer 	newkse = (ke != td->td_kse);
104448bfcdddSJulian Elischer 
104548bfcdddSJulian Elischer 	/*
104648bfcdddSJulian Elischer 	 * If the kse is already owned by another thread then we can't
104748bfcdddSJulian Elischer 	 * schedule an upcall because the other thread must be BOUND
104848bfcdddSJulian Elischer 	 * which means it is not in a position to take an upcall.
104948bfcdddSJulian Elischer 	 * We must be borrowing the KSE to allow us to complete some in-kernel
105048bfcdddSJulian Elischer 	 * work. When we complete, the Bound thread will have teh chance to
105148bfcdddSJulian Elischer 	 * complete. This thread will sleep as planned. Hopefully there will
105248bfcdddSJulian Elischer 	 * eventually be un unbound thread that can be converted to an
105348bfcdddSJulian Elischer 	 * upcall to report the completion of this thread.
105448bfcdddSJulian Elischer 	 */
105548bfcdddSJulian Elischer 	if (ke->ke_bound && ((ke->ke_bound->td_flags & TDF_UNBOUND) == 0)) {
105648bfcdddSJulian Elischer 		return (NULL);
105748bfcdddSJulian Elischer 	}
105848bfcdddSJulian Elischer 	KASSERT((ke->ke_bound == NULL), ("kse already bound"));
105948bfcdddSJulian Elischer 
106048bfcdddSJulian Elischer 	if ((td2 = td->td_standin) != NULL) {
106148bfcdddSJulian Elischer 		td->td_standin = NULL;
106244990b8cSJulian Elischer 	} else {
106348bfcdddSJulian Elischer 		if (newkse)
106448bfcdddSJulian Elischer 			panic("no reserve thread when called with a new kse");
106548bfcdddSJulian Elischer 		/*
106648bfcdddSJulian Elischer 		 * If called from (e.g.) sleep and we do not have
106748bfcdddSJulian Elischer 		 * a reserve thread, then we've used it, so do not
106848bfcdddSJulian Elischer 		 * create an upcall.
106948bfcdddSJulian Elischer 		 */
107048bfcdddSJulian Elischer 		return(NULL);
107144990b8cSJulian Elischer 	}
107244990b8cSJulian Elischer 	CTR3(KTR_PROC, "thread_schedule_upcall: thread %p (pid %d, %s)",
107348bfcdddSJulian Elischer 	     td2, td->td_proc->p_pid, td->td_proc->p_comm);
1074c0698d32SJulian Elischer 	bzero(&td2->td_startzero,
10751faf202eSJulian Elischer 	    (unsigned)RANGEOF(struct thread, td_startzero, td_endzero));
10761faf202eSJulian Elischer 	bcopy(&td->td_startcopy, &td2->td_startcopy,
10771faf202eSJulian Elischer 	    (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy));
107844990b8cSJulian Elischer 	thread_link(td2, ke->ke_ksegrp);
1079c76e33b6SJonathan Mini 	cpu_set_upcall(td2, td->td_pcb);
108048bfcdddSJulian Elischer 
1081c76e33b6SJonathan Mini 	/*
108248bfcdddSJulian Elischer 	 * XXXKSE do we really need this? (default values for the
108348bfcdddSJulian Elischer 	 * frame).
108448bfcdddSJulian Elischer 	 */
108548bfcdddSJulian Elischer 	bcopy(td->td_frame, td2->td_frame, sizeof(struct trapframe));
108648bfcdddSJulian Elischer 
108748bfcdddSJulian Elischer 	/*
108848bfcdddSJulian Elischer 	 * Bind the new thread to the KSE,
108948bfcdddSJulian Elischer 	 * and if it's our KSE, lend it back to ourself
109048bfcdddSJulian Elischer 	 * so we can continue running.
1091c76e33b6SJonathan Mini 	 */
109244990b8cSJulian Elischer 	td2->td_ucred = crhold(td->td_ucred);
109348bfcdddSJulian Elischer 	td2->td_flags = TDF_UPCALLING; /* note: BOUND */
109448bfcdddSJulian Elischer 	td2->td_kse = ke;
109548bfcdddSJulian Elischer 	td2->td_state = TDS_CAN_RUN;
109648bfcdddSJulian Elischer 	td2->td_inhibitors = 0;
109748bfcdddSJulian Elischer 	/*
109848bfcdddSJulian Elischer 	 * If called from msleep(), we are working on the current
109948bfcdddSJulian Elischer 	 * KSE so fake that we borrowed it. If called from
110048bfcdddSJulian Elischer 	 * kse_create(), don't, as we have a new kse too.
110148bfcdddSJulian Elischer 	 */
110248bfcdddSJulian Elischer 	if (!newkse) {
110348bfcdddSJulian Elischer 		/*
110448bfcdddSJulian Elischer 		 * This thread will be scheduled when the current thread
110548bfcdddSJulian Elischer 		 * blocks, exits or tries to enter userspace, (which ever
110648bfcdddSJulian Elischer 		 * happens first). When that happens the KSe will "revert"
110748bfcdddSJulian Elischer 		 * to this thread in a BOUND manner. Since we are called
110848bfcdddSJulian Elischer 		 * from msleep() this is going to be "very soon" in nearly
110948bfcdddSJulian Elischer 		 * all cases.
111048bfcdddSJulian Elischer 		 */
111148bfcdddSJulian Elischer 		ke->ke_bound = td2;
111248bfcdddSJulian Elischer 		TD_SET_LOAN(td2);
111348bfcdddSJulian Elischer 	} else {
111448bfcdddSJulian Elischer 		ke->ke_bound = NULL;
111548bfcdddSJulian Elischer 		ke->ke_thread = td2;
111644990b8cSJulian Elischer 		setrunqueue(td2);
111748bfcdddSJulian Elischer 	}
111848bfcdddSJulian Elischer 	return (td2);	/* bogus.. should be a void function */
111944990b8cSJulian Elischer }
112044990b8cSJulian Elischer 
112144990b8cSJulian Elischer /*
1122c76e33b6SJonathan Mini  * Schedule an upcall to notify a KSE process recieved signals.
112344990b8cSJulian Elischer  *
1124c76e33b6SJonathan Mini  * XXX - Modifying a sigset_t like this is totally bogus.
112544990b8cSJulian Elischer  */
1126c76e33b6SJonathan Mini struct thread *
1127c76e33b6SJonathan Mini signal_upcall(struct proc *p, int sig)
1128c76e33b6SJonathan Mini {
1129c76e33b6SJonathan Mini 	struct thread *td, *td2;
1130c76e33b6SJonathan Mini 	struct kse *ke;
1131c76e33b6SJonathan Mini 	sigset_t ss;
1132c76e33b6SJonathan Mini 	int error;
1133c76e33b6SJonathan Mini 
1134c76e33b6SJonathan Mini 	PROC_LOCK_ASSERT(p, MA_OWNED);
113548bfcdddSJulian Elischer return (NULL);
1136c76e33b6SJonathan Mini 
1137c76e33b6SJonathan Mini 	td = FIRST_THREAD_IN_PROC(p);
1138c76e33b6SJonathan Mini 	ke = td->td_kse;
1139c76e33b6SJonathan Mini 	PROC_UNLOCK(p);
1140c76e33b6SJonathan Mini 	error = copyin(&ke->ke_mailbox->km_sigscaught, &ss, sizeof(sigset_t));
1141c76e33b6SJonathan Mini 	PROC_LOCK(p);
1142c76e33b6SJonathan Mini 	if (error)
1143c76e33b6SJonathan Mini 		return (NULL);
1144c76e33b6SJonathan Mini 	SIGADDSET(ss, sig);
1145c76e33b6SJonathan Mini 	PROC_UNLOCK(p);
1146c76e33b6SJonathan Mini 	error = copyout(&ss, &ke->ke_mailbox->km_sigscaught, sizeof(sigset_t));
1147c76e33b6SJonathan Mini 	PROC_LOCK(p);
1148c76e33b6SJonathan Mini 	if (error)
1149c76e33b6SJonathan Mini 		return (NULL);
115048bfcdddSJulian Elischer 	if (td->td_standin == NULL)
115148bfcdddSJulian Elischer 		td->td_standin = thread_alloc();
1152c76e33b6SJonathan Mini 	mtx_lock_spin(&sched_lock);
115348bfcdddSJulian Elischer 	td2 = thread_schedule_upcall(td, ke); /* Bogus JRE */
1154c76e33b6SJonathan Mini 	mtx_unlock_spin(&sched_lock);
1155c76e33b6SJonathan Mini 	return (td2);
1156c76e33b6SJonathan Mini }
1157c76e33b6SJonathan Mini 
1158c76e33b6SJonathan Mini /*
1159c76e33b6SJonathan Mini  * The extra work we go through if we are a threaded process when we
1160c76e33b6SJonathan Mini  * return to userland.
1161c76e33b6SJonathan Mini  *
1162c76e33b6SJonathan Mini  * If we are a KSE process and returning to user mode, check for
1163c76e33b6SJonathan Mini  * extra work to do before we return (e.g. for more syscalls
1164c76e33b6SJonathan Mini  * to complete first).  If we were in a critical section, we should
1165c76e33b6SJonathan Mini  * just return to let it finish. Same if we were in the UTS (in
1166c76e33b6SJonathan Mini  * which case the mailbox's context's busy indicator will be set).
1167c76e33b6SJonathan Mini  * The only traps we suport will have set the mailbox.
1168c76e33b6SJonathan Mini  * We will clear it here.
116944990b8cSJulian Elischer  */
1170c76e33b6SJonathan Mini int
1171253fdd5bSJulian Elischer thread_userret(struct thread *td, struct trapframe *frame)
1172c76e33b6SJonathan Mini {
1173c76e33b6SJonathan Mini 	int error;
11743d0586d4SJulian Elischer 	int unbound;
11753d0586d4SJulian Elischer 	struct kse *ke;
117648bfcdddSJulian Elischer 	struct ksegrp *kg;
117748bfcdddSJulian Elischer 	struct thread *td2;
117848bfcdddSJulian Elischer 	struct proc *p;
1179c76e33b6SJonathan Mini 
118048bfcdddSJulian Elischer 	error = 0;
118148bfcdddSJulian Elischer 
118248bfcdddSJulian Elischer 	unbound = td->td_flags & TDF_UNBOUND;
118348bfcdddSJulian Elischer 
118448bfcdddSJulian Elischer 	kg = td->td_ksegrp;
118548bfcdddSJulian Elischer 	p = td->td_proc;
118648bfcdddSJulian Elischer 
118748bfcdddSJulian Elischer 	/*
118848bfcdddSJulian Elischer 	 * Originally bound threads never upcall but they may
118948bfcdddSJulian Elischer 	 * loan out their KSE at this point.
119048bfcdddSJulian Elischer 	 * Upcalls imply bound.. They also may want to do some Philantropy.
119148bfcdddSJulian Elischer 	 * Unbound threads on the other hand either yield to other work
119248bfcdddSJulian Elischer 	 * or transform into an upcall.
119348bfcdddSJulian Elischer 	 * (having saved their context to user space in both cases)
119448bfcdddSJulian Elischer 	 */
119548bfcdddSJulian Elischer 	if (unbound ) {
119648bfcdddSJulian Elischer 		/*
119748bfcdddSJulian Elischer 		 * We are an unbound thread, looking to return to
119848bfcdddSJulian Elischer 		 * user space.
119948bfcdddSJulian Elischer 		 * THere are several possibilities:
120048bfcdddSJulian Elischer 		 * 1) we are using a borrowed KSE. save state and exit.
120148bfcdddSJulian Elischer 		 *    kse_reassign() will recycle the kse as needed,
120248bfcdddSJulian Elischer 		 * 2) we are not.. save state, and then convert ourself
120348bfcdddSJulian Elischer 		 *    to be an upcall, bound to the KSE.
120448bfcdddSJulian Elischer 		 *    if there are others that need the kse,
120548bfcdddSJulian Elischer 		 *    give them a chance by doing an mi_switch().
120648bfcdddSJulian Elischer 		 *    Because we are bound, control will eventually return
120748bfcdddSJulian Elischer 		 *    to us here.
120848bfcdddSJulian Elischer 		 * ***
120948bfcdddSJulian Elischer 		 * Save the thread's context, and link it
121048bfcdddSJulian Elischer 		 * into the KSEGRP's list of completed threads.
121148bfcdddSJulian Elischer 		 */
121248bfcdddSJulian Elischer 		error = thread_export_context(td);
121348bfcdddSJulian Elischer 		td->td_mailbox = NULL;
121448bfcdddSJulian Elischer 		if (error) {
121548bfcdddSJulian Elischer 			/*
121648bfcdddSJulian Elischer 			 * If we are not running on a borrowed KSE, then
121748bfcdddSJulian Elischer 			 * failing to do the KSE operation just defaults
121848bfcdddSJulian Elischer 			 * back to synchonous operation, so just return from
121948bfcdddSJulian Elischer 			 * the syscall. If it IS borrowed, there is nothing
122048bfcdddSJulian Elischer 			 * we can do. We just lose that context. We
122148bfcdddSJulian Elischer 			 * probably should note this somewhere and send
122248bfcdddSJulian Elischer 			 * the process a signal.
122348bfcdddSJulian Elischer 			 */
12249eb1fdeaSJulian Elischer 			PROC_LOCK(td->td_proc);
122548bfcdddSJulian Elischer 			psignal(td->td_proc, SIGSEGV);
12269eb1fdeaSJulian Elischer 			mtx_lock_spin(&sched_lock);
122748bfcdddSJulian Elischer 			if (td->td_kse->ke_bound == NULL) {
122848bfcdddSJulian Elischer 				td->td_flags &= ~TDF_UNBOUND;
122948bfcdddSJulian Elischer 				PROC_UNLOCK(td->td_proc);
123048bfcdddSJulian Elischer 				mtx_unlock_spin(&sched_lock);
123148bfcdddSJulian Elischer 				return (error);	/* go sync */
123248bfcdddSJulian Elischer 			}
12339eb1fdeaSJulian Elischer 			thread_exit();
12349eb1fdeaSJulian Elischer 		}
12359eb1fdeaSJulian Elischer 
1236c76e33b6SJonathan Mini 		/*
123748bfcdddSJulian Elischer 		 * if the KSE is owned and we are borrowing it,
123848bfcdddSJulian Elischer 		 * don't make an upcall, just exit so that the owner
123948bfcdddSJulian Elischer 		 * can get its KSE if it wants it.
124048bfcdddSJulian Elischer 		 * Our context is already safely stored for later
124148bfcdddSJulian Elischer 		 * use by the UTS.
124248bfcdddSJulian Elischer 		 */
124348bfcdddSJulian Elischer 		PROC_LOCK(p);
124448bfcdddSJulian Elischer 		mtx_lock_spin(&sched_lock);
124548bfcdddSJulian Elischer 		if (td->td_kse->ke_bound) {
124648bfcdddSJulian Elischer 			thread_exit();
124748bfcdddSJulian Elischer 		}
124848bfcdddSJulian Elischer 		PROC_UNLOCK(p);
124948bfcdddSJulian Elischer 
125048bfcdddSJulian Elischer 		/*
125148bfcdddSJulian Elischer 		 * Turn ourself into a bound upcall.
125248bfcdddSJulian Elischer 		 * We will rely on kse_reassign()
125348bfcdddSJulian Elischer 		 * to make us run at a later time.
125448bfcdddSJulian Elischer 		 * We should look just like a sheduled upcall
125548bfcdddSJulian Elischer 		 * from msleep() or cv_wait().
125648bfcdddSJulian Elischer 		 */
125748bfcdddSJulian Elischer 		td->td_flags &= ~TDF_UNBOUND;
125848bfcdddSJulian Elischer 		td->td_flags |= TDF_UPCALLING;
125948bfcdddSJulian Elischer 		/* Only get here if we have become an upcall */
126048bfcdddSJulian Elischer 
126148bfcdddSJulian Elischer 	} else {
126248bfcdddSJulian Elischer 		mtx_lock_spin(&sched_lock);
126348bfcdddSJulian Elischer 	}
126448bfcdddSJulian Elischer 	/*
126548bfcdddSJulian Elischer 	 * We ARE going back to userland with this KSE.
126648bfcdddSJulian Elischer 	 * Check for threads that need to borrow it.
126748bfcdddSJulian Elischer 	 * Optimisation: don't call mi_switch if no-one wants the KSE.
126848bfcdddSJulian Elischer 	 * Any other thread that comes ready after this missed the boat.
1269c76e33b6SJonathan Mini 	 */
12703d0586d4SJulian Elischer 	ke = td->td_kse;
127148bfcdddSJulian Elischer 	if ((td2 = kg->kg_last_assigned))
127248bfcdddSJulian Elischer 		td2 = TAILQ_NEXT(td2, td_runq);
127348bfcdddSJulian Elischer 	else
127448bfcdddSJulian Elischer 		td2 = TAILQ_FIRST(&kg->kg_runq);
127548bfcdddSJulian Elischer 	if (td2)  {
1276c76e33b6SJonathan Mini 		/*
127748bfcdddSJulian Elischer 		 * force a switch to more urgent 'in kernel'
127848bfcdddSJulian Elischer 		 * work. Control will return to this thread
127948bfcdddSJulian Elischer 		 * when there is no more work to do.
128048bfcdddSJulian Elischer 		 * kse_reassign() will do tha for us.
1281c76e33b6SJonathan Mini 		 */
128248bfcdddSJulian Elischer 		TD_SET_LOAN(td);
128348bfcdddSJulian Elischer 		ke->ke_bound = td;
128448bfcdddSJulian Elischer 		ke->ke_thread = NULL;
128548bfcdddSJulian Elischer 		mi_switch(); /* kse_reassign() will (re)find td2 */
128648bfcdddSJulian Elischer 	}
128748bfcdddSJulian Elischer 	mtx_unlock_spin(&sched_lock);
128848bfcdddSJulian Elischer 
128948bfcdddSJulian Elischer 	/*
129048bfcdddSJulian Elischer 	 * Optimisation:
129148bfcdddSJulian Elischer 	 * Ensure that we have a spare thread available,
129248bfcdddSJulian Elischer 	 * for when we re-enter the kernel.
129348bfcdddSJulian Elischer 	 */
129448bfcdddSJulian Elischer 	if (td->td_standin == NULL) {
129548bfcdddSJulian Elischer 		if (ke->ke_tdspare) {
129648bfcdddSJulian Elischer 			td->td_standin = ke->ke_tdspare;
129748bfcdddSJulian Elischer 			ke->ke_tdspare = NULL;
129848bfcdddSJulian Elischer 		} else {
129948bfcdddSJulian Elischer 			td->td_standin = thread_alloc();
130048bfcdddSJulian Elischer 		}
130148bfcdddSJulian Elischer 	}
130248bfcdddSJulian Elischer 
130348bfcdddSJulian Elischer 	/*
130448bfcdddSJulian Elischer 	 * To get here, we know there is no other need for our
130548bfcdddSJulian Elischer 	 * KSE so we can proceed. If not upcalling, go back to
130648bfcdddSJulian Elischer 	 * userspace. If we are, get the upcall set up.
130748bfcdddSJulian Elischer 	 */
130848bfcdddSJulian Elischer 	if ((td->td_flags & TDF_UPCALLING) == 0)
1309c76e33b6SJonathan Mini 		return (0);
131048bfcdddSJulian Elischer 
1311c76e33b6SJonathan Mini 	/*
131248bfcdddSJulian Elischer 	 * We must be an upcall to get this far.
131344990b8cSJulian Elischer 	 * There is no more work to do and we are going to ride
13143d0586d4SJulian Elischer 	 * this thead/KSE up to userland as an upcall.
131548bfcdddSJulian Elischer 	 * Do the last parts of the setup needed for the upcall.
131644990b8cSJulian Elischer 	 */
1317c76e33b6SJonathan Mini 	CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)",
1318ed32df81SJulian Elischer 	    td, td->td_proc->p_pid, td->td_proc->p_comm);
1319c76e33b6SJonathan Mini 
1320c76e33b6SJonathan Mini 	/*
1321c76e33b6SJonathan Mini 	 * Set user context to the UTS.
1322c76e33b6SJonathan Mini 	 */
13233d0586d4SJulian Elischer 	cpu_set_upcall_kse(td, ke);
13243d0586d4SJulian Elischer 
1325c76e33b6SJonathan Mini 	/*
13263d0586d4SJulian Elischer 	 * Put any completed mailboxes on this KSE's list.
1327c76e33b6SJonathan Mini 	 */
132848bfcdddSJulian Elischer 	error = thread_link_mboxes(kg, ke);
13293d0586d4SJulian Elischer 	if (error)
13303d0586d4SJulian Elischer 		goto bad;
1331c76e33b6SJonathan Mini 
1332c76e33b6SJonathan Mini 	/*
1333c76e33b6SJonathan Mini 	 * Set state and mailbox.
133448bfcdddSJulian Elischer 	 * From now on we are just a bound outgoing process.
133548bfcdddSJulian Elischer 	 * **Problem** userret is often called several times.
133648bfcdddSJulian Elischer 	 * it would be nice if this all happenned only on the first time
133748bfcdddSJulian Elischer 	 * through. (the scan for extra work etc.)
1338c76e33b6SJonathan Mini 	 */
1339c76e33b6SJonathan Mini 	td->td_flags &= ~TDF_UPCALLING;
13403d0586d4SJulian Elischer #if 0
13413d0586d4SJulian Elischer 	error = suword((caddr_t)ke->ke_mailbox +
134248bfcdddSJulian Elischer 	    offsetof(struct kse_mailbox, km_curthread), 0);
13433d0586d4SJulian Elischer #else	/* if user pointer arithmetic is ok in the kernel */
13443d0586d4SJulian Elischer 	error = suword((caddr_t)&ke->ke_mailbox->km_curthread, 0);
13453d0586d4SJulian Elischer #endif
134648bfcdddSJulian Elischer 	if (!error)
134748bfcdddSJulian Elischer 		return (0);
134848bfcdddSJulian Elischer 
13493d0586d4SJulian Elischer bad:
13503d0586d4SJulian Elischer 	/*
13513d0586d4SJulian Elischer 	 * Things are going to be so screwed we should just kill the process.
13523d0586d4SJulian Elischer  	 * how do we do that?
13533d0586d4SJulian Elischer 	 */
135448bfcdddSJulian Elischer 	PROC_LOCK(td->td_proc);
135548bfcdddSJulian Elischer 	psignal(td->td_proc, SIGSEGV);
135648bfcdddSJulian Elischer 	PROC_UNLOCK(td->td_proc);
135748bfcdddSJulian Elischer 	return (error);	/* go sync */
135844990b8cSJulian Elischer }
135944990b8cSJulian Elischer 
136044990b8cSJulian Elischer /*
136144990b8cSJulian Elischer  * Enforce single-threading.
136244990b8cSJulian Elischer  *
136344990b8cSJulian Elischer  * Returns 1 if the caller must abort (another thread is waiting to
136444990b8cSJulian Elischer  * exit the process or similar). Process is locked!
136544990b8cSJulian Elischer  * Returns 0 when you are successfully the only thread running.
136644990b8cSJulian Elischer  * A process has successfully single threaded in the suspend mode when
136744990b8cSJulian Elischer  * There are no threads in user mode. Threads in the kernel must be
136844990b8cSJulian Elischer  * allowed to continue until they get to the user boundary. They may even
136944990b8cSJulian Elischer  * copy out their return values and data before suspending. They may however be
137044990b8cSJulian Elischer  * accellerated in reaching the user boundary as we will wake up
137144990b8cSJulian Elischer  * any sleeping threads that are interruptable. (PCATCH).
137244990b8cSJulian Elischer  */
137344990b8cSJulian Elischer int
137444990b8cSJulian Elischer thread_single(int force_exit)
137544990b8cSJulian Elischer {
137644990b8cSJulian Elischer 	struct thread *td;
137744990b8cSJulian Elischer 	struct thread *td2;
137844990b8cSJulian Elischer 	struct proc *p;
137944990b8cSJulian Elischer 
138044990b8cSJulian Elischer 	td = curthread;
138144990b8cSJulian Elischer 	p = td->td_proc;
138244990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
138344990b8cSJulian Elischer 	KASSERT((td != NULL), ("curthread is NULL"));
138444990b8cSJulian Elischer 
138544990b8cSJulian Elischer 	if ((p->p_flag & P_KSES) == 0)
138644990b8cSJulian Elischer 		return (0);
138744990b8cSJulian Elischer 
1388e3b9bf71SJulian Elischer 	/* Is someone already single threading? */
1389e3b9bf71SJulian Elischer 	if (p->p_singlethread)
139044990b8cSJulian Elischer 		return (1);
139144990b8cSJulian Elischer 
13921279572aSDavid Xu 	if (force_exit == SINGLE_EXIT)
139344990b8cSJulian Elischer 		p->p_flag |= P_SINGLE_EXIT;
139444990b8cSJulian Elischer 	else
139544990b8cSJulian Elischer 		p->p_flag &= ~P_SINGLE_EXIT;
13961279572aSDavid Xu 	p->p_flag |= P_STOPPED_SINGLE;
139744990b8cSJulian Elischer 	p->p_singlethread = td;
139844990b8cSJulian Elischer 	while ((p->p_numthreads - p->p_suspcount) != 1) {
139971fad9fdSJulian Elischer 		mtx_lock_spin(&sched_lock);
140044990b8cSJulian Elischer 		FOREACH_THREAD_IN_PROC(p, td2) {
140144990b8cSJulian Elischer 			if (td2 == td)
140244990b8cSJulian Elischer 				continue;
140371fad9fdSJulian Elischer 			if (TD_IS_INHIBITED(td2)) {
140471fad9fdSJulian Elischer 				if (TD_IS_SUSPENDED(td2)) {
14051279572aSDavid Xu 					if (force_exit == SINGLE_EXIT) {
140671fad9fdSJulian Elischer 						thread_unsuspend_one(td2);
140744990b8cSJulian Elischer 					}
140871fad9fdSJulian Elischer 				}
140971fad9fdSJulian Elischer 				if ( TD_IS_SLEEPING(td2)) {
1410e3b9bf71SJulian Elischer 					if (td2->td_flags & TDF_CVWAITQ)
141171fad9fdSJulian Elischer 						cv_waitq_remove(td2);
1412e3b9bf71SJulian Elischer 					else
141371fad9fdSJulian Elischer 						unsleep(td2);
141444990b8cSJulian Elischer 					break;
141571fad9fdSJulian Elischer 				}
141671fad9fdSJulian Elischer 				if (TD_CAN_RUN(td2))
141771fad9fdSJulian Elischer 					setrunqueue(td2);
141844990b8cSJulian Elischer 			}
141944990b8cSJulian Elischer 		}
142044990b8cSJulian Elischer 		/*
142144990b8cSJulian Elischer 		 * Wake us up when everyone else has suspended.
1422e3b9bf71SJulian Elischer 		 * In the mean time we suspend as well.
142344990b8cSJulian Elischer 		 */
142471fad9fdSJulian Elischer 		thread_suspend_one(td);
142544990b8cSJulian Elischer 		mtx_unlock(&Giant);
142644990b8cSJulian Elischer 		PROC_UNLOCK(p);
142744990b8cSJulian Elischer 		mi_switch();
142844990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
142944990b8cSJulian Elischer 		mtx_lock(&Giant);
143044990b8cSJulian Elischer 		PROC_LOCK(p);
143144990b8cSJulian Elischer 	}
14325c8329edSJulian Elischer 	if (force_exit == SINGLE_EXIT)
14335c8329edSJulian Elischer 		kse_purge(p, td);
143444990b8cSJulian Elischer 	return (0);
143544990b8cSJulian Elischer }
143644990b8cSJulian Elischer 
143744990b8cSJulian Elischer /*
143844990b8cSJulian Elischer  * Called in from locations that can safely check to see
143944990b8cSJulian Elischer  * whether we have to suspend or at least throttle for a
144044990b8cSJulian Elischer  * single-thread event (e.g. fork).
144144990b8cSJulian Elischer  *
144244990b8cSJulian Elischer  * Such locations include userret().
144344990b8cSJulian Elischer  * If the "return_instead" argument is non zero, the thread must be able to
144444990b8cSJulian Elischer  * accept 0 (caller may continue), or 1 (caller must abort) as a result.
144544990b8cSJulian Elischer  *
144644990b8cSJulian Elischer  * The 'return_instead' argument tells the function if it may do a
144744990b8cSJulian Elischer  * thread_exit() or suspend, or whether the caller must abort and back
144844990b8cSJulian Elischer  * out instead.
144944990b8cSJulian Elischer  *
145044990b8cSJulian Elischer  * If the thread that set the single_threading request has set the
145144990b8cSJulian Elischer  * P_SINGLE_EXIT bit in the process flags then this call will never return
145244990b8cSJulian Elischer  * if 'return_instead' is false, but will exit.
145344990b8cSJulian Elischer  *
145444990b8cSJulian Elischer  * P_SINGLE_EXIT | return_instead == 0| return_instead != 0
145544990b8cSJulian Elischer  *---------------+--------------------+---------------------
145644990b8cSJulian Elischer  *       0       | returns 0          |   returns 0 or 1
145744990b8cSJulian Elischer  *               | when ST ends       |   immediatly
145844990b8cSJulian Elischer  *---------------+--------------------+---------------------
145944990b8cSJulian Elischer  *       1       | thread exits       |   returns 1
146044990b8cSJulian Elischer  *               |                    |  immediatly
146144990b8cSJulian Elischer  * 0 = thread_exit() or suspension ok,
146244990b8cSJulian Elischer  * other = return error instead of stopping the thread.
146344990b8cSJulian Elischer  *
146444990b8cSJulian Elischer  * While a full suspension is under effect, even a single threading
146544990b8cSJulian Elischer  * thread would be suspended if it made this call (but it shouldn't).
146644990b8cSJulian Elischer  * This call should only be made from places where
146744990b8cSJulian Elischer  * thread_exit() would be safe as that may be the outcome unless
146844990b8cSJulian Elischer  * return_instead is set.
146944990b8cSJulian Elischer  */
147044990b8cSJulian Elischer int
147144990b8cSJulian Elischer thread_suspend_check(int return_instead)
147244990b8cSJulian Elischer {
1473ecafb24bSJuli Mallett 	struct thread *td;
1474ecafb24bSJuli Mallett 	struct proc *p;
14755c8329edSJulian Elischer 	struct kse *ke;
14765c8329edSJulian Elischer 	struct ksegrp *kg;
147744990b8cSJulian Elischer 
147844990b8cSJulian Elischer 	td = curthread;
147944990b8cSJulian Elischer 	p = td->td_proc;
14805c8329edSJulian Elischer 	kg = td->td_ksegrp;
148144990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
148244990b8cSJulian Elischer 	while (P_SHOULDSTOP(p)) {
14831279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
148444990b8cSJulian Elischer 			KASSERT(p->p_singlethread != NULL,
148544990b8cSJulian Elischer 			    ("singlethread not set"));
148644990b8cSJulian Elischer 			/*
1487e3b9bf71SJulian Elischer 			 * The only suspension in action is a
1488e3b9bf71SJulian Elischer 			 * single-threading. Single threader need not stop.
1489b6d5995eSJulian Elischer 			 * XXX Should be safe to access unlocked
1490b6d5995eSJulian Elischer 			 * as it can only be set to be true by us.
149144990b8cSJulian Elischer 			 */
1492e3b9bf71SJulian Elischer 			if (p->p_singlethread == td)
149344990b8cSJulian Elischer 				return (0);	/* Exempt from stopping. */
149444990b8cSJulian Elischer 		}
1495e3b9bf71SJulian Elischer 		if (return_instead)
149644990b8cSJulian Elischer 			return (1);
149744990b8cSJulian Elischer 
149844990b8cSJulian Elischer 		/*
149944990b8cSJulian Elischer 		 * If the process is waiting for us to exit,
150044990b8cSJulian Elischer 		 * this thread should just suicide.
15011279572aSDavid Xu 		 * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
150244990b8cSJulian Elischer 		 */
150344990b8cSJulian Elischer 		if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
150444990b8cSJulian Elischer 			mtx_lock_spin(&sched_lock);
150544990b8cSJulian Elischer 			while (mtx_owned(&Giant))
150644990b8cSJulian Elischer 				mtx_unlock(&Giant);
15075c8329edSJulian Elischer 			/*
15085c8329edSJulian Elischer 			 * free extra kses and ksegrps, we needn't worry
15095c8329edSJulian Elischer 			 * about if current thread is in same ksegrp as
15105c8329edSJulian Elischer 			 * p_singlethread and last kse in the group
15115c8329edSJulian Elischer 			 * could be killed, this is protected by kg_numthreads,
15125c8329edSJulian Elischer 			 * in this case, we deduce that kg_numthreads must > 1.
15135c8329edSJulian Elischer 			 */
15145c8329edSJulian Elischer 			ke = td->td_kse;
15155c8329edSJulian Elischer 			if (ke->ke_bound == NULL &&
15165c8329edSJulian Elischer 			    ((kg->kg_kses != 1) || (kg->kg_numthreads == 1)))
15175c8329edSJulian Elischer 				ke->ke_flags |= KEF_EXIT;
151844990b8cSJulian Elischer 			thread_exit();
151944990b8cSJulian Elischer 		}
152044990b8cSJulian Elischer 
152144990b8cSJulian Elischer 		/*
152244990b8cSJulian Elischer 		 * When a thread suspends, it just
152344990b8cSJulian Elischer 		 * moves to the processes's suspend queue
152444990b8cSJulian Elischer 		 * and stays there.
152544990b8cSJulian Elischer 		 *
152644990b8cSJulian Elischer 		 * XXXKSE if TDF_BOUND is true
152744990b8cSJulian Elischer 		 * it will not release it's KSE which might
152844990b8cSJulian Elischer 		 * lead to deadlock if there are not enough KSEs
152944990b8cSJulian Elischer 		 * to complete all waiting threads.
153044990b8cSJulian Elischer 		 * Maybe be able to 'lend' it out again.
153144990b8cSJulian Elischer 		 * (lent kse's can not go back to userland?)
153244990b8cSJulian Elischer 		 * and can only be lent in STOPPED state.
153344990b8cSJulian Elischer 		 */
1534721e5910SJulian Elischer 		mtx_lock_spin(&sched_lock);
15351279572aSDavid Xu 		if ((p->p_flag & P_STOPPED_SIG) &&
1536721e5910SJulian Elischer 		    (p->p_suspcount+1 == p->p_numthreads)) {
1537721e5910SJulian Elischer 			mtx_unlock_spin(&sched_lock);
1538721e5910SJulian Elischer 			PROC_LOCK(p->p_pptr);
1539721e5910SJulian Elischer 			if ((p->p_pptr->p_procsig->ps_flag &
1540721e5910SJulian Elischer 				PS_NOCLDSTOP) == 0) {
1541721e5910SJulian Elischer 				psignal(p->p_pptr, SIGCHLD);
1542721e5910SJulian Elischer 			}
1543721e5910SJulian Elischer 			PROC_UNLOCK(p->p_pptr);
15449b0e281bSJulian Elischer 			mtx_lock_spin(&sched_lock);
1545721e5910SJulian Elischer 		}
154644990b8cSJulian Elischer 		mtx_assert(&Giant, MA_NOTOWNED);
154771fad9fdSJulian Elischer 		thread_suspend_one(td);
154844990b8cSJulian Elischer 		PROC_UNLOCK(p);
15491279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
1550cf19bf91SJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
155171fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
1552cf19bf91SJulian Elischer 			}
1553cf19bf91SJulian Elischer 		}
155420568366SJulian Elischer 		p->p_stats->p_ru.ru_nivcsw++;
155544990b8cSJulian Elischer 		mi_switch();
155644990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
155744990b8cSJulian Elischer 		PROC_LOCK(p);
155844990b8cSJulian Elischer 	}
155944990b8cSJulian Elischer 	return (0);
156044990b8cSJulian Elischer }
156144990b8cSJulian Elischer 
156235c32a76SDavid Xu void
156335c32a76SDavid Xu thread_suspend_one(struct thread *td)
156435c32a76SDavid Xu {
156535c32a76SDavid Xu 	struct proc *p = td->td_proc;
156635c32a76SDavid Xu 
156735c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
156835c32a76SDavid Xu 	p->p_suspcount++;
156971fad9fdSJulian Elischer 	TD_SET_SUSPENDED(td);
157035c32a76SDavid Xu 	TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
157171fad9fdSJulian Elischer 	/*
157271fad9fdSJulian Elischer 	 * Hack: If we are suspending but are on the sleep queue
157371fad9fdSJulian Elischer 	 * then we are in msleep or the cv equivalent. We
157471fad9fdSJulian Elischer 	 * want to look like we have two Inhibitors.
157571fad9fdSJulian Elischer 	 */
157671fad9fdSJulian Elischer 	if (TD_ON_SLEEPQ(td))
157771fad9fdSJulian Elischer 		TD_SET_SLEEPING(td);
157835c32a76SDavid Xu }
157935c32a76SDavid Xu 
158035c32a76SDavid Xu void
158135c32a76SDavid Xu thread_unsuspend_one(struct thread *td)
158235c32a76SDavid Xu {
158335c32a76SDavid Xu 	struct proc *p = td->td_proc;
158435c32a76SDavid Xu 
158535c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
158635c32a76SDavid Xu 	TAILQ_REMOVE(&p->p_suspended, td, td_runq);
158771fad9fdSJulian Elischer 	TD_CLR_SUSPENDED(td);
158835c32a76SDavid Xu 	p->p_suspcount--;
158971fad9fdSJulian Elischer 	setrunnable(td);
159035c32a76SDavid Xu }
159135c32a76SDavid Xu 
159244990b8cSJulian Elischer /*
159344990b8cSJulian Elischer  * Allow all threads blocked by single threading to continue running.
159444990b8cSJulian Elischer  */
159544990b8cSJulian Elischer void
159644990b8cSJulian Elischer thread_unsuspend(struct proc *p)
159744990b8cSJulian Elischer {
159844990b8cSJulian Elischer 	struct thread *td;
159944990b8cSJulian Elischer 
1600b6d5995eSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
160144990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
160244990b8cSJulian Elischer 	if (!P_SHOULDSTOP(p)) {
160344990b8cSJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
160435c32a76SDavid Xu 			thread_unsuspend_one(td);
160544990b8cSJulian Elischer 		}
16061279572aSDavid Xu 	} else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) &&
160744990b8cSJulian Elischer 	    (p->p_numthreads == p->p_suspcount)) {
160844990b8cSJulian Elischer 		/*
160944990b8cSJulian Elischer 		 * Stopping everything also did the job for the single
161044990b8cSJulian Elischer 		 * threading request. Now we've downgraded to single-threaded,
161144990b8cSJulian Elischer 		 * let it continue.
161244990b8cSJulian Elischer 		 */
161335c32a76SDavid Xu 		thread_unsuspend_one(p->p_singlethread);
161444990b8cSJulian Elischer 	}
161544990b8cSJulian Elischer }
161644990b8cSJulian Elischer 
161744990b8cSJulian Elischer void
161844990b8cSJulian Elischer thread_single_end(void)
161944990b8cSJulian Elischer {
162044990b8cSJulian Elischer 	struct thread *td;
162144990b8cSJulian Elischer 	struct proc *p;
162244990b8cSJulian Elischer 
162344990b8cSJulian Elischer 	td = curthread;
162444990b8cSJulian Elischer 	p = td->td_proc;
162544990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
16261279572aSDavid Xu 	p->p_flag &= ~P_STOPPED_SINGLE;
162744990b8cSJulian Elischer 	p->p_singlethread = NULL;
162849539972SJulian Elischer 	/*
162949539972SJulian Elischer 	 * If there are other threads they mey now run,
163049539972SJulian Elischer 	 * unless of course there is a blanket 'stop order'
163149539972SJulian Elischer 	 * on the process. The single threader must be allowed
163249539972SJulian Elischer 	 * to continue however as this is a bad place to stop.
163349539972SJulian Elischer 	 */
163449539972SJulian Elischer 	if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
163549539972SJulian Elischer 		mtx_lock_spin(&sched_lock);
163649539972SJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
163771fad9fdSJulian Elischer 			thread_unsuspend_one(td);
163844990b8cSJulian Elischer 		}
163949539972SJulian Elischer 		mtx_unlock_spin(&sched_lock);
164049539972SJulian Elischer 	}
164149539972SJulian Elischer }
164249539972SJulian Elischer 
164344990b8cSJulian Elischer 
1644