xref: /freebsd/sys/kern/kern_thread.c (revision 4f0db5e08cf1236f0efe47f6ea6f5ae1c833d6de)
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>
3944990b8cSJulian Elischer #include <sys/filedesc.h>
4044990b8cSJulian Elischer #include <sys/tty.h>
4144990b8cSJulian Elischer #include <sys/signalvar.h>
4244990b8cSJulian Elischer #include <sys/sx.h>
4344990b8cSJulian Elischer #include <sys/user.h>
4444990b8cSJulian Elischer #include <sys/jail.h>
4544990b8cSJulian Elischer #include <sys/kse.h>
4644990b8cSJulian Elischer #include <sys/ktr.h>
4744990b8cSJulian Elischer 
4844990b8cSJulian Elischer #include <vm/vm.h>
4944990b8cSJulian Elischer #include <vm/vm_object.h>
5044990b8cSJulian Elischer #include <vm/pmap.h>
5144990b8cSJulian Elischer #include <vm/uma.h>
5244990b8cSJulian Elischer #include <vm/vm_map.h>
5344990b8cSJulian Elischer 
5402fb42b0SPeter Wemm #include <machine/frame.h>
5502fb42b0SPeter Wemm 
5644990b8cSJulian Elischer /*
574f0db5e0SJulian Elischer  * KSEGRP related storage.
5844990b8cSJulian Elischer  */
594f0db5e0SJulian Elischer static uma_zone_t ksegrp_zone;
604f0db5e0SJulian Elischer static uma_zone_t kse_zone;
6144990b8cSJulian Elischer static uma_zone_t thread_zone;
6244990b8cSJulian Elischer 
634f0db5e0SJulian Elischer /* DEBUG ONLY */
6444990b8cSJulian Elischer SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0, "thread allocation");
6544990b8cSJulian Elischer static int oiks_debug = 1;	/* 0 disable, 1 printf, 2 enter debugger */
6644990b8cSJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, oiks, CTLFLAG_RW,
6744990b8cSJulian Elischer 	&oiks_debug, 0, "OIKS thread debug");
6844990b8cSJulian Elischer 
694f0db5e0SJulian Elischer static int max_threads_per_proc = 4;
704f0db5e0SJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, max_per_proc, CTLFLAG_RW,
714f0db5e0SJulian Elischer 	&max_threads_per_proc, 0, "Limit on threads per proc");
724f0db5e0SJulian Elischer 
7344990b8cSJulian Elischer #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
7444990b8cSJulian Elischer 
7544990b8cSJulian Elischer struct threadqueue zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads);
7644990b8cSJulian Elischer struct mtx zombie_thread_lock;
7744990b8cSJulian Elischer MTX_SYSINIT(zombie_thread_lock, &zombie_thread_lock,
7844990b8cSJulian Elischer     "zombie_thread_lock", MTX_SPIN);
7944990b8cSJulian Elischer 
8044990b8cSJulian Elischer /*
8144990b8cSJulian Elischer  * Pepare a thread for use.
8244990b8cSJulian Elischer  */
8344990b8cSJulian Elischer static void
8444990b8cSJulian Elischer thread_ctor(void *mem, int size, void *arg)
8544990b8cSJulian Elischer {
8644990b8cSJulian Elischer 	struct thread	*td;
8744990b8cSJulian Elischer 
8844990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
89b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
9044990b8cSJulian Elischer 
9144990b8cSJulian Elischer 	td = (struct thread *)mem;
9271fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
9344990b8cSJulian Elischer 	td->td_flags |= TDF_UNBOUND;
9444990b8cSJulian Elischer }
9544990b8cSJulian Elischer 
9644990b8cSJulian Elischer /*
9744990b8cSJulian Elischer  * Reclaim a thread after use.
9844990b8cSJulian Elischer  */
9944990b8cSJulian Elischer static void
10044990b8cSJulian Elischer thread_dtor(void *mem, int size, void *arg)
10144990b8cSJulian Elischer {
10244990b8cSJulian Elischer 	struct thread	*td;
10344990b8cSJulian Elischer 
10444990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
105b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
10644990b8cSJulian Elischer 
10744990b8cSJulian Elischer 	td = (struct thread *)mem;
10844990b8cSJulian Elischer 
10944990b8cSJulian Elischer #ifdef INVARIANTS
11044990b8cSJulian Elischer 	/* Verify that this thread is in a safe state to free. */
11144990b8cSJulian Elischer 	switch (td->td_state) {
11271fad9fdSJulian Elischer 	case TDS_INHIBITED:
11371fad9fdSJulian Elischer 	case TDS_RUNNING:
11471fad9fdSJulian Elischer 	case TDS_CAN_RUN:
11544990b8cSJulian Elischer 	case TDS_RUNQ:
11644990b8cSJulian Elischer 		/*
11744990b8cSJulian Elischer 		 * We must never unlink a thread that is in one of
11844990b8cSJulian Elischer 		 * these states, because it is currently active.
11944990b8cSJulian Elischer 		 */
12044990b8cSJulian Elischer 		panic("bad state for thread unlinking");
12144990b8cSJulian Elischer 		/* NOTREACHED */
12271fad9fdSJulian Elischer 	case TDS_INACTIVE:
12344990b8cSJulian Elischer 		break;
12444990b8cSJulian Elischer 	default:
12544990b8cSJulian Elischer 		panic("bad thread state");
12644990b8cSJulian Elischer 		/* NOTREACHED */
12744990b8cSJulian Elischer 	}
12844990b8cSJulian Elischer #endif
12944990b8cSJulian Elischer }
13044990b8cSJulian Elischer 
13144990b8cSJulian Elischer /*
13244990b8cSJulian Elischer  * Initialize type-stable parts of a thread (when newly created).
13344990b8cSJulian Elischer  */
13444990b8cSJulian Elischer static void
13544990b8cSJulian Elischer thread_init(void *mem, int size)
13644990b8cSJulian Elischer {
13744990b8cSJulian Elischer 	struct thread	*td;
13844990b8cSJulian Elischer 
13944990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
140b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
14144990b8cSJulian Elischer 
14244990b8cSJulian Elischer 	td = (struct thread *)mem;
143e6e24ff9SJulian Elischer 	mtx_lock(&Giant);
14444990b8cSJulian Elischer 	pmap_new_thread(td);
145e6e24ff9SJulian Elischer 	mtx_unlock(&Giant);
14644990b8cSJulian Elischer 	cpu_thread_setup(td);
14744990b8cSJulian Elischer }
14844990b8cSJulian Elischer 
14944990b8cSJulian Elischer /*
15044990b8cSJulian Elischer  * Tear down type-stable parts of a thread (just before being discarded).
15144990b8cSJulian Elischer  */
15244990b8cSJulian Elischer static void
15344990b8cSJulian Elischer thread_fini(void *mem, int size)
15444990b8cSJulian Elischer {
15544990b8cSJulian Elischer 	struct thread	*td;
15644990b8cSJulian Elischer 
15744990b8cSJulian Elischer 	KASSERT((size == sizeof(struct thread)),
158b799f5a4SPeter Wemm 	    ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
15944990b8cSJulian Elischer 
16044990b8cSJulian Elischer 	td = (struct thread *)mem;
16144990b8cSJulian Elischer 	pmap_dispose_thread(td);
16244990b8cSJulian Elischer }
16344990b8cSJulian Elischer 
16444990b8cSJulian Elischer /*
16544990b8cSJulian Elischer  * Initialize global thread allocation resources.
16644990b8cSJulian Elischer  */
16744990b8cSJulian Elischer void
16844990b8cSJulian Elischer threadinit(void)
16944990b8cSJulian Elischer {
17044990b8cSJulian Elischer 
17144990b8cSJulian Elischer 	thread_zone = uma_zcreate("THREAD", sizeof (struct thread),
17244990b8cSJulian Elischer 	    thread_ctor, thread_dtor, thread_init, thread_fini,
17344990b8cSJulian Elischer 	    UMA_ALIGN_CACHE, 0);
1744f0db5e0SJulian Elischer 	ksegrp_zone = uma_zcreate("KSEGRP", sizeof (struct ksegrp),
1754f0db5e0SJulian Elischer 	    NULL, NULL, NULL, NULL,
1764f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
1774f0db5e0SJulian Elischer 	kse_zone = uma_zcreate("KSE", sizeof (struct kse),
1784f0db5e0SJulian Elischer 	    NULL, NULL, NULL, NULL,
1794f0db5e0SJulian Elischer 	    UMA_ALIGN_CACHE, 0);
18044990b8cSJulian Elischer }
18144990b8cSJulian Elischer 
18244990b8cSJulian Elischer /*
1831faf202eSJulian Elischer  * Stash an embarasingly extra thread into the zombie thread queue.
18444990b8cSJulian Elischer  */
18544990b8cSJulian Elischer void
18644990b8cSJulian Elischer thread_stash(struct thread *td)
18744990b8cSJulian Elischer {
18844990b8cSJulian Elischer 	mtx_lock_spin(&zombie_thread_lock);
18944990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&zombie_threads, td, td_runq);
19044990b8cSJulian Elischer 	mtx_unlock_spin(&zombie_thread_lock);
19144990b8cSJulian Elischer }
19244990b8cSJulian Elischer 
19344990b8cSJulian Elischer /*
19467759b33SJulian Elischer  * reap any  zombie threads.
19544990b8cSJulian Elischer  */
19644990b8cSJulian Elischer void
19744990b8cSJulian Elischer thread_reap(void)
19844990b8cSJulian Elischer {
19944990b8cSJulian Elischer 	struct thread *td_reaped;
20044990b8cSJulian Elischer 
20144990b8cSJulian Elischer 	/*
20244990b8cSJulian Elischer 	 * don't even bother to lock if none at this instant
20344990b8cSJulian Elischer 	 * We really don't care about the next instant..
20444990b8cSJulian Elischer 	 */
20544990b8cSJulian Elischer 	if (!TAILQ_EMPTY(&zombie_threads)) {
20644990b8cSJulian Elischer 		mtx_lock_spin(&zombie_thread_lock);
20744990b8cSJulian Elischer 		while (!TAILQ_EMPTY(&zombie_threads)) {
20844990b8cSJulian Elischer 			td_reaped = TAILQ_FIRST(&zombie_threads);
20944990b8cSJulian Elischer 			TAILQ_REMOVE(&zombie_threads, td_reaped, td_runq);
21044990b8cSJulian Elischer 			mtx_unlock_spin(&zombie_thread_lock);
21144990b8cSJulian Elischer 			thread_free(td_reaped);
21244990b8cSJulian Elischer 			mtx_lock_spin(&zombie_thread_lock);
21344990b8cSJulian Elischer 		}
21444990b8cSJulian Elischer 		mtx_unlock_spin(&zombie_thread_lock);
21544990b8cSJulian Elischer 	}
21644990b8cSJulian Elischer }
21744990b8cSJulian Elischer 
21844990b8cSJulian Elischer /*
2194f0db5e0SJulian Elischer  * Allocate a ksegrp.
2204f0db5e0SJulian Elischer  */
2214f0db5e0SJulian Elischer struct ksegrp *
2224f0db5e0SJulian Elischer ksegrp_alloc(void)
2234f0db5e0SJulian Elischer {
2244f0db5e0SJulian Elischer 	return (uma_zalloc(ksegrp_zone, M_WAITOK));
2254f0db5e0SJulian Elischer }
2264f0db5e0SJulian Elischer 
2274f0db5e0SJulian Elischer /*
2284f0db5e0SJulian Elischer  * Allocate a kse.
2294f0db5e0SJulian Elischer  */
2304f0db5e0SJulian Elischer struct kse *
2314f0db5e0SJulian Elischer kse_alloc(void)
2324f0db5e0SJulian Elischer {
2334f0db5e0SJulian Elischer 	return (uma_zalloc(kse_zone, M_WAITOK));
2344f0db5e0SJulian Elischer }
2354f0db5e0SJulian Elischer 
2364f0db5e0SJulian Elischer /*
23744990b8cSJulian Elischer  * Allocate a thread.
23844990b8cSJulian Elischer  */
23944990b8cSJulian Elischer struct thread *
24044990b8cSJulian Elischer thread_alloc(void)
24144990b8cSJulian Elischer {
24244990b8cSJulian Elischer 	thread_reap(); /* check if any zombies to get */
24344990b8cSJulian Elischer 	return (uma_zalloc(thread_zone, M_WAITOK));
24444990b8cSJulian Elischer }
24544990b8cSJulian Elischer 
24644990b8cSJulian Elischer /*
2474f0db5e0SJulian Elischer  * Deallocate a ksegrp.
2484f0db5e0SJulian Elischer  */
2494f0db5e0SJulian Elischer void
2504f0db5e0SJulian Elischer ksegrp_free(struct ksegrp *td)
2514f0db5e0SJulian Elischer {
2524f0db5e0SJulian Elischer 	uma_zfree(ksegrp_zone, td);
2534f0db5e0SJulian Elischer }
2544f0db5e0SJulian Elischer 
2554f0db5e0SJulian Elischer /*
2564f0db5e0SJulian Elischer  * Deallocate a kse.
2574f0db5e0SJulian Elischer  */
2584f0db5e0SJulian Elischer void
2594f0db5e0SJulian Elischer kse_free(struct kse *td)
2604f0db5e0SJulian Elischer {
2614f0db5e0SJulian Elischer 	uma_zfree(kse_zone, td);
2624f0db5e0SJulian Elischer }
2634f0db5e0SJulian Elischer 
2644f0db5e0SJulian Elischer /*
26544990b8cSJulian Elischer  * Deallocate a thread.
26644990b8cSJulian Elischer  */
26744990b8cSJulian Elischer void
26844990b8cSJulian Elischer thread_free(struct thread *td)
26944990b8cSJulian Elischer {
27044990b8cSJulian Elischer 	uma_zfree(thread_zone, td);
27144990b8cSJulian Elischer }
27244990b8cSJulian Elischer 
27344990b8cSJulian Elischer /*
27444990b8cSJulian Elischer  * Store the thread context in the UTS's mailbox.
27544990b8cSJulian Elischer  */
27644990b8cSJulian Elischer int
27744990b8cSJulian Elischer thread_export_context(struct thread *td)
27844990b8cSJulian Elischer {
27944990b8cSJulian Elischer 	struct kse *ke;
28044990b8cSJulian Elischer 	uintptr_t td2_mbx;
28144990b8cSJulian Elischer 	void *addr1;
28244990b8cSJulian Elischer 	void *addr2;
28344990b8cSJulian Elischer 	int error;
28444990b8cSJulian Elischer 
2858a2bd345SPeter Wemm #ifdef __ia64__
2868a2bd345SPeter Wemm 	td2_mbx = 0;		/* pacify gcc (!) */
2878a2bd345SPeter Wemm #endif
28844990b8cSJulian Elischer 	/* Export the register contents. */
28944990b8cSJulian Elischer 	error = cpu_export_context(td);
29044990b8cSJulian Elischer 
29144990b8cSJulian Elischer 	ke = td->td_kse;
29244990b8cSJulian Elischer 	addr1 = (caddr_t)ke->ke_mailbox
29344990b8cSJulian Elischer 			+ offsetof(struct kse_mailbox, kmbx_completed_threads);
29444990b8cSJulian Elischer 	addr2 = (caddr_t)td->td_mailbox
29544990b8cSJulian Elischer 			+ offsetof(struct thread_mailbox , next_completed);
29644990b8cSJulian Elischer 	/* Then link it into it's KSE's list of completed threads. */
29744990b8cSJulian Elischer 	if (!error) {
29844990b8cSJulian Elischer 		error = td2_mbx = fuword(addr1);
29944990b8cSJulian Elischer 		if (error == -1)
30044990b8cSJulian Elischer 			error = EFAULT;
30144990b8cSJulian Elischer 		else
30244990b8cSJulian Elischer 			error = 0;
30344990b8cSJulian Elischer 	}
30444990b8cSJulian Elischer 	if (!error)
30544990b8cSJulian Elischer 		error = suword(addr2, td2_mbx);
30644990b8cSJulian Elischer 	if (!error)
30744990b8cSJulian Elischer 		error = suword(addr1, (u_long)td->td_mailbox);
30844990b8cSJulian Elischer 	if (error == -1)
30944990b8cSJulian Elischer 		error = EFAULT;
31044990b8cSJulian Elischer 	return (error);
31144990b8cSJulian Elischer }
31244990b8cSJulian Elischer 
31344990b8cSJulian Elischer 
31444990b8cSJulian Elischer /*
31544990b8cSJulian Elischer  * Discard the current thread and exit from its context.
31644990b8cSJulian Elischer  *
31744990b8cSJulian Elischer  * Because we can't free a thread while we're operating under its context,
31844990b8cSJulian Elischer  * push the current thread into our KSE's ke_tdspare slot, freeing the
31944990b8cSJulian Elischer  * thread that might be there currently. Because we know that only this
32044990b8cSJulian Elischer  * processor will run our KSE, we needn't worry about someone else grabbing
32144990b8cSJulian Elischer  * our context before we do a cpu_throw.
32244990b8cSJulian Elischer  */
32344990b8cSJulian Elischer void
32444990b8cSJulian Elischer thread_exit(void)
32544990b8cSJulian Elischer {
32644990b8cSJulian Elischer 	struct thread *td;
32744990b8cSJulian Elischer 	struct kse *ke;
32844990b8cSJulian Elischer 	struct proc *p;
32944990b8cSJulian Elischer 	struct ksegrp	*kg;
33044990b8cSJulian Elischer 
33144990b8cSJulian Elischer 	td = curthread;
33244990b8cSJulian Elischer 	kg = td->td_ksegrp;
33344990b8cSJulian Elischer 	p = td->td_proc;
33444990b8cSJulian Elischer 	ke = td->td_kse;
33544990b8cSJulian Elischer 
33644990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
33788151aa3SJulian Elischer 	KASSERT(p != NULL, ("thread exiting without a process"));
33888151aa3SJulian Elischer 	KASSERT(ke != NULL, ("thread exiting without a kse"));
33988151aa3SJulian Elischer 	KASSERT(kg != NULL, ("thread exiting without a kse group"));
34044990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
34144990b8cSJulian Elischer 	CTR1(KTR_PROC, "thread_exit: thread %p", td);
34244990b8cSJulian Elischer 	KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
34344990b8cSJulian Elischer 
34444990b8cSJulian Elischer 	if (ke->ke_tdspare != NULL) {
34571fad9fdSJulian Elischer 		thread_stash(ke->ke_tdspare);
34644990b8cSJulian Elischer 		ke->ke_tdspare = NULL;
34744990b8cSJulian Elischer 	}
34844990b8cSJulian Elischer 	cpu_thread_exit(td);	/* XXXSMP */
34944990b8cSJulian Elischer 
3501faf202eSJulian Elischer 	/*
3511faf202eSJulian Elischer 	 * The last thread is left attached to the process
3521faf202eSJulian Elischer 	 * So that the whole bundle gets recycled. Skip
3531faf202eSJulian Elischer 	 * all this stuff.
3541faf202eSJulian Elischer 	 */
3551faf202eSJulian Elischer 	if (p->p_numthreads > 1) {
35644990b8cSJulian Elischer 		/* Reassign this thread's KSE. */
35744990b8cSJulian Elischer 		ke->ke_thread = NULL;
35844990b8cSJulian Elischer 		td->td_kse = NULL;
35944990b8cSJulian Elischer 		ke->ke_state = KES_UNQUEUED;
36044990b8cSJulian Elischer 		kse_reassign(ke);
36144990b8cSJulian Elischer 
36244990b8cSJulian Elischer 		/* Unlink this thread from its proc. and the kseg */
36344990b8cSJulian Elischer 		TAILQ_REMOVE(&p->p_threads, td, td_plist);
36444990b8cSJulian Elischer 		p->p_numthreads--;
36544990b8cSJulian Elischer 		TAILQ_REMOVE(&kg->kg_threads, td, td_kglist);
36644990b8cSJulian Elischer 		kg->kg_numthreads--;
36744990b8cSJulian Elischer 		/*
36844990b8cSJulian Elischer 		 * The test below is NOT true if we are the
3691faf202eSJulian Elischer 		 * sole exiting thread. P_STOPPED_SNGL is unset
37044990b8cSJulian Elischer 		 * in exit1() after it is the only survivor.
37144990b8cSJulian Elischer 		 */
3721279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
37344990b8cSJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
37471fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
37544990b8cSJulian Elischer 			}
37644990b8cSJulian Elischer 		}
37788151aa3SJulian Elischer 		PROC_UNLOCK(p);
37871fad9fdSJulian Elischer 		td->td_state	= TDS_INACTIVE;
37944990b8cSJulian Elischer 		td->td_proc	= NULL;
38044990b8cSJulian Elischer 		td->td_ksegrp	= NULL;
38144990b8cSJulian Elischer 		td->td_last_kse	= NULL;
38244990b8cSJulian Elischer 		ke->ke_tdspare = td;
3831faf202eSJulian Elischer 	} else {
3841faf202eSJulian Elischer 		PROC_UNLOCK(p);
3851faf202eSJulian Elischer 	}
3861faf202eSJulian Elischer 
38744990b8cSJulian Elischer 	cpu_throw();
38844990b8cSJulian Elischer 	/* NOTREACHED */
38944990b8cSJulian Elischer }
39044990b8cSJulian Elischer 
39144990b8cSJulian Elischer /*
39244990b8cSJulian Elischer  * Link a thread to a process.
3931faf202eSJulian Elischer  * set up anything that needs to be initialized for it to
3941faf202eSJulian Elischer  * be used by the process.
39544990b8cSJulian Elischer  *
39644990b8cSJulian Elischer  * Note that we do not link to the proc's ucred here.
39744990b8cSJulian Elischer  * The thread is linked as if running but no KSE assigned.
39844990b8cSJulian Elischer  */
39944990b8cSJulian Elischer void
40044990b8cSJulian Elischer thread_link(struct thread *td, struct ksegrp *kg)
40144990b8cSJulian Elischer {
40244990b8cSJulian Elischer 	struct proc *p;
40344990b8cSJulian Elischer 
40444990b8cSJulian Elischer 	p = kg->kg_proc;
40571fad9fdSJulian Elischer 	td->td_state = TDS_INACTIVE;
40644990b8cSJulian Elischer 	td->td_proc	= p;
40744990b8cSJulian Elischer 	td->td_ksegrp	= kg;
40844990b8cSJulian Elischer 	td->td_last_kse	= NULL;
40944990b8cSJulian Elischer 
4101faf202eSJulian Elischer 	LIST_INIT(&td->td_contested);
4111faf202eSJulian Elischer 	callout_init(&td->td_slpcallout, 1);
41244990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist);
41344990b8cSJulian Elischer 	TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist);
41444990b8cSJulian Elischer 	p->p_numthreads++;
41544990b8cSJulian Elischer 	kg->kg_numthreads++;
4164f0db5e0SJulian Elischer 	if (oiks_debug && p->p_numthreads > max_threads_per_proc) {
41744990b8cSJulian Elischer 		printf("OIKS %d\n", p->p_numthreads);
41844990b8cSJulian Elischer 		if (oiks_debug > 1)
41944990b8cSJulian Elischer 			Debugger("OIKS");
42044990b8cSJulian Elischer 	}
42144990b8cSJulian Elischer 	td->td_kse	= NULL;
42244990b8cSJulian Elischer }
42344990b8cSJulian Elischer 
42444990b8cSJulian Elischer /*
42544990b8cSJulian Elischer  * Set up the upcall pcb in either a given thread or a new one
42644990b8cSJulian Elischer  * if none given. Use the upcall for the given KSE
42744990b8cSJulian Elischer  * XXXKSE possibly fix cpu_set_upcall() to not need td->td_kse set.
42844990b8cSJulian Elischer  */
42944990b8cSJulian Elischer struct thread *
43044990b8cSJulian Elischer thread_schedule_upcall(struct thread *td, struct kse *ke)
43144990b8cSJulian Elischer {
43244990b8cSJulian Elischer 	struct thread *td2;
43344990b8cSJulian Elischer 
43444990b8cSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
43544990b8cSJulian Elischer 	if (ke->ke_tdspare != NULL) {
43644990b8cSJulian Elischer 		td2 = ke->ke_tdspare;
43744990b8cSJulian Elischer 		ke->ke_tdspare = NULL;
43844990b8cSJulian Elischer 	} else {
43944990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
44044990b8cSJulian Elischer 		td2 = thread_alloc();
44144990b8cSJulian Elischer 		mtx_lock_spin(&sched_lock);
44244990b8cSJulian Elischer 	}
44344990b8cSJulian Elischer 	CTR3(KTR_PROC, "thread_schedule_upcall: thread %p (pid %d, %s)",
44444990b8cSJulian Elischer 	     td, td->td_proc->p_pid, td->td_proc->p_comm);
445c0698d32SJulian Elischer 	bzero(&td2->td_startzero,
4461faf202eSJulian Elischer 	    (unsigned)RANGEOF(struct thread, td_startzero, td_endzero));
4471faf202eSJulian Elischer 	bcopy(&td->td_startcopy, &td2->td_startcopy,
4481faf202eSJulian Elischer 	    (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy));
44944990b8cSJulian Elischer 	thread_link(td2, ke->ke_ksegrp);
45044990b8cSJulian Elischer 	cpu_set_upcall(td2, ke->ke_pcb);
45144990b8cSJulian Elischer 	td2->td_ucred = crhold(td->td_ucred);
45244990b8cSJulian Elischer 	td2->td_flags = TDF_UNBOUND|TDF_UPCALLING;
45371fad9fdSJulian Elischer 	TD_SET_CAN_RUN(td2);
45444990b8cSJulian Elischer 	setrunqueue(td2);
45544990b8cSJulian Elischer 	return (td2);
45644990b8cSJulian Elischer }
45744990b8cSJulian Elischer 
45844990b8cSJulian Elischer /*
45944990b8cSJulian Elischer  * The extra work we go through if we are a threaded process when we
46044990b8cSJulian Elischer  * return to userland
46144990b8cSJulian Elischer  *
46244990b8cSJulian Elischer  * If we are a KSE process and returning to user mode, check for
46344990b8cSJulian Elischer  * extra work to do before we return (e.g. for more syscalls
46444990b8cSJulian Elischer  * to complete first).  If we were in a critical section, we should
46544990b8cSJulian Elischer  * just return to let it finish. Same if we were in the UTS (in
46644990b8cSJulian Elischer  * which case we will have no thread mailbox registered).  The only
46744990b8cSJulian Elischer  * traps we suport will have set the mailbox.  We will clear it here.
46844990b8cSJulian Elischer  */
46944990b8cSJulian Elischer int
47044990b8cSJulian Elischer thread_userret(struct proc *p, struct ksegrp *kg, struct kse *ke,
47144990b8cSJulian Elischer     struct thread *td, struct trapframe *frame)
47244990b8cSJulian Elischer {
47344990b8cSJulian Elischer 	int error = 0;
47444990b8cSJulian Elischer 
47544990b8cSJulian Elischer 	if (ke->ke_tdspare == NULL) {
47644990b8cSJulian Elischer 		ke->ke_tdspare = thread_alloc();
47744990b8cSJulian Elischer 	}
47844990b8cSJulian Elischer 	if (td->td_flags & TDF_UNBOUND) {
47944990b8cSJulian Elischer 		/*
48044990b8cSJulian Elischer 		 * Are we returning from a thread that had a mailbox?
48144990b8cSJulian Elischer 		 *
48244990b8cSJulian Elischer 		 * XXX Maybe this should be in a separate function.
48344990b8cSJulian Elischer 		 */
48444990b8cSJulian Elischer 		if (((td->td_flags & TDF_UPCALLING) == 0) && td->td_mailbox) {
48544990b8cSJulian Elischer 			/*
48644990b8cSJulian Elischer 			 * [XXXKSE Future enhancement]
48744990b8cSJulian Elischer 			 * We could also go straight back to the syscall
48844990b8cSJulian Elischer 			 * if we never had to do an upcall since then.
48944990b8cSJulian Elischer 			 * If the KSE's copy is == the thread's copy..
49044990b8cSJulian Elischer 			 * AND there are no other completed threads.
49144990b8cSJulian Elischer 			 */
49244990b8cSJulian Elischer 			/*
49344990b8cSJulian Elischer 			 * We will go back as an upcall or go do another thread.
49444990b8cSJulian Elischer 			 * Either way we need to save the context back to
49544990b8cSJulian Elischer 			 * the user thread mailbox.
49644990b8cSJulian Elischer 			 * So the UTS can restart it later.
49744990b8cSJulian Elischer 			 */
49844990b8cSJulian Elischer 			error = thread_export_context(td);
49944990b8cSJulian Elischer 			td->td_mailbox = NULL;
50044990b8cSJulian Elischer 			if (error) {
50144990b8cSJulian Elischer 				/*
50244990b8cSJulian Elischer 				 * Failing to do the KSE
50344990b8cSJulian Elischer 				 * operation just defaults operation
50444990b8cSJulian Elischer 				 * back to synchonous operation.
50544990b8cSJulian Elischer 				 */
50644990b8cSJulian Elischer 				goto cont;
50744990b8cSJulian Elischer 			}
50844990b8cSJulian Elischer 
50944990b8cSJulian Elischer 			if (TAILQ_FIRST(&kg->kg_runq)) {
51044990b8cSJulian Elischer 				/*
51144990b8cSJulian Elischer 				 * Uh-oh.. don't return to the user.
51244990b8cSJulian Elischer 				 * Instead, switch to the thread that
51344990b8cSJulian Elischer 				 * needs to run. The question is:
51444990b8cSJulian Elischer 				 * What do we do with the thread we have now?
51544990b8cSJulian Elischer 				 * We have put the completion block
51644990b8cSJulian Elischer 				 * on the kse mailbox. If we had more energy,
51744990b8cSJulian Elischer 				 * we could lazily do so, assuming someone
51844990b8cSJulian Elischer 				 * else might get to userland earlier
51944990b8cSJulian Elischer 				 * and deliver it earlier than we could.
52044990b8cSJulian Elischer 				 * To do that we could save it off the KSEG.
52144990b8cSJulian Elischer 				 * An upcalling KSE would 'reap' all completed
52244990b8cSJulian Elischer 				 * threads.
52344990b8cSJulian Elischer 				 * Being in a hurry, we'll do nothing and
52444990b8cSJulian Elischer 				 * leave it on the current KSE for now.
52544990b8cSJulian Elischer 				 *
52644990b8cSJulian Elischer 				 * As for the other threads to run;
52744990b8cSJulian Elischer 				 * we COULD rush through all the threads
52844990b8cSJulian Elischer 				 * in this KSEG at this priority, or we
52944990b8cSJulian Elischer 				 * could throw the ball back into the court
53044990b8cSJulian Elischer 				 * and just run the highest prio kse available.
53144990b8cSJulian Elischer 				 * What is OUR priority?
53244990b8cSJulian Elischer 				 * the priority of the highest sycall waiting
53344990b8cSJulian Elischer 				 * to be returned?
53444990b8cSJulian Elischer 				 * For now, just let another KSE run (easiest).
53544990b8cSJulian Elischer 				 */
53644990b8cSJulian Elischer 				PROC_LOCK(p);
53744990b8cSJulian Elischer 				mtx_lock_spin(&sched_lock);
53844990b8cSJulian Elischer 				thread_exit(); /* Abandon current thread. */
53944990b8cSJulian Elischer 				/* NOTREACHED */
54044990b8cSJulian Elischer 			} else { /* if (number of returning syscalls = 1) */
54144990b8cSJulian Elischer 				/*
54244990b8cSJulian Elischer 				 * Swap our frame for the upcall frame.
54344990b8cSJulian Elischer 				 *
54444990b8cSJulian Elischer 				 * XXXKSE Assumes we are going to user land
54544990b8cSJulian Elischer 				 * and not nested in the kernel
54644990b8cSJulian Elischer 				 */
54744990b8cSJulian Elischer 				td->td_flags |= TDF_UPCALLING;
54844990b8cSJulian Elischer 			}
54944990b8cSJulian Elischer 		}
55044990b8cSJulian Elischer 		/*
55144990b8cSJulian Elischer 		 * This is NOT just an 'else' clause for the above test...
55244990b8cSJulian Elischer 		 */
55344990b8cSJulian Elischer 		if (td->td_flags & TDF_UPCALLING) {
55444990b8cSJulian Elischer 			CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)",
55544990b8cSJulian Elischer 			    td, p->p_pid, p->p_comm);
55644990b8cSJulian Elischer 			/*
55744990b8cSJulian Elischer 			 * Make sure that it has the correct frame loaded.
55844990b8cSJulian Elischer 			 * While we know that we are on the same KSEGRP
55944990b8cSJulian Elischer 			 * as we were created on, we could very easily
56044990b8cSJulian Elischer 			 * have come in on another KSE. We therefore need
56144990b8cSJulian Elischer 			 * to do the copy of the frame after the last
56244990b8cSJulian Elischer 			 * possible switch() (the one above).
56344990b8cSJulian Elischer 			 */
56444990b8cSJulian Elischer 			bcopy(ke->ke_frame, frame, sizeof(struct trapframe));
56544990b8cSJulian Elischer 
56644990b8cSJulian Elischer 			/*
56744990b8cSJulian Elischer 			 * Decide what we are sending to the user
56844990b8cSJulian Elischer 			 * upcall sets one argument. The address of the mbox.
56944990b8cSJulian Elischer 			 */
57044990b8cSJulian Elischer 			cpu_set_args(td, ke);
57144990b8cSJulian Elischer 
57244990b8cSJulian Elischer 			/*
57344990b8cSJulian Elischer 			 * There is no more work to do and we are going to ride
57444990b8cSJulian Elischer 			 * this thead/KSE up to userland. Make sure the user's
57544990b8cSJulian Elischer 			 * pointer to the thread mailbox is cleared before we
57644990b8cSJulian Elischer 			 * re-enter the kernel next time for any reason..
57744990b8cSJulian Elischer 			 * We might as well do it here.
57844990b8cSJulian Elischer 			 */
57944990b8cSJulian Elischer 			td->td_flags &= ~TDF_UPCALLING;	/* Hmmmm. */
58044990b8cSJulian Elischer 			error = suword((caddr_t)td->td_kse->ke_mailbox +
58144990b8cSJulian Elischer 			    offsetof(struct kse_mailbox, kmbx_current_thread),
58244990b8cSJulian Elischer 			    0);
58344990b8cSJulian Elischer 		}
58444990b8cSJulian Elischer 		/*
58544990b8cSJulian Elischer 		 * Stop any chance that we may be separated from
58644990b8cSJulian Elischer 		 * the KSE we are currently on. This is "biting the bullet",
58744990b8cSJulian Elischer 		 * we are committing to go to user space as as THIS KSE here.
58844990b8cSJulian Elischer 		 */
58944990b8cSJulian Elischer cont:
59044990b8cSJulian Elischer 		td->td_flags &= ~TDF_UNBOUND;
59144990b8cSJulian Elischer 	}
59244990b8cSJulian Elischer 	return (error);
59344990b8cSJulian Elischer }
59444990b8cSJulian Elischer 
59544990b8cSJulian Elischer /*
59644990b8cSJulian Elischer  * Enforce single-threading.
59744990b8cSJulian Elischer  *
59844990b8cSJulian Elischer  * Returns 1 if the caller must abort (another thread is waiting to
59944990b8cSJulian Elischer  * exit the process or similar). Process is locked!
60044990b8cSJulian Elischer  * Returns 0 when you are successfully the only thread running.
60144990b8cSJulian Elischer  * A process has successfully single threaded in the suspend mode when
60244990b8cSJulian Elischer  * There are no threads in user mode. Threads in the kernel must be
60344990b8cSJulian Elischer  * allowed to continue until they get to the user boundary. They may even
60444990b8cSJulian Elischer  * copy out their return values and data before suspending. They may however be
60544990b8cSJulian Elischer  * accellerated in reaching the user boundary as we will wake up
60644990b8cSJulian Elischer  * any sleeping threads that are interruptable. (PCATCH).
60744990b8cSJulian Elischer  */
60844990b8cSJulian Elischer int
60944990b8cSJulian Elischer thread_single(int force_exit)
61044990b8cSJulian Elischer {
61144990b8cSJulian Elischer 	struct thread *td;
61244990b8cSJulian Elischer 	struct thread *td2;
61344990b8cSJulian Elischer 	struct proc *p;
61444990b8cSJulian Elischer 
61544990b8cSJulian Elischer 	td = curthread;
61644990b8cSJulian Elischer 	p = td->td_proc;
61744990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
61844990b8cSJulian Elischer 	KASSERT((td != NULL), ("curthread is NULL"));
61944990b8cSJulian Elischer 
62044990b8cSJulian Elischer 	if ((p->p_flag & P_KSES) == 0)
62144990b8cSJulian Elischer 		return (0);
62244990b8cSJulian Elischer 
623e3b9bf71SJulian Elischer 	/* Is someone already single threading? */
624e3b9bf71SJulian Elischer 	if (p->p_singlethread)
62544990b8cSJulian Elischer 		return (1);
62644990b8cSJulian Elischer 
6271279572aSDavid Xu 	if (force_exit == SINGLE_EXIT)
62844990b8cSJulian Elischer 		p->p_flag |= P_SINGLE_EXIT;
62944990b8cSJulian Elischer 	else
63044990b8cSJulian Elischer 		p->p_flag &= ~P_SINGLE_EXIT;
6311279572aSDavid Xu 	p->p_flag |= P_STOPPED_SINGLE;
63244990b8cSJulian Elischer 	p->p_singlethread = td;
63344990b8cSJulian Elischer 	while ((p->p_numthreads - p->p_suspcount) != 1) {
63471fad9fdSJulian Elischer 		mtx_lock_spin(&sched_lock);
63544990b8cSJulian Elischer 		FOREACH_THREAD_IN_PROC(p, td2) {
63644990b8cSJulian Elischer 			if (td2 == td)
63744990b8cSJulian Elischer 				continue;
63871fad9fdSJulian Elischer 			if (TD_IS_INHIBITED(td2)) {
63971fad9fdSJulian Elischer 				if (TD_IS_SUSPENDED(td2)) {
6401279572aSDavid Xu 					if (force_exit == SINGLE_EXIT) {
64171fad9fdSJulian Elischer 						thread_unsuspend_one(td2);
64244990b8cSJulian Elischer 					}
64371fad9fdSJulian Elischer 				}
64471fad9fdSJulian Elischer 				if ( TD_IS_SLEEPING(td2)) {
645e3b9bf71SJulian Elischer 					if (td2->td_flags & TDF_CVWAITQ)
64671fad9fdSJulian Elischer 						cv_waitq_remove(td2);
647e3b9bf71SJulian Elischer 					else
64871fad9fdSJulian Elischer 						unsleep(td2);
64944990b8cSJulian Elischer 					break;
65071fad9fdSJulian Elischer 				}
65171fad9fdSJulian Elischer 				if (TD_CAN_RUN(td2))
65271fad9fdSJulian Elischer 					setrunqueue(td2);
65344990b8cSJulian Elischer 			}
65444990b8cSJulian Elischer 		}
65544990b8cSJulian Elischer 		/*
65644990b8cSJulian Elischer 		 * Wake us up when everyone else has suspended.
657e3b9bf71SJulian Elischer 		 * In the mean time we suspend as well.
65844990b8cSJulian Elischer 		 */
65971fad9fdSJulian Elischer 		thread_suspend_one(td);
66044990b8cSJulian Elischer 		mtx_unlock(&Giant);
66144990b8cSJulian Elischer 		PROC_UNLOCK(p);
66244990b8cSJulian Elischer 		mi_switch();
66344990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
66444990b8cSJulian Elischer 		mtx_lock(&Giant);
66544990b8cSJulian Elischer 		PROC_LOCK(p);
66644990b8cSJulian Elischer 	}
66744990b8cSJulian Elischer 	return (0);
66844990b8cSJulian Elischer }
66944990b8cSJulian Elischer 
67044990b8cSJulian Elischer /*
67144990b8cSJulian Elischer  * Called in from locations that can safely check to see
67244990b8cSJulian Elischer  * whether we have to suspend or at least throttle for a
67344990b8cSJulian Elischer  * single-thread event (e.g. fork).
67444990b8cSJulian Elischer  *
67544990b8cSJulian Elischer  * Such locations include userret().
67644990b8cSJulian Elischer  * If the "return_instead" argument is non zero, the thread must be able to
67744990b8cSJulian Elischer  * accept 0 (caller may continue), or 1 (caller must abort) as a result.
67844990b8cSJulian Elischer  *
67944990b8cSJulian Elischer  * The 'return_instead' argument tells the function if it may do a
68044990b8cSJulian Elischer  * thread_exit() or suspend, or whether the caller must abort and back
68144990b8cSJulian Elischer  * out instead.
68244990b8cSJulian Elischer  *
68344990b8cSJulian Elischer  * If the thread that set the single_threading request has set the
68444990b8cSJulian Elischer  * P_SINGLE_EXIT bit in the process flags then this call will never return
68544990b8cSJulian Elischer  * if 'return_instead' is false, but will exit.
68644990b8cSJulian Elischer  *
68744990b8cSJulian Elischer  * P_SINGLE_EXIT | return_instead == 0| return_instead != 0
68844990b8cSJulian Elischer  *---------------+--------------------+---------------------
68944990b8cSJulian Elischer  *       0       | returns 0          |   returns 0 or 1
69044990b8cSJulian Elischer  *               | when ST ends       |   immediatly
69144990b8cSJulian Elischer  *---------------+--------------------+---------------------
69244990b8cSJulian Elischer  *       1       | thread exits       |   returns 1
69344990b8cSJulian Elischer  *               |                    |  immediatly
69444990b8cSJulian Elischer  * 0 = thread_exit() or suspension ok,
69544990b8cSJulian Elischer  * other = return error instead of stopping the thread.
69644990b8cSJulian Elischer  *
69744990b8cSJulian Elischer  * While a full suspension is under effect, even a single threading
69844990b8cSJulian Elischer  * thread would be suspended if it made this call (but it shouldn't).
69944990b8cSJulian Elischer  * This call should only be made from places where
70044990b8cSJulian Elischer  * thread_exit() would be safe as that may be the outcome unless
70144990b8cSJulian Elischer  * return_instead is set.
70244990b8cSJulian Elischer  */
70344990b8cSJulian Elischer int
70444990b8cSJulian Elischer thread_suspend_check(int return_instead)
70544990b8cSJulian Elischer {
70644990b8cSJulian Elischer 	struct thread *td = curthread;
70744990b8cSJulian Elischer 	struct proc *p = td->td_proc;
70844990b8cSJulian Elischer 
70944990b8cSJulian Elischer 	td = curthread;
71044990b8cSJulian Elischer 	p = td->td_proc;
71144990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
71244990b8cSJulian Elischer 	while (P_SHOULDSTOP(p)) {
7131279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
71444990b8cSJulian Elischer 			KASSERT(p->p_singlethread != NULL,
71544990b8cSJulian Elischer 			    ("singlethread not set"));
71644990b8cSJulian Elischer 			/*
717e3b9bf71SJulian Elischer 			 * The only suspension in action is a
718e3b9bf71SJulian Elischer 			 * single-threading. Single threader need not stop.
719b6d5995eSJulian Elischer 			 * XXX Should be safe to access unlocked
720b6d5995eSJulian Elischer 			 * as it can only be set to be true by us.
72144990b8cSJulian Elischer 			 */
722e3b9bf71SJulian Elischer 			if (p->p_singlethread == td)
72344990b8cSJulian Elischer 				return (0);	/* Exempt from stopping. */
72444990b8cSJulian Elischer 		}
725e3b9bf71SJulian Elischer 		if (return_instead)
72644990b8cSJulian Elischer 			return (1);
72744990b8cSJulian Elischer 
72844990b8cSJulian Elischer 		/*
72944990b8cSJulian Elischer 		 * If the process is waiting for us to exit,
73044990b8cSJulian Elischer 		 * this thread should just suicide.
7311279572aSDavid Xu 		 * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
73244990b8cSJulian Elischer 		 */
73344990b8cSJulian Elischer 		if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
73444990b8cSJulian Elischer 			mtx_lock_spin(&sched_lock);
73544990b8cSJulian Elischer 			while (mtx_owned(&Giant))
73644990b8cSJulian Elischer 				mtx_unlock(&Giant);
73744990b8cSJulian Elischer 			thread_exit();
73844990b8cSJulian Elischer 		}
73944990b8cSJulian Elischer 
74044990b8cSJulian Elischer 		/*
74144990b8cSJulian Elischer 		 * When a thread suspends, it just
74244990b8cSJulian Elischer 		 * moves to the processes's suspend queue
74344990b8cSJulian Elischer 		 * and stays there.
74444990b8cSJulian Elischer 		 *
74544990b8cSJulian Elischer 		 * XXXKSE if TDF_BOUND is true
74644990b8cSJulian Elischer 		 * it will not release it's KSE which might
74744990b8cSJulian Elischer 		 * lead to deadlock if there are not enough KSEs
74844990b8cSJulian Elischer 		 * to complete all waiting threads.
74944990b8cSJulian Elischer 		 * Maybe be able to 'lend' it out again.
75044990b8cSJulian Elischer 		 * (lent kse's can not go back to userland?)
75144990b8cSJulian Elischer 		 * and can only be lent in STOPPED state.
75244990b8cSJulian Elischer 		 */
753721e5910SJulian Elischer 		mtx_lock_spin(&sched_lock);
7541279572aSDavid Xu 		if ((p->p_flag & P_STOPPED_SIG) &&
755721e5910SJulian Elischer 		    (p->p_suspcount+1 == p->p_numthreads)) {
756721e5910SJulian Elischer 			mtx_unlock_spin(&sched_lock);
757721e5910SJulian Elischer 			PROC_LOCK(p->p_pptr);
758721e5910SJulian Elischer 			if ((p->p_pptr->p_procsig->ps_flag &
759721e5910SJulian Elischer 				PS_NOCLDSTOP) == 0) {
760721e5910SJulian Elischer 				psignal(p->p_pptr, SIGCHLD);
761721e5910SJulian Elischer 			}
762721e5910SJulian Elischer 			PROC_UNLOCK(p->p_pptr);
7639b0e281bSJulian Elischer 			mtx_lock_spin(&sched_lock);
764721e5910SJulian Elischer 		}
76544990b8cSJulian Elischer 		mtx_assert(&Giant, MA_NOTOWNED);
76671fad9fdSJulian Elischer 		thread_suspend_one(td);
76744990b8cSJulian Elischer 		PROC_UNLOCK(p);
7681279572aSDavid Xu 		if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
769cf19bf91SJulian Elischer 			if (p->p_numthreads == p->p_suspcount) {
77071fad9fdSJulian Elischer 				thread_unsuspend_one(p->p_singlethread);
771cf19bf91SJulian Elischer 			}
772cf19bf91SJulian Elischer 		}
77320568366SJulian Elischer 		p->p_stats->p_ru.ru_nivcsw++;
77444990b8cSJulian Elischer 		mi_switch();
77544990b8cSJulian Elischer 		mtx_unlock_spin(&sched_lock);
77644990b8cSJulian Elischer 		PROC_LOCK(p);
77744990b8cSJulian Elischer 	}
77844990b8cSJulian Elischer 	return (0);
77944990b8cSJulian Elischer }
78044990b8cSJulian Elischer 
78135c32a76SDavid Xu void
78235c32a76SDavid Xu thread_suspend_one(struct thread *td)
78335c32a76SDavid Xu {
78435c32a76SDavid Xu 	struct proc *p = td->td_proc;
78535c32a76SDavid Xu 
78635c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
78735c32a76SDavid Xu 	p->p_suspcount++;
78871fad9fdSJulian Elischer 	TD_SET_SUSPENDED(td);
78935c32a76SDavid Xu 	TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
79071fad9fdSJulian Elischer 	/*
79171fad9fdSJulian Elischer 	 * Hack: If we are suspending but are on the sleep queue
79271fad9fdSJulian Elischer 	 * then we are in msleep or the cv equivalent. We
79371fad9fdSJulian Elischer 	 * want to look like we have two Inhibitors.
79471fad9fdSJulian Elischer 	 */
79571fad9fdSJulian Elischer 	if (TD_ON_SLEEPQ(td))
79671fad9fdSJulian Elischer 		TD_SET_SLEEPING(td);
79735c32a76SDavid Xu }
79835c32a76SDavid Xu 
79935c32a76SDavid Xu void
80035c32a76SDavid Xu thread_unsuspend_one(struct thread *td)
80135c32a76SDavid Xu {
80235c32a76SDavid Xu 	struct proc *p = td->td_proc;
80335c32a76SDavid Xu 
80435c32a76SDavid Xu 	mtx_assert(&sched_lock, MA_OWNED);
80535c32a76SDavid Xu 	TAILQ_REMOVE(&p->p_suspended, td, td_runq);
80671fad9fdSJulian Elischer 	TD_CLR_SUSPENDED(td);
80735c32a76SDavid Xu 	p->p_suspcount--;
80871fad9fdSJulian Elischer 	setrunnable(td);
80935c32a76SDavid Xu }
81035c32a76SDavid Xu 
81144990b8cSJulian Elischer /*
81244990b8cSJulian Elischer  * Allow all threads blocked by single threading to continue running.
81344990b8cSJulian Elischer  */
81444990b8cSJulian Elischer void
81544990b8cSJulian Elischer thread_unsuspend(struct proc *p)
81644990b8cSJulian Elischer {
81744990b8cSJulian Elischer 	struct thread *td;
81844990b8cSJulian Elischer 
819b6d5995eSJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
82044990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
82144990b8cSJulian Elischer 	if (!P_SHOULDSTOP(p)) {
82244990b8cSJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
82335c32a76SDavid Xu 			thread_unsuspend_one(td);
82444990b8cSJulian Elischer 		}
8251279572aSDavid Xu 	} else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) &&
82644990b8cSJulian Elischer 	    (p->p_numthreads == p->p_suspcount)) {
82744990b8cSJulian Elischer 		/*
82844990b8cSJulian Elischer 		 * Stopping everything also did the job for the single
82944990b8cSJulian Elischer 		 * threading request. Now we've downgraded to single-threaded,
83044990b8cSJulian Elischer 		 * let it continue.
83144990b8cSJulian Elischer 		 */
83235c32a76SDavid Xu 		thread_unsuspend_one(p->p_singlethread);
83344990b8cSJulian Elischer 	}
83444990b8cSJulian Elischer }
83544990b8cSJulian Elischer 
83644990b8cSJulian Elischer void
83744990b8cSJulian Elischer thread_single_end(void)
83844990b8cSJulian Elischer {
83944990b8cSJulian Elischer 	struct thread *td;
84044990b8cSJulian Elischer 	struct proc *p;
84144990b8cSJulian Elischer 
84244990b8cSJulian Elischer 	td = curthread;
84344990b8cSJulian Elischer 	p = td->td_proc;
84444990b8cSJulian Elischer 	PROC_LOCK_ASSERT(p, MA_OWNED);
8451279572aSDavid Xu 	p->p_flag &= ~P_STOPPED_SINGLE;
84644990b8cSJulian Elischer 	p->p_singlethread = NULL;
84749539972SJulian Elischer 	/*
84849539972SJulian Elischer 	 * If there are other threads they mey now run,
84949539972SJulian Elischer 	 * unless of course there is a blanket 'stop order'
85049539972SJulian Elischer 	 * on the process. The single threader must be allowed
85149539972SJulian Elischer 	 * to continue however as this is a bad place to stop.
85249539972SJulian Elischer 	 */
85349539972SJulian Elischer 	if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
85449539972SJulian Elischer 		mtx_lock_spin(&sched_lock);
85549539972SJulian Elischer 		while (( td = TAILQ_FIRST(&p->p_suspended))) {
85671fad9fdSJulian Elischer 			thread_unsuspend_one(td);
85744990b8cSJulian Elischer 		}
85849539972SJulian Elischer 		mtx_unlock_spin(&sched_lock);
85949539972SJulian Elischer 	}
86049539972SJulian Elischer }
86149539972SJulian Elischer 
86244990b8cSJulian Elischer 
863