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

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: 
1.1.1.2 ! root      317: munmapfd(p, fd)
        !           318:        register struct proc *p;
1.1       root      319: {
                    320: #ifdef DEBUG
                    321:        if (mmapdebug & MDB_FOLLOW)
1.1.1.2 ! root      322:                printf("munmapfd(%d): fd %d\n", p->p_pid, fd);
1.1       root      323: #endif
                    324: 
                    325:        /*
                    326:         * XXX -- should vm_deallocate any regions mapped to this file
                    327:         */
1.1.1.2 ! root      328:        p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
1.1       root      329: }
                    330: 
                    331: mprotect(p, uap, retval)
                    332:        struct proc *p;
                    333:        struct args {
                    334:                caddr_t addr;
                    335:                int     len;
                    336:                int     prot;
                    337:        } *uap;
                    338:        int *retval;
                    339: {
                    340:        vm_offset_t addr;
                    341:        vm_size_t size;
                    342:        register vm_prot_t prot;
                    343: 
                    344: #ifdef DEBUG
                    345:        if (mmapdebug & MDB_FOLLOW)
                    346:                printf("mprotect(%d): addr %x len %x prot %d\n",
                    347:                       p->p_pid, uap->addr, uap->len, uap->prot);
                    348: #endif
                    349: 
                    350:        addr = (vm_offset_t) uap->addr;
                    351:        if ((addr & page_mask) || uap->len < 0)
                    352:                return(EINVAL);
                    353:        size = (vm_size_t) uap->len;
                    354:        /*
                    355:         * Map protections
                    356:         */
                    357:        prot = VM_PROT_NONE;
                    358:        if (uap->prot & PROT_READ)
                    359:                prot |= VM_PROT_READ;
                    360:        if (uap->prot & PROT_WRITE)
                    361:                prot |= VM_PROT_WRITE;
                    362:        if (uap->prot & PROT_EXEC)
                    363:                prot |= VM_PROT_EXECUTE;
                    364: 
                    365:        switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr+size, prot,
                    366:            FALSE)) {
                    367:        case KERN_SUCCESS:
                    368:                return (0);
                    369:        case KERN_PROTECTION_FAILURE:
                    370:                return (EACCES);
                    371:        }
                    372:        return (EINVAL);
                    373: }
                    374: 
                    375: /* ARGSUSED */
                    376: madvise(p, uap, retval)
                    377:        struct proc *p;
                    378:        struct args {
                    379:                caddr_t addr;
                    380:                int     len;
                    381:                int     behav;
                    382:        } *uap;
                    383:        int *retval;
                    384: {
                    385: 
                    386:        /* Not yet implemented */
                    387:        return (EOPNOTSUPP);
                    388: }
                    389: 
                    390: /* ARGSUSED */
                    391: mincore(p, uap, retval)
                    392:        struct proc *p;
                    393:        struct args {
                    394:                caddr_t addr;
                    395:                int     len;
                    396:                char    *vec;
                    397:        } *uap;
                    398:        int *retval;
                    399: {
                    400: 
                    401:        /* Not yet implemented */
                    402:        return (EOPNOTSUPP);
                    403: }
                    404: 
                    405: /*
                    406:  * Internal version of mmap.
                    407:  * Currently used by mmap, exec, and sys5 shared memory.
                    408:  * Handle is:
                    409:  *     MAP_FILE: a vnode pointer
                    410:  *     MAP_ANON: NULL or a file pointer
                    411:  */
                    412: vm_mmap(map, addr, size, prot, flags, handle, foff)
                    413:        register vm_map_t map;
                    414:        register vm_offset_t *addr;
                    415:        register vm_size_t size;
                    416:        vm_prot_t prot;
                    417:        register int flags;
                    418:        caddr_t handle;         /* XXX should be vp */
                    419:        vm_offset_t foff;
                    420: {
                    421:        register vm_pager_t pager;
                    422:        boolean_t fitit;
                    423:        vm_object_t object;
                    424:        struct vnode *vp;
                    425:        int type;
                    426:        int rv = KERN_SUCCESS;
                    427: 
                    428:        if (size == 0)
                    429:                return (0);
                    430: 
                    431:        if ((flags & MAP_FIXED) == 0) {
                    432:                fitit = TRUE;
                    433:                *addr = round_page(*addr);
                    434:        } else {
                    435:                fitit = FALSE;
                    436:                (void) vm_deallocate(map, *addr, size);
                    437:        }
                    438: 
                    439:        /*
                    440:         * Lookup/allocate pager.  All except an unnamed anonymous lookup
                    441:         * gain a reference to ensure continued existance of the object.
                    442:         * (XXX the exception is to appease the pageout daemon)
                    443:         */
                    444:        if ((flags & MAP_TYPE) == MAP_ANON)
                    445:                type = PG_DFLT;
                    446:        else {
                    447:                vp = (struct vnode *)handle;
                    448:                if (vp->v_type == VCHR) {
                    449:                        type = PG_DEVICE;
                    450:                        handle = (caddr_t)vp->v_rdev;
                    451:                } else
                    452:                        type = PG_VNODE;
                    453:        }
                    454:        pager = vm_pager_allocate(type, handle, size, prot);
                    455:        if (pager == NULL)
                    456:                return (type == PG_DEVICE ? EINVAL : ENOMEM);
                    457:        /*
                    458:         * Find object and release extra reference gained by lookup
                    459:         */
                    460:        object = vm_object_lookup(pager);
                    461:        vm_object_deallocate(object);
                    462: 
                    463:        /*
                    464:         * Anonymous memory.
                    465:         */
                    466:        if ((flags & MAP_TYPE) == MAP_ANON) {
                    467:                rv = vm_allocate_with_pager(map, addr, size, fitit,
                    468:                                            pager, (vm_offset_t)foff, TRUE);
                    469:                if (rv != KERN_SUCCESS) {
                    470:                        if (handle == NULL)
                    471:                                vm_pager_deallocate(pager);
                    472:                        else
                    473:                                vm_object_deallocate(object);
                    474:                        goto out;
                    475:                }
                    476:                /*
                    477:                 * Don't cache anonymous objects.
                    478:                 * Loses the reference gained by vm_pager_allocate.
                    479:                 */
                    480:                (void) pager_cache(object, FALSE);
                    481: #ifdef DEBUG
                    482:                if (mmapdebug & MDB_MAPIT)
                    483:                        printf("vm_mmap(%d): ANON *addr %x size %x pager %x\n",
                    484:                               curproc->p_pid, *addr, size, pager);
                    485: #endif
                    486:        }
                    487:        /*
                    488:         * Must be type MAP_FILE.
                    489:         * Distinguish between character special and regular files.
                    490:         */
                    491:        else if (vp->v_type == VCHR) {
                    492:                rv = vm_allocate_with_pager(map, addr, size, fitit,
                    493:                                            pager, (vm_offset_t)foff, FALSE);
                    494:                /*
                    495:                 * Uncache the object and lose the reference gained
                    496:                 * by vm_pager_allocate().  If the call to
                    497:                 * vm_allocate_with_pager() was sucessful, then we
                    498:                 * gained an additional reference ensuring the object
                    499:                 * will continue to exist.  If the call failed then
                    500:                 * the deallocate call below will terminate the
                    501:                 * object which is fine.
                    502:                 */
                    503:                (void) pager_cache(object, FALSE);
                    504:                if (rv != KERN_SUCCESS)
                    505:                        goto out;
                    506:        }
                    507:        /*
                    508:         * A regular file
                    509:         */
                    510:        else {
                    511: #ifdef DEBUG
                    512:                if (object == NULL)
                    513:                        printf("vm_mmap: no object: vp %x, pager %x\n",
                    514:                               vp, pager);
                    515: #endif
                    516:                /*
                    517:                 * Map it directly.
                    518:                 * Allows modifications to go out to the vnode.
                    519:                 */
                    520:                if (flags & MAP_SHARED) {
                    521:                        rv = vm_allocate_with_pager(map, addr, size,
                    522:                                                    fitit, pager,
                    523:                                                    (vm_offset_t)foff, FALSE);
                    524:                        if (rv != KERN_SUCCESS) {
                    525:                                vm_object_deallocate(object);
                    526:                                goto out;
                    527:                        }
                    528:                        /*
                    529:                         * Don't cache the object.  This is the easiest way
                    530:                         * of ensuring that data gets back to the filesystem
                    531:                         * because vnode_pager_deallocate() will fsync the
                    532:                         * vnode.  pager_cache() will lose the extra ref.
                    533:                         */
                    534:                        if (prot & VM_PROT_WRITE)
                    535:                                pager_cache(object, FALSE);
                    536:                        else
                    537:                                vm_object_deallocate(object);
                    538:                }
                    539:                /*
                    540:                 * Copy-on-write of file.  Two flavors.
                    541:                 * MAP_COPY is true COW, you essentially get a snapshot of
                    542:                 * the region at the time of mapping.  MAP_PRIVATE means only
                    543:                 * that your changes are not reflected back to the object.
                    544:                 * Changes made by others will be seen.
                    545:                 */
                    546:                else {
                    547:                        vm_map_t tmap;
                    548:                        vm_offset_t off;
                    549: 
                    550:                        /* locate and allocate the target address space */
                    551:                        rv = vm_map_find(map, NULL, (vm_offset_t)0,
                    552:                                         addr, size, fitit);
                    553:                        if (rv != KERN_SUCCESS) {
                    554:                                vm_object_deallocate(object);
                    555:                                goto out;
                    556:                        }
                    557:                        tmap = vm_map_create(pmap_create(size), VM_MIN_ADDRESS,
                    558:                                             VM_MIN_ADDRESS+size, TRUE);
                    559:                        off = VM_MIN_ADDRESS;
                    560:                        rv = vm_allocate_with_pager(tmap, &off, size,
                    561:                                                    TRUE, pager,
                    562:                                                    (vm_offset_t)foff, FALSE);
                    563:                        if (rv != KERN_SUCCESS) {
                    564:                                vm_object_deallocate(object);
                    565:                                vm_map_deallocate(tmap);
                    566:                                goto out;
                    567:                        }
                    568:                        /*
                    569:                         * (XXX)
                    570:                         * MAP_PRIVATE implies that we see changes made by
                    571:                         * others.  To ensure that we need to guarentee that
                    572:                         * no copy object is created (otherwise original
                    573:                         * pages would be pushed to the copy object and we
                    574:                         * would never see changes made by others).  We
                    575:                         * totally sleeze it right now by marking the object
                    576:                         * internal temporarily.
                    577:                         */
                    578:                        if ((flags & MAP_COPY) == 0)
                    579:                                object->internal = TRUE;
                    580:                        rv = vm_map_copy(map, tmap, *addr, size, off,
                    581:                                         FALSE, FALSE);
                    582:                        object->internal = FALSE;
                    583:                        /*
                    584:                         * (XXX)
                    585:                         * My oh my, this only gets worse...
                    586:                         * Force creation of a shadow object so that
                    587:                         * vm_map_fork will do the right thing.
                    588:                         */
                    589:                        if ((flags & MAP_COPY) == 0) {
                    590:                                vm_map_t tmap;
                    591:                                vm_map_entry_t tentry;
                    592:                                vm_object_t tobject;
                    593:                                vm_offset_t toffset;
                    594:                                vm_prot_t tprot;
                    595:                                boolean_t twired, tsu;
                    596: 
                    597:                                tmap = map;
                    598:                                vm_map_lookup(&tmap, *addr, VM_PROT_WRITE,
                    599:                                              &tentry, &tobject, &toffset,
                    600:                                              &tprot, &twired, &tsu);
                    601:                                vm_map_lookup_done(tmap, tentry);
                    602:                        }
                    603:                        /*
                    604:                         * (XXX)
                    605:                         * Map copy code cannot detect sharing unless a
                    606:                         * sharing map is involved.  So we cheat and write
                    607:                         * protect everything ourselves.
                    608:                         */
                    609:                        vm_object_pmap_copy(object, (vm_offset_t)foff,
                    610:                                            (vm_offset_t)foff+size);
                    611:                        vm_object_deallocate(object);
                    612:                        vm_map_deallocate(tmap);
                    613:                        if (rv != KERN_SUCCESS)
                    614:                                goto out;
                    615:                }
                    616: #ifdef DEBUG
                    617:                if (mmapdebug & MDB_MAPIT)
                    618:                        printf("vm_mmap(%d): FILE *addr %x size %x pager %x\n",
                    619:                               curproc->p_pid, *addr, size, pager);
                    620: #endif
                    621:        }
                    622:        /*
                    623:         * Correct protection (default is VM_PROT_ALL).
                    624:         * Note that we set the maximum protection.  This may not be
                    625:         * entirely correct.  Maybe the maximum protection should be based
                    626:         * on the object permissions where it makes sense (e.g. a vnode).
                    627:         *
                    628:         * Changed my mind: leave max prot at VM_PROT_ALL.
                    629:         */
                    630:        if (prot != VM_PROT_ALL) {
                    631:                rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE);
                    632:                if (rv != KERN_SUCCESS) {
                    633:                        (void) vm_deallocate(map, *addr, size);
                    634:                        goto out;
                    635:                }
                    636:        }
                    637:        /*
                    638:         * Shared memory is also shared with children.
                    639:         */
                    640:        if (flags & MAP_SHARED) {
                    641:                rv = vm_inherit(map, *addr, size, VM_INHERIT_SHARE);
                    642:                if (rv != KERN_SUCCESS) {
                    643:                        (void) vm_deallocate(map, *addr, size);
                    644:                        goto out;
                    645:                }
                    646:        }
                    647: out:
                    648: #ifdef DEBUG
                    649:        if (mmapdebug & MDB_MAPIT)
                    650:                printf("vm_mmap: rv %d\n", rv);
                    651: #endif
                    652:        switch (rv) {
                    653:        case KERN_SUCCESS:
                    654:                return (0);
                    655:        case KERN_INVALID_ADDRESS:
                    656:        case KERN_NO_SPACE:
                    657:                return (ENOMEM);
                    658:        case KERN_PROTECTION_FAILURE:
                    659:                return (EACCES);
                    660:        default:
                    661:                return (EINVAL);
                    662:        }
                    663: }
                    664: 
                    665: /*
                    666:  * Internal bastardized version of MACHs vm_region system call.
                    667:  * Given address and size it returns map attributes as well
                    668:  * as the (locked) object mapped at that location. 
                    669:  */
                    670: vm_region(map, addr, size, prot, max_prot, inheritance, shared, object, objoff)
                    671:        vm_map_t        map;
                    672:        vm_offset_t     *addr;          /* IN/OUT */
                    673:        vm_size_t       *size;          /* OUT */
                    674:        vm_prot_t       *prot;          /* OUT */
                    675:        vm_prot_t       *max_prot;      /* OUT */
                    676:        vm_inherit_t    *inheritance;   /* OUT */
                    677:        boolean_t       *shared;        /* OUT */
                    678:        vm_object_t     *object;        /* OUT */
                    679:        vm_offset_t     *objoff;        /* OUT */
                    680: {
                    681:        vm_map_entry_t  tmp_entry;
                    682:        register
                    683:        vm_map_entry_t  entry;
                    684:        register
                    685:        vm_offset_t     tmp_offset;
                    686:        vm_offset_t     start;
                    687: 
                    688:        if (map == NULL)
                    689:                return(KERN_INVALID_ARGUMENT);
                    690:        
                    691:        start = *addr;
                    692: 
                    693:        vm_map_lock_read(map);
                    694:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                    695:                if ((entry = tmp_entry->next) == &map->header) {
                    696:                        vm_map_unlock_read(map);
                    697:                        return(KERN_NO_SPACE);
                    698:                }
                    699:                start = entry->start;
                    700:                *addr = start;
                    701:        } else
                    702:                entry = tmp_entry;
                    703: 
                    704:        *prot = entry->protection;
                    705:        *max_prot = entry->max_protection;
                    706:        *inheritance = entry->inheritance;
                    707: 
                    708:        tmp_offset = entry->offset + (start - entry->start);
                    709:        *size = (entry->end - start);
                    710: 
                    711:        if (entry->is_a_map) {
                    712:                register vm_map_t share_map;
                    713:                vm_size_t share_size;
                    714: 
                    715:                share_map = entry->object.share_map;
                    716: 
                    717:                vm_map_lock_read(share_map);
                    718:                (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
                    719: 
                    720:                if ((share_size = (tmp_entry->end - tmp_offset)) < *size)
                    721:                        *size = share_size;
                    722: 
                    723:                vm_object_lock(tmp_entry->object);
                    724:                *object = tmp_entry->object.vm_object;
                    725:                *objoff = tmp_entry->offset + (tmp_offset - tmp_entry->start);
                    726: 
                    727:                *shared = (share_map->ref_count != 1);
                    728:                vm_map_unlock_read(share_map);
                    729:        } else {
                    730:                vm_object_lock(entry->object);
                    731:                *object = entry->object.vm_object;
                    732:                *objoff = tmp_offset;
                    733: 
                    734:                *shared = FALSE;
                    735:        }
                    736: 
                    737:        vm_map_unlock_read(map);
                    738: 
                    739:        return(KERN_SUCCESS);
                    740: }
                    741: 
                    742: /*
                    743:  * Yet another bastard routine.
                    744:  */
                    745: vm_allocate_with_pager(map, addr, size, fitit, pager, poffset, internal)
                    746:        register vm_map_t       map;
                    747:        register vm_offset_t    *addr;
                    748:        register vm_size_t      size;
                    749:        boolean_t               fitit;
                    750:        vm_pager_t              pager;
                    751:        vm_offset_t             poffset;
                    752:        boolean_t               internal;
                    753: {
                    754:        register vm_object_t    object;
                    755:        register int            result;
                    756: 
                    757:        if (map == NULL)
                    758:                return(KERN_INVALID_ARGUMENT);
                    759: 
                    760:        *addr = trunc_page(*addr);
                    761:        size = round_page(size);
                    762: 
                    763:        /*
                    764:         *      Lookup the pager/paging-space in the object cache.
                    765:         *      If it's not there, then create a new object and cache
                    766:         *      it.
                    767:         */
                    768:        object = vm_object_lookup(pager);
                    769:        vm_stat.lookups++;
                    770:        if (object == NULL) {
                    771:                object = vm_object_allocate(size);
                    772:                vm_object_enter(object, pager);
                    773:        } else
                    774:                vm_stat.hits++;
                    775:        object->internal = internal;
                    776: 
                    777:        result = vm_map_find(map, object, poffset, addr, size, fitit);
                    778:        if (result != KERN_SUCCESS)
                    779:                vm_object_deallocate(object);
                    780:        else if (pager != NULL)
                    781:                vm_object_setpager(object, pager, (vm_offset_t) 0, TRUE);
                    782:        return(result);
                    783: }
                    784: 
                    785: /*
                    786:  * XXX: this routine belongs in vm_map.c.
                    787:  *
                    788:  * Returns TRUE if the range [start - end) is allocated in either
                    789:  * a single entry (single_entry == TRUE) or multiple contiguous
                    790:  * entries (single_entry == FALSE).
                    791:  *
                    792:  * start and end should be page aligned.
                    793:  */
                    794: boolean_t
                    795: vm_map_is_allocated(map, start, end, single_entry)
                    796:        vm_map_t map;
                    797:        vm_offset_t start, end;
                    798:        boolean_t single_entry;
                    799: {
                    800:        vm_map_entry_t mapent;
                    801:        register vm_offset_t nend;
                    802: 
                    803:        vm_map_lock_read(map);
                    804: 
                    805:        /*
                    806:         * Start address not in any entry
                    807:         */
                    808:        if (!vm_map_lookup_entry(map, start, &mapent)) {
                    809:                vm_map_unlock_read(map);
                    810:                return (FALSE);
                    811:        }
                    812:        /*
                    813:         * Find the maximum stretch of contiguously allocated space
                    814:         */
                    815:        nend = mapent->end;
                    816:        if (!single_entry) {
                    817:                mapent = mapent->next;
                    818:                while (mapent != &map->header && mapent->start == nend) {
                    819:                        nend = mapent->end;
                    820:                        mapent = mapent->next;
                    821:                }
                    822:        }
                    823: 
                    824:        vm_map_unlock_read(map);
                    825:        return (end <= nend);
                    826: }

unix.superglobalmegacorp.com

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