home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / vm / vm_glue.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-15  |  13.9 KB  |  534 lines

  1. /* 
  2.  * Copyright (c) 1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * The Mach Operating System project at Carnegie-Mellon University.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)vm_glue.c    7.8 (Berkeley) 5/15/91
  37.  *
  38.  *
  39.  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
  40.  * All rights reserved.
  41.  * 
  42.  * Permission to use, copy, modify and distribute this software and
  43.  * its documentation is hereby granted, provided that both the copyright
  44.  * notice and this permission notice appear in all copies of the
  45.  * software, derivative works or modified versions, and any portions
  46.  * thereof, and that both notices appear in supporting documentation.
  47.  * 
  48.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
  49.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
  50.  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  51.  * 
  52.  * Carnegie Mellon requests users of this software to return to
  53.  *
  54.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  55.  *  School of Computer Science
  56.  *  Carnegie Mellon University
  57.  *  Pittsburgh PA 15213-3890
  58.  *
  59.  * any improvements or extensions that they make and grant Carnegie the
  60.  * rights to redistribute these changes.
  61.  */
  62.  
  63. #include "param.h"
  64. #include "systm.h"
  65. #include "proc.h"
  66. #include "resourcevar.h"
  67. #include "buf.h"
  68. #include "user.h"
  69.  
  70. #include "vm.h"
  71. #include "vm_page.h"
  72. #include "vm_kern.h"
  73.  
  74. int    avefree = 0;        /* XXX */
  75. unsigned maxdmap = MAXDSIZ;    /* XXX */
  76. int    readbuffers = 0;    /* XXX allow kgdb to read kernel buffer pool */
  77.  
  78. kernacc(addr, len, rw)
  79.     caddr_t addr;
  80.     int len, rw;
  81. {
  82.     boolean_t rv;
  83.     vm_offset_t saddr, eaddr;
  84.     vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  85.  
  86.     saddr = trunc_page(addr);
  87.     eaddr = round_page(addr+len-1);
  88.     rv = vm_map_check_protection(kernel_map, saddr, eaddr, prot);
  89.     /*
  90.      * XXX there are still some things (e.g. the buffer cache) that
  91.      * are managed behind the VM system's back so even though an
  92.      * address is accessible in the mind of the VM system, there may
  93.      * not be physical pages where the VM thinks there is.  This can
  94.      * lead to bogus allocation of pages in the kernel address space
  95.      * or worse, inconsistencies at the pmap level.  We only worry
  96.      * about the buffer cache for now.
  97.      */
  98.     if (!readbuffers && rv && (eaddr > (vm_offset_t)buffers &&
  99.            saddr < (vm_offset_t)buffers + MAXBSIZE * nbuf))
  100.         rv = FALSE;
  101.     return(rv == TRUE);
  102. }
  103.  
  104. useracc(addr, len, rw)
  105.     caddr_t addr;
  106.     int len, rw;
  107. {
  108.     boolean_t rv;
  109.     vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  110.  
  111.     rv = vm_map_check_protection(&curproc->p_vmspace->vm_map,
  112.         trunc_page(addr), round_page(addr+len-1), prot);
  113.     return(rv == TRUE);
  114. }
  115.  
  116. #ifdef KGDB
  117. /*
  118.  * Change protections on kernel pages from addr to addr+len
  119.  * (presumably so debugger can plant a breakpoint).
  120.  * All addresses are assumed to reside in the Sysmap,
  121.  */
  122. chgkprot(addr, len, rw)
  123.     register caddr_t addr;
  124.     int len, rw;
  125. {
  126.     vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  127.  
  128.     vm_map_protect(kernel_map, trunc_page(addr),
  129.                round_page(addr+len-1), prot, FALSE);
  130. }
  131. #endif
  132.  
  133. vslock(addr, len)
  134.     caddr_t    addr;
  135.     u_int    len;
  136. {
  137.     vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr),
  138.             round_page(addr+len-1), FALSE);
  139. }
  140.  
  141. vsunlock(addr, len, dirtied)
  142.     caddr_t    addr;
  143.     u_int    len;
  144.     int dirtied;
  145. {
  146. #ifdef    lint
  147.     dirtied++;
  148. #endif    lint
  149.     vm_map_pageable(&curproc->p_vmspace->vm_map, trunc_page(addr),
  150.             round_page(addr+len-1), TRUE);
  151. }
  152.  
  153. /*
  154.  * Implement fork's actions on an address space.
  155.  * Here we arrange for the address space to be copied or referenced,
  156.  * allocate a user struct (pcb and kernel stack), then call the
  157.  * machine-dependent layer to fill those in and make the new process
  158.  * ready to run.
  159.  * NOTE: the kernel stack may be at a different location in the child
  160.  * process, and thus addresses of automatic variables may be invalid
  161.  * after cpu_fork returns in the child process.  We do nothing here
  162.  * after cpu_fork returns.
  163.  */
  164. vm_fork(p1, p2, isvfork)
  165.     register struct proc *p1, *p2;
  166.     int isvfork;
  167. {
  168.     register struct user *up;
  169.     vm_offset_t addr;
  170.  
  171. #ifdef i386
  172.     /*
  173.      * avoid copying any of the parent's pagetables or other per-process
  174.      * objects that reside in the map by marking all of them non-inheritable
  175.      */
  176.     (void)vm_map_inherit(&p1->p_vmspace->vm_map,
  177.         UPT_MIN_ADDRESS-UPAGES*NBPG, VM_MAX_ADDRESS, VM_INHERIT_NONE);
  178. #endif
  179.     p2->p_vmspace = vmspace_fork(p1->p_vmspace);
  180.  
  181. #ifdef SYSVSHM
  182.     if (p1->p_vmspace->vm_shm)
  183.         shmfork(p1, p2, isvfork);
  184. #endif
  185.  
  186.     /*
  187.      * Allocate a wired-down (for now) pcb and kernel stack for the process
  188.      */
  189.     addr = kmem_alloc_pageable(kernel_map, ctob(UPAGES));
  190.     vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE);
  191.     up = (struct user *)addr;
  192.     p2->p_addr = up;
  193.  
  194.     /*
  195.      * p_stats and p_sigacts currently point at fields
  196.      * in the user struct but not at &u, instead at p_addr.
  197.      * Copy p_sigacts and parts of p_stats; zero the rest
  198.      * of p_stats (statistics).
  199.      */
  200.     p2->p_stats = &up->u_stats;
  201.     p2->p_sigacts = &up->u_sigacts;
  202.     up->u_sigacts = *p1->p_sigacts;
  203.     bzero(&up->u_stats.pstat_startzero,
  204.         (unsigned) ((caddr_t)&up->u_stats.pstat_endzero -
  205.         (caddr_t)&up->u_stats.pstat_startzero));
  206.     bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.pstat_startcopy,
  207.         ((caddr_t)&up->u_stats.pstat_endcopy -
  208.          (caddr_t)&up->u_stats.pstat_startcopy));
  209.  
  210. #ifdef i386
  211.     { u_int addr = UPT_MIN_ADDRESS - UPAGES*NBPG; struct vm_map *vp;
  212.  
  213.     vp = &p2->p_vmspace->vm_map;
  214.     (void)vm_map_pageable(vp, addr, 0xfe000000 - addr, TRUE);
  215.     (void)vm_deallocate(vp, addr, 0xfe000000 - addr);
  216.     (void)vm_allocate(vp, &addr, UPT_MAX_ADDRESS - addr, FALSE);
  217.     (void)vm_map_inherit(vp, addr, UPT_MAX_ADDRESS, VM_INHERIT_NONE);
  218.     }
  219. #endif
  220.     /*
  221.      * cpu_fork will copy and update the kernel stack and pcb,
  222.      * and make the child ready to run.  It marks the child
  223.      * so that it can return differently than the parent.
  224.      * It returns twice, once in the parent process and
  225.      * once in the child.
  226.      */
  227.     return (cpu_fork(p1, p2));
  228. }
  229.  
  230. /*
  231.  * Set default limits for VM system.
  232.  * Called for proc 0, and then inherited by all others.
  233.  */
  234. vm_init_limits(p)
  235.     register struct proc *p;
  236. {
  237.  
  238.     /*
  239.      * Set up the initial limits on process VM.
  240.      * Set the maximum resident set size to be all
  241.      * of (reasonably) available memory.  This causes
  242.      * any single, large process to start random page
  243.      * replacement once it fills memory.
  244.      */
  245.         p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;
  246.         p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ;
  247.         p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;
  248.         p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ;
  249.     p->p_rlimit[RLIMIT_RSS].rlim_cur = p->p_rlimit[RLIMIT_RSS].rlim_max =
  250.         ptoa(vm_page_free_count);
  251. }
  252.  
  253. #include "../vm/vm_pageout.h"
  254.  
  255. #ifdef DEBUG
  256. int    enableswap = 1;
  257. int    swapdebug = 0;
  258. #define    SDB_FOLLOW    1
  259. #define SDB_SWAPIN    2
  260. #define SDB_SWAPOUT    4
  261. #endif
  262.  
  263. /*
  264.  * Brutally simple:
  265.  *    1. Attempt to swapin every swaped-out, runnable process in
  266.  *       order of priority.
  267.  *    2. If not enough memory, wake the pageout daemon and let it
  268.  *       clear some space.
  269.  */
  270. sched()
  271. {
  272.     register struct proc *p;
  273.     register int pri;
  274.     struct proc *pp;
  275.     int ppri;
  276.     vm_offset_t addr;
  277.     vm_size_t size;
  278.  
  279. loop:
  280. #ifdef DEBUG
  281.     if (!enableswap) {
  282.         pp = NULL;
  283.         goto noswap;
  284.     }
  285. #endif
  286.     pp = NULL;
  287.     ppri = INT_MIN;
  288.     for (p = allproc; p != NULL; p = p->p_nxt)
  289.         if (p->p_stat == SRUN && (p->p_flag & SLOAD) == 0) {
  290.             pri = p->p_time + p->p_slptime - p->p_nice * 8;
  291.             if (pri > ppri) {
  292.                 pp = p;
  293.                 ppri = pri;
  294.             }
  295.         }
  296. #ifdef DEBUG
  297.     if (swapdebug & SDB_FOLLOW)
  298.         printf("sched: running, procp %x pri %d\n", pp, ppri);
  299. noswap:
  300. #endif
  301.     /*
  302.      * Nothing to do, back to sleep
  303.      */
  304.     if ((p = pp) == NULL) {
  305.         sleep((caddr_t)&proc0, PVM);
  306.         goto loop;
  307.     }
  308.  
  309.     /*
  310.      * We would like to bring someone in.
  311.      * This part is really bogus cuz we could deadlock on memory
  312.      * despite our feeble check.
  313.      */
  314.     size = round_page(ctob(UPAGES));
  315.     addr = (vm_offset_t) p->p_addr;
  316.     if (vm_page_free_count > atop(size)) {
  317. #ifdef DEBUG
  318.         if (swapdebug & SDB_SWAPIN)
  319.             printf("swapin: pid %d(%s)@%x, pri %d free %d\n",
  320.                    p->p_pid, p->p_comm, p->p_addr,
  321.                    ppri, vm_page_free_count);
  322. #endif
  323.         vm_map_pageable(kernel_map, addr, addr+size, FALSE);
  324.         (void) splclock();
  325.         if (p->p_stat == SRUN)
  326.             setrq(p);
  327.         p->p_flag |= SLOAD;
  328.         (void) spl0();
  329.         p->p_time = 0;
  330.         goto loop;
  331.     }
  332.     /*
  333.      * Not enough memory, jab the pageout daemon and wait til the
  334.      * coast is clear.
  335.      */
  336. #ifdef DEBUG
  337.     if (swapdebug & SDB_FOLLOW)
  338.         printf("sched: no room for pid %d(%s), free %d\n",
  339.                p->p_pid, p->p_comm, vm_page_free_count);
  340. #endif
  341.     (void) splhigh();
  342.     VM_WAIT;
  343.     (void) spl0();
  344. #ifdef DEBUG
  345.     if (swapdebug & SDB_FOLLOW)
  346.         printf("sched: room again, free %d\n", vm_page_free_count);
  347. #endif
  348.     goto loop;
  349. }
  350.  
  351. #define    swappable(p) \
  352.     (((p)->p_flag & (SSYS|SLOAD|SKEEP|SWEXIT|SPHYSIO)) == SLOAD)
  353.  
  354. /*
  355.  * Swapout is driven by the pageout daemon.  Very simple, we find eligible
  356.  * procs and unwire their u-areas.  We try to always "swap" at least one
  357.  * process in case we need the room for a swapin.
  358.  * If any procs have been sleeping/stopped for at least maxslp seconds,
  359.  * they are swapped.  Else, we swap the longest-sleeping or stopped process,
  360.  * if any, otherwise the longest-resident process.
  361.  */
  362. swapout_threads()
  363. {
  364.     register struct proc *p;
  365.     struct proc *outp, *outp2;
  366.     int outpri, outpri2;
  367.     int didswap = 0;
  368.     extern int maxslp;
  369.  
  370. #ifdef DEBUG
  371.     if (!enableswap)
  372.         return;
  373. #endif
  374.     outp = outp2 = NULL;
  375.     outpri = outpri2 = 0;
  376.     for (p = allproc; p != NULL; p = p->p_nxt) {
  377.         if (!swappable(p))
  378.             continue;
  379.         switch (p->p_stat) {
  380.         case SRUN:
  381.             if (p->p_time > outpri2) {
  382.                 outp2 = p;
  383.                 outpri2 = p->p_time;
  384.             }
  385.             continue;
  386.             
  387.         case SSLEEP:
  388.         case SSTOP:
  389.             if (p->p_slptime > maxslp) {
  390.                 swapout(p);
  391.                 didswap++;
  392.             } else if (p->p_slptime > outpri) {
  393.                 outp = p;
  394.                 outpri = p->p_slptime;
  395.             }
  396.             continue;
  397.         }
  398.     }
  399.     /*
  400.      * If we didn't get rid of any real duds, toss out the next most
  401.      * likely sleeping/stopped or running candidate.  We only do this
  402.      * if we are real low on memory since we don't gain much by doing
  403.      * it (UPAGES pages).
  404.      */
  405.     if (didswap == 0 &&
  406.         vm_page_free_count <= atop(round_page(ctob(UPAGES)))) {
  407.         if ((p = outp) == 0)
  408.             p = outp2;
  409. #ifdef DEBUG
  410.         if (swapdebug & SDB_SWAPOUT)
  411.             printf("swapout_threads: no duds, try procp %x\n", p);
  412. #endif
  413.         if (p)
  414.             swapout(p);
  415.     }
  416. }
  417.  
  418. swapout(p)
  419.     register struct proc *p;
  420. {
  421.     vm_offset_t addr;
  422.     vm_size_t size;
  423.  
  424. #ifdef DEBUG
  425.     if (swapdebug & SDB_SWAPOUT)
  426.         printf("swapout: pid %d(%s)@%x, stat %x pri %d free %d\n",
  427.                p->p_pid, p->p_comm, p->p_addr, p->p_stat,
  428.                p->p_slptime, vm_page_free_count);
  429. #endif
  430.     size = round_page(ctob(UPAGES));
  431.     addr = (vm_offset_t) p->p_addr;
  432. #ifdef hp300
  433.     /*
  434.      * Ugh!  u-area is double mapped to a fixed address behind the
  435.      * back of the VM system and accesses are usually through that
  436.      * address rather than the per-process address.  Hence reference
  437.      * and modify information are recorded at the fixed address and
  438.      * lost at context switch time.  We assume the u-struct and
  439.      * kernel stack are always accessed/modified and force it to be so.
  440.      */
  441.     {
  442.         register int i;
  443.         volatile long tmp;
  444.  
  445.         for (i = 0; i < UPAGES; i++) {
  446.             tmp = *(long *)addr; *(long *)addr = tmp;
  447.             addr += NBPG;
  448.         }
  449.         addr = (vm_offset_t) p->p_addr;
  450.     }
  451. #endif
  452.     vm_map_pageable(kernel_map, addr, addr+size, TRUE);
  453.     pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map));
  454.     (void) splhigh();
  455.     p->p_flag &= ~SLOAD;
  456.     if (p->p_stat == SRUN)
  457.         remrq(p);
  458.     (void) spl0();
  459.     p->p_time = 0;
  460. }
  461.  
  462. /*
  463.  * The rest of these routines fake thread handling
  464.  */
  465.  
  466. void
  467. assert_wait(event, ruptible)
  468.     int event;
  469.     boolean_t ruptible;
  470. {
  471. #ifdef lint
  472.     ruptible++;
  473. #endif
  474.     curproc->p_thread = event;
  475. }
  476.  
  477. void
  478. thread_block()
  479. {
  480.     int s = splhigh();
  481.  
  482.     if (curproc->p_thread)
  483.         sleep((caddr_t)curproc->p_thread, PVM);
  484.     splx(s);
  485. }
  486.  
  487. thread_sleep(event, lock, ruptible)
  488.     int event;
  489.     simple_lock_t lock;
  490.     boolean_t ruptible;
  491. {
  492. #ifdef lint
  493.     ruptible++;
  494. #endif
  495.     int s = splhigh();
  496.  
  497.     curproc->p_thread = event;
  498.     simple_unlock(lock);
  499.     if (curproc->p_thread)
  500.         sleep((caddr_t)event, PVM);
  501.     splx(s);
  502. }
  503.  
  504. thread_wakeup(event)
  505.     int event;
  506. {
  507.     int s = splhigh();
  508.  
  509.     wakeup((caddr_t)event);
  510.     splx(s);
  511. }
  512.  
  513. /*
  514.  * DEBUG stuff
  515.  */
  516.  
  517. int indent = 0;
  518.  
  519. /*ARGSUSED2*/
  520. iprintf(a, b, c, d, e, f, g, h)
  521.     char *a;
  522. {
  523.     register int i;
  524.  
  525.     i = indent;
  526.     while (i >= 8) {
  527.         printf("\t");
  528.         i -= 8;
  529.     }
  530.     for (; i > 0; --i)
  531.         printf(" ");
  532.     printf(a, b, c, d, e, f, g, h);
  533. }
  534.