The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/uvm/uvm_glue.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uvm_glue.c,v 1.97 2006/10/05 14:48:33 chs Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1997 Charles D. Cranor and Washington University.
    5  * Copyright (c) 1991, 1993, The Regents of the University of California.
    6  *
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to Berkeley by
   10  * The Mach Operating System project at Carnegie-Mellon University.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by Charles D. Cranor,
   23  *      Washington University, the University of California, Berkeley and
   24  *      its contributors.
   25  * 4. Neither the name of the University nor the names of its contributors
   26  *    may be used to endorse or promote products derived from this software
   27  *    without specific prior written permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   39  * SUCH DAMAGE.
   40  *
   41  *      @(#)vm_glue.c   8.6 (Berkeley) 1/5/94
   42  * from: Id: uvm_glue.c,v 1.1.2.8 1998/02/07 01:16:54 chs Exp
   43  *
   44  *
   45  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
   46  * All rights reserved.
   47  *
   48  * Permission to use, copy, modify and distribute this software and
   49  * its documentation is hereby granted, provided that both the copyright
   50  * notice and this permission notice appear in all copies of the
   51  * software, derivative works or modified versions, and any portions
   52  * thereof, and that both notices appear in supporting documentation.
   53  *
   54  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   55  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   56  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   57  *
   58  * Carnegie Mellon requests users of this software to return to
   59  *
   60  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   61  *  School of Computer Science
   62  *  Carnegie Mellon University
   63  *  Pittsburgh PA 15213-3890
   64  *
   65  * any improvements or extensions that they make and grant Carnegie the
   66  * rights to redistribute these changes.
   67  */
   68 
   69 #include <sys/cdefs.h>
   70 __KERNEL_RCSID(0, "$NetBSD: uvm_glue.c,v 1.97 2006/10/05 14:48:33 chs Exp $");
   71 
   72 #include "opt_coredump.h"
   73 #include "opt_kgdb.h"
   74 #include "opt_kstack.h"
   75 #include "opt_uvmhist.h"
   76 
   77 /*
   78  * uvm_glue.c: glue functions
   79  */
   80 
   81 #include <sys/param.h>
   82 #include <sys/systm.h>
   83 #include <sys/proc.h>
   84 #include <sys/resourcevar.h>
   85 #include <sys/buf.h>
   86 #include <sys/user.h>
   87 
   88 #include <uvm/uvm.h>
   89 
   90 #include <machine/cpu.h>
   91 
   92 /*
   93  * local prototypes
   94  */
   95 
   96 static void uvm_swapout(struct lwp *);
   97 
   98 #define UVM_NUAREA_MAX 16
   99 static vaddr_t uvm_uareas;
  100 static int uvm_nuarea;
  101 static struct simplelock uvm_uareas_slock = SIMPLELOCK_INITIALIZER;
  102 #define UAREA_NEXTFREE(uarea)   (*(vaddr_t *)(UAREA_TO_USER(uarea)))
  103 
  104 static void uvm_uarea_free(vaddr_t);
  105 
  106 /*
  107  * XXXCDC: do these really belong here?
  108  */
  109 
  110 /*
  111  * uvm_kernacc: can the kernel access a region of memory
  112  *
  113  * - used only by /dev/kmem driver (mem.c)
  114  */
  115 
  116 boolean_t
  117 uvm_kernacc(caddr_t addr, size_t len, int rw)
  118 {
  119         boolean_t rv;
  120         vaddr_t saddr, eaddr;
  121         vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  122 
  123         saddr = trunc_page((vaddr_t)addr);
  124         eaddr = round_page((vaddr_t)addr + len);
  125         vm_map_lock_read(kernel_map);
  126         rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot);
  127         vm_map_unlock_read(kernel_map);
  128 
  129         return(rv);
  130 }
  131 
  132 #ifdef KGDB
  133 /*
  134  * Change protections on kernel pages from addr to addr+len
  135  * (presumably so debugger can plant a breakpoint).
  136  *
  137  * We force the protection change at the pmap level.  If we were
  138  * to use vm_map_protect a change to allow writing would be lazily-
  139  * applied meaning we would still take a protection fault, something
  140  * we really don't want to do.  It would also fragment the kernel
  141  * map unnecessarily.  We cannot use pmap_protect since it also won't
  142  * enforce a write-enable request.  Using pmap_enter is the only way
  143  * we can ensure the change takes place properly.
  144  */
  145 void
  146 uvm_chgkprot(caddr_t addr, size_t len, int rw)
  147 {
  148         vm_prot_t prot;
  149         paddr_t pa;
  150         vaddr_t sva, eva;
  151 
  152         prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE;
  153         eva = round_page((vaddr_t)addr + len);
  154         for (sva = trunc_page((vaddr_t)addr); sva < eva; sva += PAGE_SIZE) {
  155                 /*
  156                  * Extract physical address for the page.
  157                  */
  158                 if (pmap_extract(pmap_kernel(), sva, &pa) == FALSE)
  159                         panic("chgkprot: invalid page");
  160                 pmap_enter(pmap_kernel(), sva, pa, prot, PMAP_WIRED);
  161         }
  162         pmap_update(pmap_kernel());
  163 }
  164 #endif
  165 
  166 /*
  167  * uvm_vslock: wire user memory for I/O
  168  *
  169  * - called from physio and sys___sysctl
  170  * - XXXCDC: consider nuking this (or making it a macro?)
  171  */
  172 
  173 int
  174 uvm_vslock(struct vmspace *vs, void *addr, size_t len, vm_prot_t access_type)
  175 {
  176         struct vm_map *map;
  177         vaddr_t start, end;
  178         int error;
  179 
  180         map = &vs->vm_map;
  181         start = trunc_page((vaddr_t)addr);
  182         end = round_page((vaddr_t)addr + len);
  183         error = uvm_fault_wire(map, start, end, access_type, 0);
  184         return error;
  185 }
  186 
  187 /*
  188  * uvm_vsunlock: unwire user memory wired by uvm_vslock()
  189  *
  190  * - called from physio and sys___sysctl
  191  * - XXXCDC: consider nuking this (or making it a macro?)
  192  */
  193 
  194 void
  195 uvm_vsunlock(struct vmspace *vs, void *addr, size_t len)
  196 {
  197         uvm_fault_unwire(&vs->vm_map, trunc_page((vaddr_t)addr),
  198                 round_page((vaddr_t)addr + len));
  199 }
  200 
  201 /*
  202  * uvm_proc_fork: fork a virtual address space
  203  *
  204  * - the address space is copied as per parent map's inherit values
  205  */
  206 void
  207 uvm_proc_fork(struct proc *p1, struct proc *p2, boolean_t shared)
  208 {
  209 
  210         if (shared == TRUE) {
  211                 p2->p_vmspace = NULL;
  212                 uvmspace_share(p1, p2);
  213         } else {
  214                 p2->p_vmspace = uvmspace_fork(p1->p_vmspace);
  215         }
  216 
  217         cpu_proc_fork(p1, p2);
  218 }
  219 
  220 
  221 /*
  222  * uvm_lwp_fork: fork a thread
  223  *
  224  * - a new "user" structure is allocated for the child process
  225  *      [filled in by MD layer...]
  226  * - if specified, the child gets a new user stack described by
  227  *      stack and stacksize
  228  * - NOTE: the kernel stack may be at a different location in the child
  229  *      process, and thus addresses of automatic variables may be invalid
  230  *      after cpu_lwp_fork returns in the child process.  We do nothing here
  231  *      after cpu_lwp_fork returns.
  232  * - XXXCDC: we need a way for this to return a failure value rather
  233  *   than just hang
  234  */
  235 void
  236 uvm_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
  237     void (*func)(void *), void *arg)
  238 {
  239         int error;
  240 
  241         /*
  242          * Wire down the U-area for the process, which contains the PCB
  243          * and the kernel stack.  Wired state is stored in l->l_flag's
  244          * L_INMEM bit rather than in the vm_map_entry's wired count
  245          * to prevent kernel_map fragmentation.  If we reused a cached U-area,
  246          * L_INMEM will already be set and we don't need to do anything.
  247          *
  248          * Note the kernel stack gets read/write accesses right off the bat.
  249          */
  250 
  251         if ((l2->l_flag & L_INMEM) == 0) {
  252                 vaddr_t uarea = USER_TO_UAREA(l2->l_addr);
  253 
  254                 error = uvm_fault_wire(kernel_map, uarea,
  255                     uarea + USPACE, VM_PROT_READ | VM_PROT_WRITE, 0);
  256                 if (error)
  257                         panic("uvm_lwp_fork: uvm_fault_wire failed: %d", error);
  258 #ifdef PMAP_UAREA
  259                 /* Tell the pmap this is a u-area mapping */
  260                 PMAP_UAREA(uarea);
  261 #endif
  262                 l2->l_flag |= L_INMEM;
  263         }
  264 
  265 #ifdef KSTACK_CHECK_MAGIC
  266         /*
  267          * fill stack with magic number
  268          */
  269         kstack_setup_magic(l2);
  270 #endif
  271 
  272         /*
  273          * cpu_lwp_fork() copy and update the pcb, and make the child ready
  274          * to run.  If this is a normal user fork, the child will exit
  275          * directly to user mode via child_return() on its first time
  276          * slice and will not return here.  If this is a kernel thread,
  277          * the specified entry point will be executed.
  278          */
  279         cpu_lwp_fork(l1, l2, stack, stacksize, func, arg);
  280 }
  281 
  282 /*
  283  * uvm_uarea_alloc: allocate a u-area
  284  */
  285 
  286 boolean_t
  287 uvm_uarea_alloc(vaddr_t *uaddrp)
  288 {
  289         vaddr_t uaddr;
  290 
  291 #ifndef USPACE_ALIGN
  292 #define USPACE_ALIGN    0
  293 #endif
  294 
  295         simple_lock(&uvm_uareas_slock);
  296         if (uvm_nuarea > 0) {
  297                 uaddr = uvm_uareas;
  298                 uvm_uareas = UAREA_NEXTFREE(uaddr);
  299                 uvm_nuarea--;
  300                 simple_unlock(&uvm_uareas_slock);
  301                 *uaddrp = uaddr;
  302                 return TRUE;
  303         } else {
  304                 simple_unlock(&uvm_uareas_slock);
  305                 *uaddrp = uvm_km_alloc(kernel_map, USPACE, USPACE_ALIGN,
  306                     UVM_KMF_PAGEABLE);
  307                 return FALSE;
  308         }
  309 }
  310 
  311 /*
  312  * uvm_uarea_free: free a u-area; never blocks
  313  */
  314 
  315 static inline void
  316 uvm_uarea_free(vaddr_t uaddr)
  317 {
  318         simple_lock(&uvm_uareas_slock);
  319         UAREA_NEXTFREE(uaddr) = uvm_uareas;
  320         uvm_uareas = uaddr;
  321         uvm_nuarea++;
  322         simple_unlock(&uvm_uareas_slock);
  323 }
  324 
  325 /*
  326  * uvm_uarea_drain: return memory of u-areas over limit
  327  * back to system
  328  */
  329 
  330 void
  331 uvm_uarea_drain(boolean_t empty)
  332 {
  333         int leave = empty ? 0 : UVM_NUAREA_MAX;
  334         vaddr_t uaddr;
  335 
  336         if (uvm_nuarea <= leave)
  337                 return;
  338 
  339         simple_lock(&uvm_uareas_slock);
  340         while(uvm_nuarea > leave) {
  341                 uaddr = uvm_uareas;
  342                 uvm_uareas = UAREA_NEXTFREE(uaddr);
  343                 uvm_nuarea--;
  344                 simple_unlock(&uvm_uareas_slock);
  345                 uvm_km_free(kernel_map, uaddr, USPACE, UVM_KMF_PAGEABLE);
  346                 simple_lock(&uvm_uareas_slock);
  347         }
  348         simple_unlock(&uvm_uareas_slock);
  349 }
  350 
  351 /*
  352  * uvm_exit: exit a virtual address space
  353  *
  354  * - the process passed to us is a dead (pre-zombie) process; we
  355  *   are running on a different context now (the reaper).
  356  * - borrow proc0's address space because freeing the vmspace
  357  *   of the dead process may block.
  358  */
  359 
  360 void
  361 uvm_proc_exit(struct proc *p)
  362 {
  363         struct lwp *l = curlwp; /* XXX */
  364         struct vmspace *ovm;
  365 
  366         KASSERT(p == l->l_proc);
  367         ovm = p->p_vmspace;
  368 
  369         /*
  370          * borrow proc0's address space.
  371          */
  372         pmap_deactivate(l);
  373         p->p_vmspace = proc0.p_vmspace;
  374         pmap_activate(l);
  375 
  376         uvmspace_free(ovm);
  377 }
  378 
  379 void
  380 uvm_lwp_exit(struct lwp *l)
  381 {
  382         vaddr_t va = USER_TO_UAREA(l->l_addr);
  383 
  384         l->l_flag &= ~L_INMEM;
  385         uvm_uarea_free(va);
  386         l->l_addr = NULL;
  387 }
  388 
  389 /*
  390  * uvm_init_limit: init per-process VM limits
  391  *
  392  * - called for process 0 and then inherited by all others.
  393  */
  394 
  395 void
  396 uvm_init_limits(struct proc *p)
  397 {
  398 
  399         /*
  400          * Set up the initial limits on process VM.  Set the maximum
  401          * resident set size to be all of (reasonably) available memory.
  402          * This causes any single, large process to start random page
  403          * replacement once it fills memory.
  404          */
  405 
  406         p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;
  407         p->p_rlimit[RLIMIT_STACK].rlim_max = maxsmap;
  408         p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;
  409         p->p_rlimit[RLIMIT_DATA].rlim_max = maxdmap;
  410         p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(uvmexp.free);
  411 }
  412 
  413 #ifdef DEBUG
  414 int     enableswap = 1;
  415 int     swapdebug = 0;
  416 #define SDB_FOLLOW      1
  417 #define SDB_SWAPIN      2
  418 #define SDB_SWAPOUT     4
  419 #endif
  420 
  421 /*
  422  * uvm_swapin: swap in an lwp's u-area.
  423  */
  424 
  425 void
  426 uvm_swapin(struct lwp *l)
  427 {
  428         vaddr_t addr;
  429         int s, error;
  430 
  431         addr = USER_TO_UAREA(l->l_addr);
  432         /* make L_INMEM true */
  433         error = uvm_fault_wire(kernel_map, addr, addr + USPACE,
  434             VM_PROT_READ | VM_PROT_WRITE, 0);
  435         if (error) {
  436                 panic("uvm_swapin: rewiring stack failed: %d", error);
  437         }
  438 
  439         /*
  440          * Some architectures need to be notified when the user area has
  441          * moved to new physical page(s) (e.g.  see mips/mips/vm_machdep.c).
  442          */
  443         cpu_swapin(l);
  444         SCHED_LOCK(s);
  445         if (l->l_stat == LSRUN)
  446                 setrunqueue(l);
  447         l->l_flag |= L_INMEM;
  448         SCHED_UNLOCK(s);
  449         l->l_swtime = 0;
  450         ++uvmexp.swapins;
  451 }
  452 
  453 /*
  454  * uvm_scheduler: process zero main loop
  455  *
  456  * - attempt to swapin every swaped-out, runnable process in order of
  457  *      priority.
  458  * - if not enough memory, wake the pagedaemon and let it clear space.
  459  */
  460 
  461 void
  462 uvm_scheduler(void)
  463 {
  464         struct lwp *l, *ll;
  465         int pri;
  466         int ppri;
  467 
  468 loop:
  469 #ifdef DEBUG
  470         while (!enableswap)
  471                 tsleep(&proc0, PVM, "noswap", 0);
  472 #endif
  473         ll = NULL;              /* process to choose */
  474         ppri = INT_MIN; /* its priority */
  475         proclist_lock_read();
  476 
  477         LIST_FOREACH(l, &alllwp, l_list) {
  478                 /* is it a runnable swapped out process? */
  479                 if (l->l_stat == LSRUN && (l->l_flag & L_INMEM) == 0) {
  480                         pri = l->l_swtime + l->l_slptime -
  481                             (l->l_proc->p_nice - NZERO) * 8;
  482                         if (pri > ppri) {   /* higher priority?  remember it. */
  483                                 ll = l;
  484                                 ppri = pri;
  485                         }
  486                 }
  487         }
  488         /*
  489          * XXXSMP: possible unlock/sleep race between here and the
  490          * "scheduler" tsleep below..
  491          */
  492         proclist_unlock_read();
  493 
  494 #ifdef DEBUG
  495         if (swapdebug & SDB_FOLLOW)
  496                 printf("scheduler: running, procp %p pri %d\n", ll, ppri);
  497 #endif
  498         /*
  499          * Nothing to do, back to sleep
  500          */
  501         if ((l = ll) == NULL) {
  502                 tsleep(&proc0, PVM, "scheduler", 0);
  503                 goto loop;
  504         }
  505 
  506         /*
  507          * we have found swapped out process which we would like to bring
  508          * back in.
  509          *
  510          * XXX: this part is really bogus cuz we could deadlock on memory
  511          * despite our feeble check
  512          */
  513         if (uvmexp.free > atop(USPACE)) {
  514 #ifdef DEBUG
  515                 if (swapdebug & SDB_SWAPIN)
  516                         printf("swapin: pid %d(%s)@%p, pri %d free %d\n",
  517              l->l_proc->p_pid, l->l_proc->p_comm, l->l_addr, ppri, uvmexp.free);
  518 #endif
  519                 uvm_swapin(l);
  520                 goto loop;
  521         }
  522         /*
  523          * not enough memory, jab the pageout daemon and wait til the coast
  524          * is clear
  525          */
  526 #ifdef DEBUG
  527         if (swapdebug & SDB_FOLLOW)
  528                 printf("scheduler: no room for pid %d(%s), free %d\n",
  529            l->l_proc->p_pid, l->l_proc->p_comm, uvmexp.free);
  530 #endif
  531         uvm_wait("schedpwait");
  532 #ifdef DEBUG
  533         if (swapdebug & SDB_FOLLOW)
  534                 printf("scheduler: room again, free %d\n", uvmexp.free);
  535 #endif
  536         goto loop;
  537 }
  538 
  539 /*
  540  * swappable: is LWP "l" swappable?
  541  */
  542 
  543 #define swappable(l)                                                    \
  544         (((l)->l_flag & (L_INMEM)) &&                                   \
  545          ((((l)->l_proc->p_flag) & (P_SYSTEM | P_WEXIT)) == 0) &&       \
  546          (l)->l_holdcnt == 0)
  547 
  548 /*
  549  * swapout_threads: find threads that can be swapped and unwire their
  550  *      u-areas.
  551  *
  552  * - called by the pagedaemon
  553  * - try and swap at least one processs
  554  * - processes that are sleeping or stopped for maxslp or more seconds
  555  *   are swapped... otherwise the longest-sleeping or stopped process
  556  *   is swapped, otherwise the longest resident process...
  557  */
  558 
  559 void
  560 uvm_swapout_threads(void)
  561 {
  562         struct lwp *l;
  563         struct lwp *outl, *outl2;
  564         int outpri, outpri2;
  565         int didswap = 0;
  566         extern int maxslp;
  567         /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */
  568 
  569 #ifdef DEBUG
  570         if (!enableswap)
  571                 return;
  572 #endif
  573 
  574         /*
  575          * outl/outpri  : stop/sleep thread with largest sleeptime < maxslp
  576          * outl2/outpri2: the longest resident thread (its swap time)
  577          */
  578         outl = outl2 = NULL;
  579         outpri = outpri2 = 0;
  580         proclist_lock_read();
  581         LIST_FOREACH(l, &alllwp, l_list) {
  582                 KASSERT(l->l_proc != NULL);
  583                 if (!swappable(l))
  584                         continue;
  585                 switch (l->l_stat) {
  586                 case LSONPROC:
  587                         continue;
  588 
  589                 case LSRUN:
  590                         if (l->l_swtime > outpri2) {
  591                                 outl2 = l;
  592                                 outpri2 = l->l_swtime;
  593                         }
  594                         continue;
  595 
  596                 case LSSLEEP:
  597                 case LSSTOP:
  598                         if (l->l_slptime >= maxslp) {
  599                                 uvm_swapout(l);
  600                                 didswap++;
  601                         } else if (l->l_slptime > outpri) {
  602                                 outl = l;
  603                                 outpri = l->l_slptime;
  604                         }
  605                         continue;
  606                 }
  607         }
  608         proclist_unlock_read();
  609 
  610         /*
  611          * If we didn't get rid of any real duds, toss out the next most
  612          * likely sleeping/stopped or running candidate.  We only do this
  613          * if we are real low on memory since we don't gain much by doing
  614          * it (USPACE bytes).
  615          */
  616         if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) {
  617                 if ((l = outl) == NULL)
  618                         l = outl2;
  619 #ifdef DEBUG
  620                 if (swapdebug & SDB_SWAPOUT)
  621                         printf("swapout_threads: no duds, try procp %p\n", l);
  622 #endif
  623                 if (l)
  624                         uvm_swapout(l);
  625         }
  626 }
  627 
  628 /*
  629  * uvm_swapout: swap out lwp "l"
  630  *
  631  * - currently "swapout" means "unwire U-area" and "pmap_collect()"
  632  *   the pmap.
  633  * - XXXCDC: should deactivate all process' private anonymous memory
  634  */
  635 
  636 static void
  637 uvm_swapout(struct lwp *l)
  638 {
  639         vaddr_t addr;
  640         int s;
  641         struct proc *p = l->l_proc;
  642 
  643 #ifdef DEBUG
  644         if (swapdebug & SDB_SWAPOUT)
  645                 printf("swapout: lid %d.%d(%s)@%p, stat %x pri %d free %d\n",
  646            p->p_pid, l->l_lid, p->p_comm, l->l_addr, l->l_stat,
  647            l->l_slptime, uvmexp.free);
  648 #endif
  649 
  650         /*
  651          * Mark it as (potentially) swapped out.
  652          */
  653         SCHED_LOCK(s);
  654         if (l->l_stat == LSONPROC) {
  655                 KDASSERT(l->l_cpu != curcpu());
  656                 SCHED_UNLOCK(s);
  657                 return;
  658         }
  659         l->l_flag &= ~L_INMEM;
  660         if (l->l_stat == LSRUN)
  661                 remrunqueue(l);
  662         SCHED_UNLOCK(s);
  663         l->l_swtime = 0;
  664         p->p_stats->p_ru.ru_nswap++;
  665         ++uvmexp.swapouts;
  666 
  667         /*
  668          * Do any machine-specific actions necessary before swapout.
  669          * This can include saving floating point state, etc.
  670          */
  671         cpu_swapout(l);
  672 
  673         /*
  674          * Unwire the to-be-swapped process's user struct and kernel stack.
  675          */
  676         addr = USER_TO_UAREA(l->l_addr);
  677         uvm_fault_unwire(kernel_map, addr, addr + USPACE); /* !L_INMEM */
  678         pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map));
  679 }
  680 
  681 #ifdef COREDUMP
  682 /*
  683  * uvm_coredump_walkmap: walk a process's map for the purpose of dumping
  684  * a core file.
  685  */
  686 
  687 int
  688 uvm_coredump_walkmap(struct proc *p, void *iocookie,
  689     int (*func)(struct proc *, void *, struct uvm_coredump_state *),
  690     void *cookie)
  691 {
  692         struct uvm_coredump_state state;
  693         struct vmspace *vm = p->p_vmspace;
  694         struct vm_map *map = &vm->vm_map;
  695         struct vm_map_entry *entry;
  696         int error;
  697 
  698         entry = NULL;
  699         vm_map_lock_read(map);
  700         state.end = 0;
  701         for (;;) {
  702                 if (entry == NULL)
  703                         entry = map->header.next;
  704                 else if (!uvm_map_lookup_entry(map, state.end, &entry))
  705                         entry = entry->next;
  706                 if (entry == &map->header)
  707                         break;
  708 
  709                 state.cookie = cookie;
  710                 if (state.end > entry->start) {
  711                         state.start = state.end;
  712                 } else {
  713                         state.start = entry->start;
  714                 }
  715                 state.realend = entry->end;
  716                 state.end = entry->end;
  717                 state.prot = entry->protection;
  718                 state.flags = 0;
  719 
  720                 /*
  721                  * Dump the region unless one of the following is true:
  722                  *
  723                  * (1) the region has neither object nor amap behind it
  724                  *     (ie. it has never been accessed).
  725                  *
  726                  * (2) the region has no amap and is read-only
  727                  *     (eg. an executable text section).
  728                  *
  729                  * (3) the region's object is a device.
  730                  *
  731                  * (4) the region is unreadable by the process.
  732                  */
  733 
  734                 KASSERT(!UVM_ET_ISSUBMAP(entry));
  735                 KASSERT(state.start < VM_MAXUSER_ADDRESS);
  736                 KASSERT(state.end <= VM_MAXUSER_ADDRESS);
  737                 if (entry->object.uvm_obj == NULL &&
  738                     entry->aref.ar_amap == NULL) {
  739                         state.realend = state.start;
  740                 } else if ((entry->protection & VM_PROT_WRITE) == 0 &&
  741                     entry->aref.ar_amap == NULL) {
  742                         state.realend = state.start;
  743                 } else if (entry->object.uvm_obj != NULL &&
  744                     UVM_OBJ_IS_DEVICE(entry->object.uvm_obj)) {
  745                         state.realend = state.start;
  746                 } else if ((entry->protection & VM_PROT_READ) == 0) {
  747                         state.realend = state.start;
  748                 } else {
  749                         if (state.start >= (vaddr_t)vm->vm_maxsaddr)
  750                                 state.flags |= UVM_COREDUMP_STACK;
  751 
  752                         /*
  753                          * If this an anonymous entry, only dump instantiated
  754                          * pages.
  755                          */
  756                         if (entry->object.uvm_obj == NULL) {
  757                                 vaddr_t end;
  758 
  759                                 amap_lock(entry->aref.ar_amap);
  760                                 for (end = state.start;
  761                                      end < state.end; end += PAGE_SIZE) {
  762                                         struct vm_anon *anon;
  763                                         anon = amap_lookup(&entry->aref,
  764                                             end - entry->start);
  765                                         /*
  766                                          * If we have already encountered an
  767                                          * uninstantiated page, stop at the
  768                                          * first instantied page.
  769                                          */
  770                                         if (anon != NULL &&
  771                                             state.realend != state.end) {
  772                                                 state.end = end;
  773                                                 break;
  774                                         }
  775 
  776                                         /*
  777                                          * If this page is the first
  778                                          * uninstantiated page, mark this as
  779                                          * the real ending point.  Continue to
  780                                          * counting uninstantiated pages.
  781                                          */
  782                                         if (anon == NULL &&
  783                                             state.realend == state.end) {
  784                                                 state.realend = end;
  785                                         }
  786                                 }
  787                                 amap_unlock(entry->aref.ar_amap);
  788                         }
  789                 }
  790                 
  791 
  792                 vm_map_unlock_read(map);
  793                 error = (*func)(p, iocookie, &state);
  794                 if (error)
  795                         return (error);
  796                 vm_map_lock_read(map);
  797         }
  798         vm_map_unlock_read(map);
  799 
  800         return (0);
  801 }
  802 #endif /* COREDUMP */

Cache object: 4f6d8aa53103b9fe7e854b6fde60e664


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.