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.78.2.1 2005/11/06 00:24:19 riz 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.78.2.1 2005/11/06 00:24:19 riz Exp $");
   71 
   72 #include "opt_kgdb.h"
   73 #include "opt_kstack.h"
   74 #include "opt_uvmhist.h"
   75 
   76 /*
   77  * uvm_glue.c: glue functions
   78  */
   79 
   80 #include <sys/param.h>
   81 #include <sys/systm.h>
   82 #include <sys/proc.h>
   83 #include <sys/resourcevar.h>
   84 #include <sys/buf.h>
   85 #include <sys/user.h>
   86 
   87 #include <uvm/uvm.h>
   88 
   89 #include <machine/cpu.h>
   90 
   91 /*
   92  * local prototypes
   93  */
   94 
   95 static void uvm_swapout(struct lwp *);
   96 
   97 #define UVM_NUAREA_MAX 16
   98 void *uvm_uareas;
   99 int uvm_nuarea;
  100 struct simplelock uvm_uareas_slock = SIMPLELOCK_INITIALIZER;
  101 
  102 static void uvm_uarea_free(vaddr_t);
  103 
  104 /*
  105  * XXXCDC: do these really belong here?
  106  */
  107 
  108 /*
  109  * uvm_kernacc: can the kernel access a region of memory
  110  *
  111  * - called from malloc [DIAGNOSTIC], and /dev/kmem driver (mem.c)
  112  */
  113 
  114 boolean_t
  115 uvm_kernacc(addr, len, rw)
  116         caddr_t addr;
  117         size_t len;
  118         int rw;
  119 {
  120         boolean_t rv;
  121         vaddr_t saddr, eaddr;
  122         vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  123 
  124         saddr = trunc_page((vaddr_t)addr);
  125         eaddr = round_page((vaddr_t)addr + len);
  126         vm_map_lock_read(kernel_map);
  127         rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot);
  128         vm_map_unlock_read(kernel_map);
  129 
  130         return(rv);
  131 }
  132 
  133 #ifdef KGDB
  134 /*
  135  * Change protections on kernel pages from addr to addr+len
  136  * (presumably so debugger can plant a breakpoint).
  137  *
  138  * We force the protection change at the pmap level.  If we were
  139  * to use vm_map_protect a change to allow writing would be lazily-
  140  * applied meaning we would still take a protection fault, something
  141  * we really don't want to do.  It would also fragment the kernel
  142  * map unnecessarily.  We cannot use pmap_protect since it also won't
  143  * enforce a write-enable request.  Using pmap_enter is the only way
  144  * we can ensure the change takes place properly.
  145  */
  146 void
  147 uvm_chgkprot(addr, len, rw)
  148         caddr_t addr;
  149         size_t len;
  150         int rw;
  151 {
  152         vm_prot_t prot;
  153         paddr_t pa;
  154         vaddr_t sva, eva;
  155 
  156         prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE;
  157         eva = round_page((vaddr_t)addr + len);
  158         for (sva = trunc_page((vaddr_t)addr); sva < eva; sva += PAGE_SIZE) {
  159                 /*
  160                  * Extract physical address for the page.
  161                  */
  162                 if (pmap_extract(pmap_kernel(), sva, &pa) == FALSE)
  163                         panic("chgkprot: invalid page");
  164                 pmap_enter(pmap_kernel(), sva, pa, prot, PMAP_WIRED);
  165         }
  166         pmap_update(pmap_kernel());
  167 }
  168 #endif
  169 
  170 /*
  171  * uvm_vslock: wire user memory for I/O
  172  *
  173  * - called from physio and sys___sysctl
  174  * - XXXCDC: consider nuking this (or making it a macro?)
  175  */
  176 
  177 int
  178 uvm_vslock(p, addr, len, access_type)
  179         struct proc *p;
  180         caddr_t addr;
  181         size_t  len;
  182         vm_prot_t access_type;
  183 {
  184         struct vm_map *map;
  185         vaddr_t start, end;
  186         int error;
  187 
  188         map = &p->p_vmspace->vm_map;
  189         start = trunc_page((vaddr_t)addr);
  190         end = round_page((vaddr_t)addr + len);
  191         error = uvm_fault_wire(map, start, end, VM_FAULT_WIRE, access_type);
  192         return error;
  193 }
  194 
  195 /*
  196  * uvm_vsunlock: unwire user memory wired by uvm_vslock()
  197  *
  198  * - called from physio and sys___sysctl
  199  * - XXXCDC: consider nuking this (or making it a macro?)
  200  */
  201 
  202 void
  203 uvm_vsunlock(p, addr, len)
  204         struct proc *p;
  205         caddr_t addr;
  206         size_t  len;
  207 {
  208         uvm_fault_unwire(&p->p_vmspace->vm_map, trunc_page((vaddr_t)addr),
  209                 round_page((vaddr_t)addr + len));
  210 }
  211 
  212 /*
  213  * uvm_proc_fork: fork a virtual address space
  214  *
  215  * - the address space is copied as per parent map's inherit values
  216  */
  217 void
  218 uvm_proc_fork(p1, p2, shared)
  219         struct proc *p1, *p2;
  220         boolean_t shared;
  221 {
  222 
  223         if (shared == TRUE) {
  224                 p2->p_vmspace = NULL;
  225                 uvmspace_share(p1, p2);
  226         } else {
  227                 p2->p_vmspace = uvmspace_fork(p1->p_vmspace);
  228         }
  229 
  230         cpu_proc_fork(p1, p2);
  231 }
  232 
  233 
  234 /*
  235  * uvm_lwp_fork: fork a thread
  236  *
  237  * - a new "user" structure is allocated for the child process
  238  *      [filled in by MD layer...]
  239  * - if specified, the child gets a new user stack described by
  240  *      stack and stacksize
  241  * - NOTE: the kernel stack may be at a different location in the child
  242  *      process, and thus addresses of automatic variables may be invalid
  243  *      after cpu_lwp_fork returns in the child process.  We do nothing here
  244  *      after cpu_lwp_fork returns.
  245  * - XXXCDC: we need a way for this to return a failure value rather
  246  *   than just hang
  247  */
  248 void
  249 uvm_lwp_fork(l1, l2, stack, stacksize, func, arg)
  250         struct lwp *l1, *l2;
  251         void *stack;
  252         size_t stacksize;
  253         void (*func)(void *);
  254         void *arg;
  255 {
  256         struct user *up = l2->l_addr;
  257         int error;
  258 
  259         /*
  260          * Wire down the U-area for the process, which contains the PCB
  261          * and the kernel stack.  Wired state is stored in l->l_flag's
  262          * L_INMEM bit rather than in the vm_map_entry's wired count
  263          * to prevent kernel_map fragmentation.  If we reused a cached U-area,
  264          * L_INMEM will already be set and we don't need to do anything.
  265          *
  266          * Note the kernel stack gets read/write accesses right off the bat.
  267          */
  268 
  269         if ((l2->l_flag & L_INMEM) == 0) {
  270                 error = uvm_fault_wire(kernel_map, (vaddr_t)up,
  271                     (vaddr_t)up + USPACE, VM_FAULT_WIRE,
  272                     VM_PROT_READ | VM_PROT_WRITE);
  273                 if (error)
  274                         panic("uvm_lwp_fork: uvm_fault_wire failed: %d", error);
  275 #ifdef PMAP_UAREA
  276                 /* Tell the pmap this is a u-area mapping */
  277                 PMAP_UAREA((vaddr_t)up);
  278 #endif
  279                 l2->l_flag |= L_INMEM;
  280         }
  281 
  282 #ifdef KSTACK_CHECK_MAGIC
  283         /*
  284          * fill stack with magic number
  285          */
  286         kstack_setup_magic(l2);
  287 #endif
  288 
  289         /*
  290          * cpu_lwp_fork() copy and update the pcb, and make the child ready
  291          * to run.  If this is a normal user fork, the child will exit
  292          * directly to user mode via child_return() on its first time
  293          * slice and will not return here.  If this is a kernel thread,
  294          * the specified entry point will be executed.
  295          */
  296         cpu_lwp_fork(l1, l2, stack, stacksize, func, arg);
  297 }
  298 
  299 /*
  300  * uvm_exit: exit a virtual address space
  301  *
  302  * - the process passed to us is a dead (pre-zombie) process; we
  303  *   are running on a different context now (the reaper).
  304  * - borrow proc0's address space because freeing the vmspace
  305  *   of the dead process may block.
  306  */
  307 
  308 void
  309 uvm_proc_exit(p)
  310         struct proc *p;
  311 {
  312         struct lwp *l = curlwp; /* XXX */
  313         struct vmspace *ovm;
  314 
  315         KASSERT(p == l->l_proc);
  316         ovm = p->p_vmspace;
  317 
  318         /*
  319          * borrow proc0's address space.
  320          */
  321         pmap_deactivate(l);
  322         p->p_vmspace = proc0.p_vmspace;
  323         pmap_activate(l);
  324 
  325         uvmspace_free(ovm);
  326 }
  327 
  328 void
  329 uvm_lwp_exit(struct lwp *l)
  330 {
  331         vaddr_t va = (vaddr_t)l->l_addr;
  332 
  333         l->l_flag &= ~L_INMEM;
  334         uvm_uarea_free(va);
  335         l->l_addr = NULL;
  336 }
  337 
  338 /*
  339  * uvm_uarea_alloc: allocate a u-area
  340  */
  341 
  342 boolean_t
  343 uvm_uarea_alloc(vaddr_t *uaddrp)
  344 {
  345         vaddr_t uaddr;
  346 
  347 #ifndef USPACE_ALIGN
  348 #define USPACE_ALIGN    0
  349 #endif
  350 
  351         simple_lock(&uvm_uareas_slock);
  352         if (uvm_nuarea > 0) {
  353                 uaddr = (vaddr_t)uvm_uareas;
  354                 uvm_uareas = *(void **)uvm_uareas;
  355                 uvm_nuarea--;
  356                 simple_unlock(&uvm_uareas_slock);
  357                 *uaddrp = uaddr;
  358                 return TRUE;
  359         } else {
  360                 simple_unlock(&uvm_uareas_slock);
  361                 *uaddrp = uvm_km_valloc_align(kernel_map, USPACE, USPACE_ALIGN);
  362                 return FALSE;
  363         }
  364 }
  365 
  366 /*
  367  * uvm_uarea_free: free a u-area; never blocks
  368  */
  369 
  370 static void
  371 uvm_uarea_free(vaddr_t uaddr)
  372 {
  373         simple_lock(&uvm_uareas_slock);
  374         *(void **)uaddr = uvm_uareas;
  375         uvm_uareas = (void *)uaddr;
  376         uvm_nuarea++;
  377         simple_unlock(&uvm_uareas_slock);
  378 }
  379 
  380 /*
  381  * uvm_uarea_drain: return memory of u-areas over limit
  382  * back to system
  383  */
  384 
  385 void
  386 uvm_uarea_drain(boolean_t empty)
  387 {
  388         int leave = empty ? 0 : UVM_NUAREA_MAX;
  389         vaddr_t uaddr;
  390 
  391         if (uvm_nuarea <= leave)
  392                 return;
  393 
  394         simple_lock(&uvm_uareas_slock);
  395         while(uvm_nuarea > leave) {
  396                 uaddr = (vaddr_t)uvm_uareas;
  397                 uvm_uareas = *(void **)uvm_uareas;
  398                 uvm_nuarea--;
  399                 simple_unlock(&uvm_uareas_slock);
  400                 uvm_km_free(kernel_map, uaddr, USPACE);
  401                 simple_lock(&uvm_uareas_slock);
  402         }
  403         simple_unlock(&uvm_uareas_slock);
  404 }
  405 
  406 /*
  407  * uvm_init_limit: init per-process VM limits
  408  *
  409  * - called for process 0 and then inherited by all others.
  410  */
  411 
  412 void
  413 uvm_init_limits(p)
  414         struct proc *p;
  415 {
  416 
  417         /*
  418          * Set up the initial limits on process VM.  Set the maximum
  419          * resident set size to be all of (reasonably) available memory.
  420          * This causes any single, large process to start random page
  421          * replacement once it fills memory.
  422          */
  423 
  424         p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;
  425         p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ;
  426         p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;
  427         p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ;
  428         p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(uvmexp.free);
  429 }
  430 
  431 #ifdef DEBUG
  432 int     enableswap = 1;
  433 int     swapdebug = 0;
  434 #define SDB_FOLLOW      1
  435 #define SDB_SWAPIN      2
  436 #define SDB_SWAPOUT     4
  437 #endif
  438 
  439 /*
  440  * uvm_swapin: swap in a process's u-area.
  441  */
  442 
  443 void
  444 uvm_swapin(l)
  445         struct lwp *l;
  446 {
  447         vaddr_t addr;
  448         int s, error;
  449 
  450         addr = (vaddr_t)l->l_addr;
  451         /* make L_INMEM true */
  452         error = uvm_fault_wire(kernel_map, addr, addr + USPACE, VM_FAULT_WIRE,
  453             VM_PROT_READ | VM_PROT_WRITE);
  454         if (error) {
  455                 panic("uvm_swapin: rewiring stack failed: %d", error);
  456         }
  457 
  458         /*
  459          * Some architectures need to be notified when the user area has
  460          * moved to new physical page(s) (e.g.  see mips/mips/vm_machdep.c).
  461          */
  462         cpu_swapin(l);
  463         SCHED_LOCK(s);
  464         if (l->l_stat == LSRUN)
  465                 setrunqueue(l);
  466         l->l_flag |= L_INMEM;
  467         SCHED_UNLOCK(s);
  468         l->l_swtime = 0;
  469         ++uvmexp.swapins;
  470 }
  471 
  472 /*
  473  * uvm_scheduler: process zero main loop
  474  *
  475  * - attempt to swapin every swaped-out, runnable process in order of
  476  *      priority.
  477  * - if not enough memory, wake the pagedaemon and let it clear space.
  478  */
  479 
  480 void
  481 uvm_scheduler()
  482 {
  483         struct lwp *l, *ll;
  484         int pri;
  485         int ppri;
  486 
  487 loop:
  488 #ifdef DEBUG
  489         while (!enableswap)
  490                 tsleep(&proc0, PVM, "noswap", 0);
  491 #endif
  492         ll = NULL;              /* process to choose */
  493         ppri = INT_MIN; /* its priority */
  494         proclist_lock_read();
  495 
  496         LIST_FOREACH(l, &alllwp, l_list) {
  497                 /* is it a runnable swapped out process? */
  498                 if (l->l_stat == LSRUN && (l->l_flag & L_INMEM) == 0) {
  499                         pri = l->l_swtime + l->l_slptime -
  500                             (l->l_proc->p_nice - NZERO) * 8;
  501                         if (pri > ppri) {   /* higher priority?  remember it. */
  502                                 ll = l;
  503                                 ppri = pri;
  504                         }
  505                 }
  506         }
  507         /*
  508          * XXXSMP: possible unlock/sleep race between here and the
  509          * "scheduler" tsleep below..
  510          */
  511         proclist_unlock_read();
  512 
  513 #ifdef DEBUG
  514         if (swapdebug & SDB_FOLLOW)
  515                 printf("scheduler: running, procp %p pri %d\n", ll, ppri);
  516 #endif
  517         /*
  518          * Nothing to do, back to sleep
  519          */
  520         if ((l = ll) == NULL) {
  521                 tsleep(&proc0, PVM, "scheduler", 0);
  522                 goto loop;
  523         }
  524 
  525         /*
  526          * we have found swapped out process which we would like to bring
  527          * back in.
  528          *
  529          * XXX: this part is really bogus cuz we could deadlock on memory
  530          * despite our feeble check
  531          */
  532         if (uvmexp.free > atop(USPACE)) {
  533 #ifdef DEBUG
  534                 if (swapdebug & SDB_SWAPIN)
  535                         printf("swapin: pid %d(%s)@%p, pri %d free %d\n",
  536              l->l_proc->p_pid, l->l_proc->p_comm, l->l_addr, ppri, uvmexp.free);
  537 #endif
  538                 uvm_swapin(l);
  539                 goto loop;
  540         }
  541         /*
  542          * not enough memory, jab the pageout daemon and wait til the coast
  543          * is clear
  544          */
  545 #ifdef DEBUG
  546         if (swapdebug & SDB_FOLLOW)
  547                 printf("scheduler: no room for pid %d(%s), free %d\n",
  548            l->l_proc->p_pid, l->l_proc->p_comm, uvmexp.free);
  549 #endif
  550         uvm_wait("schedpwait");
  551 #ifdef DEBUG
  552         if (swapdebug & SDB_FOLLOW)
  553                 printf("scheduler: room again, free %d\n", uvmexp.free);
  554 #endif
  555         goto loop;
  556 }
  557 
  558 /*
  559  * swappable: is LWP "l" swappable?
  560  */
  561 
  562 #define swappable(l)                                                    \
  563         (((l)->l_flag & (L_INMEM)) &&                                   \
  564          ((((l)->l_proc->p_flag) & (P_SYSTEM | P_WEXIT)) == 0) &&       \
  565          (l)->l_holdcnt == 0)
  566 
  567 /*
  568  * swapout_threads: find threads that can be swapped and unwire their
  569  *      u-areas.
  570  *
  571  * - called by the pagedaemon
  572  * - try and swap at least one processs
  573  * - processes that are sleeping or stopped for maxslp or more seconds
  574  *   are swapped... otherwise the longest-sleeping or stopped process
  575  *   is swapped, otherwise the longest resident process...
  576  */
  577 
  578 void
  579 uvm_swapout_threads()
  580 {
  581         struct lwp *l;
  582         struct lwp *outl, *outl2;
  583         int outpri, outpri2;
  584         int didswap = 0;
  585         extern int maxslp;
  586         /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */
  587 
  588 #ifdef DEBUG
  589         if (!enableswap)
  590                 return;
  591 #endif
  592 
  593         /*
  594          * outl/outpri  : stop/sleep thread with largest sleeptime < maxslp
  595          * outl2/outpri2: the longest resident thread (its swap time)
  596          */
  597         outl = outl2 = NULL;
  598         outpri = outpri2 = 0;
  599         proclist_lock_read();
  600         LIST_FOREACH(l, &alllwp, l_list) {
  601                 if (!swappable(l))
  602                         continue;
  603                 switch (l->l_stat) {
  604                 case LSONPROC:
  605                         continue;
  606 
  607                 case LSRUN:
  608                         if (l->l_swtime > outpri2) {
  609                                 outl2 = l;
  610                                 outpri2 = l->l_swtime;
  611                         }
  612                         continue;
  613 
  614                 case LSSLEEP:
  615                 case LSSTOP:
  616                         if (l->l_slptime >= maxslp) {
  617                                 uvm_swapout(l);
  618                                 didswap++;
  619                         } else if (l->l_slptime > outpri) {
  620                                 outl = l;
  621                                 outpri = l->l_slptime;
  622                         }
  623                         continue;
  624                 }
  625         }
  626         proclist_unlock_read();
  627 
  628         /*
  629          * If we didn't get rid of any real duds, toss out the next most
  630          * likely sleeping/stopped or running candidate.  We only do this
  631          * if we are real low on memory since we don't gain much by doing
  632          * it (USPACE bytes).
  633          */
  634         if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) {
  635                 if ((l = outl) == NULL)
  636                         l = outl2;
  637 #ifdef DEBUG
  638                 if (swapdebug & SDB_SWAPOUT)
  639                         printf("swapout_threads: no duds, try procp %p\n", l);
  640 #endif
  641                 if (l)
  642                         uvm_swapout(l);
  643         }
  644 }
  645 
  646 /*
  647  * uvm_swapout: swap out lwp "l"
  648  *
  649  * - currently "swapout" means "unwire U-area" and "pmap_collect()"
  650  *   the pmap.
  651  * - XXXCDC: should deactivate all process' private anonymous memory
  652  */
  653 
  654 static void
  655 uvm_swapout(l)
  656         struct lwp *l;
  657 {
  658         vaddr_t addr;
  659         int s;
  660         struct proc *p = l->l_proc;
  661 
  662 #ifdef DEBUG
  663         if (swapdebug & SDB_SWAPOUT)
  664                 printf("swapout: lid %d.%d(%s)@%p, stat %x pri %d free %d\n",
  665            p->p_pid, l->l_lid, p->p_comm, l->l_addr, l->l_stat,
  666            l->l_slptime, uvmexp.free);
  667 #endif
  668 
  669         /*
  670          * Mark it as (potentially) swapped out.
  671          */
  672         SCHED_LOCK(s);
  673         if (l->l_stat == LSONPROC) {
  674                 KDASSERT(l->l_cpu != curcpu());
  675                 SCHED_UNLOCK(s);
  676                 return;
  677         }
  678         l->l_flag &= ~L_INMEM;
  679         if (l->l_stat == LSRUN)
  680                 remrunqueue(l);
  681         SCHED_UNLOCK(s);
  682         l->l_swtime = 0;
  683         p->p_stats->p_ru.ru_nswap++;
  684         ++uvmexp.swapouts;
  685 
  686         /*
  687          * Do any machine-specific actions necessary before swapout.
  688          * This can include saving floating point state, etc.
  689          */
  690         cpu_swapout(l);
  691 
  692         /*
  693          * Unwire the to-be-swapped process's user struct and kernel stack.
  694          */
  695         addr = (vaddr_t)l->l_addr;
  696         uvm_fault_unwire(kernel_map, addr, addr + USPACE); /* !L_INMEM */
  697         pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map));
  698 }
  699 
  700 /*
  701  * uvm_coredump_walkmap: walk a process's map for the purpose of dumping
  702  * a core file.
  703  */
  704 
  705 int
  706 uvm_coredump_walkmap(p, vp, cred, func, cookie)
  707         struct proc *p;
  708         struct vnode *vp;
  709         struct ucred *cred;
  710         int (*func)(struct proc *, struct vnode *, struct ucred *,
  711             struct uvm_coredump_state *);
  712         void *cookie;
  713 {
  714         struct uvm_coredump_state state;
  715         struct vmspace *vm = p->p_vmspace;
  716         struct vm_map *map = &vm->vm_map;
  717         struct vm_map_entry *entry;
  718         vaddr_t maxstack;
  719         int error;
  720 
  721         maxstack = trunc_page(USRSTACK - ctob(vm->vm_ssize));
  722 
  723         entry = NULL;
  724         vm_map_lock_read(map);
  725         for (;;) {
  726                 if (entry == NULL)
  727                         entry = map->header.next;
  728                 else if (!uvm_map_lookup_entry(map, state.end, &entry))
  729                         entry = entry->next;
  730                 if (entry == &map->header)
  731                         break;
  732 
  733                 /* Should never happen for a user process. */
  734                 if (UVM_ET_ISSUBMAP(entry))
  735                         panic("uvm_coredump_walkmap: user process with "
  736                             "submap?");
  737 
  738                 state.cookie = cookie;
  739                 state.start = entry->start;
  740                 state.end = entry->end;
  741                 state.prot = entry->protection;
  742                 state.flags = 0;
  743 
  744                 if (state.start >= VM_MAXUSER_ADDRESS)
  745                         continue;
  746 
  747                 if (state.end > VM_MAXUSER_ADDRESS)
  748                         state.end = VM_MAXUSER_ADDRESS;
  749 
  750                 if (state.start >= (vaddr_t)vm->vm_maxsaddr) {
  751                         if (state.end <= maxstack)
  752                                 continue;
  753                         if (state.start < maxstack)
  754                                 state.start = maxstack;
  755                         state.flags |= UVM_COREDUMP_STACK;
  756                 }
  757 
  758                 if ((entry->protection & VM_PROT_WRITE) == 0)
  759                         state.flags |= UVM_COREDUMP_NODUMP;
  760 
  761                 if (entry->object.uvm_obj != NULL &&
  762                     UVM_OBJ_IS_DEVICE(entry->object.uvm_obj))
  763                         state.flags |= UVM_COREDUMP_NODUMP;
  764 
  765                 vm_map_unlock_read(map);
  766                 error = (*func)(p, vp, cred, &state);
  767                 if (error)
  768                         return (error);
  769                 vm_map_lock_read(map);
  770         }
  771         vm_map_unlock_read(map);
  772 
  773         return (0);
  774 }

Cache object: 0a42a0b6c42d84d955e3d7c7123383ba


[ 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.