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*52611Smckusick * @(#)vm_glue.c 7.14 (Berkeley) 02/19/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 3745748Smckusick #include "param.h" 3845748Smckusick #include "systm.h" 3945748Smckusick #include "proc.h" 4048382Skarels #include "resourcevar.h" 4145748Smckusick #include "buf.h" 4248382Skarels #include "user.h" 4345748Smckusick 4448382Skarels #include "vm.h" 4548382Skarels #include "vm_page.h" 4648382Skarels #include "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 5245748Smckusick kernacc(addr, len, rw) 5345748Smckusick caddr_t addr; 5445748Smckusick int len, rw; 5545748Smckusick { 5645748Smckusick boolean_t rv; 5749295Shibler vm_offset_t saddr, eaddr; 5845748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 5945748Smckusick 6049295Shibler saddr = trunc_page(addr); 6149295Shibler eaddr = round_page(addr+len-1); 6249295Shibler rv = vm_map_check_protection(kernel_map, saddr, eaddr, prot); 6349295Shibler /* 6449295Shibler * XXX there are still some things (e.g. the buffer cache) that 6549295Shibler * are managed behind the VM system's back so even though an 6649295Shibler * address is accessible in the mind of the VM system, there may 6749295Shibler * not be physical pages where the VM thinks there is. This can 6849295Shibler * lead to bogus allocation of pages in the kernel address space 6949295Shibler * or worse, inconsistencies at the pmap level. We only worry 7049295Shibler * about the buffer cache for now. 7149295Shibler */ 7249743Smckusick if (!readbuffers && rv && (eaddr > (vm_offset_t)buffers && 7349667Shibler saddr < (vm_offset_t)buffers + MAXBSIZE * nbuf)) 7449295Shibler rv = FALSE; 7545748Smckusick return(rv == TRUE); 7645748Smckusick } 7745748Smckusick 7845748Smckusick useracc(addr, len, rw) 7945748Smckusick caddr_t addr; 8045748Smckusick int len, rw; 8145748Smckusick { 8245748Smckusick boolean_t rv; 8345748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 8445748Smckusick 8548382Skarels rv = vm_map_check_protection(&curproc->p_vmspace->vm_map, 8648382Skarels trunc_page(addr), round_page(addr+len-1), prot); 8745748Smckusick return(rv == TRUE); 8845748Smckusick } 8945748Smckusick 9045748Smckusick #ifdef KGDB 9145748Smckusick /* 9248947Skarels * Change protections on kernel pages from addr to addr+len 9345748Smckusick * (presumably so debugger can plant a breakpoint). 9445748Smckusick * All addresses are assumed to reside in the Sysmap, 9545748Smckusick */ 9645748Smckusick chgkprot(addr, len, rw) 9745748Smckusick register caddr_t addr; 9845748Smckusick int len, rw; 9945748Smckusick { 10045748Smckusick vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; 10145748Smckusick 10245748Smckusick vm_map_protect(kernel_map, trunc_page(addr), 10345748Smckusick round_page(addr+len-1), prot, FALSE); 10445748Smckusick } 10545748Smckusick #endif 10645748Smckusick 10745748Smckusick vslock(addr, len) 10845748Smckusick caddr_t addr; 10945748Smckusick u_int len; 11045748Smckusick { 11148382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 11245748Smckusick round_page(addr+len-1), FALSE); 11345748Smckusick } 11445748Smckusick 11545748Smckusick vsunlock(addr, len, dirtied) 11645748Smckusick caddr_t addr; 11745748Smckusick u_int len; 11845748Smckusick int dirtied; 11945748Smckusick { 12045748Smckusick #ifdef lint 12145748Smckusick dirtied++; 12245748Smckusick #endif lint 12348382Skarels vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr), 12445748Smckusick round_page(addr+len-1), TRUE); 12545748Smckusick } 12645748Smckusick 12748947Skarels /* 12848947Skarels * Implement fork's actions on an address space. 12948947Skarels * Here we arrange for the address space to be copied or referenced, 13048947Skarels * allocate a user struct (pcb and kernel stack), then call the 13148947Skarels * machine-dependent layer to fill those in and make the new process 13248947Skarels * ready to run. 13348947Skarels * NOTE: the kernel stack may be at a different location in the child 13448947Skarels * process, and thus addresses of automatic variables may be invalid 13548947Skarels * after cpu_fork returns in the child process. We do nothing here 13648947Skarels * after cpu_fork returns. 13748947Skarels */ 13848382Skarels vm_fork(p1, p2, isvfork) 13948382Skarels register struct proc *p1, *p2; 14045748Smckusick int isvfork; 14145748Smckusick { 14245748Smckusick register struct user *up; 14345748Smckusick vm_offset_t addr; 14445748Smckusick 14549702Swilliam #ifdef i386 14649702Swilliam /* 14749702Swilliam * avoid copying any of the parent's pagetables or other per-process 14849702Swilliam * objects that reside in the map by marking all of them non-inheritable 14949702Swilliam */ 15049702Swilliam (void)vm_map_inherit(&p1->p_vmspace->vm_map, 15149702Swilliam UPT_MIN_ADDRESS-UPAGES*NBPG, VM_MAX_ADDRESS, VM_INHERIT_NONE); 15249702Swilliam #endif 15348382Skarels p2->p_vmspace = vmspace_fork(p1->p_vmspace); 15448382Skarels 15548382Skarels #ifdef SYSVSHM 15648382Skarels if (p1->p_vmspace->vm_shm) 15748382Skarels shmfork(p1, p2, isvfork); 15845748Smckusick #endif 15948382Skarels 16050852Swilliam #ifndef i386 16145748Smckusick /* 16248947Skarels * Allocate a wired-down (for now) pcb and kernel stack for the process 16345748Smckusick */ 16448947Skarels addr = kmem_alloc_pageable(kernel_map, ctob(UPAGES)); 16548947Skarels vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE); 16650852Swilliam #else 16750852Swilliam /* XXX somehow, on 386, ocassionally pageout removes active, wired down kstack, 16850852Swilliam and pagetables, WITHOUT going thru vm_page_unwire! Why this appears to work is 16950852Swilliam not yet clear, yet it does... */ 17050852Swilliam addr = kmem_alloc(kernel_map, ctob(UPAGES)); 17150852Swilliam #endif 17245748Smckusick up = (struct user *)addr; 17348947Skarels p2->p_addr = up; 17445748Smckusick 17545748Smckusick /* 17648382Skarels * p_stats and p_sigacts currently point at fields 17748382Skarels * in the user struct but not at &u, instead at p_addr. 17848947Skarels * Copy p_sigacts and parts of p_stats; zero the rest 17948947Skarels * of p_stats (statistics). 18048382Skarels */ 18148947Skarels p2->p_stats = &up->u_stats; 18248947Skarels p2->p_sigacts = &up->u_sigacts; 18348947Skarels up->u_sigacts = *p1->p_sigacts; 18448947Skarels bzero(&up->u_stats.pstat_startzero, 18548947Skarels (unsigned) ((caddr_t)&up->u_stats.pstat_endzero - 18648947Skarels (caddr_t)&up->u_stats.pstat_startzero)); 18748947Skarels bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.pstat_startcopy, 18848947Skarels ((caddr_t)&up->u_stats.pstat_endcopy - 18948947Skarels (caddr_t)&up->u_stats.pstat_startcopy)); 19045748Smckusick 19149295Shibler #ifdef i386 19249295Shibler { u_int addr = UPT_MIN_ADDRESS - UPAGES*NBPG; struct vm_map *vp; 19349295Shibler 19449295Shibler vp = &p2->p_vmspace->vm_map; 19550852Swilliam (void)vm_deallocate(vp, addr, UPT_MAX_ADDRESS - addr); 19649295Shibler (void)vm_allocate(vp, &addr, UPT_MAX_ADDRESS - addr, FALSE); 19749295Shibler (void)vm_map_inherit(vp, addr, UPT_MAX_ADDRESS, VM_INHERIT_NONE); 19849295Shibler } 19949295Shibler #endif 20045748Smckusick /* 20148947Skarels * cpu_fork will copy and update the kernel stack and pcb, 20248947Skarels * and make the child ready to run. It marks the child 20348947Skarels * so that it can return differently than the parent. 20448947Skarels * It returns twice, once in the parent process and 20548947Skarels * once in the child. 20648382Skarels */ 20748947Skarels return (cpu_fork(p1, p2)); 20845748Smckusick } 20945748Smckusick 21045748Smckusick /* 21148382Skarels * Set default limits for VM system. 21248382Skarels * Called for proc 0, and then inherited by all others. 21345748Smckusick */ 21448382Skarels vm_init_limits(p) 21548382Skarels register struct proc *p; 21645748Smckusick { 21748382Skarels 21845748Smckusick /* 21945748Smckusick * Set up the initial limits on process VM. 22045748Smckusick * Set the maximum resident set size to be all 22145748Smckusick * of (reasonably) available memory. This causes 22245748Smckusick * any single, large process to start random page 22345748Smckusick * replacement once it fills memory. 22445748Smckusick */ 22548382Skarels p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ; 22648382Skarels p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ; 22748382Skarels p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ; 22848382Skarels p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ; 22948382Skarels p->p_rlimit[RLIMIT_RSS].rlim_cur = p->p_rlimit[RLIMIT_RSS].rlim_max = 23050915Smckusick ptoa(cnt.v_free_count); 23145748Smckusick } 23245748Smckusick 23345748Smckusick #include "../vm/vm_pageout.h" 23445748Smckusick 23545748Smckusick #ifdef DEBUG 23645748Smckusick int enableswap = 1; 23745748Smckusick int swapdebug = 0; 23845748Smckusick #define SDB_FOLLOW 1 23945748Smckusick #define SDB_SWAPIN 2 24045748Smckusick #define SDB_SWAPOUT 4 24145748Smckusick #endif 24245748Smckusick 24345748Smckusick /* 24445748Smckusick * Brutally simple: 24545748Smckusick * 1. Attempt to swapin every swaped-out, runnable process in 24645748Smckusick * order of priority. 24745748Smckusick * 2. If not enough memory, wake the pageout daemon and let it 24845748Smckusick * clear some space. 24945748Smckusick */ 25045748Smckusick sched() 25145748Smckusick { 25248382Skarels register struct proc *p; 25348382Skarels register int pri; 25448382Skarels struct proc *pp; 25548382Skarels int ppri; 25645748Smckusick vm_offset_t addr; 25745748Smckusick vm_size_t size; 25845748Smckusick 25945748Smckusick loop: 26045748Smckusick #ifdef DEBUG 26152600Storek while (!enableswap) 26252600Storek sleep((caddr_t)&proc0, PVM); 26345748Smckusick #endif 26448382Skarels pp = NULL; 26548382Skarels ppri = INT_MIN; 26652600Storek for (p = allproc; p != NULL; p = p->p_nxt) { 26748382Skarels if (p->p_stat == SRUN && (p->p_flag & SLOAD) == 0) { 26848382Skarels pri = p->p_time + p->p_slptime - p->p_nice * 8; 26948382Skarels if (pri > ppri) { 27048382Skarels pp = p; 27148382Skarels ppri = pri; 27245748Smckusick } 27345748Smckusick } 27452600Storek } 27545748Smckusick #ifdef DEBUG 27645748Smckusick if (swapdebug & SDB_FOLLOW) 27748382Skarels printf("sched: running, procp %x pri %d\n", pp, ppri); 27845748Smckusick #endif 27945748Smckusick /* 28045748Smckusick * Nothing to do, back to sleep 28145748Smckusick */ 28248382Skarels if ((p = pp) == NULL) { 28348382Skarels sleep((caddr_t)&proc0, PVM); 28445748Smckusick goto loop; 28545748Smckusick } 28648382Skarels 28745748Smckusick /* 28845748Smckusick * We would like to bring someone in. 28945748Smckusick * This part is really bogus cuz we could deadlock on memory 29045748Smckusick * despite our feeble check. 29145748Smckusick */ 29245748Smckusick size = round_page(ctob(UPAGES)); 29348382Skarels addr = (vm_offset_t) p->p_addr; 29450915Smckusick if (cnt.v_free_count > atop(size)) { 29545748Smckusick #ifdef DEBUG 29645748Smckusick if (swapdebug & SDB_SWAPIN) 29745748Smckusick printf("swapin: pid %d(%s)@%x, pri %d free %d\n", 29848382Skarels p->p_pid, p->p_comm, p->p_addr, 29950915Smckusick ppri, cnt.v_free_count); 30045748Smckusick #endif 30145748Smckusick vm_map_pageable(kernel_map, addr, addr+size, FALSE); 30245748Smckusick (void) splclock(); 30348382Skarels if (p->p_stat == SRUN) 30448382Skarels setrq(p); 30548382Skarels p->p_flag |= SLOAD; 30645748Smckusick (void) spl0(); 30748382Skarels p->p_time = 0; 30845748Smckusick goto loop; 30945748Smckusick } 31045748Smckusick /* 31145748Smckusick * Not enough memory, jab the pageout daemon and wait til the 31245748Smckusick * coast is clear. 31345748Smckusick */ 31445748Smckusick #ifdef DEBUG 31545748Smckusick if (swapdebug & SDB_FOLLOW) 31645748Smckusick printf("sched: no room for pid %d(%s), free %d\n", 31750915Smckusick p->p_pid, p->p_comm, cnt.v_free_count); 31845748Smckusick #endif 31945748Smckusick (void) splhigh(); 32045748Smckusick VM_WAIT; 32145748Smckusick (void) spl0(); 32245748Smckusick #ifdef DEBUG 32345748Smckusick if (swapdebug & SDB_FOLLOW) 32450915Smckusick printf("sched: room again, free %d\n", cnt.v_free_count); 32545748Smckusick #endif 32645748Smckusick goto loop; 32745748Smckusick } 32845748Smckusick 32945748Smckusick #define swappable(p) \ 33048382Skarels (((p)->p_flag & (SSYS|SLOAD|SKEEP|SWEXIT|SPHYSIO)) == SLOAD) 33145748Smckusick 33245748Smckusick /* 33345748Smckusick * Swapout is driven by the pageout daemon. Very simple, we find eligible 33445748Smckusick * procs and unwire their u-areas. We try to always "swap" at least one 33545748Smckusick * process in case we need the room for a swapin. 33648382Skarels * If any procs have been sleeping/stopped for at least maxslp seconds, 33748382Skarels * they are swapped. Else, we swap the longest-sleeping or stopped process, 33848382Skarels * if any, otherwise the longest-resident process. 33945748Smckusick */ 34045748Smckusick swapout_threads() 34145748Smckusick { 34248382Skarels register struct proc *p; 34345748Smckusick struct proc *outp, *outp2; 34445748Smckusick int outpri, outpri2; 34545748Smckusick int didswap = 0; 34645748Smckusick extern int maxslp; 34745748Smckusick 34845748Smckusick #ifdef DEBUG 34945748Smckusick if (!enableswap) 35045748Smckusick return; 35145748Smckusick #endif 35245748Smckusick outp = outp2 = NULL; 35348382Skarels outpri = outpri2 = 0; 35448382Skarels for (p = allproc; p != NULL; p = p->p_nxt) { 35548382Skarels if (!swappable(p)) 35645748Smckusick continue; 35748382Skarels switch (p->p_stat) { 35845748Smckusick case SRUN: 35948382Skarels if (p->p_time > outpri2) { 36048382Skarels outp2 = p; 36148382Skarels outpri2 = p->p_time; 36245748Smckusick } 36345748Smckusick continue; 36445748Smckusick 36545748Smckusick case SSLEEP: 36645748Smckusick case SSTOP: 36748382Skarels if (p->p_slptime > maxslp) { 36848382Skarels swapout(p); 36945748Smckusick didswap++; 37048382Skarels } else if (p->p_slptime > outpri) { 37148382Skarels outp = p; 37248382Skarels outpri = p->p_slptime; 37345748Smckusick } 37445748Smckusick continue; 37545748Smckusick } 37645748Smckusick } 37745748Smckusick /* 37845748Smckusick * If we didn't get rid of any real duds, toss out the next most 37945748Smckusick * likely sleeping/stopped or running candidate. We only do this 38045748Smckusick * if we are real low on memory since we don't gain much by doing 38145748Smckusick * it (UPAGES pages). 38245748Smckusick */ 38345748Smckusick if (didswap == 0 && 38450915Smckusick cnt.v_free_count <= atop(round_page(ctob(UPAGES)))) { 38548382Skarels if ((p = outp) == 0) 38648382Skarels p = outp2; 38745748Smckusick #ifdef DEBUG 38845748Smckusick if (swapdebug & SDB_SWAPOUT) 38948382Skarels printf("swapout_threads: no duds, try procp %x\n", p); 39045748Smckusick #endif 39148382Skarels if (p) 39248382Skarels swapout(p); 39345748Smckusick } 39445748Smckusick } 39545748Smckusick 39645748Smckusick swapout(p) 39745748Smckusick register struct proc *p; 39845748Smckusick { 39945748Smckusick vm_offset_t addr; 40045748Smckusick vm_size_t size; 40145748Smckusick 40245748Smckusick #ifdef DEBUG 40345748Smckusick if (swapdebug & SDB_SWAPOUT) 40445748Smckusick printf("swapout: pid %d(%s)@%x, stat %x pri %d free %d\n", 40545748Smckusick p->p_pid, p->p_comm, p->p_addr, p->p_stat, 40650915Smckusick p->p_slptime, cnt.v_free_count); 40745748Smckusick #endif 40845748Smckusick size = round_page(ctob(UPAGES)); 40945748Smckusick addr = (vm_offset_t) p->p_addr; 41049295Shibler #ifdef hp300 41149295Shibler /* 41249295Shibler * Ugh! u-area is double mapped to a fixed address behind the 41349295Shibler * back of the VM system and accesses are usually through that 41449295Shibler * address rather than the per-process address. Hence reference 41549295Shibler * and modify information are recorded at the fixed address and 41649295Shibler * lost at context switch time. We assume the u-struct and 41749295Shibler * kernel stack are always accessed/modified and force it to be so. 41849295Shibler */ 41949295Shibler { 42049295Shibler register int i; 42149295Shibler volatile long tmp; 42249295Shibler 42349295Shibler for (i = 0; i < UPAGES; i++) { 42449295Shibler tmp = *(long *)addr; *(long *)addr = tmp; 42549295Shibler addr += NBPG; 42649295Shibler } 42749295Shibler addr = (vm_offset_t) p->p_addr; 42849295Shibler } 42949295Shibler #endif 43051774Smarc #ifdef mips 43151774Smarc /* 43251774Smarc * Be sure to save the floating point coprocessor state before 43351774Smarc * paging out the u-struct. 43451774Smarc */ 43551774Smarc { 43651774Smarc extern struct proc *machFPCurProcPtr; 43751774Smarc 43851774Smarc if (p == machFPCurProcPtr) { 43951774Smarc MachSaveCurFPState(p); 44051774Smarc machFPCurProcPtr = (struct proc *)0; 44151774Smarc } 44251774Smarc } 44351774Smarc #endif 44450852Swilliam #ifndef i386 /* temporary measure till we find spontaineous unwire of kstack */ 44545748Smckusick vm_map_pageable(kernel_map, addr, addr+size, TRUE); 44648382Skarels pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); 44750852Swilliam #endif 44845748Smckusick (void) splhigh(); 44945748Smckusick p->p_flag &= ~SLOAD; 45045748Smckusick if (p->p_stat == SRUN) 45145748Smckusick remrq(p); 45245748Smckusick (void) spl0(); 45345748Smckusick p->p_time = 0; 45445748Smckusick } 45545748Smckusick 45645748Smckusick /* 45745748Smckusick * The rest of these routines fake thread handling 45845748Smckusick */ 45945748Smckusick 46045748Smckusick void 46145748Smckusick assert_wait(event, ruptible) 46245748Smckusick int event; 46345748Smckusick boolean_t ruptible; 46445748Smckusick { 46545748Smckusick #ifdef lint 46645748Smckusick ruptible++; 46745748Smckusick #endif 46848382Skarels curproc->p_thread = event; 46945748Smckusick } 47045748Smckusick 47145748Smckusick void 47245748Smckusick thread_block() 47345748Smckusick { 47445748Smckusick int s = splhigh(); 47545748Smckusick 47648382Skarels if (curproc->p_thread) 47748382Skarels sleep((caddr_t)curproc->p_thread, PVM); 47845748Smckusick splx(s); 47945748Smckusick } 48045748Smckusick 481*52611Smckusick void 48245748Smckusick thread_sleep(event, lock, ruptible) 48345748Smckusick int event; 48445748Smckusick simple_lock_t lock; 48545748Smckusick boolean_t ruptible; 48645748Smckusick { 48745748Smckusick #ifdef lint 48845748Smckusick ruptible++; 48945748Smckusick #endif 49045748Smckusick int s = splhigh(); 49145748Smckusick 49248382Skarels curproc->p_thread = event; 49345748Smckusick simple_unlock(lock); 49448382Skarels if (curproc->p_thread) 49548382Skarels sleep((caddr_t)event, PVM); 49645748Smckusick splx(s); 49745748Smckusick } 49845748Smckusick 499*52611Smckusick void 50045748Smckusick thread_wakeup(event) 50145748Smckusick int event; 50245748Smckusick { 50345748Smckusick int s = splhigh(); 50445748Smckusick 50545748Smckusick wakeup((caddr_t)event); 50645748Smckusick splx(s); 50745748Smckusick } 50845748Smckusick 50945748Smckusick /* 51045748Smckusick * DEBUG stuff 51145748Smckusick */ 51245748Smckusick 51345748Smckusick int indent = 0; 51445748Smckusick 51552600Storek #include <machine/stdarg.h> /* see subr_prf.c */ 51652600Storek 51745748Smckusick /*ARGSUSED2*/ 51852600Storek #if __STDC__ 51952600Storek iprintf(const char *fmt, ...) 52052600Storek #else 52152600Storek iprintf(fmt /* , va_alist */) 52252600Storek char *fmt; 52352600Storek /* va_dcl */ 52452600Storek #endif 52545748Smckusick { 52645748Smckusick register int i; 52752600Storek va_list ap; 52845748Smckusick 52952600Storek for (i = indent; i >= 8; i -= 8) 53049295Shibler printf("\t"); 53152600Storek while (--i >= 0) 53249295Shibler printf(" "); 53352600Storek va_start(ap, fmt); 53452600Storek printf("%r", fmt, ap); 53552600Storek va_end(ap); 53645748Smckusick } 537