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