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> 47c76e33b6SJonathan Mini #include <sys/ucontext.h> 4844990b8cSJulian Elischer 4944990b8cSJulian Elischer #include <vm/vm.h> 5044990b8cSJulian Elischer #include <vm/vm_object.h> 5144990b8cSJulian Elischer #include <vm/pmap.h> 5244990b8cSJulian Elischer #include <vm/uma.h> 5344990b8cSJulian Elischer #include <vm/vm_map.h> 5444990b8cSJulian Elischer 5502fb42b0SPeter Wemm #include <machine/frame.h> 5602fb42b0SPeter Wemm 5744990b8cSJulian Elischer /* 584f0db5e0SJulian Elischer * KSEGRP related storage. 5944990b8cSJulian Elischer */ 604f0db5e0SJulian Elischer static uma_zone_t ksegrp_zone; 614f0db5e0SJulian Elischer static uma_zone_t kse_zone; 6244990b8cSJulian Elischer static uma_zone_t thread_zone; 6344990b8cSJulian Elischer 644f0db5e0SJulian Elischer /* DEBUG ONLY */ 6544990b8cSJulian Elischer SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0, "thread allocation"); 6644990b8cSJulian Elischer static int oiks_debug = 1; /* 0 disable, 1 printf, 2 enter debugger */ 6744990b8cSJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, oiks, CTLFLAG_RW, 6844990b8cSJulian Elischer &oiks_debug, 0, "OIKS thread debug"); 6944990b8cSJulian Elischer 7048bfcdddSJulian Elischer static int max_threads_per_proc = 10; 714f0db5e0SJulian Elischer SYSCTL_INT(_kern_threads, OID_AUTO, max_per_proc, CTLFLAG_RW, 724f0db5e0SJulian Elischer &max_threads_per_proc, 0, "Limit on threads per proc"); 734f0db5e0SJulian Elischer 7444990b8cSJulian Elischer #define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start)) 7544990b8cSJulian Elischer 7644990b8cSJulian Elischer struct threadqueue zombie_threads = TAILQ_HEAD_INITIALIZER(zombie_threads); 7744990b8cSJulian Elischer struct mtx zombie_thread_lock; 7844990b8cSJulian Elischer MTX_SYSINIT(zombie_thread_lock, &zombie_thread_lock, 7944990b8cSJulian Elischer "zombie_thread_lock", MTX_SPIN); 8044990b8cSJulian Elischer 8144990b8cSJulian Elischer /* 8244990b8cSJulian Elischer * Pepare a thread for use. 8344990b8cSJulian Elischer */ 8444990b8cSJulian Elischer static void 8544990b8cSJulian Elischer thread_ctor(void *mem, int size, void *arg) 8644990b8cSJulian Elischer { 8744990b8cSJulian Elischer struct thread *td; 8844990b8cSJulian Elischer 8944990b8cSJulian Elischer KASSERT((size == sizeof(struct thread)), 90b799f5a4SPeter Wemm ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread))); 9144990b8cSJulian Elischer 9244990b8cSJulian Elischer td = (struct thread *)mem; 9371fad9fdSJulian Elischer td->td_state = TDS_INACTIVE; 9444990b8cSJulian Elischer td->td_flags |= TDF_UNBOUND; 9544990b8cSJulian Elischer } 9644990b8cSJulian Elischer 9744990b8cSJulian Elischer /* 9844990b8cSJulian Elischer * Reclaim a thread after use. 9944990b8cSJulian Elischer */ 10044990b8cSJulian Elischer static void 10144990b8cSJulian Elischer thread_dtor(void *mem, int size, void *arg) 10244990b8cSJulian Elischer { 10344990b8cSJulian Elischer struct thread *td; 10444990b8cSJulian Elischer 10544990b8cSJulian Elischer KASSERT((size == sizeof(struct thread)), 106b799f5a4SPeter Wemm ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread))); 10744990b8cSJulian Elischer 10844990b8cSJulian Elischer td = (struct thread *)mem; 10944990b8cSJulian Elischer 11044990b8cSJulian Elischer #ifdef INVARIANTS 11144990b8cSJulian Elischer /* Verify that this thread is in a safe state to free. */ 11244990b8cSJulian Elischer switch (td->td_state) { 11371fad9fdSJulian Elischer case TDS_INHIBITED: 11471fad9fdSJulian Elischer case TDS_RUNNING: 11571fad9fdSJulian Elischer case TDS_CAN_RUN: 11644990b8cSJulian Elischer case TDS_RUNQ: 11744990b8cSJulian Elischer /* 11844990b8cSJulian Elischer * We must never unlink a thread that is in one of 11944990b8cSJulian Elischer * these states, because it is currently active. 12044990b8cSJulian Elischer */ 12144990b8cSJulian Elischer panic("bad state for thread unlinking"); 12244990b8cSJulian Elischer /* NOTREACHED */ 12371fad9fdSJulian Elischer case TDS_INACTIVE: 12444990b8cSJulian Elischer break; 12544990b8cSJulian Elischer default: 12644990b8cSJulian Elischer panic("bad thread state"); 12744990b8cSJulian Elischer /* NOTREACHED */ 12844990b8cSJulian Elischer } 12944990b8cSJulian Elischer #endif 13044990b8cSJulian Elischer } 13144990b8cSJulian Elischer 13244990b8cSJulian Elischer /* 13344990b8cSJulian Elischer * Initialize type-stable parts of a thread (when newly created). 13444990b8cSJulian Elischer */ 13544990b8cSJulian Elischer static void 13644990b8cSJulian Elischer thread_init(void *mem, int size) 13744990b8cSJulian Elischer { 13844990b8cSJulian Elischer struct thread *td; 13944990b8cSJulian Elischer 14044990b8cSJulian Elischer KASSERT((size == sizeof(struct thread)), 141b799f5a4SPeter Wemm ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread))); 14244990b8cSJulian Elischer 14344990b8cSJulian Elischer td = (struct thread *)mem; 144e6e24ff9SJulian Elischer mtx_lock(&Giant); 145316ec49aSScott Long pmap_new_thread(td, 0); 146e6e24ff9SJulian Elischer mtx_unlock(&Giant); 14744990b8cSJulian Elischer cpu_thread_setup(td); 14844990b8cSJulian Elischer } 14944990b8cSJulian Elischer 15044990b8cSJulian Elischer /* 15144990b8cSJulian Elischer * Tear down type-stable parts of a thread (just before being discarded). 15244990b8cSJulian Elischer */ 15344990b8cSJulian Elischer static void 15444990b8cSJulian Elischer thread_fini(void *mem, int size) 15544990b8cSJulian Elischer { 15644990b8cSJulian Elischer struct thread *td; 15744990b8cSJulian Elischer 15844990b8cSJulian Elischer KASSERT((size == sizeof(struct thread)), 159b799f5a4SPeter Wemm ("size mismatch: %d != %d\n", size, (int)sizeof(struct thread))); 16044990b8cSJulian Elischer 16144990b8cSJulian Elischer td = (struct thread *)mem; 16244990b8cSJulian Elischer pmap_dispose_thread(td); 16344990b8cSJulian Elischer } 16444990b8cSJulian Elischer 16544990b8cSJulian Elischer /* 166c76e33b6SJonathan Mini * Fill a ucontext_t with a thread's context information. 167c76e33b6SJonathan Mini * 168c76e33b6SJonathan Mini * This is an analogue to getcontext(3). 169c76e33b6SJonathan Mini */ 170c76e33b6SJonathan Mini void 171c76e33b6SJonathan Mini thread_getcontext(struct thread *td, ucontext_t *uc) 172c76e33b6SJonathan Mini { 173c76e33b6SJonathan Mini 174acaa1566SPeter Wemm /* 175acaa1566SPeter Wemm * XXX this is declared in a MD include file, i386/include/ucontext.h but 176acaa1566SPeter Wemm * is used in MI code. 177acaa1566SPeter Wemm */ 1781e19df33SPeter Wemm #ifdef __i386__ 179c76e33b6SJonathan Mini get_mcontext(td, &uc->uc_mcontext); 1801e19df33SPeter Wemm #endif 181c76e33b6SJonathan Mini uc->uc_sigmask = td->td_proc->p_sigmask; 182c76e33b6SJonathan Mini } 183c76e33b6SJonathan Mini 184c76e33b6SJonathan Mini /* 185c76e33b6SJonathan Mini * Set a thread's context from a ucontext_t. 186c76e33b6SJonathan Mini * 187c76e33b6SJonathan Mini * This is an analogue to setcontext(3). 188c76e33b6SJonathan Mini */ 189c76e33b6SJonathan Mini int 190c76e33b6SJonathan Mini thread_setcontext(struct thread *td, ucontext_t *uc) 191c76e33b6SJonathan Mini { 192c76e33b6SJonathan Mini int ret; 193c76e33b6SJonathan Mini 194acaa1566SPeter Wemm /* 195acaa1566SPeter Wemm * XXX this is declared in a MD include file, i386/include/ucontext.h but 196acaa1566SPeter Wemm * is used in MI code. 197acaa1566SPeter Wemm */ 1981e19df33SPeter Wemm #ifdef __i386__ 199c76e33b6SJonathan Mini ret = set_mcontext(td, &uc->uc_mcontext); 2001e19df33SPeter Wemm #else 2011e19df33SPeter Wemm ret = ENOSYS; 2021e19df33SPeter Wemm #endif 203c76e33b6SJonathan Mini if (ret == 0) { 204c76e33b6SJonathan Mini SIG_CANTMASK(uc->uc_sigmask); 205c76e33b6SJonathan Mini PROC_LOCK(td->td_proc); 206c76e33b6SJonathan Mini td->td_proc->p_sigmask = uc->uc_sigmask; 207c76e33b6SJonathan Mini PROC_UNLOCK(td->td_proc); 208c76e33b6SJonathan Mini } 209c76e33b6SJonathan Mini return (ret); 210c76e33b6SJonathan Mini } 211c76e33b6SJonathan Mini 212c76e33b6SJonathan Mini /* 21344990b8cSJulian Elischer * Initialize global thread allocation resources. 21444990b8cSJulian Elischer */ 21544990b8cSJulian Elischer void 21644990b8cSJulian Elischer threadinit(void) 21744990b8cSJulian Elischer { 21844990b8cSJulian Elischer 219c281972eSPeter Wemm #ifndef __ia64__ 22044990b8cSJulian Elischer thread_zone = uma_zcreate("THREAD", sizeof (struct thread), 22144990b8cSJulian Elischer thread_ctor, thread_dtor, thread_init, thread_fini, 22244990b8cSJulian Elischer UMA_ALIGN_CACHE, 0); 223c281972eSPeter Wemm #else 224c281972eSPeter Wemm /* 225c281972eSPeter Wemm * XXX the ia64 kstack allocator is really lame and is at the mercy 226c281972eSPeter Wemm * of contigmallloc(). This hackery is to pre-construct a whole 227c281972eSPeter Wemm * pile of thread structures with associated kernel stacks early 228c281972eSPeter Wemm * in the system startup while contigmalloc() still works. Once we 229c281972eSPeter Wemm * have them, keep them. Sigh. 230c281972eSPeter Wemm */ 231c281972eSPeter Wemm thread_zone = uma_zcreate("THREAD", sizeof (struct thread), 232c281972eSPeter Wemm thread_ctor, thread_dtor, thread_init, thread_fini, 233c281972eSPeter Wemm UMA_ALIGN_CACHE, UMA_ZONE_NOFREE); 234c281972eSPeter Wemm uma_prealloc(thread_zone, 512); /* XXX arbitary */ 235c281972eSPeter Wemm #endif 2364f0db5e0SJulian Elischer ksegrp_zone = uma_zcreate("KSEGRP", sizeof (struct ksegrp), 2374f0db5e0SJulian Elischer NULL, NULL, NULL, NULL, 2384f0db5e0SJulian Elischer UMA_ALIGN_CACHE, 0); 2394f0db5e0SJulian Elischer kse_zone = uma_zcreate("KSE", sizeof (struct kse), 2404f0db5e0SJulian Elischer NULL, NULL, NULL, NULL, 2414f0db5e0SJulian Elischer UMA_ALIGN_CACHE, 0); 24244990b8cSJulian Elischer } 24344990b8cSJulian Elischer 24444990b8cSJulian Elischer /* 2451faf202eSJulian Elischer * Stash an embarasingly extra thread into the zombie thread queue. 24644990b8cSJulian Elischer */ 24744990b8cSJulian Elischer void 24844990b8cSJulian Elischer thread_stash(struct thread *td) 24944990b8cSJulian Elischer { 25044990b8cSJulian Elischer mtx_lock_spin(&zombie_thread_lock); 25144990b8cSJulian Elischer TAILQ_INSERT_HEAD(&zombie_threads, td, td_runq); 25244990b8cSJulian Elischer mtx_unlock_spin(&zombie_thread_lock); 25344990b8cSJulian Elischer } 25444990b8cSJulian Elischer 25544990b8cSJulian Elischer /* 256c76e33b6SJonathan Mini * Reap zombie threads. 25744990b8cSJulian Elischer */ 25844990b8cSJulian Elischer void 25944990b8cSJulian Elischer thread_reap(void) 26044990b8cSJulian Elischer { 26144990b8cSJulian Elischer struct thread *td_reaped; 26244990b8cSJulian Elischer 26344990b8cSJulian Elischer /* 26444990b8cSJulian Elischer * don't even bother to lock if none at this instant 26544990b8cSJulian Elischer * We really don't care about the next instant.. 26644990b8cSJulian Elischer */ 26744990b8cSJulian Elischer if (!TAILQ_EMPTY(&zombie_threads)) { 26844990b8cSJulian Elischer mtx_lock_spin(&zombie_thread_lock); 26944990b8cSJulian Elischer while (!TAILQ_EMPTY(&zombie_threads)) { 27044990b8cSJulian Elischer td_reaped = TAILQ_FIRST(&zombie_threads); 27144990b8cSJulian Elischer TAILQ_REMOVE(&zombie_threads, td_reaped, td_runq); 27244990b8cSJulian Elischer mtx_unlock_spin(&zombie_thread_lock); 27344990b8cSJulian Elischer thread_free(td_reaped); 27444990b8cSJulian Elischer mtx_lock_spin(&zombie_thread_lock); 27544990b8cSJulian Elischer } 27644990b8cSJulian Elischer mtx_unlock_spin(&zombie_thread_lock); 27744990b8cSJulian Elischer } 27844990b8cSJulian Elischer } 27944990b8cSJulian Elischer 28044990b8cSJulian Elischer /* 2814f0db5e0SJulian Elischer * Allocate a ksegrp. 2824f0db5e0SJulian Elischer */ 2834f0db5e0SJulian Elischer struct ksegrp * 2844f0db5e0SJulian Elischer ksegrp_alloc(void) 2854f0db5e0SJulian Elischer { 2864f0db5e0SJulian Elischer return (uma_zalloc(ksegrp_zone, M_WAITOK)); 2874f0db5e0SJulian Elischer } 2884f0db5e0SJulian Elischer 2894f0db5e0SJulian Elischer /* 2904f0db5e0SJulian Elischer * Allocate a kse. 2914f0db5e0SJulian Elischer */ 2924f0db5e0SJulian Elischer struct kse * 2934f0db5e0SJulian Elischer kse_alloc(void) 2944f0db5e0SJulian Elischer { 2954f0db5e0SJulian Elischer return (uma_zalloc(kse_zone, M_WAITOK)); 2964f0db5e0SJulian Elischer } 2974f0db5e0SJulian Elischer 2984f0db5e0SJulian Elischer /* 29944990b8cSJulian Elischer * Allocate a thread. 30044990b8cSJulian Elischer */ 30144990b8cSJulian Elischer struct thread * 30244990b8cSJulian Elischer thread_alloc(void) 30344990b8cSJulian Elischer { 30444990b8cSJulian Elischer thread_reap(); /* check if any zombies to get */ 30544990b8cSJulian Elischer return (uma_zalloc(thread_zone, M_WAITOK)); 30644990b8cSJulian Elischer } 30744990b8cSJulian Elischer 30844990b8cSJulian Elischer /* 3094f0db5e0SJulian Elischer * Deallocate a ksegrp. 3104f0db5e0SJulian Elischer */ 3114f0db5e0SJulian Elischer void 3124f0db5e0SJulian Elischer ksegrp_free(struct ksegrp *td) 3134f0db5e0SJulian Elischer { 3144f0db5e0SJulian Elischer uma_zfree(ksegrp_zone, td); 3154f0db5e0SJulian Elischer } 3164f0db5e0SJulian Elischer 3174f0db5e0SJulian Elischer /* 3184f0db5e0SJulian Elischer * Deallocate a kse. 3194f0db5e0SJulian Elischer */ 3204f0db5e0SJulian Elischer void 3214f0db5e0SJulian Elischer kse_free(struct kse *td) 3224f0db5e0SJulian Elischer { 3234f0db5e0SJulian Elischer uma_zfree(kse_zone, td); 3244f0db5e0SJulian Elischer } 3254f0db5e0SJulian Elischer 3264f0db5e0SJulian Elischer /* 32744990b8cSJulian Elischer * Deallocate a thread. 32844990b8cSJulian Elischer */ 32944990b8cSJulian Elischer void 33044990b8cSJulian Elischer thread_free(struct thread *td) 33144990b8cSJulian Elischer { 33244990b8cSJulian Elischer uma_zfree(thread_zone, td); 33344990b8cSJulian Elischer } 33444990b8cSJulian Elischer 33544990b8cSJulian Elischer /* 33644990b8cSJulian Elischer * Store the thread context in the UTS's mailbox. 3373d0586d4SJulian Elischer * then add the mailbox at the head of a list we are building in user space. 3383d0586d4SJulian Elischer * The list is anchored in the ksegrp structure. 33944990b8cSJulian Elischer */ 34044990b8cSJulian Elischer int 34144990b8cSJulian Elischer thread_export_context(struct thread *td) 34244990b8cSJulian Elischer { 3430d294460SJuli Mallett struct proc *p; 3443d0586d4SJulian Elischer struct ksegrp *kg; 3453d0586d4SJulian Elischer uintptr_t mbx; 3463d0586d4SJulian Elischer void *addr; 34744990b8cSJulian Elischer int error; 348c76e33b6SJonathan Mini ucontext_t uc; 34944990b8cSJulian Elischer 3500d294460SJuli Mallett p = td->td_proc; 3510d294460SJuli Mallett kg = td->td_ksegrp; 3520d294460SJuli Mallett 353c76e33b6SJonathan Mini /* Export the user/machine context. */ 3543d0586d4SJulian Elischer #if 0 3553d0586d4SJulian Elischer addr = (caddr_t)td->td_mailbox + 3563d0586d4SJulian Elischer offsetof(struct kse_thr_mailbox, tm_context); 3573d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */ 3583d0586d4SJulian Elischer addr = (void *)(&td->td_mailbox->tm_context); 3593d0586d4SJulian Elischer #endif 3603d0586d4SJulian Elischer error = copyin(addr, &uc, sizeof(ucontext_t)); 361c76e33b6SJonathan Mini if (error == 0) { 362c76e33b6SJonathan Mini thread_getcontext(td, &uc); 3633d0586d4SJulian Elischer error = copyout(&uc, addr, sizeof(ucontext_t)); 36444990b8cSJulian Elischer 36544990b8cSJulian Elischer } 3663d0586d4SJulian Elischer if (error) { 3670cd3964fSJulian Elischer PROC_LOCK(p); 3680cd3964fSJulian Elischer psignal(p, SIGSEGV); 3690cd3964fSJulian Elischer PROC_UNLOCK(p); 37044990b8cSJulian Elischer return (error); 37144990b8cSJulian Elischer } 3723d0586d4SJulian Elischer /* get address in latest mbox of list pointer */ 3733d0586d4SJulian Elischer #if 0 3743d0586d4SJulian Elischer addr = (caddr_t)td->td_mailbox 3753d0586d4SJulian Elischer + offsetof(struct kse_thr_mailbox , tm_next); 3763d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */ 3773d0586d4SJulian Elischer addr = (void *)(&td->td_mailbox->tm_next); 3783d0586d4SJulian Elischer #endif 3793d0586d4SJulian Elischer /* 3803d0586d4SJulian Elischer * Put the saved address of the previous first 3813d0586d4SJulian Elischer * entry into this one 3823d0586d4SJulian Elischer */ 3833d0586d4SJulian Elischer for (;;) { 3843d0586d4SJulian Elischer mbx = (uintptr_t)kg->kg_completed; 3853d0586d4SJulian Elischer if (suword(addr, mbx)) { 3860cd3964fSJulian Elischer PROC_LOCK(p); 3870cd3964fSJulian Elischer psignal(p, SIGSEGV); 3880cd3964fSJulian Elischer PROC_UNLOCK(p); 3893d0586d4SJulian Elischer return (EFAULT); 3903d0586d4SJulian Elischer } 3910cd3964fSJulian Elischer PROC_LOCK(p); 3923d0586d4SJulian Elischer if (mbx == (uintptr_t)kg->kg_completed) { 3933d0586d4SJulian Elischer kg->kg_completed = td->td_mailbox; 3940cd3964fSJulian Elischer PROC_UNLOCK(p); 3953d0586d4SJulian Elischer break; 3963d0586d4SJulian Elischer } 3970cd3964fSJulian Elischer PROC_UNLOCK(p); 3983d0586d4SJulian Elischer } 3993d0586d4SJulian Elischer return (0); 4003d0586d4SJulian Elischer } 40144990b8cSJulian Elischer 4023d0586d4SJulian Elischer /* 4033d0586d4SJulian Elischer * Take the list of completed mailboxes for this KSEGRP and put them on this 4043d0586d4SJulian Elischer * KSE's mailbox as it's the next one going up. 4053d0586d4SJulian Elischer */ 4063d0586d4SJulian Elischer static int 4073d0586d4SJulian Elischer thread_link_mboxes(struct ksegrp *kg, struct kse *ke) 4083d0586d4SJulian Elischer { 4090cd3964fSJulian Elischer struct proc *p = kg->kg_proc; 4103d0586d4SJulian Elischer void *addr; 4113d0586d4SJulian Elischer uintptr_t mbx; 4123d0586d4SJulian Elischer 4133d0586d4SJulian Elischer #if 0 4143d0586d4SJulian Elischer addr = (caddr_t)ke->ke_mailbox 4153d0586d4SJulian Elischer + offsetof(struct kse_mailbox, km_completed); 4163d0586d4SJulian Elischer #else /* if user pointer arithmetic is valid in the kernel */ 4173d0586d4SJulian Elischer addr = (void *)(&ke->ke_mailbox->km_completed); 4183d0586d4SJulian Elischer #endif 4193d0586d4SJulian Elischer for (;;) { 4203d0586d4SJulian Elischer mbx = (uintptr_t)kg->kg_completed; 4213d0586d4SJulian Elischer if (suword(addr, mbx)) { 4220cd3964fSJulian Elischer PROC_LOCK(p); 4230cd3964fSJulian Elischer psignal(p, SIGSEGV); 4240cd3964fSJulian Elischer PROC_UNLOCK(p); 4253d0586d4SJulian Elischer return (EFAULT); 4263d0586d4SJulian Elischer } 4273d0586d4SJulian Elischer /* XXXKSE could use atomic CMPXCH here */ 4280cd3964fSJulian Elischer PROC_LOCK(p); 4293d0586d4SJulian Elischer if (mbx == (uintptr_t)kg->kg_completed) { 4303d0586d4SJulian Elischer kg->kg_completed = NULL; 4310cd3964fSJulian Elischer PROC_UNLOCK(p); 4323d0586d4SJulian Elischer break; 4333d0586d4SJulian Elischer } 4340cd3964fSJulian Elischer PROC_UNLOCK(p); 4353d0586d4SJulian Elischer } 4363d0586d4SJulian Elischer return (0); 4373d0586d4SJulian Elischer } 43844990b8cSJulian Elischer 43944990b8cSJulian Elischer /* 44044990b8cSJulian Elischer * Discard the current thread and exit from its context. 44144990b8cSJulian Elischer * 44244990b8cSJulian Elischer * Because we can't free a thread while we're operating under its context, 44344990b8cSJulian Elischer * push the current thread into our KSE's ke_tdspare slot, freeing the 44444990b8cSJulian Elischer * thread that might be there currently. Because we know that only this 44544990b8cSJulian Elischer * processor will run our KSE, we needn't worry about someone else grabbing 44644990b8cSJulian Elischer * our context before we do a cpu_throw. 44744990b8cSJulian Elischer */ 44844990b8cSJulian Elischer void 44944990b8cSJulian Elischer thread_exit(void) 45044990b8cSJulian Elischer { 45144990b8cSJulian Elischer struct thread *td; 45244990b8cSJulian Elischer struct kse *ke; 45344990b8cSJulian Elischer struct proc *p; 45444990b8cSJulian Elischer struct ksegrp *kg; 45544990b8cSJulian Elischer 45644990b8cSJulian Elischer td = curthread; 45744990b8cSJulian Elischer kg = td->td_ksegrp; 45844990b8cSJulian Elischer p = td->td_proc; 45944990b8cSJulian Elischer ke = td->td_kse; 46044990b8cSJulian Elischer 46144990b8cSJulian Elischer mtx_assert(&sched_lock, MA_OWNED); 46288151aa3SJulian Elischer KASSERT(p != NULL, ("thread exiting without a process")); 46388151aa3SJulian Elischer KASSERT(ke != NULL, ("thread exiting without a kse")); 46488151aa3SJulian Elischer KASSERT(kg != NULL, ("thread exiting without a kse group")); 46544990b8cSJulian Elischer PROC_LOCK_ASSERT(p, MA_OWNED); 46644990b8cSJulian Elischer CTR1(KTR_PROC, "thread_exit: thread %p", td); 46744990b8cSJulian Elischer KASSERT(!mtx_owned(&Giant), ("dying thread owns giant")); 46844990b8cSJulian Elischer 46944990b8cSJulian Elischer if (ke->ke_tdspare != NULL) { 47071fad9fdSJulian Elischer thread_stash(ke->ke_tdspare); 47144990b8cSJulian Elischer ke->ke_tdspare = NULL; 47244990b8cSJulian Elischer } 47348bfcdddSJulian Elischer if (td->td_standin != NULL) { 47448bfcdddSJulian Elischer thread_stash(td->td_standin); 47548bfcdddSJulian Elischer td->td_standin = NULL; 47648bfcdddSJulian Elischer } 47748bfcdddSJulian Elischer 47844990b8cSJulian Elischer cpu_thread_exit(td); /* XXXSMP */ 47944990b8cSJulian Elischer 4801faf202eSJulian Elischer /* 4811faf202eSJulian Elischer * The last thread is left attached to the process 4821faf202eSJulian Elischer * So that the whole bundle gets recycled. Skip 4831faf202eSJulian Elischer * all this stuff. 4841faf202eSJulian Elischer */ 4851faf202eSJulian Elischer if (p->p_numthreads > 1) { 48644990b8cSJulian Elischer /* Unlink this thread from its proc. and the kseg */ 48744990b8cSJulian Elischer TAILQ_REMOVE(&p->p_threads, td, td_plist); 48844990b8cSJulian Elischer p->p_numthreads--; 48944990b8cSJulian Elischer TAILQ_REMOVE(&kg->kg_threads, td, td_kglist); 49044990b8cSJulian Elischer kg->kg_numthreads--; 49144990b8cSJulian Elischer /* 49244990b8cSJulian Elischer * The test below is NOT true if we are the 4931faf202eSJulian Elischer * sole exiting thread. P_STOPPED_SNGL is unset 49444990b8cSJulian Elischer * in exit1() after it is the only survivor. 49544990b8cSJulian Elischer */ 4961279572aSDavid Xu if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { 49744990b8cSJulian Elischer if (p->p_numthreads == p->p_suspcount) { 49871fad9fdSJulian Elischer thread_unsuspend_one(p->p_singlethread); 49944990b8cSJulian Elischer } 50044990b8cSJulian Elischer } 50148bfcdddSJulian Elischer 50248bfcdddSJulian Elischer /* Reassign this thread's KSE. */ 50348bfcdddSJulian Elischer ke->ke_thread = NULL; 50448bfcdddSJulian Elischer td->td_kse = NULL; 50548bfcdddSJulian Elischer ke->ke_state = KES_UNQUEUED; 50648bfcdddSJulian Elischer if (ke->ke_bound == td) { 50748bfcdddSJulian Elischer printf("thread_exit: entered with ke_bound set\n"); 50848bfcdddSJulian Elischer ke->ke_bound = NULL; /* should never happen */ 50948bfcdddSJulian Elischer } 51048bfcdddSJulian Elischer 51148bfcdddSJulian Elischer kse_reassign(ke); 51288151aa3SJulian Elischer PROC_UNLOCK(p); 51371fad9fdSJulian Elischer td->td_state = TDS_INACTIVE; 51444990b8cSJulian Elischer td->td_proc = NULL; 51544990b8cSJulian Elischer td->td_ksegrp = NULL; 51644990b8cSJulian Elischer td->td_last_kse = NULL; 51748bfcdddSJulian Elischer /* 51848bfcdddSJulian Elischer * For now stash this here, however 51948bfcdddSJulian Elischer * it's not a permanent solution. 52048bfcdddSJulian Elischer * When we want to make KSEs exit as well 52148bfcdddSJulian Elischer * we'll have to face this one again. 52248bfcdddSJulian Elischer * Where will we hide it then? 52348bfcdddSJulian Elischer * 52448bfcdddSJulian Elischer * In borrower threads, stash it in the lender 52548bfcdddSJulian Elischer * Where it won't be needed until 52648bfcdddSJulian Elischer * this thread is long gone. 52748bfcdddSJulian Elischer */ 52848bfcdddSJulian Elischer if (ke->ke_bound) { 52948bfcdddSJulian Elischer if (ke->ke_bound->td_standin) { 53048bfcdddSJulian Elischer thread_stash(ke->ke_bound->td_standin); 53148bfcdddSJulian Elischer } 53248bfcdddSJulian Elischer ke->ke_bound->td_standin = td; 53348bfcdddSJulian Elischer } else { 53444990b8cSJulian Elischer ke->ke_tdspare = td; 53548bfcdddSJulian Elischer } 5361faf202eSJulian Elischer } else { 5371faf202eSJulian Elischer PROC_UNLOCK(p); 5381faf202eSJulian Elischer } 5391faf202eSJulian Elischer 54044990b8cSJulian Elischer cpu_throw(); 54144990b8cSJulian Elischer /* NOTREACHED */ 54244990b8cSJulian Elischer } 54344990b8cSJulian Elischer 54444990b8cSJulian Elischer /* 54544990b8cSJulian Elischer * Link a thread to a process. 5461faf202eSJulian Elischer * set up anything that needs to be initialized for it to 5471faf202eSJulian Elischer * be used by the process. 54844990b8cSJulian Elischer * 54944990b8cSJulian Elischer * Note that we do not link to the proc's ucred here. 55044990b8cSJulian Elischer * The thread is linked as if running but no KSE assigned. 55144990b8cSJulian Elischer */ 55244990b8cSJulian Elischer void 55344990b8cSJulian Elischer thread_link(struct thread *td, struct ksegrp *kg) 55444990b8cSJulian Elischer { 55544990b8cSJulian Elischer struct proc *p; 55644990b8cSJulian Elischer 55744990b8cSJulian Elischer p = kg->kg_proc; 55871fad9fdSJulian Elischer td->td_state = TDS_INACTIVE; 55944990b8cSJulian Elischer td->td_proc = p; 56044990b8cSJulian Elischer td->td_ksegrp = kg; 56144990b8cSJulian Elischer td->td_last_kse = NULL; 56244990b8cSJulian Elischer 5631faf202eSJulian Elischer LIST_INIT(&td->td_contested); 5641faf202eSJulian Elischer callout_init(&td->td_slpcallout, 1); 56544990b8cSJulian Elischer TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist); 56644990b8cSJulian Elischer TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist); 56744990b8cSJulian Elischer p->p_numthreads++; 56844990b8cSJulian Elischer kg->kg_numthreads++; 5694f0db5e0SJulian Elischer if (oiks_debug && p->p_numthreads > max_threads_per_proc) { 57044990b8cSJulian Elischer printf("OIKS %d\n", p->p_numthreads); 57144990b8cSJulian Elischer if (oiks_debug > 1) 57244990b8cSJulian Elischer Debugger("OIKS"); 57344990b8cSJulian Elischer } 57444990b8cSJulian Elischer td->td_kse = NULL; 57544990b8cSJulian Elischer } 57644990b8cSJulian Elischer 57744990b8cSJulian Elischer /* 578c76e33b6SJonathan Mini * Create a thread and schedule it for upcall on the KSE given. 57944990b8cSJulian Elischer */ 58044990b8cSJulian Elischer struct thread * 58144990b8cSJulian Elischer thread_schedule_upcall(struct thread *td, struct kse *ke) 58244990b8cSJulian Elischer { 58344990b8cSJulian Elischer struct thread *td2; 58448bfcdddSJulian Elischer int newkse; 58544990b8cSJulian Elischer 58644990b8cSJulian Elischer mtx_assert(&sched_lock, MA_OWNED); 58748bfcdddSJulian Elischer newkse = (ke != td->td_kse); 58848bfcdddSJulian Elischer 58948bfcdddSJulian Elischer /* 59048bfcdddSJulian Elischer * If the kse is already owned by another thread then we can't 59148bfcdddSJulian Elischer * schedule an upcall because the other thread must be BOUND 59248bfcdddSJulian Elischer * which means it is not in a position to take an upcall. 59348bfcdddSJulian Elischer * We must be borrowing the KSE to allow us to complete some in-kernel 59448bfcdddSJulian Elischer * work. When we complete, the Bound thread will have teh chance to 59548bfcdddSJulian Elischer * complete. This thread will sleep as planned. Hopefully there will 59648bfcdddSJulian Elischer * eventually be un unbound thread that can be converted to an 59748bfcdddSJulian Elischer * upcall to report the completion of this thread. 59848bfcdddSJulian Elischer */ 59948bfcdddSJulian Elischer if (ke->ke_bound && ((ke->ke_bound->td_flags & TDF_UNBOUND) == 0)) { 60048bfcdddSJulian Elischer return (NULL); 60148bfcdddSJulian Elischer } 60248bfcdddSJulian Elischer KASSERT((ke->ke_bound == NULL), ("kse already bound")); 60348bfcdddSJulian Elischer 60448bfcdddSJulian Elischer if ((td2 = td->td_standin) != NULL) { 60548bfcdddSJulian Elischer td->td_standin = NULL; 60644990b8cSJulian Elischer } else { 60748bfcdddSJulian Elischer if (newkse) 60848bfcdddSJulian Elischer panic("no reserve thread when called with a new kse"); 60948bfcdddSJulian Elischer /* 61048bfcdddSJulian Elischer * If called from (e.g.) sleep and we do not have 61148bfcdddSJulian Elischer * a reserve thread, then we've used it, so do not 61248bfcdddSJulian Elischer * create an upcall. 61348bfcdddSJulian Elischer */ 61448bfcdddSJulian Elischer return(NULL); 61544990b8cSJulian Elischer } 61644990b8cSJulian Elischer CTR3(KTR_PROC, "thread_schedule_upcall: thread %p (pid %d, %s)", 61748bfcdddSJulian Elischer td2, td->td_proc->p_pid, td->td_proc->p_comm); 618c0698d32SJulian Elischer bzero(&td2->td_startzero, 6191faf202eSJulian Elischer (unsigned)RANGEOF(struct thread, td_startzero, td_endzero)); 6201faf202eSJulian Elischer bcopy(&td->td_startcopy, &td2->td_startcopy, 6211faf202eSJulian Elischer (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy)); 62244990b8cSJulian Elischer thread_link(td2, ke->ke_ksegrp); 623c76e33b6SJonathan Mini cpu_set_upcall(td2, td->td_pcb); 62448bfcdddSJulian Elischer 625c76e33b6SJonathan Mini /* 62648bfcdddSJulian Elischer * XXXKSE do we really need this? (default values for the 62748bfcdddSJulian Elischer * frame). 62848bfcdddSJulian Elischer */ 62948bfcdddSJulian Elischer bcopy(td->td_frame, td2->td_frame, sizeof(struct trapframe)); 63048bfcdddSJulian Elischer 63148bfcdddSJulian Elischer /* 63248bfcdddSJulian Elischer * Bind the new thread to the KSE, 63348bfcdddSJulian Elischer * and if it's our KSE, lend it back to ourself 63448bfcdddSJulian Elischer * so we can continue running. 635c76e33b6SJonathan Mini */ 63644990b8cSJulian Elischer td2->td_ucred = crhold(td->td_ucred); 63748bfcdddSJulian Elischer td2->td_flags = TDF_UPCALLING; /* note: BOUND */ 63848bfcdddSJulian Elischer td2->td_kse = ke; 63948bfcdddSJulian Elischer td2->td_state = TDS_CAN_RUN; 64048bfcdddSJulian Elischer td2->td_inhibitors = 0; 64148bfcdddSJulian Elischer /* 64248bfcdddSJulian Elischer * If called from msleep(), we are working on the current 64348bfcdddSJulian Elischer * KSE so fake that we borrowed it. If called from 64448bfcdddSJulian Elischer * kse_create(), don't, as we have a new kse too. 64548bfcdddSJulian Elischer */ 64648bfcdddSJulian Elischer if (!newkse) { 64748bfcdddSJulian Elischer /* 64848bfcdddSJulian Elischer * This thread will be scheduled when the current thread 64948bfcdddSJulian Elischer * blocks, exits or tries to enter userspace, (which ever 65048bfcdddSJulian Elischer * happens first). When that happens the KSe will "revert" 65148bfcdddSJulian Elischer * to this thread in a BOUND manner. Since we are called 65248bfcdddSJulian Elischer * from msleep() this is going to be "very soon" in nearly 65348bfcdddSJulian Elischer * all cases. 65448bfcdddSJulian Elischer */ 65548bfcdddSJulian Elischer ke->ke_bound = td2; 65648bfcdddSJulian Elischer TD_SET_LOAN(td2); 65748bfcdddSJulian Elischer } else { 65848bfcdddSJulian Elischer ke->ke_bound = NULL; 65948bfcdddSJulian Elischer ke->ke_thread = td2; 66044990b8cSJulian Elischer setrunqueue(td2); 66148bfcdddSJulian Elischer } 66248bfcdddSJulian Elischer return (td2); /* bogus.. should be a void function */ 66344990b8cSJulian Elischer } 66444990b8cSJulian Elischer 66544990b8cSJulian Elischer /* 666c76e33b6SJonathan Mini * Schedule an upcall to notify a KSE process recieved signals. 66744990b8cSJulian Elischer * 668c76e33b6SJonathan Mini * XXX - Modifying a sigset_t like this is totally bogus. 66944990b8cSJulian Elischer */ 670c76e33b6SJonathan Mini struct thread * 671c76e33b6SJonathan Mini signal_upcall(struct proc *p, int sig) 672c76e33b6SJonathan Mini { 673c76e33b6SJonathan Mini struct thread *td, *td2; 674c76e33b6SJonathan Mini struct kse *ke; 675c76e33b6SJonathan Mini sigset_t ss; 676c76e33b6SJonathan Mini int error; 677c76e33b6SJonathan Mini 678c76e33b6SJonathan Mini PROC_LOCK_ASSERT(p, MA_OWNED); 67948bfcdddSJulian Elischer return (NULL); 680c76e33b6SJonathan Mini 681c76e33b6SJonathan Mini td = FIRST_THREAD_IN_PROC(p); 682c76e33b6SJonathan Mini ke = td->td_kse; 683c76e33b6SJonathan Mini PROC_UNLOCK(p); 684c76e33b6SJonathan Mini error = copyin(&ke->ke_mailbox->km_sigscaught, &ss, sizeof(sigset_t)); 685c76e33b6SJonathan Mini PROC_LOCK(p); 686c76e33b6SJonathan Mini if (error) 687c76e33b6SJonathan Mini return (NULL); 688c76e33b6SJonathan Mini SIGADDSET(ss, sig); 689c76e33b6SJonathan Mini PROC_UNLOCK(p); 690c76e33b6SJonathan Mini error = copyout(&ss, &ke->ke_mailbox->km_sigscaught, sizeof(sigset_t)); 691c76e33b6SJonathan Mini PROC_LOCK(p); 692c76e33b6SJonathan Mini if (error) 693c76e33b6SJonathan Mini return (NULL); 69448bfcdddSJulian Elischer if (td->td_standin == NULL) 69548bfcdddSJulian Elischer td->td_standin = thread_alloc(); 696c76e33b6SJonathan Mini mtx_lock_spin(&sched_lock); 69748bfcdddSJulian Elischer td2 = thread_schedule_upcall(td, ke); /* Bogus JRE */ 698c76e33b6SJonathan Mini mtx_unlock_spin(&sched_lock); 699c76e33b6SJonathan Mini return (td2); 700c76e33b6SJonathan Mini } 701c76e33b6SJonathan Mini 702c76e33b6SJonathan Mini /* 703c76e33b6SJonathan Mini * The extra work we go through if we are a threaded process when we 704c76e33b6SJonathan Mini * return to userland. 705c76e33b6SJonathan Mini * 706c76e33b6SJonathan Mini * If we are a KSE process and returning to user mode, check for 707c76e33b6SJonathan Mini * extra work to do before we return (e.g. for more syscalls 708c76e33b6SJonathan Mini * to complete first). If we were in a critical section, we should 709c76e33b6SJonathan Mini * just return to let it finish. Same if we were in the UTS (in 710c76e33b6SJonathan Mini * which case the mailbox's context's busy indicator will be set). 711c76e33b6SJonathan Mini * The only traps we suport will have set the mailbox. 712c76e33b6SJonathan Mini * We will clear it here. 71344990b8cSJulian Elischer */ 714c76e33b6SJonathan Mini int 715253fdd5bSJulian Elischer thread_userret(struct thread *td, struct trapframe *frame) 716c76e33b6SJonathan Mini { 717c76e33b6SJonathan Mini int error; 7183d0586d4SJulian Elischer int unbound; 7193d0586d4SJulian Elischer struct kse *ke; 72048bfcdddSJulian Elischer struct ksegrp *kg; 72148bfcdddSJulian Elischer struct thread *td2; 72248bfcdddSJulian Elischer struct proc *p; 723c76e33b6SJonathan Mini 72448bfcdddSJulian Elischer error = 0; 72548bfcdddSJulian Elischer 72648bfcdddSJulian Elischer unbound = td->td_flags & TDF_UNBOUND; 72748bfcdddSJulian Elischer 72848bfcdddSJulian Elischer kg = td->td_ksegrp; 72948bfcdddSJulian Elischer p = td->td_proc; 73048bfcdddSJulian Elischer 73148bfcdddSJulian Elischer /* 73248bfcdddSJulian Elischer * Originally bound threads never upcall but they may 73348bfcdddSJulian Elischer * loan out their KSE at this point. 73448bfcdddSJulian Elischer * Upcalls imply bound.. They also may want to do some Philantropy. 73548bfcdddSJulian Elischer * Unbound threads on the other hand either yield to other work 73648bfcdddSJulian Elischer * or transform into an upcall. 73748bfcdddSJulian Elischer * (having saved their context to user space in both cases) 73848bfcdddSJulian Elischer */ 73948bfcdddSJulian Elischer if (unbound ) { 74048bfcdddSJulian Elischer /* 74148bfcdddSJulian Elischer * We are an unbound thread, looking to return to 74248bfcdddSJulian Elischer * user space. 74348bfcdddSJulian Elischer * THere are several possibilities: 74448bfcdddSJulian Elischer * 1) we are using a borrowed KSE. save state and exit. 74548bfcdddSJulian Elischer * kse_reassign() will recycle the kse as needed, 74648bfcdddSJulian Elischer * 2) we are not.. save state, and then convert ourself 74748bfcdddSJulian Elischer * to be an upcall, bound to the KSE. 74848bfcdddSJulian Elischer * if there are others that need the kse, 74948bfcdddSJulian Elischer * give them a chance by doing an mi_switch(). 75048bfcdddSJulian Elischer * Because we are bound, control will eventually return 75148bfcdddSJulian Elischer * to us here. 75248bfcdddSJulian Elischer * *** 75348bfcdddSJulian Elischer * Save the thread's context, and link it 75448bfcdddSJulian Elischer * into the KSEGRP's list of completed threads. 75548bfcdddSJulian Elischer */ 75648bfcdddSJulian Elischer error = thread_export_context(td); 75748bfcdddSJulian Elischer td->td_mailbox = NULL; 75848bfcdddSJulian Elischer if (error) { 75948bfcdddSJulian Elischer /* 76048bfcdddSJulian Elischer * If we are not running on a borrowed KSE, then 76148bfcdddSJulian Elischer * failing to do the KSE operation just defaults 76248bfcdddSJulian Elischer * back to synchonous operation, so just return from 76348bfcdddSJulian Elischer * the syscall. If it IS borrowed, there is nothing 76448bfcdddSJulian Elischer * we can do. We just lose that context. We 76548bfcdddSJulian Elischer * probably should note this somewhere and send 76648bfcdddSJulian Elischer * the process a signal. 76748bfcdddSJulian Elischer */ 7689eb1fdeaSJulian Elischer PROC_LOCK(td->td_proc); 76948bfcdddSJulian Elischer psignal(td->td_proc, SIGSEGV); 7709eb1fdeaSJulian Elischer mtx_lock_spin(&sched_lock); 77148bfcdddSJulian Elischer if (td->td_kse->ke_bound == NULL) { 77248bfcdddSJulian Elischer td->td_flags &= ~TDF_UNBOUND; 77348bfcdddSJulian Elischer PROC_UNLOCK(td->td_proc); 77448bfcdddSJulian Elischer mtx_unlock_spin(&sched_lock); 77548bfcdddSJulian Elischer return (error); /* go sync */ 77648bfcdddSJulian Elischer } 7779eb1fdeaSJulian Elischer thread_exit(); 7789eb1fdeaSJulian Elischer } 7799eb1fdeaSJulian Elischer 780c76e33b6SJonathan Mini /* 78148bfcdddSJulian Elischer * if the KSE is owned and we are borrowing it, 78248bfcdddSJulian Elischer * don't make an upcall, just exit so that the owner 78348bfcdddSJulian Elischer * can get its KSE if it wants it. 78448bfcdddSJulian Elischer * Our context is already safely stored for later 78548bfcdddSJulian Elischer * use by the UTS. 78648bfcdddSJulian Elischer */ 78748bfcdddSJulian Elischer PROC_LOCK(p); 78848bfcdddSJulian Elischer mtx_lock_spin(&sched_lock); 78948bfcdddSJulian Elischer if (td->td_kse->ke_bound) { 79048bfcdddSJulian Elischer thread_exit(); 79148bfcdddSJulian Elischer } 79248bfcdddSJulian Elischer PROC_UNLOCK(p); 79348bfcdddSJulian Elischer 79448bfcdddSJulian Elischer /* 79548bfcdddSJulian Elischer * Turn ourself into a bound upcall. 79648bfcdddSJulian Elischer * We will rely on kse_reassign() 79748bfcdddSJulian Elischer * to make us run at a later time. 79848bfcdddSJulian Elischer * We should look just like a sheduled upcall 79948bfcdddSJulian Elischer * from msleep() or cv_wait(). 80048bfcdddSJulian Elischer */ 80148bfcdddSJulian Elischer td->td_flags &= ~TDF_UNBOUND; 80248bfcdddSJulian Elischer td->td_flags |= TDF_UPCALLING; 80348bfcdddSJulian Elischer /* Only get here if we have become an upcall */ 80448bfcdddSJulian Elischer 80548bfcdddSJulian Elischer } else { 80648bfcdddSJulian Elischer mtx_lock_spin(&sched_lock); 80748bfcdddSJulian Elischer } 80848bfcdddSJulian Elischer /* 80948bfcdddSJulian Elischer * We ARE going back to userland with this KSE. 81048bfcdddSJulian Elischer * Check for threads that need to borrow it. 81148bfcdddSJulian Elischer * Optimisation: don't call mi_switch if no-one wants the KSE. 81248bfcdddSJulian Elischer * Any other thread that comes ready after this missed the boat. 813c76e33b6SJonathan Mini */ 8143d0586d4SJulian Elischer ke = td->td_kse; 81548bfcdddSJulian Elischer if ((td2 = kg->kg_last_assigned)) 81648bfcdddSJulian Elischer td2 = TAILQ_NEXT(td2, td_runq); 81748bfcdddSJulian Elischer else 81848bfcdddSJulian Elischer td2 = TAILQ_FIRST(&kg->kg_runq); 81948bfcdddSJulian Elischer if (td2) { 820c76e33b6SJonathan Mini /* 82148bfcdddSJulian Elischer * force a switch to more urgent 'in kernel' 82248bfcdddSJulian Elischer * work. Control will return to this thread 82348bfcdddSJulian Elischer * when there is no more work to do. 82448bfcdddSJulian Elischer * kse_reassign() will do tha for us. 825c76e33b6SJonathan Mini */ 82648bfcdddSJulian Elischer TD_SET_LOAN(td); 82748bfcdddSJulian Elischer ke->ke_bound = td; 82848bfcdddSJulian Elischer ke->ke_thread = NULL; 82948bfcdddSJulian Elischer mi_switch(); /* kse_reassign() will (re)find td2 */ 83048bfcdddSJulian Elischer } 83148bfcdddSJulian Elischer mtx_unlock_spin(&sched_lock); 83248bfcdddSJulian Elischer 83348bfcdddSJulian Elischer /* 83448bfcdddSJulian Elischer * Optimisation: 83548bfcdddSJulian Elischer * Ensure that we have a spare thread available, 83648bfcdddSJulian Elischer * for when we re-enter the kernel. 83748bfcdddSJulian Elischer */ 83848bfcdddSJulian Elischer if (td->td_standin == NULL) { 83948bfcdddSJulian Elischer if (ke->ke_tdspare) { 84048bfcdddSJulian Elischer td->td_standin = ke->ke_tdspare; 84148bfcdddSJulian Elischer ke->ke_tdspare = NULL; 84248bfcdddSJulian Elischer } else { 84348bfcdddSJulian Elischer td->td_standin = thread_alloc(); 84448bfcdddSJulian Elischer } 84548bfcdddSJulian Elischer } 84648bfcdddSJulian Elischer 84748bfcdddSJulian Elischer /* 84848bfcdddSJulian Elischer * To get here, we know there is no other need for our 84948bfcdddSJulian Elischer * KSE so we can proceed. If not upcalling, go back to 85048bfcdddSJulian Elischer * userspace. If we are, get the upcall set up. 85148bfcdddSJulian Elischer */ 85248bfcdddSJulian Elischer if ((td->td_flags & TDF_UPCALLING) == 0) 853c76e33b6SJonathan Mini return (0); 85448bfcdddSJulian Elischer 855c76e33b6SJonathan Mini /* 85648bfcdddSJulian Elischer * We must be an upcall to get this far. 85744990b8cSJulian Elischer * There is no more work to do and we are going to ride 8583d0586d4SJulian Elischer * this thead/KSE up to userland as an upcall. 85948bfcdddSJulian Elischer * Do the last parts of the setup needed for the upcall. 86044990b8cSJulian Elischer */ 861c76e33b6SJonathan Mini CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)", 862ed32df81SJulian Elischer td, td->td_proc->p_pid, td->td_proc->p_comm); 863c76e33b6SJonathan Mini 864c76e33b6SJonathan Mini /* 865c76e33b6SJonathan Mini * Set user context to the UTS. 866c76e33b6SJonathan Mini */ 8673d0586d4SJulian Elischer cpu_set_upcall_kse(td, ke); 8683d0586d4SJulian Elischer 869c76e33b6SJonathan Mini /* 8703d0586d4SJulian Elischer * Put any completed mailboxes on this KSE's list. 871c76e33b6SJonathan Mini */ 87248bfcdddSJulian Elischer error = thread_link_mboxes(kg, ke); 8733d0586d4SJulian Elischer if (error) 8743d0586d4SJulian Elischer goto bad; 875c76e33b6SJonathan Mini 876c76e33b6SJonathan Mini /* 877c76e33b6SJonathan Mini * Set state and mailbox. 87848bfcdddSJulian Elischer * From now on we are just a bound outgoing process. 87948bfcdddSJulian Elischer * **Problem** userret is often called several times. 88048bfcdddSJulian Elischer * it would be nice if this all happenned only on the first time 88148bfcdddSJulian Elischer * through. (the scan for extra work etc.) 882c76e33b6SJonathan Mini */ 883c76e33b6SJonathan Mini td->td_flags &= ~TDF_UPCALLING; 8843d0586d4SJulian Elischer #if 0 8853d0586d4SJulian Elischer error = suword((caddr_t)ke->ke_mailbox + 88648bfcdddSJulian Elischer offsetof(struct kse_mailbox, km_curthread), 0); 8873d0586d4SJulian Elischer #else /* if user pointer arithmetic is ok in the kernel */ 8883d0586d4SJulian Elischer error = suword((caddr_t)&ke->ke_mailbox->km_curthread, 0); 8893d0586d4SJulian Elischer #endif 89048bfcdddSJulian Elischer if (!error) 89148bfcdddSJulian Elischer return (0); 89248bfcdddSJulian Elischer 8933d0586d4SJulian Elischer bad: 8943d0586d4SJulian Elischer /* 8953d0586d4SJulian Elischer * Things are going to be so screwed we should just kill the process. 8963d0586d4SJulian Elischer * how do we do that? 8973d0586d4SJulian Elischer */ 89848bfcdddSJulian Elischer PROC_LOCK(td->td_proc); 89948bfcdddSJulian Elischer psignal(td->td_proc, SIGSEGV); 90048bfcdddSJulian Elischer PROC_UNLOCK(td->td_proc); 90148bfcdddSJulian Elischer return (error); /* go sync */ 90244990b8cSJulian Elischer } 90344990b8cSJulian Elischer 90444990b8cSJulian Elischer /* 90544990b8cSJulian Elischer * Enforce single-threading. 90644990b8cSJulian Elischer * 90744990b8cSJulian Elischer * Returns 1 if the caller must abort (another thread is waiting to 90844990b8cSJulian Elischer * exit the process or similar). Process is locked! 90944990b8cSJulian Elischer * Returns 0 when you are successfully the only thread running. 91044990b8cSJulian Elischer * A process has successfully single threaded in the suspend mode when 91144990b8cSJulian Elischer * There are no threads in user mode. Threads in the kernel must be 91244990b8cSJulian Elischer * allowed to continue until they get to the user boundary. They may even 91344990b8cSJulian Elischer * copy out their return values and data before suspending. They may however be 91444990b8cSJulian Elischer * accellerated in reaching the user boundary as we will wake up 91544990b8cSJulian Elischer * any sleeping threads that are interruptable. (PCATCH). 91644990b8cSJulian Elischer */ 91744990b8cSJulian Elischer int 91844990b8cSJulian Elischer thread_single(int force_exit) 91944990b8cSJulian Elischer { 92044990b8cSJulian Elischer struct thread *td; 92144990b8cSJulian Elischer struct thread *td2; 92244990b8cSJulian Elischer struct proc *p; 92344990b8cSJulian Elischer 92444990b8cSJulian Elischer td = curthread; 92544990b8cSJulian Elischer p = td->td_proc; 92644990b8cSJulian Elischer PROC_LOCK_ASSERT(p, MA_OWNED); 92744990b8cSJulian Elischer KASSERT((td != NULL), ("curthread is NULL")); 92844990b8cSJulian Elischer 92944990b8cSJulian Elischer if ((p->p_flag & P_KSES) == 0) 93044990b8cSJulian Elischer return (0); 93144990b8cSJulian Elischer 932e3b9bf71SJulian Elischer /* Is someone already single threading? */ 933e3b9bf71SJulian Elischer if (p->p_singlethread) 93444990b8cSJulian Elischer return (1); 93544990b8cSJulian Elischer 9361279572aSDavid Xu if (force_exit == SINGLE_EXIT) 93744990b8cSJulian Elischer p->p_flag |= P_SINGLE_EXIT; 93844990b8cSJulian Elischer else 93944990b8cSJulian Elischer p->p_flag &= ~P_SINGLE_EXIT; 9401279572aSDavid Xu p->p_flag |= P_STOPPED_SINGLE; 94144990b8cSJulian Elischer p->p_singlethread = td; 94244990b8cSJulian Elischer while ((p->p_numthreads - p->p_suspcount) != 1) { 94371fad9fdSJulian Elischer mtx_lock_spin(&sched_lock); 94444990b8cSJulian Elischer FOREACH_THREAD_IN_PROC(p, td2) { 94544990b8cSJulian Elischer if (td2 == td) 94644990b8cSJulian Elischer continue; 94771fad9fdSJulian Elischer if (TD_IS_INHIBITED(td2)) { 94871fad9fdSJulian Elischer if (TD_IS_SUSPENDED(td2)) { 9491279572aSDavid Xu if (force_exit == SINGLE_EXIT) { 95071fad9fdSJulian Elischer thread_unsuspend_one(td2); 95144990b8cSJulian Elischer } 95271fad9fdSJulian Elischer } 95371fad9fdSJulian Elischer if ( TD_IS_SLEEPING(td2)) { 954e3b9bf71SJulian Elischer if (td2->td_flags & TDF_CVWAITQ) 95571fad9fdSJulian Elischer cv_waitq_remove(td2); 956e3b9bf71SJulian Elischer else 95771fad9fdSJulian Elischer unsleep(td2); 95844990b8cSJulian Elischer break; 95971fad9fdSJulian Elischer } 96071fad9fdSJulian Elischer if (TD_CAN_RUN(td2)) 96171fad9fdSJulian Elischer setrunqueue(td2); 96244990b8cSJulian Elischer } 96344990b8cSJulian Elischer } 96444990b8cSJulian Elischer /* 96544990b8cSJulian Elischer * Wake us up when everyone else has suspended. 966e3b9bf71SJulian Elischer * In the mean time we suspend as well. 96744990b8cSJulian Elischer */ 96871fad9fdSJulian Elischer thread_suspend_one(td); 96944990b8cSJulian Elischer mtx_unlock(&Giant); 97044990b8cSJulian Elischer PROC_UNLOCK(p); 97144990b8cSJulian Elischer mi_switch(); 97244990b8cSJulian Elischer mtx_unlock_spin(&sched_lock); 97344990b8cSJulian Elischer mtx_lock(&Giant); 97444990b8cSJulian Elischer PROC_LOCK(p); 97544990b8cSJulian Elischer } 97644990b8cSJulian Elischer return (0); 97744990b8cSJulian Elischer } 97844990b8cSJulian Elischer 97944990b8cSJulian Elischer /* 98044990b8cSJulian Elischer * Called in from locations that can safely check to see 98144990b8cSJulian Elischer * whether we have to suspend or at least throttle for a 98244990b8cSJulian Elischer * single-thread event (e.g. fork). 98344990b8cSJulian Elischer * 98444990b8cSJulian Elischer * Such locations include userret(). 98544990b8cSJulian Elischer * If the "return_instead" argument is non zero, the thread must be able to 98644990b8cSJulian Elischer * accept 0 (caller may continue), or 1 (caller must abort) as a result. 98744990b8cSJulian Elischer * 98844990b8cSJulian Elischer * The 'return_instead' argument tells the function if it may do a 98944990b8cSJulian Elischer * thread_exit() or suspend, or whether the caller must abort and back 99044990b8cSJulian Elischer * out instead. 99144990b8cSJulian Elischer * 99244990b8cSJulian Elischer * If the thread that set the single_threading request has set the 99344990b8cSJulian Elischer * P_SINGLE_EXIT bit in the process flags then this call will never return 99444990b8cSJulian Elischer * if 'return_instead' is false, but will exit. 99544990b8cSJulian Elischer * 99644990b8cSJulian Elischer * P_SINGLE_EXIT | return_instead == 0| return_instead != 0 99744990b8cSJulian Elischer *---------------+--------------------+--------------------- 99844990b8cSJulian Elischer * 0 | returns 0 | returns 0 or 1 99944990b8cSJulian Elischer * | when ST ends | immediatly 100044990b8cSJulian Elischer *---------------+--------------------+--------------------- 100144990b8cSJulian Elischer * 1 | thread exits | returns 1 100244990b8cSJulian Elischer * | | immediatly 100344990b8cSJulian Elischer * 0 = thread_exit() or suspension ok, 100444990b8cSJulian Elischer * other = return error instead of stopping the thread. 100544990b8cSJulian Elischer * 100644990b8cSJulian Elischer * While a full suspension is under effect, even a single threading 100744990b8cSJulian Elischer * thread would be suspended if it made this call (but it shouldn't). 100844990b8cSJulian Elischer * This call should only be made from places where 100944990b8cSJulian Elischer * thread_exit() would be safe as that may be the outcome unless 101044990b8cSJulian Elischer * return_instead is set. 101144990b8cSJulian Elischer */ 101244990b8cSJulian Elischer int 101344990b8cSJulian Elischer thread_suspend_check(int return_instead) 101444990b8cSJulian Elischer { 1015ecafb24bSJuli Mallett struct thread *td; 1016ecafb24bSJuli Mallett struct proc *p; 101744990b8cSJulian Elischer 101844990b8cSJulian Elischer td = curthread; 101944990b8cSJulian Elischer p = td->td_proc; 102044990b8cSJulian Elischer PROC_LOCK_ASSERT(p, MA_OWNED); 102144990b8cSJulian Elischer while (P_SHOULDSTOP(p)) { 10221279572aSDavid Xu if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { 102344990b8cSJulian Elischer KASSERT(p->p_singlethread != NULL, 102444990b8cSJulian Elischer ("singlethread not set")); 102544990b8cSJulian Elischer /* 1026e3b9bf71SJulian Elischer * The only suspension in action is a 1027e3b9bf71SJulian Elischer * single-threading. Single threader need not stop. 1028b6d5995eSJulian Elischer * XXX Should be safe to access unlocked 1029b6d5995eSJulian Elischer * as it can only be set to be true by us. 103044990b8cSJulian Elischer */ 1031e3b9bf71SJulian Elischer if (p->p_singlethread == td) 103244990b8cSJulian Elischer return (0); /* Exempt from stopping. */ 103344990b8cSJulian Elischer } 1034e3b9bf71SJulian Elischer if (return_instead) 103544990b8cSJulian Elischer return (1); 103644990b8cSJulian Elischer 103744990b8cSJulian Elischer /* 103844990b8cSJulian Elischer * If the process is waiting for us to exit, 103944990b8cSJulian Elischer * this thread should just suicide. 10401279572aSDavid Xu * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE. 104144990b8cSJulian Elischer */ 104244990b8cSJulian Elischer if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) { 104344990b8cSJulian Elischer mtx_lock_spin(&sched_lock); 104444990b8cSJulian Elischer while (mtx_owned(&Giant)) 104544990b8cSJulian Elischer mtx_unlock(&Giant); 104644990b8cSJulian Elischer thread_exit(); 104744990b8cSJulian Elischer } 104844990b8cSJulian Elischer 104944990b8cSJulian Elischer /* 105044990b8cSJulian Elischer * When a thread suspends, it just 105144990b8cSJulian Elischer * moves to the processes's suspend queue 105244990b8cSJulian Elischer * and stays there. 105344990b8cSJulian Elischer * 105444990b8cSJulian Elischer * XXXKSE if TDF_BOUND is true 105544990b8cSJulian Elischer * it will not release it's KSE which might 105644990b8cSJulian Elischer * lead to deadlock if there are not enough KSEs 105744990b8cSJulian Elischer * to complete all waiting threads. 105844990b8cSJulian Elischer * Maybe be able to 'lend' it out again. 105944990b8cSJulian Elischer * (lent kse's can not go back to userland?) 106044990b8cSJulian Elischer * and can only be lent in STOPPED state. 106144990b8cSJulian Elischer */ 1062721e5910SJulian Elischer mtx_lock_spin(&sched_lock); 10631279572aSDavid Xu if ((p->p_flag & P_STOPPED_SIG) && 1064721e5910SJulian Elischer (p->p_suspcount+1 == p->p_numthreads)) { 1065721e5910SJulian Elischer mtx_unlock_spin(&sched_lock); 1066721e5910SJulian Elischer PROC_LOCK(p->p_pptr); 1067721e5910SJulian Elischer if ((p->p_pptr->p_procsig->ps_flag & 1068721e5910SJulian Elischer PS_NOCLDSTOP) == 0) { 1069721e5910SJulian Elischer psignal(p->p_pptr, SIGCHLD); 1070721e5910SJulian Elischer } 1071721e5910SJulian Elischer PROC_UNLOCK(p->p_pptr); 10729b0e281bSJulian Elischer mtx_lock_spin(&sched_lock); 1073721e5910SJulian Elischer } 107444990b8cSJulian Elischer mtx_assert(&Giant, MA_NOTOWNED); 107571fad9fdSJulian Elischer thread_suspend_one(td); 107644990b8cSJulian Elischer PROC_UNLOCK(p); 10771279572aSDavid Xu if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { 1078cf19bf91SJulian Elischer if (p->p_numthreads == p->p_suspcount) { 107971fad9fdSJulian Elischer thread_unsuspend_one(p->p_singlethread); 1080cf19bf91SJulian Elischer } 1081cf19bf91SJulian Elischer } 108220568366SJulian Elischer p->p_stats->p_ru.ru_nivcsw++; 108344990b8cSJulian Elischer mi_switch(); 108444990b8cSJulian Elischer mtx_unlock_spin(&sched_lock); 108544990b8cSJulian Elischer PROC_LOCK(p); 108644990b8cSJulian Elischer } 108744990b8cSJulian Elischer return (0); 108844990b8cSJulian Elischer } 108944990b8cSJulian Elischer 109035c32a76SDavid Xu void 109135c32a76SDavid Xu thread_suspend_one(struct thread *td) 109235c32a76SDavid Xu { 109335c32a76SDavid Xu struct proc *p = td->td_proc; 109435c32a76SDavid Xu 109535c32a76SDavid Xu mtx_assert(&sched_lock, MA_OWNED); 109635c32a76SDavid Xu p->p_suspcount++; 109771fad9fdSJulian Elischer TD_SET_SUSPENDED(td); 109835c32a76SDavid Xu TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq); 109971fad9fdSJulian Elischer /* 110071fad9fdSJulian Elischer * Hack: If we are suspending but are on the sleep queue 110171fad9fdSJulian Elischer * then we are in msleep or the cv equivalent. We 110271fad9fdSJulian Elischer * want to look like we have two Inhibitors. 110371fad9fdSJulian Elischer */ 110471fad9fdSJulian Elischer if (TD_ON_SLEEPQ(td)) 110571fad9fdSJulian Elischer TD_SET_SLEEPING(td); 110635c32a76SDavid Xu } 110735c32a76SDavid Xu 110835c32a76SDavid Xu void 110935c32a76SDavid Xu thread_unsuspend_one(struct thread *td) 111035c32a76SDavid Xu { 111135c32a76SDavid Xu struct proc *p = td->td_proc; 111235c32a76SDavid Xu 111335c32a76SDavid Xu mtx_assert(&sched_lock, MA_OWNED); 111435c32a76SDavid Xu TAILQ_REMOVE(&p->p_suspended, td, td_runq); 111571fad9fdSJulian Elischer TD_CLR_SUSPENDED(td); 111635c32a76SDavid Xu p->p_suspcount--; 111771fad9fdSJulian Elischer setrunnable(td); 111835c32a76SDavid Xu } 111935c32a76SDavid Xu 112044990b8cSJulian Elischer /* 112144990b8cSJulian Elischer * Allow all threads blocked by single threading to continue running. 112244990b8cSJulian Elischer */ 112344990b8cSJulian Elischer void 112444990b8cSJulian Elischer thread_unsuspend(struct proc *p) 112544990b8cSJulian Elischer { 112644990b8cSJulian Elischer struct thread *td; 112744990b8cSJulian Elischer 1128b6d5995eSJulian Elischer mtx_assert(&sched_lock, MA_OWNED); 112944990b8cSJulian Elischer PROC_LOCK_ASSERT(p, MA_OWNED); 113044990b8cSJulian Elischer if (!P_SHOULDSTOP(p)) { 113144990b8cSJulian Elischer while (( td = TAILQ_FIRST(&p->p_suspended))) { 113235c32a76SDavid Xu thread_unsuspend_one(td); 113344990b8cSJulian Elischer } 11341279572aSDavid Xu } else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) && 113544990b8cSJulian Elischer (p->p_numthreads == p->p_suspcount)) { 113644990b8cSJulian Elischer /* 113744990b8cSJulian Elischer * Stopping everything also did the job for the single 113844990b8cSJulian Elischer * threading request. Now we've downgraded to single-threaded, 113944990b8cSJulian Elischer * let it continue. 114044990b8cSJulian Elischer */ 114135c32a76SDavid Xu thread_unsuspend_one(p->p_singlethread); 114244990b8cSJulian Elischer } 114344990b8cSJulian Elischer } 114444990b8cSJulian Elischer 114544990b8cSJulian Elischer void 114644990b8cSJulian Elischer thread_single_end(void) 114744990b8cSJulian Elischer { 114844990b8cSJulian Elischer struct thread *td; 114944990b8cSJulian Elischer struct proc *p; 115044990b8cSJulian Elischer 115144990b8cSJulian Elischer td = curthread; 115244990b8cSJulian Elischer p = td->td_proc; 115344990b8cSJulian Elischer PROC_LOCK_ASSERT(p, MA_OWNED); 11541279572aSDavid Xu p->p_flag &= ~P_STOPPED_SINGLE; 115544990b8cSJulian Elischer p->p_singlethread = NULL; 115649539972SJulian Elischer /* 115749539972SJulian Elischer * If there are other threads they mey now run, 115849539972SJulian Elischer * unless of course there is a blanket 'stop order' 115949539972SJulian Elischer * on the process. The single threader must be allowed 116049539972SJulian Elischer * to continue however as this is a bad place to stop. 116149539972SJulian Elischer */ 116249539972SJulian Elischer if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) { 116349539972SJulian Elischer mtx_lock_spin(&sched_lock); 116449539972SJulian Elischer while (( td = TAILQ_FIRST(&p->p_suspended))) { 116571fad9fdSJulian Elischer thread_unsuspend_one(td); 116644990b8cSJulian Elischer } 116749539972SJulian Elischer mtx_unlock_spin(&sched_lock); 116849539972SJulian Elischer } 116949539972SJulian Elischer } 117049539972SJulian Elischer 117144990b8cSJulian Elischer 1172