[BACK]Return to uvm_glue.c CVS log [TXT][DIR] Up to [local] / sys / uvm

Annotation of sys/uvm/uvm_glue.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: uvm_glue.c,v 1.47 2007/05/26 20:26:51 pedro Exp $     */
        !             2: /*     $NetBSD: uvm_glue.c,v 1.44 2001/02/06 19:54:44 eeh Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1997 Charles D. Cranor and Washington University.
        !             6:  * Copyright (c) 1991, 1993, The Regents of the University of California.
        !             7:  *
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * The Mach Operating System project at Carnegie-Mellon University.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. All advertising materials mentioning features or use of this software
        !            22:  *    must display the following acknowledgement:
        !            23:  *     This product includes software developed by Charles D. Cranor,
        !            24:  *      Washington University, the University of California, Berkeley and
        !            25:  *      its contributors.
        !            26:  * 4. Neither the name of the University nor the names of its contributors
        !            27:  *    may be used to endorse or promote products derived from this software
        !            28:  *    without specific prior written permission.
        !            29:  *
        !            30:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            31:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            32:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            33:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            34:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            35:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            36:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            37:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            38:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            39:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            40:  * SUCH DAMAGE.
        !            41:  *
        !            42:  *     @(#)vm_glue.c   8.6 (Berkeley) 1/5/94
        !            43:  * from: Id: uvm_glue.c,v 1.1.2.8 1998/02/07 01:16:54 chs Exp
        !            44:  *
        !            45:  *
        !            46:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
        !            47:  * All rights reserved.
        !            48:  *
        !            49:  * Permission to use, copy, modify and distribute this software and
        !            50:  * its documentation is hereby granted, provided that both the copyright
        !            51:  * notice and this permission notice appear in all copies of the
        !            52:  * software, derivative works or modified versions, and any portions
        !            53:  * thereof, and that both notices appear in supporting documentation.
        !            54:  *
        !            55:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            56:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            57:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            58:  *
        !            59:  * Carnegie Mellon requests users of this software to return to
        !            60:  *
        !            61:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            62:  *  School of Computer Science
        !            63:  *  Carnegie Mellon University
        !            64:  *  Pittsburgh PA 15213-3890
        !            65:  *
        !            66:  * any improvements or extensions that they make and grant Carnegie the
        !            67:  * rights to redistribute these changes.
        !            68:  */
        !            69:
        !            70: /*
        !            71:  * uvm_glue.c: glue functions
        !            72:  */
        !            73:
        !            74: #include <sys/param.h>
        !            75: #include <sys/systm.h>
        !            76: #include <sys/proc.h>
        !            77: #include <sys/resourcevar.h>
        !            78: #include <sys/buf.h>
        !            79: #include <sys/user.h>
        !            80: #ifdef SYSVSHM
        !            81: #include <sys/shm.h>
        !            82: #endif
        !            83: #include <sys/sched.h>
        !            84:
        !            85: #include <uvm/uvm.h>
        !            86:
        !            87: #include <machine/cpu.h>
        !            88:
        !            89: /*
        !            90:  * XXXCDC: do these really belong here?
        !            91:  */
        !            92:
        !            93: int readbuffers = 0;           /* allow KGDB to read kern buffer pool */
        !            94:                                /* XXX: see uvm_kernacc */
        !            95:
        !            96:
        !            97: /*
        !            98:  * uvm_kernacc: can the kernel access a region of memory
        !            99:  *
        !           100:  * - called from malloc [DIAGNOSTIC], and /dev/kmem driver (mem.c)
        !           101:  */
        !           102:
        !           103: boolean_t
        !           104: uvm_kernacc(addr, len, rw)
        !           105:        caddr_t addr;
        !           106:        size_t len;
        !           107:        int rw;
        !           108: {
        !           109:        boolean_t rv;
        !           110:        vaddr_t saddr, eaddr;
        !           111:        vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
        !           112:
        !           113:        saddr = trunc_page((vaddr_t)addr);
        !           114:        eaddr = round_page((vaddr_t)addr + len);
        !           115:        vm_map_lock_read(kernel_map);
        !           116:        rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot);
        !           117:        vm_map_unlock_read(kernel_map);
        !           118:
        !           119:        return(rv);
        !           120: }
        !           121:
        !           122: #ifdef KGDB
        !           123: /*
        !           124:  * Change protections on kernel pages from addr to addr+len
        !           125:  * (presumably so debugger can plant a breakpoint).
        !           126:  *
        !           127:  * We force the protection change at the pmap level.  If we were
        !           128:  * to use vm_map_protect a change to allow writing would be lazily-
        !           129:  * applied meaning we would still take a protection fault, something
        !           130:  * we really don't want to do.  It would also fragment the kernel
        !           131:  * map unnecessarily.  We cannot use pmap_protect since it also won't
        !           132:  * enforce a write-enable request.  Using pmap_enter is the only way
        !           133:  * we can ensure the change takes place properly.
        !           134:  */
        !           135: void
        !           136: uvm_chgkprot(addr, len, rw)
        !           137:        caddr_t addr;
        !           138:        size_t len;
        !           139:        int rw;
        !           140: {
        !           141:        vm_prot_t prot;
        !           142:        paddr_t pa;
        !           143:        vaddr_t sva, eva;
        !           144:
        !           145:        prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE;
        !           146:        eva = round_page((vaddr_t)addr + len);
        !           147:        for (sva = trunc_page((vaddr_t)addr); sva < eva; sva += PAGE_SIZE) {
        !           148:                /*
        !           149:                 * Extract physical address for the page.
        !           150:                 * We use a cheezy hack to differentiate physical
        !           151:                 * page 0 from an invalid mapping, not that it
        !           152:                 * really matters...
        !           153:                 */
        !           154:                if (pmap_extract(pmap_kernel(), sva, &pa) == FALSE)
        !           155:                        panic("chgkprot: invalid page");
        !           156:                pmap_enter(pmap_kernel(), sva, pa, prot, PMAP_WIRED);
        !           157:        }
        !           158:        pmap_update(pmap_kernel());
        !           159: }
        !           160: #endif
        !           161:
        !           162: /*
        !           163:  * uvm_vslock: wire user memory for I/O
        !           164:  *
        !           165:  * - called from physio and sys___sysctl
        !           166:  * - XXXCDC: consider nuking this (or making it a macro?)
        !           167:  */
        !           168:
        !           169: int
        !           170: uvm_vslock(p, addr, len, access_type)
        !           171:        struct proc *p;
        !           172:        caddr_t addr;
        !           173:        size_t  len;
        !           174:        vm_prot_t access_type;
        !           175: {
        !           176:        vm_map_t map;
        !           177:        vaddr_t start, end;
        !           178:        int rv;
        !           179:
        !           180:        map = &p->p_vmspace->vm_map;
        !           181:        start = trunc_page((vaddr_t)addr);
        !           182:        end = round_page((vaddr_t)addr + len);
        !           183:        if (end <= start)
        !           184:                return (EINVAL);
        !           185:
        !           186:        rv = uvm_fault_wire(map, start, end, access_type);
        !           187:
        !           188:        return (rv);
        !           189: }
        !           190:
        !           191: /*
        !           192:  * uvm_vsunlock: unwire user memory wired by uvm_vslock()
        !           193:  *
        !           194:  * - called from physio and sys___sysctl
        !           195:  * - XXXCDC: consider nuking this (or making it a macro?)
        !           196:  */
        !           197:
        !           198: void
        !           199: uvm_vsunlock(p, addr, len)
        !           200:        struct proc *p;
        !           201:        caddr_t addr;
        !           202:        size_t  len;
        !           203: {
        !           204:        vaddr_t start, end;
        !           205:
        !           206:        start = trunc_page((vaddr_t)addr);
        !           207:        end = round_page((vaddr_t)addr + len);
        !           208:        if (end <= start)
        !           209:                return;
        !           210:
        !           211:        uvm_fault_unwire(&p->p_vmspace->vm_map, start, end);
        !           212: }
        !           213:
        !           214: /*
        !           215:  * uvm_fork: fork a virtual address space
        !           216:  *
        !           217:  * - the address space is copied as per parent map's inherit values
        !           218:  * - a new "user" structure is allocated for the child process
        !           219:  *     [filled in by MD layer...]
        !           220:  * - if specified, the child gets a new user stack described by
        !           221:  *     stack and stacksize
        !           222:  * - NOTE: the kernel stack may be at a different location in the child
        !           223:  *     process, and thus addresses of automatic variables may be invalid
        !           224:  *     after cpu_fork returns in the child process.  We do nothing here
        !           225:  *     after cpu_fork returns.
        !           226:  * - XXXCDC: we need a way for this to return a failure value rather
        !           227:  *   than just hang
        !           228:  */
        !           229: void
        !           230: uvm_fork(p1, p2, shared, stack, stacksize, func, arg)
        !           231:        struct proc *p1, *p2;
        !           232:        boolean_t shared;
        !           233:        void *stack;
        !           234:        size_t stacksize;
        !           235:        void (*func)(void *);
        !           236:        void *arg;
        !           237: {
        !           238:        struct user *up = p2->p_addr;
        !           239:
        !           240:        if (shared == TRUE) {
        !           241:                p2->p_vmspace = NULL;
        !           242:                uvmspace_share(p1, p2);                 /* share vmspace */
        !           243:        } else
        !           244:                p2->p_vmspace = uvmspace_fork(p1->p_vmspace); /* fork vmspace */
        !           245:
        !           246: #ifdef PMAP_UAREA
        !           247:        /* Tell the pmap this is a u-area mapping */
        !           248:        PMAP_UAREA((vaddr_t)up);
        !           249: #endif
        !           250:
        !           251:        /*
        !           252:         * p_stats currently points at a field in the user struct.  Copy
        !           253:         * parts of p_stats, and zero out the rest.
        !           254:         */
        !           255:        p2->p_stats = &up->u_stats;
        !           256:        memset(&up->u_stats.pstat_startzero, 0,
        !           257:               ((caddr_t)&up->u_stats.pstat_endzero -
        !           258:                (caddr_t)&up->u_stats.pstat_startzero));
        !           259:        memcpy(&up->u_stats.pstat_startcopy, &p1->p_stats->pstat_startcopy,
        !           260:               ((caddr_t)&up->u_stats.pstat_endcopy -
        !           261:                (caddr_t)&up->u_stats.pstat_startcopy));
        !           262:
        !           263:        /*
        !           264:         * cpu_fork() copy and update the pcb, and make the child ready
        !           265:         * to run.  If this is a normal user fork, the child will exit
        !           266:         * directly to user mode via child_return() on its first time
        !           267:         * slice and will not return here.  If this is a kernel thread,
        !           268:         * the specified entry point will be executed.
        !           269:         */
        !           270:        cpu_fork(p1, p2, stack, stacksize, func, arg);
        !           271: }
        !           272:
        !           273: /*
        !           274:  * uvm_exit: exit a virtual address space
        !           275:  *
        !           276:  * - the process passed to us is a dead (pre-zombie) process; we
        !           277:  *   are running on a different context now (the reaper).
        !           278:  * - we must run in a separate thread because freeing the vmspace
        !           279:  *   of the dead process may block.
        !           280:  */
        !           281: void
        !           282: uvm_exit(struct proc *p)
        !           283: {
        !           284:        uvmspace_free(p->p_vmspace);
        !           285:        uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE);
        !           286:        p->p_addr = NULL;
        !           287: }
        !           288:
        !           289: /*
        !           290:  * uvm_init_limit: init per-process VM limits
        !           291:  *
        !           292:  * - called for process 0 and then inherited by all others.
        !           293:  */
        !           294: void
        !           295: uvm_init_limits(struct proc *p)
        !           296: {
        !           297:
        !           298:        /*
        !           299:         * Set up the initial limits on process VM.  Set the maximum
        !           300:         * resident set size to be all of (reasonably) available memory.
        !           301:         * This causes any single, large process to start random page
        !           302:         * replacement once it fills memory.
        !           303:         */
        !           304:
        !           305:        p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;
        !           306:        p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ;
        !           307:        p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;
        !           308:        p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ;
        !           309:        p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(uvmexp.free);
        !           310: }
        !           311:
        !           312: #ifdef DEBUG
        !           313: int    enableswap = 1;
        !           314: int    swapdebug = 0;
        !           315: #define        SDB_FOLLOW      1
        !           316: #define SDB_SWAPIN     2
        !           317: #define SDB_SWAPOUT    4
        !           318: #endif
        !           319:
        !           320: /*
        !           321:  * uvm_scheduler: process zero main loop
        !           322:  *
        !           323:  * - if not enough memory, wake the pagedaemon and let it clear space.
        !           324:  */
        !           325:
        !           326: void
        !           327: uvm_scheduler(void)
        !           328: {
        !           329:        /*
        !           330:         * Nothing to do, back to sleep
        !           331:         */
        !           332:        while (1)
        !           333:                tsleep(&proc0, PVM, "scheduler", 0);
        !           334: }
        !           335:
        !           336: /*
        !           337:  * swappable: is process "p" swappable?
        !           338:  */
        !           339:
        !           340: #define        swappable(p) (((p)->p_flag & (P_SYSTEM | P_WEXIT)) == 0)
        !           341:
        !           342: /*
        !           343:  * swapout_threads: find threads that can be swapped
        !           344:  *
        !           345:  * - called by the pagedaemon
        !           346:  * - try and swap at least one processs
        !           347:  * - processes that are sleeping or stopped for maxslp or more seconds
        !           348:  *   are swapped... otherwise the longest-sleeping or stopped process
        !           349:  *   is swapped, otherwise the longest resident process...
        !           350:  */
        !           351: void
        !           352: uvm_swapout_threads(void)
        !           353: {
        !           354:        struct proc *p;
        !           355:        struct proc *outp, *outp2;
        !           356:        int outpri, outpri2;
        !           357:        int didswap = 0;
        !           358:        extern int maxslp;
        !           359:        /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */
        !           360:
        !           361: #ifdef DEBUG
        !           362:        if (!enableswap)
        !           363:                return;
        !           364: #endif
        !           365:
        !           366:        /*
        !           367:         * outp/outpri  : stop/sleep process with largest sleeptime < maxslp
        !           368:         * outp2/outpri2: the longest resident process (its swap time)
        !           369:         */
        !           370:        outp = outp2 = NULL;
        !           371:        outpri = outpri2 = 0;
        !           372:        LIST_FOREACH(p, &allproc, p_list) {
        !           373:                if (!swappable(p))
        !           374:                        continue;
        !           375:                switch (p->p_stat) {
        !           376:                case SRUN:
        !           377:                        if (p->p_swtime > outpri2) {
        !           378:                                outp2 = p;
        !           379:                                outpri2 = p->p_swtime;
        !           380:                        }
        !           381:                        continue;
        !           382:
        !           383:                case SSLEEP:
        !           384:                case SSTOP:
        !           385:                        if (p->p_slptime >= maxslp) {
        !           386:                                pmap_collect(p->p_vmspace->vm_map.pmap);
        !           387:                                didswap++;
        !           388:                        } else if (p->p_slptime > outpri) {
        !           389:                                outp = p;
        !           390:                                outpri = p->p_slptime;
        !           391:                        }
        !           392:                        continue;
        !           393:                }
        !           394:        }
        !           395:
        !           396:        /*
        !           397:         * If we didn't get rid of any real duds, toss out the next most
        !           398:         * likely sleeping/stopped or running candidate.  We only do this
        !           399:         * if we are real low on memory since we don't gain much by doing
        !           400:         * it.
        !           401:         */
        !           402:        if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) {
        !           403:                if ((p = outp) == NULL)
        !           404:                        p = outp2;
        !           405: #ifdef DEBUG
        !           406:                if (swapdebug & SDB_SWAPOUT)
        !           407:                        printf("swapout_threads: no duds, try procp %p\n", p);
        !           408: #endif
        !           409:                if (p)
        !           410:                        pmap_collect(p->p_vmspace->vm_map.pmap);
        !           411:        }
        !           412: }

CVSweb