Annotation of Net2/vm/vm_mmap.c, revision 1.1.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.