Annotation of XNU/bsd/kern/sysv_shm.c, revision 1.1.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: /*     $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $      */
                     23: 
                     24: /*
                     25:  * Copyright (c) 1994 Adam Glass and Charles Hannum.  All rights reserved.
                     26:  *
                     27:  * Redistribution and use in source and binary forms, with or without
                     28:  * modification, are permitted provided that the following conditions
                     29:  * are met:
                     30:  * 1. Redistributions of source code must retain the above copyright
                     31:  *    notice, this list of conditions and the following disclaimer.
                     32:  * 2. Redistributions in binary form must reproduce the above copyright
                     33:  *    notice, this list of conditions and the following disclaimer in the
                     34:  *    documentation and/or other materials provided with the distribution.
                     35:  * 3. All advertising materials mentioning features or use of this software
                     36:  *    must display the following acknowledgement:
                     37:  *     This product includes software developed by Adam Glass and Charles
                     38:  *     Hannum.
                     39:  * 4. The names of the authors may not be used to endorse or promote products
                     40:  *    derived from this software without specific prior written permission.
                     41:  *
                     42:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
                     43:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     44:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     45:  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
                     46:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     47:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     48:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     49:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     50:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     51:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     52:  */
                     53: 
                     54: 
                     55: #include <sys/param.h>
                     56: #include <sys/systm.h>
                     57: #include <sys/kernel.h>
                     58: #include <sys/shm.h>
                     59: #include <sys/proc.h>
                     60: #include <sys/malloc.h>
                     61: #include <sys/mman.h>
                     62: #include <sys/stat.h>
                     63: 
                     64: #include <mach/mach_types.h>
                     65: #include <mach/vm_inherit.h>
                     66: #include <vm/vm_map.h>
                     67: 
                     68: struct shmat_args;
                     69: extern int shmat __P((struct proc *p, struct shmat_args *uap, int *retval));
                     70: struct shmctl_args;
                     71: extern int shmctl __P((struct proc *p, struct shmctl_args *uap, int *retval));
                     72: struct shmdt_args;
                     73: extern int shmdt __P((struct proc *p, struct shmdt_args *uap, int *retval));
                     74: struct shmget_args;
                     75: extern int shmget __P((struct proc *p, struct shmget_args *uap, int *retval));
                     76: 
                     77: #if 0
                     78: static void shminit __P((void *));
                     79: SYSINIT(sysv_shm, SI_SUB_SYSV_SHM, SI_ORDER_FIRST, shminit, NULL)
                     80: #endif 0
                     81: 
                     82: struct oshmctl_args;
                     83: static int oshmctl __P((struct proc *p, struct oshmctl_args *uap, int * retval));
                     84: static int shmget_allocate_segment __P((struct proc *p, struct shmget_args *uap, int mode, int * retval));
                     85: static int shmget_existing __P((struct proc *p, struct shmget_args *uap, int mode, int segnum, int  * retval));
                     86: 
                     87: typedef        int     sy_call_t __P((struct proc *, void *, int *));
                     88: 
                     89: /* XXX casting to (sy_call_t *) is bogus, as usual. */
                     90: static sy_call_t *shmcalls[] = {
                     91:        (sy_call_t *)shmat, (sy_call_t *)oshmctl,
                     92:        (sy_call_t *)shmdt, (sy_call_t *)shmget,
                     93:        (sy_call_t *)shmctl
                     94: };
                     95: 
                     96: #define        SHMSEG_FREE             0x0200
                     97: #define        SHMSEG_REMOVED          0x0400
                     98: #define        SHMSEG_ALLOCATED        0x0800
                     99: #define        SHMSEG_WANTED           0x1000
                    100: 
                    101: static int shm_last_free, shm_nused, shm_committed;
                    102: struct shmid_ds        *shmsegs;
                    103: 
                    104: struct shm_handle {
                    105:        /* vm_offset_t kva; */
                    106:        void * shm_object;
                    107: };
                    108: 
                    109: struct shmmap_state {
                    110:        vm_offset_t va;
                    111:        int shmid;
                    112: };
                    113: 
                    114: static void shm_deallocate_segment __P((struct shmid_ds *));
                    115: static int shm_find_segment_by_key __P((key_t));
                    116: static struct shmid_ds *shm_find_segment_by_shmid __P((int));
                    117: static int shm_delete_mapping __P((struct proc *, struct shmmap_state *));
                    118: 
                    119: static int
                    120: shm_find_segment_by_key(key)
                    121:        key_t key;
                    122: {
                    123:        int i;
                    124: 
                    125:        for (i = 0; i < shminfo.shmmni; i++)
                    126:                if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
                    127:                    shmsegs[i].shm_perm.key == key)
                    128:                        return i;
                    129:        return -1;
                    130: }
                    131: 
                    132: static struct shmid_ds *
                    133: shm_find_segment_by_shmid(shmid)
                    134:        int shmid;
                    135: {
                    136:        int segnum;
                    137:        struct shmid_ds *shmseg;
                    138: 
                    139:        segnum = IPCID_TO_IX(shmid);
                    140:        if (segnum < 0 || segnum >= shminfo.shmmni)
                    141:                return NULL;
                    142:        shmseg = &shmsegs[segnum];
                    143:        if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED))
                    144:            != SHMSEG_ALLOCATED ||
                    145:            shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid))
                    146:                return NULL;
                    147:        return shmseg;
                    148: }
                    149: 
                    150: static void
                    151: shm_deallocate_segment(shmseg)
                    152:        struct shmid_ds *shmseg;
                    153: {
                    154:        struct shm_handle *shm_handle;
                    155:        struct shmmap_state *shmmap_s=NULL;
                    156:        size_t size;
                    157:        char * ptr;
                    158: 
                    159:        shm_handle = shmseg->shm_internal;
                    160:        size = round_page(shmseg->shm_segsz);
                    161:        mach_destroy_memory_entry(shm_handle->shm_object);
                    162:        FREE((caddr_t)shm_handle, M_SHM);
                    163:        shmseg->shm_internal = NULL;
                    164:        shm_committed -= btoc(size);
                    165:        shm_nused--;
                    166:        shmseg->shm_perm.mode = SHMSEG_FREE;
                    167: }
                    168: 
                    169: static int
                    170: shm_delete_mapping(p, shmmap_s)
                    171:        struct proc *p;
                    172:        struct shmmap_state *shmmap_s;
                    173: {
                    174:        struct shmid_ds *shmseg;
                    175:        int segnum, result;
                    176:        size_t size;
                    177: 
                    178:        segnum = IPCID_TO_IX(shmmap_s->shmid);
                    179:        shmseg = &shmsegs[segnum];
                    180:        size = round_page(shmseg->shm_segsz);
                    181:        result = vm_deallocate(current_map(), shmmap_s->va, size);
                    182:        if (result != KERN_SUCCESS)
                    183:                return EINVAL;
                    184:        shmmap_s->shmid = -1;
                    185:        shmseg->shm_dtime = time_second;
                    186:        if ((--shmseg->shm_nattch <= 0) &&
                    187:            (shmseg->shm_perm.mode & SHMSEG_REMOVED)) {
                    188:                shm_deallocate_segment(shmseg);
                    189:                shm_last_free = segnum;
                    190:        }
                    191:        return 0;
                    192: }
                    193: 
                    194: struct shmdt_args {
                    195:        void *shmaddr;
                    196: };
                    197: 
                    198: int
                    199: shmdt(p, uap, retval)
                    200:        struct proc *p;
                    201:        struct shmdt_args *uap;
                    202:        register_t *retval;
                    203: {
                    204:        struct shmmap_state *shmmap_s;
                    205:        int i;
                    206: 
                    207:        shmmap_s = (struct shmmap_state *)p->vm_shm;
                    208:        if (shmmap_s == NULL)
                    209:            return EINVAL;
                    210:        for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
                    211:                if (shmmap_s->shmid != -1 &&
                    212:                    shmmap_s->va == (vm_offset_t)uap->shmaddr)
                    213:                        break;
                    214:        if (i == shminfo.shmseg)
                    215:                return EINVAL;
                    216:        return shm_delete_mapping(p, shmmap_s);
                    217: }
                    218: 
                    219: #ifndef _SYS_SYSPROTO_H_
                    220: struct shmat_args {
                    221:        int shmid;
                    222:        void *shmaddr;
                    223:        int shmflg;
                    224: };
                    225: #endif
                    226: 
                    227: int
                    228: shmat(p, uap, retval)
                    229:        struct proc *p;
                    230:        struct shmat_args *uap;
                    231:        register_t *retval;
                    232: {
                    233:        int error, i, flags;
                    234:        struct ucred *cred = p->p_ucred;
                    235:        struct shmid_ds *shmseg;
                    236:        struct shmmap_state *shmmap_s = NULL;
                    237:        struct shm_handle *shm_handle;
                    238:        vm_offset_t attach_va;
                    239:        vm_prot_t prot;
                    240:        vm_size_t size;
                    241:        kern_return_t rv;
                    242: 
                    243:        shmmap_s = (struct shmmap_state *)p->vm_shm;
                    244:        if (shmmap_s == NULL) {
                    245:                size = shminfo.shmseg * sizeof(struct shmmap_state);
                    246:                shmmap_s = (struct shmmap_state *)_MALLOC(size, M_SHM, M_WAITOK);
                    247:                for (i = 0; i < shminfo.shmseg; i++)
                    248:                        shmmap_s[i].shmid = -1;
                    249:                p->vm_shm = (caddr_t)shmmap_s;
                    250:        }
                    251:        shmseg = shm_find_segment_by_shmid(uap->shmid);
                    252:        if (shmseg == NULL)
                    253:                return EINVAL;
                    254:        error = ipcperm(cred, &shmseg->shm_perm,
                    255:            (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
                    256:        if (error)
                    257:                return error;
                    258:        for (i = 0; i < shminfo.shmseg; i++) {
                    259:                if (shmmap_s->shmid == -1)
                    260:                        break;
                    261:                shmmap_s++;
                    262:        }
                    263:        if (i >= shminfo.shmseg)
                    264:                return EMFILE;
                    265:        size = round_page(shmseg->shm_segsz);
                    266:        prot = VM_PROT_READ;
                    267:        if ((uap->shmflg & SHM_RDONLY) == 0)
                    268:                prot |= VM_PROT_WRITE;
                    269:        flags = MAP_ANON | MAP_SHARED;
                    270:        if (uap->shmaddr) {
                    271:                flags |= MAP_FIXED;
                    272:                if (uap->shmflg & SHM_RND)
                    273:                        attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1);
                    274:                else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0)
                    275:                        attach_va = (vm_offset_t)uap->shmaddr;
                    276:                else
                    277:                        return EINVAL;
                    278:        } else {
                    279:                attach_va = round_page(uap->shmaddr);
                    280:        }
                    281: 
                    282:        shm_handle = shmseg->shm_internal;
                    283:        rv = vm_map(current_map(), &attach_va, size, 0, (flags & MAP_FIXED)? FALSE: TRUE,
                    284:                shm_handle->shm_object, 0, FALSE, prot, prot, VM_INHERIT_DEFAULT);
                    285:        if (rv != KERN_SUCCESS) 
                    286:                        goto out;
                    287:        rv = vm_inherit(current_map(), attach_va, size,
                    288:                        VM_INHERIT_SHARE);
                    289:        if (rv != KERN_SUCCESS) {
                    290:                (void) vm_deallocate(current_map(), attach_va, size);
                    291:                goto out;
                    292:        }
                    293: 
                    294:        shmmap_s->va = attach_va;
                    295:        shmmap_s->shmid = uap->shmid;
                    296:        shmseg->shm_lpid = p->p_pid;
                    297:        shmseg->shm_atime = time_second;
                    298:        shmseg->shm_nattch++;
                    299:        *retval = attach_va;
                    300:        return( 0);
                    301: out:
                    302:        switch (rv) {
                    303:        case KERN_INVALID_ADDRESS:
                    304:        case KERN_NO_SPACE:
                    305:                return (ENOMEM);
                    306:        case KERN_PROTECTION_FAILURE:
                    307:                return (EACCES);
                    308:        default:
                    309:                return (EINVAL);
                    310:        }
                    311: 
                    312: }
                    313: 
                    314: struct oshmid_ds {
                    315:        struct  ipc_perm shm_perm;      /* operation perms */
                    316:        int     shm_segsz;              /* size of segment (bytes) */
                    317:        ushort  shm_cpid;               /* pid, creator */
                    318:        ushort  shm_lpid;               /* pid, last operation */
                    319:        short   shm_nattch;             /* no. of current attaches */
                    320:        time_t  shm_atime;              /* last attach time */
                    321:        time_t  shm_dtime;              /* last detach time */
                    322:        time_t  shm_ctime;              /* last change time */
                    323:        void    *shm_handle;            /* internal handle for shm segment */
                    324: };
                    325: 
                    326: struct oshmctl_args {
                    327:        int shmid;
                    328:        int cmd;
                    329:        struct oshmid_ds *ubuf;
                    330: };
                    331: 
                    332: static int
                    333: oshmctl(p, uap, retval)
                    334:        struct proc *p;
                    335:        struct oshmctl_args *uap;
                    336:        register_t *retval;
                    337: {
                    338: #ifdef COMPAT_43
                    339:        int error;
                    340:        struct ucred *cred = p->p_ucred;
                    341:        struct shmid_ds *shmseg;
                    342:        struct oshmid_ds outbuf;
                    343: 
                    344:        shmseg = shm_find_segment_by_shmid(uap->shmid);
                    345:        if (shmseg == NULL)
                    346:                return EINVAL;
                    347:        switch (uap->cmd) {
                    348:        case IPC_STAT:
                    349:                error = ipcperm(cred, &shmseg->shm_perm, IPC_R);
                    350:                if (error)
                    351:                        return error;
                    352:                outbuf.shm_perm = shmseg->shm_perm;
                    353:                outbuf.shm_segsz = shmseg->shm_segsz;
                    354:                outbuf.shm_cpid = shmseg->shm_cpid;
                    355:                outbuf.shm_lpid = shmseg->shm_lpid;
                    356:                outbuf.shm_nattch = shmseg->shm_nattch;
                    357:                outbuf.shm_atime = shmseg->shm_atime;
                    358:                outbuf.shm_dtime = shmseg->shm_dtime;
                    359:                outbuf.shm_ctime = shmseg->shm_ctime;
                    360:                outbuf.shm_handle = shmseg->shm_internal;
                    361:                error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf));
                    362:                if (error)
                    363:                        return error;
                    364:                break;
                    365:        default:
                    366:                /* XXX casting to (sy_call_t *) is bogus, as usual. */
                    367:                return ((sy_call_t *)shmctl)(p, uap, retval);
                    368:        }
                    369:        return 0;
                    370: #else
                    371:        return EINVAL;
                    372: #endif
                    373: }
                    374: 
                    375: #ifndef _SYS_SYSPROTO_H_
                    376: struct shmctl_args {
                    377:        int shmid;
                    378:        int cmd;
                    379:        struct shmid_ds *buf;
                    380: };
                    381: #endif
                    382: 
                    383: int
                    384: shmctl(p, uap,         retval)
                    385:        struct proc *p;
                    386:        struct shmctl_args *uap;
                    387:        register_t *retval;
                    388: {
                    389:        int error;
                    390:        struct ucred *cred = p->p_ucred;
                    391:        struct shmid_ds inbuf;
                    392:        struct shmid_ds *shmseg;
                    393: 
                    394:        shmseg = shm_find_segment_by_shmid(uap->shmid);
                    395:        if (shmseg == NULL)
                    396:                return EINVAL;
                    397:        switch (uap->cmd) {
                    398:        case IPC_STAT:
                    399:                error = ipcperm(cred, &shmseg->shm_perm, IPC_R);
                    400:                if (error)
                    401:                        return error;
                    402:                error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf));
                    403:                if (error)
                    404:                        return error;
                    405:                break;
                    406:        case IPC_SET:
                    407:                error = ipcperm(cred, &shmseg->shm_perm, IPC_M);
                    408:                if (error)
                    409:                        return error;
                    410:                error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf));
                    411:                if (error)
                    412:                        return error;
                    413:                shmseg->shm_perm.uid = inbuf.shm_perm.uid;
                    414:                shmseg->shm_perm.gid = inbuf.shm_perm.gid;
                    415:                shmseg->shm_perm.mode =
                    416:                    (shmseg->shm_perm.mode & ~ACCESSPERMS) |
                    417:                    (inbuf.shm_perm.mode & ACCESSPERMS);
                    418:                shmseg->shm_ctime = time_second;
                    419:                break;
                    420:        case IPC_RMID:
                    421:                error = ipcperm(cred, &shmseg->shm_perm, IPC_M);
                    422:                if (error)
                    423:                        return error;
                    424:                shmseg->shm_perm.key = IPC_PRIVATE;
                    425:                shmseg->shm_perm.mode |= SHMSEG_REMOVED;
                    426:                if (shmseg->shm_nattch <= 0) {
                    427:                        shm_deallocate_segment(shmseg);
                    428:                        shm_last_free = IPCID_TO_IX(uap->shmid);
                    429:                }
                    430:                break;
                    431: #if 0
                    432:        case SHM_LOCK:
                    433:        case SHM_UNLOCK:
                    434: #endif
                    435:        default:
                    436:                return EINVAL;
                    437:        }
                    438:        return 0;
                    439: }
                    440: 
                    441: #ifndef _SYS_SYSPROTO_H_
                    442: struct shmget_args {
                    443:        key_t key;
                    444:        size_t size;
                    445:        int shmflg;
                    446: };
                    447: #endif
                    448: 
                    449: static int
                    450: shmget_existing(p, uap, mode, segnum, retval)
                    451:        struct proc *p;
                    452:        struct shmget_args *uap;
                    453:        int mode;
                    454:        int segnum;
                    455:        int *retval;
                    456: {
                    457:        struct shmid_ds *shmseg;
                    458:        struct ucred *cred = p->p_ucred;
                    459:        int error;
                    460: 
                    461:        shmseg = &shmsegs[segnum];
                    462:        if (shmseg->shm_perm.mode & SHMSEG_REMOVED) {
                    463:                /*
                    464:                 * This segment is in the process of being allocated.  Wait
                    465:                 * until it's done, and look the key up again (in case the
                    466:                 * allocation failed or it was freed).
                    467:                 */
                    468:                shmseg->shm_perm.mode |= SHMSEG_WANTED;
                    469:                error = tsleep((caddr_t)shmseg, PLOCK | PCATCH, "shmget", 0);
                    470:                if (error)
                    471:                        return error;
                    472:                return EAGAIN;
                    473:        }
                    474:        error = ipcperm(cred, &shmseg->shm_perm, mode);
                    475:        if (error)
                    476:                return error;
                    477:        if (uap->size && uap->size > shmseg->shm_segsz)
                    478:                return EINVAL;
                    479:        if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL))
                    480:                return EEXIST;
                    481:        *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
                    482:        return 0;
                    483: }
                    484: 
                    485: static int
                    486: shmget_allocate_segment(p, uap, mode, retval)
                    487:        struct proc *p;
                    488:        struct shmget_args *uap;
                    489:        int mode;
                    490:        int * retval;
                    491: {
                    492:        int i, segnum, shmid, size;
                    493:        struct ucred *cred = p->p_ucred;
                    494:        struct shmid_ds *shmseg;
                    495:        struct shm_handle *shm_handle;
                    496:        kern_return_t kret;
                    497:        vm_offset_t user_addr;
                    498:        void * mem_object;
                    499: 
                    500:        if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax)
                    501:                return EINVAL;
                    502:        if (shm_nused >= shminfo.shmmni) /* any shmids left? */
                    503:                return ENOSPC;
                    504:        size = round_page(uap->size);
                    505:        if (shm_committed + btoc(size) > shminfo.shmall)
                    506:                return ENOMEM;
                    507:        if (shm_last_free < 0) {
                    508:                for (i = 0; i < shminfo.shmmni; i++)
                    509:                        if (shmsegs[i].shm_perm.mode & SHMSEG_FREE)
                    510:                                break;
                    511:                if (i == shminfo.shmmni)
                    512:                        panic("shmseg free count inconsistent");
                    513:                segnum = i;
                    514:        } else  {
                    515:                segnum = shm_last_free;
                    516:                shm_last_free = -1;
                    517:        }
                    518:        shmseg = &shmsegs[segnum];
                    519:        /*
                    520:         * In case we sleep in malloc(), mark the segment present but deleted
                    521:         * so that noone else tries to create the same key.
                    522:         */
                    523:        kret = vm_allocate(current_map(), &user_addr, size, TRUE);
                    524:        if (kret != KERN_SUCCESS) 
                    525:                goto out;
                    526: 
                    527:        kret = mach_make_memory_entry (current_map(), &size,
                    528:                        user_addr, VM_PROT_DEFAULT, &mem_object, 0);
                    529: 
                    530:        if (kret != KERN_SUCCESS) 
                    531:                goto out;
                    532:        shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
                    533:        shmseg->shm_perm.key = uap->key;
                    534:        shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff;
                    535:        shm_handle = (struct shm_handle *)
                    536:            _MALLOC(sizeof(struct shm_handle), M_SHM, M_WAITOK);
                    537:        shm_handle->shm_object = mem_object;
                    538:        shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
                    539: 
                    540:        shmseg->shm_internal = shm_handle;
                    541:        shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid;
                    542:        shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid;
                    543:        shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) |
                    544:            (mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
                    545:        shmseg->shm_segsz = uap->size;
                    546:        shmseg->shm_cpid = p->p_pid;
                    547:        shmseg->shm_lpid = shmseg->shm_nattch = 0;
                    548:        shmseg->shm_atime = shmseg->shm_dtime = 0;
                    549:        shmseg->shm_ctime = time_second;
                    550:        shm_committed += btoc(size);
                    551:        shm_nused++;
                    552:        if (shmseg->shm_perm.mode & SHMSEG_WANTED) {
                    553:                /*
                    554:                 * Somebody else wanted this key while we were asleep.  Wake
                    555:                 * them up now.
                    556:                 */
                    557:                shmseg->shm_perm.mode &= ~SHMSEG_WANTED;
                    558:                wakeup((caddr_t)shmseg);
                    559:        }
                    560:        *retval = shmid;
                    561:        return 0;
                    562: out: 
                    563:        switch (kret) {
                    564:        case KERN_INVALID_ADDRESS:
                    565:        case KERN_NO_SPACE:
                    566:                return (ENOMEM);
                    567:        case KERN_PROTECTION_FAILURE:
                    568:                return (EACCES);
                    569:        default:
                    570:                return (EINVAL);
                    571:        }
                    572: 
                    573: }
                    574: 
                    575: int
                    576: shmget(p, uap, retval)
                    577:        struct proc *p;
                    578:        struct shmget_args *uap;
                    579:        register_t *retval;
                    580: {
                    581:        int segnum, mode, error;
                    582: 
                    583:        mode = uap->shmflg & ACCESSPERMS;
                    584:        if (uap->key != IPC_PRIVATE) {
                    585:        again:
                    586:                segnum = shm_find_segment_by_key(uap->key);
                    587:                if (segnum >= 0) {
                    588:                        error = shmget_existing(p, uap, mode, segnum, retval);
                    589:                        if (error == EAGAIN)
                    590:                                goto again;
                    591:                        return(error);
                    592:                }
                    593:                if ((uap->shmflg & IPC_CREAT) == 0)
                    594:                        return ENOENT;
                    595:        }
                    596:        return( shmget_allocate_segment(p, uap, mode, retval));;
                    597:        /*NOTREACHED*/
                    598: 
                    599: }
                    600: 
                    601: struct shmsys_args  {
                    602:        u_int   which;
                    603:        int     a2;
                    604:        int     a3;
                    605:        int     a4;
                    606: };
                    607: int
                    608: shmsys(p, uap, retval)
                    609:        struct proc *p;
                    610:        /* XXX actually varargs. */
                    611:        struct shmsys_args *uap;
                    612:        register_t *retval;
                    613: {
                    614: 
                    615:        if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0]))
                    616:                return EINVAL;
                    617:        return ((*shmcalls[uap->which])(p, &uap->a2, retval));
                    618: }
                    619: 
                    620: void
                    621: shmfork(p1, p2)
                    622:        struct proc *p1, *p2;
                    623: {
                    624:        struct shmmap_state *shmmap_s;
                    625:        size_t size;
                    626:        int i;
                    627: 
                    628:        size = shminfo.shmseg * sizeof(struct shmmap_state);
                    629:        shmmap_s = (struct shmmap_state *)_MALLOC(size, M_SHM, M_WAITOK);
                    630:        bcopy((caddr_t)p1->vm_shm, (caddr_t)shmmap_s, size);
                    631:        p2->vm_shm = (caddr_t)shmmap_s;
                    632:        for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
                    633:                if (shmmap_s->shmid != -1)
                    634:                        shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
                    635: }
                    636: 
                    637: void
                    638: shmexit(p)
                    639:        struct proc *p;
                    640: {
                    641:        struct shmmap_state *shmmap_s;
                    642:        int i;
                    643: 
                    644:        shmmap_s = (struct shmmap_state *)p->vm_shm;
                    645:        for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
                    646:                if (shmmap_s->shmid != -1)
                    647:                        shm_delete_mapping(p, shmmap_s);
                    648:        FREE((caddr_t)p->vm_shm, M_SHM);
                    649:        p->vm_shm = NULL;
                    650: }
                    651: 
                    652: void
                    653: shminit(dummy)
                    654:        void *dummy;
                    655: {
                    656:        int i;
                    657:        int s;
                    658: 
                    659:        s = sizeof(struct shmid_ds) * shminfo.shmmni;
                    660: 
                    661:        MALLOC(shmsegs, struct shmid_ds *, s, 
                    662:                M_SHM, M_WAITOK);
                    663:        for (i = 0; i < shminfo.shmmni; i++) {
                    664:                shmsegs[i].shm_perm.mode = SHMSEG_FREE;
                    665:                shmsegs[i].shm_perm.seq = 0;
                    666:        }
                    667:        shm_last_free = 0;
                    668:        shm_nused = 0;
                    669:        shm_committed = 0;
                    670: }

unix.superglobalmegacorp.com

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