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*54792Storek * @(#)vm_glue.c 7.17 (Berkeley) 07/08/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). 9645748Smckusick * All addresses are assumed to reside in the Sysmap, 9745748Smckusick */ 9853355Sbostic void 9945748Smckusick chgkprot(addr, len, rw) 10045748Smckusick register caddr_t addr; 10145748Smckusick int len, rw; 10245748Smckusick { 10345748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 10445748Smckusick 10545748Smckusick vm_map_protect(kernel_map, trunc_page(addr), 10645748Smckusick round_page(addr+len-1), prot, FALSE); 10745748Smckusick } 10845748Smckusick #endif 10945748Smckusick 11053355Sbostic void 11145748Smckusick vslock(addr, len) 11245748Smckusick caddr_t addr; 11345748Smckusick u_int len; 11445748Smckusick { 11548382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 11645748Smckusick round_page(addr+len-1), FALSE); 11745748Smckusick } 11845748Smckusick 11953355Sbostic void 12045748Smckusick vsunlock(addr, len, dirtied) 12145748Smckusick caddr_t addr; 12245748Smckusick u_int len; 12345748Smckusick int dirtied; 12445748Smckusick { 12545748Smckusick #ifdef lint 12645748Smckusick dirtied++; 12745748Smckusick #endif lint 12848382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 12945748Smckusick round_page(addr+len-1), TRUE); 13045748Smckusick } 13145748Smckusick 13248947Skarels /* 13348947Skarels * Implement fork's actions on an address space. 13448947Skarels * Here we arrange for the address space to be copied or referenced, 13548947Skarels * allocate a user struct (pcb and kernel stack), then call the 13648947Skarels * machine-dependent layer to fill those in and make the new process 13748947Skarels * ready to run. 13848947Skarels * NOTE: the kernel stack may be at a different location in the child 13948947Skarels * process, and thus addresses of automatic variables may be invalid 14048947Skarels * after cpu_fork returns in the child process. We do nothing here 14148947Skarels * after cpu_fork returns. 14248947Skarels */ 14353355Sbostic int 14448382Skarels vm_fork(p1, p2, isvfork) 14548382Skarels register struct proc *p1, *p2; 14645748Smckusick int isvfork; 14745748Smckusick { 14845748Smckusick register struct user *up; 14945748Smckusick vm_offset_t addr; 15045748Smckusick 15149702Swilliam #ifdef i386 15249702Swilliam /* 15349702Swilliam * avoid copying any of the parent's pagetables or other per-process 15449702Swilliam * objects that reside in the map by marking all of them non-inheritable 15549702Swilliam */ 15649702Swilliam (void)vm_map_inherit(&p1->p_vmspace->vm_map, 15749702Swilliam UPT_MIN_ADDRESS-UPAGES*NBPG, VM_MAX_ADDRESS, VM_INHERIT_NONE); 15849702Swilliam #endif 15948382Skarels p2->p_vmspace = vmspace_fork(p1->p_vmspace); 16048382Skarels 16148382Skarels #ifdef SYSVSHM 16248382Skarels if (p1->p_vmspace->vm_shm) 16348382Skarels shmfork(p1, p2, isvfork); 16445748Smckusick #endif 16548382Skarels 16650852Swilliam #ifndef i386 16745748Smckusick /* 16848947Skarels * Allocate a wired-down (for now) pcb and kernel stack for the process 16945748Smckusick */ 17048947Skarels addr = kmem_alloc_pageable(kernel_map, ctob(UPAGES)); 17148947Skarels vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE); 17250852Swilliam #else 17350852Swilliam /* XXX somehow, on 386, ocassionally pageout removes active, wired down kstack, 17450852Swilliam and pagetables, WITHOUT going thru vm_page_unwire! Why this appears to work is 17550852Swilliam not yet clear, yet it does... */ 17650852Swilliam addr = kmem_alloc(kernel_map, ctob(UPAGES)); 17750852Swilliam #endif 17845748Smckusick up = (struct user *)addr; 17948947Skarels p2->p_addr = up; 18045748Smckusick 18145748Smckusick /* 18248382Skarels * p_stats and p_sigacts currently point at fields 18348382Skarels * in the user struct but not at &u, instead at p_addr. 18448947Skarels * Copy p_sigacts and parts of p_stats; zero the rest 18548947Skarels * of p_stats (statistics). 18648382Skarels */ 18748947Skarels p2->p_stats = &up->u_stats; 18848947Skarels p2->p_sigacts = &up->u_sigacts; 18948947Skarels up->u_sigacts = *p1->p_sigacts; 19048947Skarels bzero(&up->u_stats.pstat_startzero, 19148947Skarels (unsigned) ((caddr_t)&up->u_stats.pstat_endzero - 19248947Skarels (caddr_t)&up->u_stats.pstat_startzero)); 19348947Skarels bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.pstat_startcopy, 19448947Skarels ((caddr_t)&up->u_stats.pstat_endcopy - 19548947Skarels (caddr_t)&up->u_stats.pstat_startcopy)); 19645748Smckusick 19749295Shibler #ifdef i386 19849295Shibler { u_int addr = UPT_MIN_ADDRESS - UPAGES*NBPG; struct vm_map *vp; 19949295Shibler 20049295Shibler vp = &p2->p_vmspace->vm_map; 20150852Swilliam (void)vm_deallocate(vp, addr, UPT_MAX_ADDRESS - addr); 20249295Shibler (void)vm_allocate(vp, &addr, UPT_MAX_ADDRESS - addr, FALSE); 20349295Shibler (void)vm_map_inherit(vp, addr, UPT_MAX_ADDRESS, VM_INHERIT_NONE); 20449295Shibler } 20549295Shibler #endif 20645748Smckusick /* 20748947Skarels * cpu_fork will copy and update the kernel stack and pcb, 20848947Skarels * and make the child ready to run. It marks the child 20948947Skarels * so that it can return differently than the parent. 21048947Skarels * It returns twice, once in the parent process and 21148947Skarels * once in the child. 21248382Skarels */ 21348947Skarels return (cpu_fork(p1, p2)); 21445748Smckusick } 21545748Smckusick 21645748Smckusick /* 21748382Skarels * Set default limits for VM system. 21848382Skarels * Called for proc 0, and then inherited by all others. 21945748Smckusick */ 22053355Sbostic void 22148382Skarels vm_init_limits(p) 22248382Skarels register struct proc *p; 22345748Smckusick { 22448382Skarels 22545748Smckusick /* 22645748Smckusick * Set up the initial limits on process VM. 22745748Smckusick * Set the maximum resident set size to be all 22845748Smckusick * of (reasonably) available memory. This causes 22945748Smckusick * any single, large process to start random page 23045748Smckusick * replacement once it fills memory. 23145748Smckusick */ 23248382Skarels p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ; 23348382Skarels p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ; 23448382Skarels p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ; 23548382Skarels p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ; 23648382Skarels p->p_rlimit[RLIMIT_RSS].rlim_cur = p->p_rlimit[RLIMIT_RSS].rlim_max = 23750915Smckusick ptoa(cnt.v_free_count); 23845748Smckusick } 23945748Smckusick 24045748Smckusick #include "../vm/vm_pageout.h" 24145748Smckusick 24245748Smckusick #ifdef DEBUG 24345748Smckusick int enableswap = 1; 24445748Smckusick int swapdebug = 0; 24545748Smckusick #define SDB_FOLLOW 1 24645748Smckusick #define SDB_SWAPIN 2 24745748Smckusick #define SDB_SWAPOUT 4 24845748Smckusick #endif 24945748Smckusick 25045748Smckusick /* 25145748Smckusick * Brutally simple: 25245748Smckusick * 1. Attempt to swapin every swaped-out, runnable process in 25345748Smckusick * order of priority. 25445748Smckusick * 2. If not enough memory, wake the pageout daemon and let it 25545748Smckusick * clear some space. 25645748Smckusick */ 25753355Sbostic void 25845748Smckusick sched() 25945748Smckusick { 26048382Skarels register struct proc *p; 26148382Skarels register int pri; 26248382Skarels struct proc *pp; 26348382Skarels int ppri; 26445748Smckusick vm_offset_t addr; 26545748Smckusick vm_size_t size; 26645748Smckusick 26745748Smckusick loop: 26845748Smckusick #ifdef DEBUG 26952600Storek while (!enableswap) 27052600Storek sleep((caddr_t)&proc0, PVM); 27145748Smckusick #endif 27248382Skarels pp = NULL; 27348382Skarels ppri = INT_MIN; 274*54792Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 27548382Skarels if (p->p_stat == SRUN && (p->p_flag & SLOAD) == 0) { 27648382Skarels pri = p->p_time + p->p_slptime - p->p_nice * 8; 27748382Skarels if (pri > ppri) { 27848382Skarels pp = p; 27948382Skarels ppri = pri; 28045748Smckusick } 28145748Smckusick } 28252600Storek } 28345748Smckusick #ifdef DEBUG 28445748Smckusick if (swapdebug & SDB_FOLLOW) 28548382Skarels printf("sched: running, procp %x pri %d\n", pp, ppri); 28645748Smckusick #endif 28745748Smckusick /* 28845748Smckusick * Nothing to do, back to sleep 28945748Smckusick */ 29048382Skarels if ((p = pp) == NULL) { 29148382Skarels sleep((caddr_t)&proc0, PVM); 29245748Smckusick goto loop; 29345748Smckusick } 29448382Skarels 29545748Smckusick /* 29645748Smckusick * We would like to bring someone in. 29745748Smckusick * This part is really bogus cuz we could deadlock on memory 29845748Smckusick * despite our feeble check. 29945748Smckusick */ 30045748Smckusick size = round_page(ctob(UPAGES)); 30148382Skarels addr = (vm_offset_t) p->p_addr; 30250915Smckusick if (cnt.v_free_count > atop(size)) { 30345748Smckusick #ifdef DEBUG 30445748Smckusick if (swapdebug & SDB_SWAPIN) 30545748Smckusick printf("swapin: pid %d(%s)@%x, pri %d free %d\n", 30648382Skarels p->p_pid, p->p_comm, p->p_addr, 30750915Smckusick ppri, cnt.v_free_count); 30845748Smckusick #endif 30945748Smckusick vm_map_pageable(kernel_map, addr, addr+size, FALSE); 310*54792Storek (void) splstatclock(); 31148382Skarels if (p->p_stat == SRUN) 31248382Skarels setrq(p); 31348382Skarels p->p_flag |= SLOAD; 31445748Smckusick (void) spl0(); 31548382Skarels p->p_time = 0; 31645748Smckusick goto loop; 31745748Smckusick } 31845748Smckusick /* 31945748Smckusick * Not enough memory, jab the pageout daemon and wait til the 32045748Smckusick * coast is clear. 32145748Smckusick */ 32245748Smckusick #ifdef DEBUG 32345748Smckusick if (swapdebug & SDB_FOLLOW) 32445748Smckusick printf("sched: no room for pid %d(%s), free %d\n", 32550915Smckusick p->p_pid, p->p_comm, cnt.v_free_count); 32645748Smckusick #endif 32745748Smckusick (void) splhigh(); 32845748Smckusick VM_WAIT; 32945748Smckusick (void) spl0(); 33045748Smckusick #ifdef DEBUG 33145748Smckusick if (swapdebug & SDB_FOLLOW) 33250915Smckusick printf("sched: room again, free %d\n", cnt.v_free_count); 33345748Smckusick #endif 33445748Smckusick goto loop; 33545748Smckusick } 33645748Smckusick 33745748Smckusick #define swappable(p) \ 33848382Skarels (((p)->p_flag & (SSYS|SLOAD|SKEEP|SWEXIT|SPHYSIO)) == SLOAD) 33945748Smckusick 34045748Smckusick /* 34145748Smckusick * Swapout is driven by the pageout daemon. Very simple, we find eligible 34245748Smckusick * procs and unwire their u-areas. We try to always "swap" at least one 34345748Smckusick * process in case we need the room for a swapin. 34448382Skarels * If any procs have been sleeping/stopped for at least maxslp seconds, 34548382Skarels * they are swapped. Else, we swap the longest-sleeping or stopped process, 34648382Skarels * if any, otherwise the longest-resident process. 34745748Smckusick */ 34853355Sbostic void 34945748Smckusick swapout_threads() 35045748Smckusick { 35148382Skarels register struct proc *p; 35245748Smckusick struct proc *outp, *outp2; 35345748Smckusick int outpri, outpri2; 35445748Smckusick int didswap = 0; 35545748Smckusick extern int maxslp; 35645748Smckusick 35745748Smckusick #ifdef DEBUG 35845748Smckusick if (!enableswap) 35945748Smckusick return; 36045748Smckusick #endif 36145748Smckusick outp = outp2 = NULL; 36248382Skarels outpri = outpri2 = 0; 363*54792Storek for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 36448382Skarels if (!swappable(p)) 36545748Smckusick continue; 36648382Skarels switch (p->p_stat) { 36745748Smckusick case SRUN: 36848382Skarels if (p->p_time > outpri2) { 36948382Skarels outp2 = p; 37048382Skarels outpri2 = p->p_time; 37145748Smckusick } 37245748Smckusick continue; 37345748Smckusick 37445748Smckusick case SSLEEP: 37545748Smckusick case SSTOP: 37648382Skarels if (p->p_slptime > maxslp) { 37748382Skarels swapout(p); 37845748Smckusick didswap++; 37948382Skarels } else if (p->p_slptime > outpri) { 38048382Skarels outp = p; 38148382Skarels outpri = p->p_slptime; 38245748Smckusick } 38345748Smckusick continue; 38445748Smckusick } 38545748Smckusick } 38645748Smckusick /* 38745748Smckusick * If we didn't get rid of any real duds, toss out the next most 38845748Smckusick * likely sleeping/stopped or running candidate. We only do this 38945748Smckusick * if we are real low on memory since we don't gain much by doing 39045748Smckusick * it (UPAGES pages). 39145748Smckusick */ 39245748Smckusick if (didswap == 0 && 39350915Smckusick cnt.v_free_count <= atop(round_page(ctob(UPAGES)))) { 39448382Skarels if ((p = outp) == 0) 39548382Skarels p = outp2; 39645748Smckusick #ifdef DEBUG 39745748Smckusick if (swapdebug & SDB_SWAPOUT) 39848382Skarels printf("swapout_threads: no duds, try procp %x\n", p); 39945748Smckusick #endif 40048382Skarels if (p) 40148382Skarels swapout(p); 40245748Smckusick } 40345748Smckusick } 40445748Smckusick 40553355Sbostic void 40645748Smckusick swapout(p) 40745748Smckusick register struct proc *p; 40845748Smckusick { 40945748Smckusick vm_offset_t addr; 41045748Smckusick vm_size_t size; 41145748Smckusick 41245748Smckusick #ifdef DEBUG 41345748Smckusick if (swapdebug & SDB_SWAPOUT) 41445748Smckusick printf("swapout: pid %d(%s)@%x, stat %x pri %d free %d\n", 41545748Smckusick p->p_pid, p->p_comm, p->p_addr, p->p_stat, 41650915Smckusick p->p_slptime, cnt.v_free_count); 41745748Smckusick #endif 41845748Smckusick size = round_page(ctob(UPAGES)); 41945748Smckusick addr = (vm_offset_t) p->p_addr; 42053876Smckusick #if defined(hp300) || defined(luna68k) 42149295Shibler /* 42249295Shibler * Ugh! u-area is double mapped to a fixed address behind the 42349295Shibler * back of the VM system and accesses are usually through that 42449295Shibler * address rather than the per-process address. Hence reference 42549295Shibler * and modify information are recorded at the fixed address and 42649295Shibler * lost at context switch time. We assume the u-struct and 42749295Shibler * kernel stack are always accessed/modified and force it to be so. 42849295Shibler */ 42949295Shibler { 43049295Shibler register int i; 43149295Shibler volatile long tmp; 43249295Shibler 43349295Shibler for (i = 0; i < UPAGES; i++) { 43449295Shibler tmp = *(long *)addr; *(long *)addr = tmp; 43549295Shibler addr += NBPG; 43649295Shibler } 43749295Shibler addr = (vm_offset_t) p->p_addr; 43849295Shibler } 43949295Shibler #endif 44051774Smarc #ifdef mips 44151774Smarc /* 44251774Smarc * Be sure to save the floating point coprocessor state before 44351774Smarc * paging out the u-struct. 44451774Smarc */ 44551774Smarc { 44651774Smarc extern struct proc *machFPCurProcPtr; 44751774Smarc 44851774Smarc if (p == machFPCurProcPtr) { 44951774Smarc MachSaveCurFPState(p); 45051774Smarc machFPCurProcPtr = (struct proc *)0; 45151774Smarc } 45251774Smarc } 45351774Smarc #endif 45450852Swilliam #ifndef i386 /* temporary measure till we find spontaineous unwire of kstack */ 45545748Smckusick vm_map_pageable(kernel_map, addr, addr+size, TRUE); 45648382Skarels pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); 45750852Swilliam #endif 45845748Smckusick (void) splhigh(); 45945748Smckusick p->p_flag &= ~SLOAD; 46045748Smckusick if (p->p_stat == SRUN) 46145748Smckusick remrq(p); 46245748Smckusick (void) spl0(); 46345748Smckusick p->p_time = 0; 46445748Smckusick } 46545748Smckusick 46645748Smckusick /* 46745748Smckusick * The rest of these routines fake thread handling 46845748Smckusick */ 46945748Smckusick 47045748Smckusick void 47145748Smckusick assert_wait(event, ruptible) 47245748Smckusick int event; 47345748Smckusick boolean_t ruptible; 47445748Smckusick { 47545748Smckusick #ifdef lint 47645748Smckusick ruptible++; 47745748Smckusick #endif 47848382Skarels curproc->p_thread = event; 47945748Smckusick } 48045748Smckusick 48145748Smckusick void 48245748Smckusick thread_block() 48345748Smckusick { 48445748Smckusick int s = splhigh(); 48545748Smckusick 48648382Skarels if (curproc->p_thread) 48748382Skarels sleep((caddr_t)curproc->p_thread, PVM); 48845748Smckusick splx(s); 48945748Smckusick } 49045748Smckusick 49152611Smckusick void 49245748Smckusick thread_sleep(event, lock, ruptible) 49345748Smckusick int event; 49445748Smckusick simple_lock_t lock; 49545748Smckusick boolean_t ruptible; 49645748Smckusick { 49745748Smckusick #ifdef lint 49845748Smckusick ruptible++; 49945748Smckusick #endif 50045748Smckusick int s = splhigh(); 50145748Smckusick 50248382Skarels curproc->p_thread = event; 50345748Smckusick simple_unlock(lock); 50448382Skarels if (curproc->p_thread) 50548382Skarels sleep((caddr_t)event, PVM); 50645748Smckusick splx(s); 50745748Smckusick } 50845748Smckusick 50952611Smckusick void 51045748Smckusick thread_wakeup(event) 51145748Smckusick int event; 51245748Smckusick { 51345748Smckusick int s = splhigh(); 51445748Smckusick 51545748Smckusick wakeup((caddr_t)event); 51645748Smckusick splx(s); 51745748Smckusick } 51845748Smckusick 51945748Smckusick /* 52045748Smckusick * DEBUG stuff 52145748Smckusick */ 52245748Smckusick 52345748Smckusick int indent = 0; 52445748Smckusick 52552600Storek #include <machine/stdarg.h> /* see subr_prf.c */ 52652600Storek 52745748Smckusick /*ARGSUSED2*/ 52853355Sbostic void 52952600Storek #if __STDC__ 53052600Storek iprintf(const char *fmt, ...) 53152600Storek #else 53252600Storek iprintf(fmt /* , va_alist */) 53352600Storek char *fmt; 53452600Storek /* va_dcl */ 53552600Storek #endif 53645748Smckusick { 53745748Smckusick register int i; 53852600Storek va_list ap; 53945748Smckusick 54052600Storek for (i = indent; i >= 8; i -= 8) 54149295Shibler printf("\t"); 54252600Storek while (--i >= 0) 54349295Shibler printf(" "); 54452600Storek va_start(ap, fmt); 54552600Storek printf("%r", fmt, ap); 54652600Storek va_end(ap); 54745748Smckusick } 548