145748Smckusick /* 245748Smckusick * Copyright (c) 1991 Regents of the University of California. 345748Smckusick * All rights reserved. 445748Smckusick * 545748Smckusick * This code is derived from software contributed to Berkeley by 645748Smckusick * The Mach Operating System project at Carnegie-Mellon University. 745748Smckusick * 848493Smckusick * %sccs.include.redist.c% 945748Smckusick * 10*57302Shibler * @(#)vm_glue.c 7.19 (Berkeley) 12/27/92 1148493Smckusick * 1248493Smckusick * 1348493Smckusick * Copyright (c) 1987, 1990 Carnegie-Mellon University. 1448493Smckusick * All rights reserved. 1548493Smckusick * 1648493Smckusick * Permission to use, copy, modify and distribute this software and 1748493Smckusick * its documentation is hereby granted, provided that both the copyright 1848493Smckusick * notice and this permission notice appear in all copies of the 1948493Smckusick * software, derivative works or modified versions, and any portions 2048493Smckusick * thereof, and that both notices appear in supporting documentation. 2148493Smckusick * 2248493Smckusick * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 2348493Smckusick * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 2448493Smckusick * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2548493Smckusick * 2648493Smckusick * Carnegie Mellon requests users of this software to return to 2748493Smckusick * 2848493Smckusick * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 2948493Smckusick * School of Computer Science 3048493Smckusick * Carnegie Mellon University 3148493Smckusick * Pittsburgh PA 15213-3890 3248493Smckusick * 3348493Smckusick * any improvements or extensions that they make and grant Carnegie the 3448493Smckusick * rights to redistribute these changes. 3545748Smckusick */ 3645748Smckusick 3753355Sbostic #include <sys/param.h> 3853355Sbostic #include <sys/systm.h> 3953355Sbostic #include <sys/proc.h> 4053355Sbostic #include <sys/resourcevar.h> 4153355Sbostic #include <sys/buf.h> 4253355Sbostic #include <sys/user.h> 4345748Smckusick 4453355Sbostic #include <vm/vm.h> 4553355Sbostic #include <vm/vm_page.h> 4653355Sbostic #include <vm/vm_kern.h> 4745748Smckusick 4845748Smckusick int avefree = 0; /* XXX */ 4945748Smckusick unsigned maxdmap = MAXDSIZ; /* XXX */ 5049743Smckusick int readbuffers = 0; /* XXX allow kgdb to read kernel buffer pool */ 5145748Smckusick 5253355Sbostic int 5345748Smckusick kernacc(addr, len, rw) 5445748Smckusick caddr_t addr; 5545748Smckusick int len, rw; 5645748Smckusick { 5745748Smckusick boolean_t rv; 5849295Shibler vm_offset_t saddr, eaddr; 5945748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 6045748Smckusick 6149295Shibler saddr = trunc_page(addr); 6249295Shibler eaddr = round_page(addr+len-1); 6349295Shibler rv = vm_map_check_protection(kernel_map, saddr, eaddr, prot); 6449295Shibler /* 6549295Shibler * XXX there are still some things (e.g. the buffer cache) that 6649295Shibler * are managed behind the VM system's back so even though an 6749295Shibler * address is accessible in the mind of the VM system, there may 6849295Shibler * not be physical pages where the VM thinks there is. This can 6949295Shibler * lead to bogus allocation of pages in the kernel address space 7049295Shibler * or worse, inconsistencies at the pmap level. We only worry 7149295Shibler * about the buffer cache for now. 7249295Shibler */ 7349743Smckusick if (!readbuffers && rv && (eaddr > (vm_offset_t)buffers && 7449667Shibler saddr < (vm_offset_t)buffers + MAXBSIZE * nbuf)) 7549295Shibler rv = FALSE; 7645748Smckusick return(rv == TRUE); 7745748Smckusick } 7845748Smckusick 7953355Sbostic int 8045748Smckusick useracc(addr, len, rw) 8145748Smckusick caddr_t addr; 8245748Smckusick int len, rw; 8345748Smckusick { 8445748Smckusick boolean_t rv; 8545748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 8645748Smckusick 8748382Skarels rv = vm_map_check_protection(&curproc->p_vmspace->vm_map, 8848382Skarels trunc_page(addr), round_page(addr+len-1), prot); 8945748Smckusick return(rv == TRUE); 9045748Smckusick } 9145748Smckusick 9245748Smckusick #ifdef KGDB 9345748Smckusick /* 9448947Skarels * Change protections on kernel pages from addr to addr+len 9545748Smckusick * (presumably so debugger can plant a breakpoint). 96*57302Shibler * 97*57302Shibler * We force the protection change at the pmap level. If we were 98*57302Shibler * to use vm_map_protect a change to allow writing would be lazily- 99*57302Shibler * applied meaning we would still take a protection fault, something 100*57302Shibler * we really don't want to do. It would also fragment the kernel 101*57302Shibler * map unnecessarily. We cannot use pmap_protect since it also won't 102*57302Shibler * enforce a write-enable request. Using pmap_enter is the only way 103*57302Shibler * we can ensure the change takes place properly. 10445748Smckusick */ 10553355Sbostic void 10645748Smckusick chgkprot(addr, len, rw) 10745748Smckusick register caddr_t addr; 10845748Smckusick int len, rw; 10945748Smckusick { 110*57302Shibler vm_prot_t prot; 111*57302Shibler vm_offset_t pa, sva, eva; 11245748Smckusick 113*57302Shibler prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE; 114*57302Shibler eva = round_page(addr + len - 1); 115*57302Shibler for (sva = trunc_page(addr); sva < eva; sva += PAGE_SIZE) { 116*57302Shibler /* 117*57302Shibler * Extract physical address for the page. 118*57302Shibler * We use a cheezy hack to differentiate physical 119*57302Shibler * page 0 from an invalid mapping, not that it 120*57302Shibler * really matters... 121*57302Shibler */ 122*57302Shibler pa = pmap_extract(kernel_pmap, sva|1); 123*57302Shibler if (pa == 0) 124*57302Shibler panic("chgkprot: invalid page"); 125*57302Shibler pmap_enter(kernel_pmap, sva, pva&~1, prot, TRUE); 126*57302Shibler } 12745748Smckusick } 12845748Smckusick #endif 12945748Smckusick 13053355Sbostic void 13145748Smckusick vslock(addr, len) 13245748Smckusick caddr_t addr; 13345748Smckusick u_int len; 13445748Smckusick { 13548382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 13645748Smckusick round_page(addr+len-1), FALSE); 13745748Smckusick } 13845748Smckusick 13953355Sbostic void 14045748Smckusick vsunlock(addr, len, dirtied) 14145748Smckusick caddr_t addr; 14245748Smckusick u_int len; 14345748Smckusick int dirtied; 14445748Smckusick { 14545748Smckusick #ifdef lint 14645748Smckusick dirtied++; 14745748Smckusick #endif lint 14848382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 14945748Smckusick round_page(addr+len-1), TRUE); 15045748Smckusick } 15145748Smckusick 15248947Skarels /* 15348947Skarels * Implement fork's actions on an address space. 15448947Skarels * Here we arrange for the address space to be copied or referenced, 15548947Skarels * allocate a user struct (pcb and kernel stack), then call the 15648947Skarels * machine-dependent layer to fill those in and make the new process 15748947Skarels * ready to run. 15848947Skarels * NOTE: the kernel stack may be at a different location in the child 15948947Skarels * process, and thus addresses of automatic variables may be invalid 16048947Skarels * after cpu_fork returns in the child process. We do nothing here 16148947Skarels * after cpu_fork returns. 16248947Skarels */ 16353355Sbostic int 16448382Skarels vm_fork(p1, p2, isvfork) 16548382Skarels register struct proc *p1, *p2; 16645748Smckusick int isvfork; 16745748Smckusick { 16845748Smckusick register struct user *up; 16945748Smckusick vm_offset_t addr; 17045748Smckusick 17149702Swilliam #ifdef i386 17249702Swilliam /* 17349702Swilliam * avoid copying any of the parent's pagetables or other per-process 17449702Swilliam * objects that reside in the map by marking all of them non-inheritable 17549702Swilliam */ 17649702Swilliam (void)vm_map_inherit(&p1->p_vmspace->vm_map, 17749702Swilliam UPT_MIN_ADDRESS-UPAGES*NBPG, VM_MAX_ADDRESS, VM_INHERIT_NONE); 17849702Swilliam #endif 17948382Skarels p2->p_vmspace = vmspace_fork(p1->p_vmspace); 18048382Skarels 18148382Skarels #ifdef SYSVSHM 18248382Skarels if (p1->p_vmspace->vm_shm) 18348382Skarels shmfork(p1, p2, isvfork); 18445748Smckusick #endif 18548382Skarels 18650852Swilliam #ifndef i386 18745748Smckusick /* 18848947Skarels * Allocate a wired-down (for now) pcb and kernel stack for the process 18945748Smckusick */ 19048947Skarels addr = kmem_alloc_pageable(kernel_map, ctob(UPAGES)); 19148947Skarels vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE); 19250852Swilliam #else 19350852Swilliam /* XXX somehow, on 386, ocassionally pageout removes active, wired down kstack, 19450852Swilliam and pagetables, WITHOUT going thru vm_page_unwire! Why this appears to work is 19550852Swilliam not yet clear, yet it does... */ 19650852Swilliam addr = kmem_alloc(kernel_map, ctob(UPAGES)); 19750852Swilliam #endif 19845748Smckusick up = (struct user *)addr; 19948947Skarels p2->p_addr = up; 20045748Smckusick 20145748Smckusick /* 20248382Skarels * p_stats and p_sigacts currently point at fields 20348382Skarels * in the user struct but not at &u, instead at p_addr. 20448947Skarels * Copy p_sigacts and parts of p_stats; zero the rest 20548947Skarels * of p_stats (statistics). 20648382Skarels */ 20748947Skarels p2->p_stats = &up->u_stats; 20848947Skarels p2->p_sigacts = &up->u_sigacts; 20948947Skarels up->u_sigacts = *p1->p_sigacts; 21048947Skarels bzero(&up->u_stats.pstat_startzero, 21148947Skarels (unsigned) ((caddr_t)&up->u_stats.pstat_endzero - 21248947Skarels (caddr_t)&up->u_stats.pstat_startzero)); 21348947Skarels bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.pstat_startcopy, 21448947Skarels ((caddr_t)&up->u_stats.pstat_endcopy - 21548947Skarels (caddr_t)&up->u_stats.pstat_startcopy)); 21645748Smckusick 21749295Shibler #ifdef i386 21849295Shibler { u_int addr = UPT_MIN_ADDRESS - UPAGES*NBPG; struct vm_map *vp; 21949295Shibler 22049295Shibler vp = &p2->p_vmspace->vm_map; 22150852Swilliam (void)vm_deallocate(vp, addr, UPT_MAX_ADDRESS - addr); 22249295Shibler (void)vm_allocate(vp, &addr, UPT_MAX_ADDRESS - addr, FALSE); 22349295Shibler (void)vm_map_inherit(vp, addr, UPT_MAX_ADDRESS, VM_INHERIT_NONE); 22449295Shibler } 22549295Shibler #endif 22645748Smckusick /* 22748947Skarels * cpu_fork will copy and update the kernel stack and pcb, 22848947Skarels * and make the child ready to run. It marks the child 22948947Skarels * so that it can return differently than the parent. 23048947Skarels * It returns twice, once in the parent process and 23148947Skarels * once in the child. 23248382Skarels */ 23348947Skarels return (cpu_fork(p1, p2)); 23445748Smckusick } 23545748Smckusick 23645748Smckusick /* 23748382Skarels * Set default limits for VM system. 23848382Skarels * Called for proc 0, and then inherited by all others. 23945748Smckusick */ 24053355Sbostic void 24148382Skarels vm_init_limits(p) 24248382Skarels register struct proc *p; 24345748Smckusick { 24448382Skarels 24545748Smckusick /* 24645748Smckusick * Set up the initial limits on process VM. 24745748Smckusick * Set the maximum resident set size to be all 24845748Smckusick * of (reasonably) available memory. This causes 24945748Smckusick * any single, large process to start random page 25045748Smckusick * replacement once it fills memory. 25145748Smckusick */ 25248382Skarels p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ; 25348382Skarels p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ; 25448382Skarels p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ; 25548382Skarels p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ; 25648382Skarels p->p_rlimit[RLIMIT_RSS].rlim_cur = p->p_rlimit[RLIMIT_RSS].rlim_max = 25750915Smckusick ptoa(cnt.v_free_count); 25845748Smckusick } 25945748Smckusick 26056544Sbostic #include <vm/vm_pageout.h> 26145748Smckusick 26245748Smckusick #ifdef DEBUG 26345748Smckusick int enableswap = 1; 26445748Smckusick int swapdebug = 0; 26545748Smckusick #define SDB_FOLLOW 1 26645748Smckusick #define SDB_SWAPIN 2 26745748Smckusick #define SDB_SWAPOUT 4 26845748Smckusick #endif 26945748Smckusick 27045748Smckusick /* 27145748Smckusick * Brutally simple: 27245748Smckusick * 1. Attempt to swapin every swaped-out, runnable process in 27345748Smckusick * order of priority. 27445748Smckusick * 2. If not enough memory, wake the pageout daemon and let it 27545748Smckusick * clear some space. 27645748Smckusick */ 27753355Sbostic void 27845748Smckusick sched() 27945748Smckusick { 28048382Skarels register struct proc *p; 28148382Skarels register int pri; 28248382Skarels struct proc *pp; 28348382Skarels int ppri; 28445748Smckusick vm_offset_t addr; 28545748Smckusick vm_size_t size; 28645748Smckusick 28745748Smckusick loop: 28845748Smckusick #ifdef DEBUG 28952600Storek while (!enableswap) 29052600Storek sleep((caddr_t)&proc0, PVM); 29145748Smckusick #endif 29248382Skarels pp = NULL; 29348382Skarels ppri = INT_MIN; 29454792Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 29548382Skarels if (p->p_stat == SRUN && (p->p_flag & SLOAD) == 0) { 29648382Skarels pri = p->p_time + p->p_slptime - p->p_nice * 8; 29748382Skarels if (pri > ppri) { 29848382Skarels pp = p; 29948382Skarels ppri = pri; 30045748Smckusick } 30145748Smckusick } 30252600Storek } 30345748Smckusick #ifdef DEBUG 30445748Smckusick if (swapdebug & SDB_FOLLOW) 30548382Skarels printf("sched: running, procp %x pri %d\n", pp, ppri); 30645748Smckusick #endif 30745748Smckusick /* 30845748Smckusick * Nothing to do, back to sleep 30945748Smckusick */ 31048382Skarels if ((p = pp) == NULL) { 31148382Skarels sleep((caddr_t)&proc0, PVM); 31245748Smckusick goto loop; 31345748Smckusick } 31448382Skarels 31545748Smckusick /* 31645748Smckusick * We would like to bring someone in. 31745748Smckusick * This part is really bogus cuz we could deadlock on memory 31845748Smckusick * despite our feeble check. 31945748Smckusick */ 32045748Smckusick size = round_page(ctob(UPAGES)); 32148382Skarels addr = (vm_offset_t) p->p_addr; 32250915Smckusick if (cnt.v_free_count > atop(size)) { 32345748Smckusick #ifdef DEBUG 32445748Smckusick if (swapdebug & SDB_SWAPIN) 32545748Smckusick printf("swapin: pid %d(%s)@%x, pri %d free %d\n", 32648382Skarels p->p_pid, p->p_comm, p->p_addr, 32750915Smckusick ppri, cnt.v_free_count); 32845748Smckusick #endif 32945748Smckusick vm_map_pageable(kernel_map, addr, addr+size, FALSE); 33054792Storek (void) splstatclock(); 33148382Skarels if (p->p_stat == SRUN) 33248382Skarels setrq(p); 33348382Skarels p->p_flag |= SLOAD; 33445748Smckusick (void) spl0(); 33548382Skarels p->p_time = 0; 33645748Smckusick goto loop; 33745748Smckusick } 33845748Smckusick /* 33945748Smckusick * Not enough memory, jab the pageout daemon and wait til the 34045748Smckusick * coast is clear. 34145748Smckusick */ 34245748Smckusick #ifdef DEBUG 34345748Smckusick if (swapdebug & SDB_FOLLOW) 34445748Smckusick printf("sched: no room for pid %d(%s), free %d\n", 34550915Smckusick p->p_pid, p->p_comm, cnt.v_free_count); 34645748Smckusick #endif 34745748Smckusick (void) splhigh(); 34845748Smckusick VM_WAIT; 34945748Smckusick (void) spl0(); 35045748Smckusick #ifdef DEBUG 35145748Smckusick if (swapdebug & SDB_FOLLOW) 35250915Smckusick printf("sched: room again, free %d\n", cnt.v_free_count); 35345748Smckusick #endif 35445748Smckusick goto loop; 35545748Smckusick } 35645748Smckusick 35745748Smckusick #define swappable(p) \ 35848382Skarels (((p)->p_flag & (SSYS|SLOAD|SKEEP|SWEXIT|SPHYSIO)) == SLOAD) 35945748Smckusick 36045748Smckusick /* 36145748Smckusick * Swapout is driven by the pageout daemon. Very simple, we find eligible 36245748Smckusick * procs and unwire their u-areas. We try to always "swap" at least one 36345748Smckusick * process in case we need the room for a swapin. 36448382Skarels * If any procs have been sleeping/stopped for at least maxslp seconds, 36548382Skarels * they are swapped. Else, we swap the longest-sleeping or stopped process, 36648382Skarels * if any, otherwise the longest-resident process. 36745748Smckusick */ 36853355Sbostic void 36945748Smckusick swapout_threads() 37045748Smckusick { 37148382Skarels register struct proc *p; 37245748Smckusick struct proc *outp, *outp2; 37345748Smckusick int outpri, outpri2; 37445748Smckusick int didswap = 0; 37545748Smckusick extern int maxslp; 37645748Smckusick 37745748Smckusick #ifdef DEBUG 37845748Smckusick if (!enableswap) 37945748Smckusick return; 38045748Smckusick #endif 38145748Smckusick outp = outp2 = NULL; 38248382Skarels outpri = outpri2 = 0; 38354792Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 38448382Skarels if (!swappable(p)) 38545748Smckusick continue; 38648382Skarels switch (p->p_stat) { 38745748Smckusick case SRUN: 38848382Skarels if (p->p_time > outpri2) { 38948382Skarels outp2 = p; 39048382Skarels outpri2 = p->p_time; 39145748Smckusick } 39245748Smckusick continue; 39345748Smckusick 39445748Smckusick case SSLEEP: 39545748Smckusick case SSTOP: 39648382Skarels if (p->p_slptime > maxslp) { 39748382Skarels swapout(p); 39845748Smckusick didswap++; 39948382Skarels } else if (p->p_slptime > outpri) { 40048382Skarels outp = p; 40148382Skarels outpri = p->p_slptime; 40245748Smckusick } 40345748Smckusick continue; 40445748Smckusick } 40545748Smckusick } 40645748Smckusick /* 40745748Smckusick * If we didn't get rid of any real duds, toss out the next most 40845748Smckusick * likely sleeping/stopped or running candidate. We only do this 40945748Smckusick * if we are real low on memory since we don't gain much by doing 41045748Smckusick * it (UPAGES pages). 41145748Smckusick */ 41245748Smckusick if (didswap == 0 && 41350915Smckusick cnt.v_free_count <= atop(round_page(ctob(UPAGES)))) { 41448382Skarels if ((p = outp) == 0) 41548382Skarels p = outp2; 41645748Smckusick #ifdef DEBUG 41745748Smckusick if (swapdebug & SDB_SWAPOUT) 41848382Skarels printf("swapout_threads: no duds, try procp %x\n", p); 41945748Smckusick #endif 42048382Skarels if (p) 42148382Skarels swapout(p); 42245748Smckusick } 42345748Smckusick } 42445748Smckusick 42553355Sbostic void 42645748Smckusick swapout(p) 42745748Smckusick register struct proc *p; 42845748Smckusick { 42945748Smckusick vm_offset_t addr; 43045748Smckusick vm_size_t size; 43145748Smckusick 43245748Smckusick #ifdef DEBUG 43345748Smckusick if (swapdebug & SDB_SWAPOUT) 43445748Smckusick printf("swapout: pid %d(%s)@%x, stat %x pri %d free %d\n", 43545748Smckusick p->p_pid, p->p_comm, p->p_addr, p->p_stat, 43650915Smckusick p->p_slptime, cnt.v_free_count); 43745748Smckusick #endif 43845748Smckusick size = round_page(ctob(UPAGES)); 43945748Smckusick addr = (vm_offset_t) p->p_addr; 44053876Smckusick #if defined(hp300) || defined(luna68k) 44149295Shibler /* 44249295Shibler * Ugh! u-area is double mapped to a fixed address behind the 44349295Shibler * back of the VM system and accesses are usually through that 44449295Shibler * address rather than the per-process address. Hence reference 44549295Shibler * and modify information are recorded at the fixed address and 44649295Shibler * lost at context switch time. We assume the u-struct and 44749295Shibler * kernel stack are always accessed/modified and force it to be so. 44849295Shibler */ 44949295Shibler { 45049295Shibler register int i; 45149295Shibler volatile long tmp; 45249295Shibler 45349295Shibler for (i = 0; i < UPAGES; i++) { 45449295Shibler tmp = *(long *)addr; *(long *)addr = tmp; 45549295Shibler addr += NBPG; 45649295Shibler } 45749295Shibler addr = (vm_offset_t) p->p_addr; 45849295Shibler } 45949295Shibler #endif 46051774Smarc #ifdef mips 46151774Smarc /* 46251774Smarc * Be sure to save the floating point coprocessor state before 46351774Smarc * paging out the u-struct. 46451774Smarc */ 46551774Smarc { 46651774Smarc extern struct proc *machFPCurProcPtr; 46751774Smarc 46851774Smarc if (p == machFPCurProcPtr) { 46951774Smarc MachSaveCurFPState(p); 47051774Smarc machFPCurProcPtr = (struct proc *)0; 47151774Smarc } 47251774Smarc } 47351774Smarc #endif 47450852Swilliam #ifndef i386 /* temporary measure till we find spontaineous unwire of kstack */ 47545748Smckusick vm_map_pageable(kernel_map, addr, addr+size, TRUE); 47648382Skarels pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); 47750852Swilliam #endif 47845748Smckusick (void) splhigh(); 47945748Smckusick p->p_flag &= ~SLOAD; 48045748Smckusick if (p->p_stat == SRUN) 48145748Smckusick remrq(p); 48245748Smckusick (void) spl0(); 48345748Smckusick p->p_time = 0; 48445748Smckusick } 48545748Smckusick 48645748Smckusick /* 48745748Smckusick * The rest of these routines fake thread handling 48845748Smckusick */ 48945748Smckusick 49045748Smckusick void 49145748Smckusick assert_wait(event, ruptible) 49245748Smckusick int event; 49345748Smckusick boolean_t ruptible; 49445748Smckusick { 49545748Smckusick #ifdef lint 49645748Smckusick ruptible++; 49745748Smckusick #endif 49848382Skarels curproc->p_thread = event; 49945748Smckusick } 50045748Smckusick 50145748Smckusick void 50245748Smckusick thread_block() 50345748Smckusick { 50445748Smckusick int s = splhigh(); 50545748Smckusick 50648382Skarels if (curproc->p_thread) 50748382Skarels sleep((caddr_t)curproc->p_thread, PVM); 50845748Smckusick splx(s); 50945748Smckusick } 51045748Smckusick 51152611Smckusick void 51245748Smckusick thread_sleep(event, lock, ruptible) 51345748Smckusick int event; 51445748Smckusick simple_lock_t lock; 51545748Smckusick boolean_t ruptible; 51645748Smckusick { 51745748Smckusick #ifdef lint 51845748Smckusick ruptible++; 51945748Smckusick #endif 52045748Smckusick int s = splhigh(); 52145748Smckusick 52248382Skarels curproc->p_thread = event; 52345748Smckusick simple_unlock(lock); 52448382Skarels if (curproc->p_thread) 52548382Skarels sleep((caddr_t)event, PVM); 52645748Smckusick splx(s); 52745748Smckusick } 52845748Smckusick 52952611Smckusick void 53045748Smckusick thread_wakeup(event) 53145748Smckusick int event; 53245748Smckusick { 53345748Smckusick int s = splhigh(); 53445748Smckusick 53545748Smckusick wakeup((caddr_t)event); 53645748Smckusick splx(s); 53745748Smckusick } 53845748Smckusick 53945748Smckusick /* 54045748Smckusick * DEBUG stuff 54145748Smckusick */ 54245748Smckusick 54345748Smckusick int indent = 0; 54445748Smckusick 54552600Storek #include <machine/stdarg.h> /* see subr_prf.c */ 54652600Storek 54745748Smckusick /*ARGSUSED2*/ 54853355Sbostic void 54952600Storek #if __STDC__ 55052600Storek iprintf(const char *fmt, ...) 55152600Storek #else 55252600Storek iprintf(fmt /* , va_alist */) 55352600Storek char *fmt; 55452600Storek /* va_dcl */ 55552600Storek #endif 55645748Smckusick { 55745748Smckusick register int i; 55852600Storek va_list ap; 55945748Smckusick 56052600Storek for (i = indent; i >= 8; i -= 8) 56149295Shibler printf("\t"); 56252600Storek while (--i >= 0) 56349295Shibler printf(" "); 56452600Storek va_start(ap, fmt); 56552600Storek printf("%r", fmt, ap); 56652600Storek va_end(ap); 56745748Smckusick } 568