Annotation of XNU/bsd/vm/vm_unix.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* 
        !            23:  * Mach Operating System
        !            24:  * Copyright (c) 1987 Carnegie-Mellon University
        !            25:  * All rights reserved.  The CMU software License Agreement specifies
        !            26:  * the terms and conditions for use and redistribution.
        !            27:  */
        !            28: 
        !            29: /*
        !            30:  */
        !            31: #include <mach_nbc.h>
        !            32: #include <meta_features.h>
        !            33: 
        !            34: #include <kern/task.h>
        !            35: #include <kern/thread.h>
        !            36: #include <mach/time_value.h>
        !            37: #include <mach/vm_param.h>
        !            38: #include <mach/vm_prot.h>
        !            39: #include <mach/port.h>
        !            40: 
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/dir.h>
        !            44: #include <sys/namei.h>
        !            45: #include <sys/proc.h>
        !            46: #include <sys/vm.h>
        !            47: #include <sys/file.h>
        !            48: #include <sys/vnode.h>
        !            49: #include <sys/buf.h>
        !            50: #include <sys/mount.h>
        !            51: #include <sys/trace.h>
        !            52: #include <sys/kernel.h>
        !            53: 
        !            54: #include <kern/kalloc.h>
        !            55: #include <kern/parallel.h>
        !            56: #include <kern/mapfs.h>
        !            57: #include <vm/vm_map.h>
        !            58: #include <vm/vm_kern.h>
        !            59: 
        !            60: #include <machine/spl.h>
        !            61: #include <mach/shared_memory_server.h>
        !            62: 
        !            63: useracc(addr, len, prot)
        !            64:        caddr_t addr;
        !            65:        u_int   len;
        !            66:        int     prot;
        !            67: {
        !            68:        return (vm_map_check_protection(
        !            69:                        current_map(),
        !            70:                        trunc_page(addr), round_page(addr+len),
        !            71:                        prot == B_READ ? VM_PROT_READ : VM_PROT_WRITE));
        !            72: }
        !            73: 
        !            74: vslock(addr, len)
        !            75:        caddr_t addr;
        !            76:        int     len;
        !            77: {
        !            78:        vm_map_wire(current_map(), trunc_page(addr),
        !            79:                        round_page(addr+len), 
        !            80:                        VM_PROT_READ | VM_PROT_WRITE ,FALSE);
        !            81: }
        !            82: 
        !            83: vsunlock(addr, len, dirtied)
        !            84:        caddr_t addr;
        !            85:        int     len;
        !            86:        int dirtied;
        !            87: {
        !            88:        pmap_t          pmap;
        !            89: #if FIXME  /* [ */
        !            90:        vm_page_t       pg;
        !            91: #endif  /* FIXME ] */
        !            92:        vm_offset_t     vaddr, paddr;
        !            93: 
        !            94: #if FIXME  /* [ */
        !            95:        if (dirtied) {
        !            96:                pmap = get_task_pmap(current_task());
        !            97:                for (vaddr = trunc_page(addr); vaddr < round_page(addr+len);
        !            98:                                vaddr += PAGE_SIZE) {
        !            99:                        paddr = pmap_extract(pmap, vaddr);
        !           100:                        pg = PHYS_TO_VM_PAGE(paddr);
        !           101:                        vm_page_set_modified(pg);
        !           102:                }
        !           103:        }
        !           104: #endif  /* FIXME ] */
        !           105: #ifdef lint
        !           106:        dirtied++;
        !           107: #endif /* lint */
        !           108:        vm_map_unwire(current_map(), trunc_page(addr),
        !           109:                                round_page(addr+len), FALSE);
        !           110: }
        !           111: 
        !           112: #if    defined(sun) || BALANCE || defined(m88k)
        !           113: #else  /*defined(sun) || BALANCE || defined(m88k)*/
        !           114: subyte(addr, byte)
        !           115:        void * addr;
        !           116:        int byte;
        !           117: {
        !           118:        char character;
        !           119:        
        !           120:        character = (char)byte;
        !           121:        return (copyout((void *)&(character), addr, sizeof(char)) == 0 ? 0 : -1);
        !           122: }
        !           123: 
        !           124: suibyte(addr, byte)
        !           125:        void * addr;
        !           126:        int byte;
        !           127: {
        !           128:        char character;
        !           129:        
        !           130:        character = (char)byte;
        !           131:        return (copyout((void *) &(character), addr, sizeof(char)) == 0 ? 0 : -1);
        !           132: }
        !           133: 
        !           134: int fubyte(addr)
        !           135:        void * addr;
        !           136: {
        !           137:        unsigned char byte;
        !           138: 
        !           139:        if (copyin(addr, (void *) &byte, sizeof(char)))
        !           140:                return(-1);
        !           141:        return(byte);
        !           142: }
        !           143: 
        !           144: int fuibyte(addr)
        !           145:        void * addr;
        !           146: {
        !           147:        unsigned char byte;
        !           148: 
        !           149:        if (copyin(addr, (void *) &(byte), sizeof(char)))
        !           150:                return(-1);
        !           151:        return(byte);
        !           152: }
        !           153: 
        !           154: suword(addr, word)
        !           155:        void * addr;
        !           156:        long word;
        !           157: {
        !           158:        return (copyout((void *) &word, addr, sizeof(int)) == 0 ? 0 : -1);
        !           159: }
        !           160: 
        !           161: long fuword(addr)
        !           162:        void * addr;
        !           163: {
        !           164:        long word;
        !           165: 
        !           166:        if (copyin(addr, (void *) &word, sizeof(int)))
        !           167:                return(-1);
        !           168:        return(word);
        !           169: }
        !           170: 
        !           171: /* suiword and fuiword are the same as suword and fuword, respectively */
        !           172: 
        !           173: suiword(addr, word)
        !           174:        void * addr;
        !           175:        long word;
        !           176: {
        !           177:        return (copyout((void *) &word, addr, sizeof(int)) == 0 ? 0 : -1);
        !           178: }
        !           179: 
        !           180: long fuiword(addr)
        !           181:        void * addr;
        !           182: {
        !           183:        long word;
        !           184: 
        !           185:        if (copyin(addr, (void *) &word, sizeof(int)))
        !           186:                return(-1);
        !           187:        return(word);
        !           188: }
        !           189: #endif /* defined(sun) || BALANCE || defined(m88k) || defined(i386) */
        !           190: 
        !           191: int
        !           192: swapon()
        !           193: {
        !           194:        return(EOPNOTSUPP);
        !           195: }
        !           196: 
        !           197: thread_t procdup(
        !           198:        struct proc             *child,
        !           199:        struct proc             *parent)
        !           200: {
        !           201:        thread_t                thread;
        !           202:        task_t                  task;
        !           203:        kern_return_t   result;
        !           204: 
        !           205:        if (parent->task == kernel_task)
        !           206:                result = task_create_local(TASK_NULL, FALSE, FALSE, &task);
        !           207:        else
        !           208:                result = task_create_local(parent->task, TRUE, FALSE, &task);
        !           209:        if (result != KERN_SUCCESS)
        !           210:            printf("fork/procdup: task_create failed. Code: 0x%x\n", result);
        !           211:        child->task = task;
        !           212:        /* task->proc = child; */
        !           213:        set_bsdtask_info(task, child);
        !           214: 
        !           215:        task_deallocate(task); // extra ref for convert_task_to_port()
        !           216: 
        !           217:        result = thread_create(task, &thread);
        !           218:        if (result != KERN_SUCCESS)
        !           219:            printf("fork/procdup: thread_create failed. Code: 0x%x\n", result);
        !           220:        act_deallocate(thread); 
        !           221: 
        !           222: #if FIXME /* [ */
        !           223:        thread_deallocate(thread); // extra ref
        !           224: 
        !           225:        /*
        !           226:         *      Don't need to lock thread here because it can't
        !           227:         *      possibly execute and no one else knows about it.
        !           228:         */
        !           229:        /* compute_priority(thread, FALSE); */
        !           230: #endif /* ] */
        !           231:        return(thread);
        !           232: }
        !           233: 
        !           234: kern_return_t  pid_for_task(t, x)
        !           235:        mach_port_t     t;
        !           236:        int     *x;
        !           237: {
        !           238:        struct proc * p;
        !           239:        task_t          t1;
        !           240:        extern task_t port_name_to_task(mach_port_t t);
        !           241:        int     pid = -1;
        !           242:        kern_return_t   err;
        !           243: 
        !           244:        t1 = port_name_to_task(t);
        !           245: 
        !           246:        if (t1 == TASK_NULL) {
        !           247:                err = KERN_FAILURE;
        !           248:        } else {
        !           249:                p = get_bsdtask_info(t1);
        !           250:                if (p) {
        !           251:                        pid  = p->p_pid;
        !           252:                        err = KERN_SUCCESS;
        !           253:                } else {
        !           254:                        err = KERN_FAILURE;
        !           255:                }
        !           256:        }
        !           257:        task_deallocate(t1);
        !           258:        (void) copyout((char *) &pid, (char *) x, sizeof(*x));
        !           259:        return err;
        !           260: }
        !           261: 
        !           262: /*
        !           263:  *     Routine:        task_by_unix_pid
        !           264:  *     Purpose:
        !           265:  *             Get the task port for another "process", named by its
        !           266:  *             process ID on the same host as "target_task".
        !           267:  *
        !           268:  *             Only permitted to privileged processes, or processes
        !           269:  *             with the same user ID.
        !           270:  */
        !           271: kern_return_t  task_for_pid(target_tport, pid, t)
        !           272:        mach_port_t     target_tport;
        !           273:        int             pid;
        !           274:        mach_port_t     *t;
        !           275: {
        !           276:        struct proc     *p;
        !           277:        struct proc *p1;
        !           278:        task_t          t1;
        !           279:        mach_port_t     tret;
        !           280:        extern task_t port_name_to_task(mach_port_t tp);
        !           281:        void * sright;
        !           282: 
        !           283:        unix_master();
        !           284:        t1 = port_name_to_task(target_tport);
        !           285:        if (t1 == TASK_NULL) {
        !           286:                *t = TASK_NULL;
        !           287:                unix_release();
        !           288:                return (KERN_FAILURE);
        !           289:        } 
        !           290: 
        !           291:        p1 = get_bsdtask_info(t1);
        !           292:        if (
        !           293:                ((p = pfind(pid)) != (struct proc *) 0)
        !           294:                && (p1 != (struct proc *) 0)
        !           295:                && ((p->p_ucred->cr_uid == p1->p_ucred->cr_uid)
        !           296:                || !(suser(p1->p_ucred, &p1->p_acflag)))
        !           297:                && (p->p_stat != SZOMB)
        !           298:                ) {
        !           299:                        task_deallocate(t1);
        !           300:                        if (p->task != TASK_NULL) {
        !           301:                                task_reference(p->task);
        !           302: #if 0
        !           303:                                sright = retrieve_task_self_fast(p->task);
        !           304: #else
        !           305:                                sright = convert_task_to_port(p->task);
        !           306: #endif
        !           307:                                tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task()));
        !           308:                        } else
        !           309:                                tret  = MACH_PORT_NULL;
        !           310:                        (void ) copyout((char *)&tret, (char *) t, sizeof(mach_port_t));
        !           311:                        /* compatibility with NeXT 2.0 debuggers, launchers */
        !           312:                        if (suser(p->p_ucred, &p->p_acflag)) {
        !           313:                                /* don't set it for anyone; could exec a careless nameserver */
        !           314:                        struct proc *p=get_bsdtask_info(current_task());
        !           315: 
        !           316:                                if (p)
        !           317:                                        p->p_debugger = 1;
        !           318:                        }
        !           319:                        unix_release();
        !           320:                        return(KERN_SUCCESS);
        !           321:        }
        !           322:         task_deallocate(t1);
        !           323:        tret = MACH_PORT_NULL;
        !           324:        (void) copyout((char *) &tret, (char *) t, sizeof(mach_port_t));
        !           325: 
        !           326:        unix_release();
        !           327:        return(KERN_FAILURE);
        !           328: }
        !           329: 
        !           330: #if 0
        !           331: /*
        !           332:  *     Routine:        task_by_pid
        !           333:  *     Purpose:
        !           334:  *             Trap form of "task_by_unix_pid"; soon to be eliminated.
        !           335:  */
        !           336: mach_port_t            task_by_pid(pid)
        !           337:        int             pid;
        !           338: {
        !           339:        task_t          self = current_task();
        !           340:        port_t          t = PORT_NULL;
        !           341:        task_t          result_task;
        !           342: 
        !           343:        if (task_by_unix_pid(self, pid, &result_task) == KERN_SUCCESS) {
        !           344:                t = convert_task_to_port(result_task);
        !           345:                if (t != PORT_NULL)
        !           346:                        object_copyout(self, t, MSG_TYPE_PORT, &t);
        !           347:        }
        !           348: 
        !           349:        return(t);
        !           350: }
        !           351: #endif /* 0 */
        !           352: 
        !           353: 
        !           354: 
        !           355: 
        !           356: int
        !           357: load_shared_file(
        !           358:        caddr_t         mapped_file_addr,
        !           359:        u_long          mapped_file_size,
        !           360:         caddr_t                *base_address,
        !           361:         int             map_cnt,
        !           362:         sf_mapping_t       *mappings,
        !           363:         char            *filename,
        !           364:         int             *flags)
        !           365: {
        !           366:        struct vnode            *vp = 0; 
        !           367:        struct nameidata        nd, *ndp;
        !           368:        struct proc             *p =  current_proc();
        !           369:        register int            error;
        !           370:        kern_return_t           kr;
        !           371: 
        !           372:        struct vattr    vattr;
        !           373:        void            *pager_cport;
        !           374:        void            *object;
        !           375:        void            *file_object;
        !           376:         sf_mapping_t    *map_list;
        !           377:         caddr_t                local_base;
        !           378:        int             local_flags;
        !           379:        kern_return_t   kret;
        !           380: 
        !           381:        ndp = &nd;
        !           382: 
        !           383: 
        !           384: 
        !           385:        unix_master();
        !           386: 
        !           387:        /* Retrieve the base address */
        !           388:        if (copyin(base_address, &local_base, sizeof (caddr_t))) {
        !           389:                        error = EINVAL;
        !           390:                        goto lsf_bailout;
        !           391:         }
        !           392:        if (copyin(flags, &local_flags, sizeof (int))) {
        !           393:                        error = EINVAL;
        !           394:                        goto lsf_bailout;
        !           395:         }
        !           396:        kret = kmem_alloc(kernel_map, &map_list,
        !           397:                        (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           398:        if (kret != KERN_SUCCESS) {
        !           399:                        error = ENOMEM;
        !           400:                        goto lsf_bailout;
        !           401:        }
        !           402: 
        !           403:        if (copyin(mappings, map_list, (map_cnt*sizeof(sf_mapping_t)))) {
        !           404:                        kmem_free(kernel_map, map_list, 
        !           405:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           406:                        error = EINVAL;
        !           407:                        goto lsf_bailout;
        !           408:        }
        !           409: 
        !           410:        /*
        !           411:         * Get a vnode for the target file
        !           412:         */
        !           413:        NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
        !           414:            filename, p);
        !           415: 
        !           416:        if ((error = namei(ndp))) {
        !           417:                error = EINVAL;
        !           418:                kmem_free(kernel_map, map_list, 
        !           419:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           420:                goto lsf_bailout;
        !           421:        }
        !           422: 
        !           423:        vp = ndp->ni_vp;
        !           424: 
        !           425:        if (vp->v_type != VREG) {
        !           426:                error = EINVAL;
        !           427:                kmem_free(kernel_map, map_list, 
        !           428:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           429:                VOP_UNLOCK(vp, 0, p);
        !           430:                goto lsf_bailout;
        !           431:        }
        !           432: 
        !           433:        if (!vp->v_vm_info) {
        !           434:                vm_info_init(vp);
        !           435:        }
        !           436: 
        !           437:        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) {
        !           438:                VOP_UNLOCK(vp, 0, p);
        !           439:                kmem_free(kernel_map, map_list, 
        !           440:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           441:                goto lsf_bailout;
        !           442:        }
        !           443: 
        !           444: 
        !           445:        if(pager_cport = (void *)vnode_pager_lookup(vp, vp->v_vm_info->pager)) {
        !           446:                if(file_object = (void *)vm_object_lookup(pager_cport)) {
        !           447:                        error = 0;
        !           448:                } else {
        !           449:                        VOP_UNLOCK(vp, 0, p);
        !           450:                        kmem_free(kernel_map, map_list, 
        !           451:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           452:                        error = EINVAL;
        !           453:                        goto lsf_bailout;
        !           454:                }
        !           455:        } else {
        !           456:                VOP_UNLOCK(vp, 0, p);
        !           457:                error = EINVAL;
        !           458:                goto lsf_bailout;
        !           459:        }
        !           460: 
        !           461:        vp->v_vm_info->vnode_size = vattr.va_size;
        !           462: 
        !           463:        if(vattr.va_size != mapped_file_size) {
        !           464:                VOP_UNLOCK(vp, 0, p);
        !           465:                kmem_free(kernel_map, map_list, 
        !           466:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           467:                error = EINVAL;
        !           468:                goto lsf_bailout;
        !           469:        }
        !           470: 
        !           471:        VREF(vp);
        !           472:        if(copyin_shared_file(mapped_file_addr, mapped_file_size, &local_base,
        !           473:                        map_cnt, map_list, file_object, &local_flags)) {
        !           474:                vrele(vp);
        !           475:                error = EINVAL;
        !           476:        } else {
        !           477:                copyout(&local_flags, flags, sizeof (int));
        !           478:                copyout(&local_base, base_address, sizeof (caddr_t));
        !           479:                if (local_flags & SF_PREV_LOADED) {
        !           480:                        vrele(vp);
        !           481:                }
        !           482:        }
        !           483:        kmem_free(kernel_map, map_list, 
        !           484:                                (vm_size_t)(map_cnt*sizeof(sf_mapping_t)));
        !           485:        VOP_UNLOCK(vp, 0, p);
        !           486: 
        !           487: lsf_bailout:
        !           488:        /* deallocate any remaining remnants of mapped file sent by caller */
        !           489:        vm_deallocate(current_map(), mapped_file_addr, mapped_file_size);
        !           490:        unix_release();
        !           491:        return error;
        !           492: }

unix.superglobalmegacorp.com

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