Annotation of Net2/vm/vm_mmap.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1991 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  * from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
        !            39:  *
        !            40:  *     @(#)vm_mmap.c   7.5 (Berkeley) 6/28/91
        !            41:  */
        !            42: 
        !            43: /*
        !            44:  * Mapped file (mmap) interface to VM
        !            45:  */
        !            46: 
        !            47: #include "param.h"
        !            48: #include "systm.h"
        !            49: #include "filedesc.h"
        !            50: #include "proc.h"
        !            51: #include "vnode.h"
        !            52: #include "specdev.h"
        !            53: #include "file.h"
        !            54: #include "mman.h"
        !            55: #include "conf.h"
        !            56: 
        !            57: #include "vm.h"
        !            58: #include "vm_pager.h"
        !            59: #include "vm_prot.h"
        !            60: #include "vm_statistics.h"
        !            61: 
        !            62: #ifdef DEBUG
        !            63: int mmapdebug = 0;
        !            64: #define MDB_FOLLOW     0x01
        !            65: #define MDB_SYNC       0x02
        !            66: #define MDB_MAPIT      0x04
        !            67: #endif
        !            68: 
        !            69: /* ARGSUSED */
        !            70: getpagesize(p, uap, retval)
        !            71:        struct proc *p;
        !            72:        void *uap;
        !            73:        int *retval;
        !            74: {
        !            75: 
        !            76:        *retval = NBPG * CLSIZE;
        !            77:        return (0);
        !            78: }
        !            79: 
        !            80: /* ARGSUSED */
        !            81: sbrk(p, uap, retval)
        !            82:        struct proc *p;
        !            83:        struct args {
        !            84:                int     incr;
        !            85:        } *uap;
        !            86:        int *retval;
        !            87: {
        !            88: 
        !            89:        /* Not yet implemented */
        !            90:        return (EOPNOTSUPP);
        !            91: }
        !            92: 
        !            93: /* ARGSUSED */
        !            94: sstk(p, uap, retval)
        !            95:        struct proc *p;
        !            96:        struct args {
        !            97:                int     incr;
        !            98:        } *uap;
        !            99:        int *retval;
        !           100: {
        !           101: 
        !           102:        /* Not yet implemented */
        !           103:        return (EOPNOTSUPP);
        !           104: }
        !           105: 
        !           106: smmap(p, uap, retval)
        !           107:        struct proc *p;
        !           108:        register struct args {
        !           109:                caddr_t addr;
        !           110:                int     len;
        !           111:                int     prot;
        !           112:                int     flags;
        !           113:                int     fd;
        !           114:                off_t   pos;
        !           115:        } *uap;
        !           116:        int *retval;
        !           117: {
        !           118:        register struct filedesc *fdp = p->p_fd;
        !           119:        register struct file *fp;
        !           120:        struct vnode *vp;
        !           121:        vm_offset_t addr;
        !           122:        vm_size_t size;
        !           123:        vm_prot_t prot;
        !           124:        caddr_t handle;
        !           125:        int mtype, error;
        !           126: 
        !           127: #ifdef DEBUG
        !           128:        if (mmapdebug & MDB_FOLLOW)
        !           129:                printf("mmap(%d): addr %x len %x pro %x flg %x fd %d pos %x\n",
        !           130:                       p->p_pid, uap->addr, uap->len, uap->prot,
        !           131:                       uap->flags, uap->fd, uap->pos);
        !           132: #endif
        !           133:        /*
        !           134:         * Make sure one of the sharing types is specified
        !           135:         */
        !           136:        mtype = uap->flags & MAP_TYPE;
        !           137:        switch (mtype) {
        !           138:        case MAP_FILE:
        !           139:        case MAP_ANON:
        !           140:                break;
        !           141:        default:
        !           142:                return(EINVAL);
        !           143:        }
        !           144:        /*
        !           145:         * Address (if FIXED) must be page aligned.
        !           146:         * Size is implicitly rounded to a page boundary.
        !           147:         */
        !           148:        addr = (vm_offset_t) uap->addr;
        !           149:        if ((uap->flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0)
        !           150:                return(EINVAL);
        !           151:        size = (vm_size_t) round_page(uap->len);
        !           152:        /*
        !           153:         * XXX if no hint provided for a non-fixed mapping place it after
        !           154:         * the end of the largest possible heap.
        !           155:         *
        !           156:         * There should really be a pmap call to determine a reasonable
        !           157:         * location.
        !           158:         */
        !           159:        if (addr == 0 && (uap->flags & MAP_FIXED) == 0)
        !           160:                addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
        !           161:        /*
        !           162:         * Mapping file or named anonymous, get fp for validation
        !           163:         */
        !           164:        if (mtype == MAP_FILE || uap->fd != -1) {
        !           165:                if (((unsigned)uap->fd) >= fdp->fd_nfiles ||
        !           166:                    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
        !           167:                        return(EBADF);
        !           168:        }
        !           169:        /*
        !           170:         * If we are mapping a file we need to check various
        !           171:         * file/vnode related things.
        !           172:         */
        !           173:        if (mtype == MAP_FILE) {
        !           174:                /*
        !           175:                 * Obtain vnode and make sure it is of appropriate type
        !           176:                 */
        !           177:                if (fp->f_type != DTYPE_VNODE)
        !           178:                        return(EINVAL);
        !           179:                vp = (struct vnode *)fp->f_data;
        !           180:                if (vp->v_type != VREG && vp->v_type != VCHR)
        !           181:                        return(EINVAL);
        !           182:                /*
        !           183:                 * Ensure that file protection and desired protection
        !           184:                 * are compatible.  Note that we only worry about writability
        !           185:                 * if mapping is shared.
        !           186:                 */
        !           187:                if ((uap->prot & PROT_READ) && (fp->f_flag & FREAD) == 0 ||
        !           188:                    ((uap->flags & MAP_SHARED) &&
        !           189:                     (uap->prot & PROT_WRITE) && (fp->f_flag & FWRITE) == 0))
        !           190:                        return(EACCES);
        !           191:                handle = (caddr_t)vp;
        !           192:        } else if (uap->fd != -1)
        !           193:                handle = (caddr_t)fp;
        !           194:        else
        !           195:                handle = NULL;
        !           196:        /*
        !           197:         * Map protections to MACH style
        !           198:         */
        !           199:        prot = VM_PROT_NONE;
        !           200:        if (uap->prot & PROT_READ)
        !           201:                prot |= VM_PROT_READ;
        !           202:        if (uap->prot & PROT_WRITE)
        !           203:                prot |= VM_PROT_WRITE;
        !           204:        if (uap->prot & PROT_EXEC)
        !           205:                prot |= VM_PROT_EXECUTE;
        !           206: 
        !           207:        error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot,
        !           208:                        uap->flags, handle, (vm_offset_t)uap->pos);
        !           209:        if (error == 0)
        !           210:                *retval = (int) addr;
        !           211:        return(error);
        !           212: }
        !           213: 
        !           214: msync(p, uap, retval)
        !           215:        struct proc *p;
        !           216:        struct args {
        !           217:                caddr_t addr;
        !           218:                int     len;
        !           219:        } *uap;
        !           220:        int *retval;
        !           221: {
        !           222:        vm_offset_t addr, objoff, oaddr;
        !           223:        vm_size_t size, osize;
        !           224:        vm_prot_t prot, mprot;
        !           225:        vm_inherit_t inherit;
        !           226:        vm_object_t object;
        !           227:        boolean_t shared;
        !           228:        int rv;
        !           229: 
        !           230: #ifdef DEBUG
        !           231:        if (mmapdebug & (MDB_FOLLOW|MDB_SYNC))
        !           232:                printf("msync(%d): addr %x len %x\n",
        !           233:                       p->p_pid, uap->addr, uap->len);
        !           234: #endif
        !           235:        if (((int)uap->addr & page_mask) || uap->len < 0)
        !           236:                return(EINVAL);
        !           237:        addr = oaddr = (vm_offset_t)uap->addr;
        !           238:        osize = (vm_size_t)uap->len;
        !           239:        /*
        !           240:         * Region must be entirely contained in a single entry
        !           241:         */
        !           242:        if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+osize,
        !           243:            TRUE))
        !           244:                return(EINVAL);
        !           245:        /*
        !           246:         * Determine the object associated with that entry
        !           247:         * (object is returned locked on KERN_SUCCESS)
        !           248:         */
        !           249:        rv = vm_region(&p->p_vmspace->vm_map, &addr, &size, &prot, &mprot,
        !           250:                       &inherit, &shared, &object, &objoff);
        !           251:        if (rv != KERN_SUCCESS)
        !           252:                return(EINVAL);
        !           253: #ifdef DEBUG
        !           254:        if (mmapdebug & MDB_SYNC)
        !           255:                printf("msync: region: object %x addr %x size %d objoff %d\n",
        !           256:                       object, addr, size, objoff);
        !           257: #endif
        !           258:        /*
        !           259:         * Do not msync non-vnoded backed objects.
        !           260:         */
        !           261:        if (object->internal || object->pager == NULL ||
        !           262:            object->pager->pg_type != PG_VNODE) {
        !           263:                vm_object_unlock(object);
        !           264:                return(EINVAL);
        !           265:        }
        !           266:        objoff += oaddr - addr;
        !           267:        if (osize == 0)
        !           268:                osize = size;
        !           269: #ifdef DEBUG
        !           270:        if (mmapdebug & MDB_SYNC)
        !           271:                printf("msync: cleaning/flushing object range [%x-%x)\n",
        !           272:                       objoff, objoff+osize);
        !           273: #endif
        !           274:        if (prot & VM_PROT_WRITE)
        !           275:                vm_object_page_clean(object, objoff, objoff+osize);
        !           276:        /*
        !           277:         * (XXX)
        !           278:         * Bummer, gotta flush all cached pages to ensure
        !           279:         * consistency with the file system cache.
        !           280:         */
        !           281:        vm_object_page_remove(object, objoff, objoff+osize);
        !           282:        vm_object_unlock(object);
        !           283:        return(0);
        !           284: }
        !           285: 
        !           286: munmap(p, uap, retval)
        !           287:        register struct proc *p;
        !           288:        register struct args {
        !           289:                caddr_t addr;
        !           290:                int     len;
        !           291:        } *uap;
        !           292:        int *retval;
        !           293: {
        !           294:        vm_offset_t addr;
        !           295:        vm_size_t size;
        !           296: 
        !           297: #ifdef DEBUG
        !           298:        if (mmapdebug & MDB_FOLLOW)
        !           299:                printf("munmap(%d): addr %x len %x\n",
        !           300:                       p->p_pid, uap->addr, uap->len);
        !           301: #endif
        !           302: 
        !           303:        addr = (vm_offset_t) uap->addr;
        !           304:        if ((addr & page_mask) || uap->len < 0)
        !           305:                return(EINVAL);
        !           306:        size = (vm_size_t) round_page(uap->len);
        !           307:        if (size == 0)
        !           308:                return(0);
        !           309:        if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+size,
        !           310:            FALSE))
        !           311:                return(EINVAL);
        !           312:        /* returns nothing but KERN_SUCCESS anyway */
        !           313:        (void) vm_map_remove(&p->p_vmspace->vm_map, addr, addr+size);
        !           314:        return(0);
        !           315: }
        !           316: 
        !           317: munmapfd(fd)
        !           318: {
        !           319: #ifdef DEBUG
        !           320:        if (mmapdebug & MDB_FOLLOW)
        !           321:                printf("munmapfd(%d): fd %d\n", curproc->p_pid, fd);
        !           322: #endif
        !           323: 
        !           324:        /*
        !           325:         * XXX -- should vm_deallocate any regions mapped to this file
        !           326:         */
        !           327:        curproc->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
        !           328: }
        !           329: 
        !           330: mprotect(p, uap, retval)
        !           331:        struct proc *p;
        !           332:        struct args {
        !           333:                caddr_t addr;
        !           334:                int     len;
        !           335:                int     prot;
        !           336:        } *uap;
        !           337:        int *retval;
        !           338: {
        !           339:        vm_offset_t addr;
        !           340:        vm_size_t size;
        !           341:        register vm_prot_t prot;
        !           342: 
        !           343: #ifdef DEBUG
        !           344:        if (mmapdebug & MDB_FOLLOW)
        !           345:                printf("mprotect(%d): addr %x len %x prot %d\n",
        !           346:                       p->p_pid, uap->addr, uap->len, uap->prot);
        !           347: #endif
        !           348: 
        !           349:        addr = (vm_offset_t) uap->addr;
        !           350:        if ((addr & page_mask) || uap->len < 0)
        !           351:                return(EINVAL);
        !           352:        size = (vm_size_t) uap->len;
        !           353:        /*
        !           354:         * Map protections
        !           355:         */
        !           356:        prot = VM_PROT_NONE;
        !           357:        if (uap->prot & PROT_READ)
        !           358:                prot |= VM_PROT_READ;
        !           359:        if (uap->prot & PROT_WRITE)
        !           360:                prot |= VM_PROT_WRITE;
        !           361:        if (uap->prot & PROT_EXEC)
        !           362:                prot |= VM_PROT_EXECUTE;
        !           363: 
        !           364:        switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr+size, prot,
        !           365:            FALSE)) {
        !           366:        case KERN_SUCCESS:
        !           367:                return (0);
        !           368:        case KERN_PROTECTION_FAILURE:
        !           369:                return (EACCES);
        !           370:        }
        !           371:        return (EINVAL);
        !           372: }
        !           373: 
        !           374: /* ARGSUSED */
        !           375: madvise(p, uap, retval)
        !           376:        struct proc *p;
        !           377:        struct args {
        !           378:                caddr_t addr;
        !           379:                int     len;
        !           380:                int     behav;
        !           381:        } *uap;
        !           382:        int *retval;
        !           383: {
        !           384: 
        !           385:        /* Not yet implemented */
        !           386:        return (EOPNOTSUPP);
        !           387: }
        !           388: 
        !           389: /* ARGSUSED */
        !           390: mincore(p, uap, retval)
        !           391:        struct proc *p;
        !           392:        struct args {
        !           393:                caddr_t addr;
        !           394:                int     len;
        !           395:                char    *vec;
        !           396:        } *uap;
        !           397:        int *retval;
        !           398: {
        !           399: 
        !           400:        /* Not yet implemented */
        !           401:        return (EOPNOTSUPP);
        !           402: }
        !           403: 
        !           404: /*
        !           405:  * Internal version of mmap.
        !           406:  * Currently used by mmap, exec, and sys5 shared memory.
        !           407:  * Handle is:
        !           408:  *     MAP_FILE: a vnode pointer
        !           409:  *     MAP_ANON: NULL or a file pointer
        !           410:  */
        !           411: vm_mmap(map, addr, size, prot, flags, handle, foff)
        !           412:        register vm_map_t map;
        !           413:        register vm_offset_t *addr;
        !           414:        register vm_size_t size;
        !           415:        vm_prot_t prot;
        !           416:        register int flags;
        !           417:        caddr_t handle;         /* XXX should be vp */
        !           418:        vm_offset_t foff;
        !           419: {
        !           420:        register vm_pager_t pager;
        !           421:        boolean_t fitit;
        !           422:        vm_object_t object;
        !           423:        struct vnode *vp;
        !           424:        int type;
        !           425:        int rv = KERN_SUCCESS;
        !           426: 
        !           427:        if (size == 0)
        !           428:                return (0);
        !           429: 
        !           430:        if ((flags & MAP_FIXED) == 0) {
        !           431:                fitit = TRUE;
        !           432:                *addr = round_page(*addr);
        !           433:        } else {
        !           434:                fitit = FALSE;
        !           435:                (void) vm_deallocate(map, *addr, size);
        !           436:        }
        !           437: 
        !           438:        /*
        !           439:         * Lookup/allocate pager.  All except an unnamed anonymous lookup
        !           440:         * gain a reference to ensure continued existance of the object.
        !           441:         * (XXX the exception is to appease the pageout daemon)
        !           442:         */
        !           443:        if ((flags & MAP_TYPE) == MAP_ANON)
        !           444:                type = PG_DFLT;
        !           445:        else {
        !           446:                vp = (struct vnode *)handle;
        !           447:                if (vp->v_type == VCHR) {
        !           448:                        type = PG_DEVICE;
        !           449:                        handle = (caddr_t)vp->v_rdev;
        !           450:                } else
        !           451:                        type = PG_VNODE;
        !           452:        }
        !           453:        pager = vm_pager_allocate(type, handle, size, prot);
        !           454:        if (pager == NULL)
        !           455:                return (type == PG_DEVICE ? EINVAL : ENOMEM);
        !           456:        /*
        !           457:         * Find object and release extra reference gained by lookup
        !           458:         */
        !           459:        object = vm_object_lookup(pager);
        !           460:        vm_object_deallocate(object);
        !           461: 
        !           462:        /*
        !           463:         * Anonymous memory.
        !           464:         */
        !           465:        if ((flags & MAP_TYPE) == MAP_ANON) {
        !           466:                rv = vm_allocate_with_pager(map, addr, size, fitit,
        !           467:                                            pager, (vm_offset_t)foff, TRUE);
        !           468:                if (rv != KERN_SUCCESS) {
        !           469:                        if (handle == NULL)
        !           470:                                vm_pager_deallocate(pager);
        !           471:                        else
        !           472:                                vm_object_deallocate(object);
        !           473:                        goto out;
        !           474:                }
        !           475:                /*
        !           476:                 * Don't cache anonymous objects.
        !           477:                 * Loses the reference gained by vm_pager_allocate.
        !           478:                 */
        !           479:                (void) pager_cache(object, FALSE);
        !           480: #ifdef DEBUG
        !           481:                if (mmapdebug & MDB_MAPIT)
        !           482:                        printf("vm_mmap(%d): ANON *addr %x size %x pager %x\n",
        !           483:                               curproc->p_pid, *addr, size, pager);
        !           484: #endif
        !           485:        }
        !           486:        /*
        !           487:         * Must be type MAP_FILE.
        !           488:         * Distinguish between character special and regular files.
        !           489:         */
        !           490:        else if (vp->v_type == VCHR) {
        !           491:                rv = vm_allocate_with_pager(map, addr, size, fitit,
        !           492:                                            pager, (vm_offset_t)foff, FALSE);
        !           493:                /*
        !           494:                 * Uncache the object and lose the reference gained
        !           495:                 * by vm_pager_allocate().  If the call to
        !           496:                 * vm_allocate_with_pager() was sucessful, then we
        !           497:                 * gained an additional reference ensuring the object
        !           498:                 * will continue to exist.  If the call failed then
        !           499:                 * the deallocate call below will terminate the
        !           500:                 * object which is fine.
        !           501:                 */
        !           502:                (void) pager_cache(object, FALSE);
        !           503:                if (rv != KERN_SUCCESS)
        !           504:                        goto out;
        !           505:        }
        !           506:        /*
        !           507:         * A regular file
        !           508:         */
        !           509:        else {
        !           510: #ifdef DEBUG
        !           511:                if (object == NULL)
        !           512:                        printf("vm_mmap: no object: vp %x, pager %x\n",
        !           513:                               vp, pager);
        !           514: #endif
        !           515:                /*
        !           516:                 * Map it directly.
        !           517:                 * Allows modifications to go out to the vnode.
        !           518:                 */
        !           519:                if (flags & MAP_SHARED) {
        !           520:                        rv = vm_allocate_with_pager(map, addr, size,
        !           521:                                                    fitit, pager,
        !           522:                                                    (vm_offset_t)foff, FALSE);
        !           523:                        if (rv != KERN_SUCCESS) {
        !           524:                                vm_object_deallocate(object);
        !           525:                                goto out;
        !           526:                        }
        !           527:                        /*
        !           528:                         * Don't cache the object.  This is the easiest way
        !           529:                         * of ensuring that data gets back to the filesystem
        !           530:                         * because vnode_pager_deallocate() will fsync the
        !           531:                         * vnode.  pager_cache() will lose the extra ref.
        !           532:                         */
        !           533:                        if (prot & VM_PROT_WRITE)
        !           534:                                pager_cache(object, FALSE);
        !           535:                        else
        !           536:                                vm_object_deallocate(object);
        !           537:                }
        !           538:                /*
        !           539:                 * Copy-on-write of file.  Two flavors.
        !           540:                 * MAP_COPY is true COW, you essentially get a snapshot of
        !           541:                 * the region at the time of mapping.  MAP_PRIVATE means only
        !           542:                 * that your changes are not reflected back to the object.
        !           543:                 * Changes made by others will be seen.
        !           544:                 */
        !           545:                else {
        !           546:                        vm_map_t tmap;
        !           547:                        vm_offset_t off;
        !           548: 
        !           549:                        /* locate and allocate the target address space */
        !           550:                        rv = vm_map_find(map, NULL, (vm_offset_t)0,
        !           551:                                         addr, size, fitit);
        !           552:                        if (rv != KERN_SUCCESS) {
        !           553:                                vm_object_deallocate(object);
        !           554:                                goto out;
        !           555:                        }
        !           556:                        tmap = vm_map_create(pmap_create(size), VM_MIN_ADDRESS,
        !           557:                                             VM_MIN_ADDRESS+size, TRUE);
        !           558:                        off = VM_MIN_ADDRESS;
        !           559:                        rv = vm_allocate_with_pager(tmap, &off, size,
        !           560:                                                    TRUE, pager,
        !           561:                                                    (vm_offset_t)foff, FALSE);
        !           562:                        if (rv != KERN_SUCCESS) {
        !           563:                                vm_object_deallocate(object);
        !           564:                                vm_map_deallocate(tmap);
        !           565:                                goto out;
        !           566:                        }
        !           567:                        /*
        !           568:                         * (XXX)
        !           569:                         * MAP_PRIVATE implies that we see changes made by
        !           570:                         * others.  To ensure that we need to guarentee that
        !           571:                         * no copy object is created (otherwise original
        !           572:                         * pages would be pushed to the copy object and we
        !           573:                         * would never see changes made by others).  We
        !           574:                         * totally sleeze it right now by marking the object
        !           575:                         * internal temporarily.
        !           576:                         */
        !           577:                        if ((flags & MAP_COPY) == 0)
        !           578:                                object->internal = TRUE;
        !           579:                        rv = vm_map_copy(map, tmap, *addr, size, off,
        !           580:                                         FALSE, FALSE);
        !           581:                        object->internal = FALSE;
        !           582:                        /*
        !           583:                         * (XXX)
        !           584:                         * My oh my, this only gets worse...
        !           585:                         * Force creation of a shadow object so that
        !           586:                         * vm_map_fork will do the right thing.
        !           587:                         */
        !           588:                        if ((flags & MAP_COPY) == 0) {
        !           589:                                vm_map_t tmap;
        !           590:                                vm_map_entry_t tentry;
        !           591:                                vm_object_t tobject;
        !           592:                                vm_offset_t toffset;
        !           593:                                vm_prot_t tprot;
        !           594:                                boolean_t twired, tsu;
        !           595: 
        !           596:                                tmap = map;
        !           597:                                vm_map_lookup(&tmap, *addr, VM_PROT_WRITE,
        !           598:                                              &tentry, &tobject, &toffset,
        !           599:                                              &tprot, &twired, &tsu);
        !           600:                                vm_map_lookup_done(tmap, tentry);
        !           601:                        }
        !           602:                        /*
        !           603:                         * (XXX)
        !           604:                         * Map copy code cannot detect sharing unless a
        !           605:                         * sharing map is involved.  So we cheat and write
        !           606:                         * protect everything ourselves.
        !           607:                         */
        !           608:                        vm_object_pmap_copy(object, (vm_offset_t)foff,
        !           609:                                            (vm_offset_t)foff+size);
        !           610:                        vm_object_deallocate(object);
        !           611:                        vm_map_deallocate(tmap);
        !           612:                        if (rv != KERN_SUCCESS)
        !           613:                                goto out;
        !           614:                }
        !           615: #ifdef DEBUG
        !           616:                if (mmapdebug & MDB_MAPIT)
        !           617:                        printf("vm_mmap(%d): FILE *addr %x size %x pager %x\n",
        !           618:                               curproc->p_pid, *addr, size, pager);
        !           619: #endif
        !           620:        }
        !           621:        /*
        !           622:         * Correct protection (default is VM_PROT_ALL).
        !           623:         * Note that we set the maximum protection.  This may not be
        !           624:         * entirely correct.  Maybe the maximum protection should be based
        !           625:         * on the object permissions where it makes sense (e.g. a vnode).
        !           626:         *
        !           627:         * Changed my mind: leave max prot at VM_PROT_ALL.
        !           628:         */
        !           629:        if (prot != VM_PROT_ALL) {
        !           630:                rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE);
        !           631:                if (rv != KERN_SUCCESS) {
        !           632:                        (void) vm_deallocate(map, *addr, size);
        !           633:                        goto out;
        !           634:                }
        !           635:        }
        !           636:        /*
        !           637:         * Shared memory is also shared with children.
        !           638:         */
        !           639:        if (flags & MAP_SHARED) {
        !           640:                rv = vm_inherit(map, *addr, size, VM_INHERIT_SHARE);
        !           641:                if (rv != KERN_SUCCESS) {
        !           642:                        (void) vm_deallocate(map, *addr, size);
        !           643:                        goto out;
        !           644:                }
        !           645:        }
        !           646: out:
        !           647: #ifdef DEBUG
        !           648:        if (mmapdebug & MDB_MAPIT)
        !           649:                printf("vm_mmap: rv %d\n", rv);
        !           650: #endif
        !           651:        switch (rv) {
        !           652:        case KERN_SUCCESS:
        !           653:                return (0);
        !           654:        case KERN_INVALID_ADDRESS:
        !           655:        case KERN_NO_SPACE:
        !           656:                return (ENOMEM);
        !           657:        case KERN_PROTECTION_FAILURE:
        !           658:                return (EACCES);
        !           659:        default:
        !           660:                return (EINVAL);
        !           661:        }
        !           662: }
        !           663: 
        !           664: /*
        !           665:  * Internal bastardized version of MACHs vm_region system call.
        !           666:  * Given address and size it returns map attributes as well
        !           667:  * as the (locked) object mapped at that location. 
        !           668:  */
        !           669: vm_region(map, addr, size, prot, max_prot, inheritance, shared, object, objoff)
        !           670:        vm_map_t        map;
        !           671:        vm_offset_t     *addr;          /* IN/OUT */
        !           672:        vm_size_t       *size;          /* OUT */
        !           673:        vm_prot_t       *prot;          /* OUT */
        !           674:        vm_prot_t       *max_prot;      /* OUT */
        !           675:        vm_inherit_t    *inheritance;   /* OUT */
        !           676:        boolean_t       *shared;        /* OUT */
        !           677:        vm_object_t     *object;        /* OUT */
        !           678:        vm_offset_t     *objoff;        /* OUT */
        !           679: {
        !           680:        vm_map_entry_t  tmp_entry;
        !           681:        register
        !           682:        vm_map_entry_t  entry;
        !           683:        register
        !           684:        vm_offset_t     tmp_offset;
        !           685:        vm_offset_t     start;
        !           686: 
        !           687:        if (map == NULL)
        !           688:                return(KERN_INVALID_ARGUMENT);
        !           689:        
        !           690:        start = *addr;
        !           691: 
        !           692:        vm_map_lock_read(map);
        !           693:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
        !           694:                if ((entry = tmp_entry->next) == &map->header) {
        !           695:                        vm_map_unlock_read(map);
        !           696:                        return(KERN_NO_SPACE);
        !           697:                }
        !           698:                start = entry->start;
        !           699:                *addr = start;
        !           700:        } else
        !           701:                entry = tmp_entry;
        !           702: 
        !           703:        *prot = entry->protection;
        !           704:        *max_prot = entry->max_protection;
        !           705:        *inheritance = entry->inheritance;
        !           706: 
        !           707:        tmp_offset = entry->offset + (start - entry->start);
        !           708:        *size = (entry->end - start);
        !           709: 
        !           710:        if (entry->is_a_map) {
        !           711:                register vm_map_t share_map;
        !           712:                vm_size_t share_size;
        !           713: 
        !           714:                share_map = entry->object.share_map;
        !           715: 
        !           716:                vm_map_lock_read(share_map);
        !           717:                (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
        !           718: 
        !           719:                if ((share_size = (tmp_entry->end - tmp_offset)) < *size)
        !           720:                        *size = share_size;
        !           721: 
        !           722:                vm_object_lock(tmp_entry->object);
        !           723:                *object = tmp_entry->object.vm_object;
        !           724:                *objoff = tmp_entry->offset + (tmp_offset - tmp_entry->start);
        !           725: 
        !           726:                *shared = (share_map->ref_count != 1);
        !           727:                vm_map_unlock_read(share_map);
        !           728:        } else {
        !           729:                vm_object_lock(entry->object);
        !           730:                *object = entry->object.vm_object;
        !           731:                *objoff = tmp_offset;
        !           732: 
        !           733:                *shared = FALSE;
        !           734:        }
        !           735: 
        !           736:        vm_map_unlock_read(map);
        !           737: 
        !           738:        return(KERN_SUCCESS);
        !           739: }
        !           740: 
        !           741: /*
        !           742:  * Yet another bastard routine.
        !           743:  */
        !           744: vm_allocate_with_pager(map, addr, size, fitit, pager, poffset, internal)
        !           745:        register vm_map_t       map;
        !           746:        register vm_offset_t    *addr;
        !           747:        register vm_size_t      size;
        !           748:        boolean_t               fitit;
        !           749:        vm_pager_t              pager;
        !           750:        vm_offset_t             poffset;
        !           751:        boolean_t               internal;
        !           752: {
        !           753:        register vm_object_t    object;
        !           754:        register int            result;
        !           755: 
        !           756:        if (map == NULL)
        !           757:                return(KERN_INVALID_ARGUMENT);
        !           758: 
        !           759:        *addr = trunc_page(*addr);
        !           760:        size = round_page(size);
        !           761: 
        !           762:        /*
        !           763:         *      Lookup the pager/paging-space in the object cache.
        !           764:         *      If it's not there, then create a new object and cache
        !           765:         *      it.
        !           766:         */
        !           767:        object = vm_object_lookup(pager);
        !           768:        vm_stat.lookups++;
        !           769:        if (object == NULL) {
        !           770:                object = vm_object_allocate(size);
        !           771:                vm_object_enter(object, pager);
        !           772:        } else
        !           773:                vm_stat.hits++;
        !           774:        object->internal = internal;
        !           775: 
        !           776:        result = vm_map_find(map, object, poffset, addr, size, fitit);
        !           777:        if (result != KERN_SUCCESS)
        !           778:                vm_object_deallocate(object);
        !           779:        else if (pager != NULL)
        !           780:                vm_object_setpager(object, pager, (vm_offset_t) 0, TRUE);
        !           781:        return(result);
        !           782: }
        !           783: 
        !           784: /*
        !           785:  * XXX: this routine belongs in vm_map.c.
        !           786:  *
        !           787:  * Returns TRUE if the range [start - end) is allocated in either
        !           788:  * a single entry (single_entry == TRUE) or multiple contiguous
        !           789:  * entries (single_entry == FALSE).
        !           790:  *
        !           791:  * start and end should be page aligned.
        !           792:  */
        !           793: boolean_t
        !           794: vm_map_is_allocated(map, start, end, single_entry)
        !           795:        vm_map_t map;
        !           796:        vm_offset_t start, end;
        !           797:        boolean_t single_entry;
        !           798: {
        !           799:        vm_map_entry_t mapent;
        !           800:        register vm_offset_t nend;
        !           801: 
        !           802:        vm_map_lock_read(map);
        !           803: 
        !           804:        /*
        !           805:         * Start address not in any entry
        !           806:         */
        !           807:        if (!vm_map_lookup_entry(map, start, &mapent)) {
        !           808:                vm_map_unlock_read(map);
        !           809:                return (FALSE);
        !           810:        }
        !           811:        /*
        !           812:         * Find the maximum stretch of contiguously allocated space
        !           813:         */
        !           814:        nend = mapent->end;
        !           815:        if (!single_entry) {
        !           816:                mapent = mapent->next;
        !           817:                while (mapent != &map->header && mapent->start == nend) {
        !           818:                        nend = mapent->end;
        !           819:                        mapent = mapent->next;
        !           820:                }
        !           821:        }
        !           822: 
        !           823:        vm_map_unlock_read(map);
        !           824:        return (end <= nend);
        !           825: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.