Annotation of XNU/bsd/kern/posix_sem.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: /*
                     23:  *     Copyright (c) 1990, 1996-1998 Apple Computer, Inc.
                     24:  *     All Rights Reserved.
                     25:  */
                     26: /*
                     27:  * posix_shm.c : Support for POSIX semaphore apis
                     28:  *
                     29:  *     File:   posix_sem.c
                     30:  *     Author: Ananthakrishna Ramesh
                     31:  *
                     32:  * HISTORY
                     33:  * 2-Sep-1999  A.Ramesh
                     34:  *     Created for MacOSX
                     35:  *
                     36:  */
                     37: 
                     38: #include <sys/cdefs.h>
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41: #include <sys/kernel.h>
                     42: #include <sys/file.h>
                     43: #include <sys/filedesc.h>
                     44: #include <sys/stat.h>
                     45: #include <sys/buf.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/mount.h>
                     48: #include <sys/namei.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/ioctl.h>
                     51: #include <sys/tty.h>
                     52: #include <sys/malloc.h>
                     53: #include <sys/semaphore.h>
                     54: #include <mach/mach_types.h>
                     55: #include <mach/vm_prot.h>
                     56: #include <mach/sync_policy.h>
                     57: #include <kern/task.h>
                     58: #include <kern/sync_sema.h>
                     59: #include <kern/clock.h>
                     60: #include <mach/kern_return.h>
                     61: 
                     62: 
                     63: #define        PSEMNAMLEN      31      /* maximum name segment length we bother with */
                     64: 
                     65: struct pseminfo {
                     66:        unsigned int    psem_flags;
                     67:        unsigned int    psem_usecount;
                     68:        mode_t          psem_mode;
                     69:        uid_t           psem_uid;
                     70:        gid_t           psem_gid;
                     71:        char            psem_name[PSEMNAMLEN + 1];      /* segment name */
                     72:        void *          psem_semobject;
                     73:        struct proc *   sem_proc;
                     74: };
                     75: #define PSEMINFO_NULL (struct pseminfo *)0
                     76: 
                     77: #define        PSEM_NONE       1
                     78: #define        PSEM_DEFINED    2
                     79: #define        PSEM_ALLOCATED  4
                     80: #define        PSEM_MAPPED     8
                     81: #define        PSEM_INUSE      0x10
                     82: #define        PSEM_REMOVED    0x20
                     83: #define        PSEM_INCREATE   0x40
                     84: #define        PSEM_INDELETE   0x80
                     85: 
                     86: struct psemcache {
                     87:        LIST_ENTRY(psemcache) psem_hash;        /* hash chain */
                     88:        struct  pseminfo *pseminfo;             /* vnode the name refers to */
                     89:        int     psem_nlen;              /* length of name */
                     90:        char    psem_name[PSEMNAMLEN + 1];      /* segment name */
                     91: };
                     92: #define PSEMCACHE_NULL (struct psemcache *)0
                     93: 
                     94: struct psemstats {
                     95:        long    goodhits;               /* hits that we can really use */
                     96:        long    neghits;                /* negative hits that we can use */
                     97:        long    badhits;                /* hits we must drop */
                     98:        long    falsehits;              /* hits with id mismatch */
                     99:        long    miss;           /* misses */
                    100:        long    longnames;              /* long names that ignore cache */
                    101: };
                    102: 
                    103: struct psemname {
                    104:        char    *psem_nameptr;  /* pointer to looked up name */
                    105:        long    psem_namelen;   /* length of looked up component */
                    106:        u_long  psem_hash;      /* hash value of looked up name */
                    107: };
                    108: 
                    109: struct psemnode {
                    110:        struct pseminfo *pinfo;
                    111: #if DIAGNOSTIC
                    112:        unsigned int readcnt;
                    113:        unsigned int writecnt;
                    114: #endif
                    115: };
                    116: #define PSEMNODE_NULL (struct psemnode *)0
                    117: 
                    118: 
                    119: #define PSEMHASH(pnp) \
                    120:        (&psemhashtbl[(pnp)->psem_hash & psemhash])
                    121: LIST_HEAD(psemhashhead, psemcache) *psemhashtbl;       /* Hash Table */
                    122: u_long psemhash;                               /* size of hash table - 1 */
                    123: long   psemnument;                     /* number of cache entries allocated */
                    124: struct psemstats psemstats;            /* cache effectiveness statistics */
                    125: static psem_init =0; 
                    126: 
                    127: int psem_cache_search __P((struct pseminfo **, struct psemname *, struct psemcache **));
                    128: 
                    129: int psem_read  __P((struct file *fp, struct uio *uio,
                    130:                                            struct ucred *cred));
                    131: int psem_write  __P((struct file *fp, struct uio *uio,
                    132:                                            struct ucred *cred));
                    133: int psem_ioctl  __P((struct file *fp, u_long com,
                    134:                                            caddr_t data, struct proc *p));
                    135: int psem_select  __P((struct file *fp, int which,
                    136:                                            struct proc *p));
                    137: int psem_closefile  __P((struct file *fp, struct proc *p));
                    138: 
                    139: struct         fileops psemops =
                    140:        { psem_read, psem_write, psem_ioctl, psem_select, psem_closefile };
                    141: 
                    142: /*
                    143:  * Lookup an entry in the cache 
                    144:  * 
                    145:  * 
                    146:  * status of -1 is returned if matches
                    147:  * If the lookup determines that the name does not exist
                    148:  * (negative cacheing), a status of ENOENT is returned. If the lookup
                    149:  * fails, a status of zero is returned.
                    150:  */
                    151: 
                    152: int
                    153: psem_cache_search(psemp, pnp, pcache)
                    154:        struct pseminfo **psemp;
                    155:        struct psemname *pnp;
                    156:        struct psemcache **pcache;
                    157: {
                    158:        register struct psemcache *pcp, *nnp;
                    159:        register struct psemhashhead *pcpp;
                    160: 
                    161:        if (pnp->psem_namelen > PSEMNAMLEN) {
                    162:                psemstats.longnames++;
                    163:                return (0);
                    164:        }
                    165: 
                    166:        pcpp = PSEMHASH(pnp);
                    167:        for (pcp = pcpp->lh_first; pcp != 0; pcp = nnp) {
                    168:                nnp = pcp->psem_hash.le_next;
                    169:                if (pcp->psem_nlen == pnp->psem_namelen &&
                    170:                    !bcmp(pcp->psem_name, pnp->psem_nameptr,                                            (u_int)pcp-> psem_nlen))
                    171:                        break;
                    172:        }
                    173: 
                    174:        if (pcp == 0) {
                    175:                psemstats.miss++;
                    176:                return (0);
                    177:        }
                    178: 
                    179:        /* We found a "positive" match, return the vnode */
                    180:         if (pcp->pseminfo) {
                    181:                psemstats.goodhits++;
                    182:                /* TOUCH(ncp); */
                    183:                *psemp = pcp->pseminfo;
                    184:                *pcache = pcp;
                    185:                return (-1);
                    186:        }
                    187: 
                    188:        /*
                    189:         * We found a "negative" match, ENOENT notifies client of this match.
                    190:         * The nc_vpid field records whether this is a whiteout.
                    191:         */
                    192:        psemstats.neghits++;
                    193:        return (ENOENT);
                    194: }
                    195: 
                    196: /*
                    197:  * Add an entry to the cache.
                    198:  */
                    199: int
                    200: psem_cache_add(psemp, pnp)
                    201:        struct pseminfo *psemp;
                    202:        struct psemname *pnp;
                    203: {
                    204:        register struct psemcache *pcp;
                    205:        register struct psemhashhead *pcpp;
                    206:        struct pseminfo *dpinfo;
                    207:        struct psemcache *dpcp;
                    208: 
                    209: #if DIAGNOSTIC
                    210:        if (pnp->psem_namelen > NCHNAMLEN)
                    211:                panic("cache_enter: name too long");
                    212: #endif
                    213: 
                    214:        /*
                    215:         * We allocate a new entry if we are less than the maximum
                    216:         * allowed and the one at the front of the LRU list is in use.
                    217:         * Otherwise we use the one at the front of the LRU list.
                    218:         */
                    219:        pcp = (struct psemcache *)_MALLOC(sizeof(struct psemcache), M_SHM, M_WAITOK);
                    220:        /*  if the entry has already been added by some one else return */
                    221:        if (psem_cache_search(&dpinfo, pnp, &dpcp) == -1) {
                    222:                _FREE(pcp, M_SHM);
                    223:                return(EEXIST);
                    224:        }
                    225:        psemnument++;
                    226: 
                    227:        bzero(pcp, sizeof(struct psemcache));
                    228:        /*
                    229:         * Fill in cache info, if vp is NULL this is a "negative" cache entry.
                    230:         * For negative entries, we have to record whether it is a whiteout.
                    231:         * the whiteout flag is stored in the nc_vpid field which is
                    232:         * otherwise unused.
                    233:         */
                    234:        pcp->pseminfo = psemp;
                    235:        pcp->psem_nlen = pnp->psem_namelen;
                    236:        bcopy(pnp->psem_nameptr, pcp->psem_name, (unsigned)pcp->psem_nlen);
                    237:        pcpp = PSEMHASH(pnp);
                    238: #if DIAGNOSTIC
                    239:        {
                    240:                register struct psemcache *p;
                    241: 
                    242:                for (p = pcpp->lh_first; p != 0; p = p->psem_hash.le_next)
                    243:                        if (p == pcp)
                    244:                                panic("psem:cache_enter duplicate");
                    245:        }
                    246: #endif
                    247:        LIST_INSERT_HEAD(pcpp, pcp, psem_hash);
                    248:        return(0);
                    249: }
                    250: 
                    251: /*
                    252:  * Name cache initialization, from vfs_init() when we are booting
                    253:  */
                    254: void
                    255: psem_cache_init()
                    256: {
                    257:        psemhashtbl = hashinit(desiredvnodes, M_SHM, &psemhash);
                    258:        psem_init = 1;
                    259: }
                    260: 
                    261: /*
                    262:  * Invalidate a all entries to particular vnode.
                    263:  * 
                    264:  * We actually just increment the v_id, that will do it. The entries will
                    265:  * be purged by lookup as they get found. If the v_id wraps around, we
                    266:  * need to ditch the entire cache, to avoid confusion. No valid vnode will
                    267:  * ever have (v_id == 0).
                    268:  */
                    269: void
                    270: psem_cache_purge(void)
                    271: {
                    272:        struct psemcache *pcp;
                    273:        struct psemhashhead *pcpp;
                    274: 
                    275:        for (pcpp = &psemhashtbl[psemhash]; pcpp >= psemhashtbl; pcpp--) {
                    276:                while (pcp = pcpp->lh_first)
                    277:                        psem_cache_delete(pcp);
                    278:        }
                    279: }
                    280: 
                    281: psem_cache_delete(pcp)
                    282:        struct psemcache *pcp;
                    283: {
                    284: #if DIAGNOSTIC
                    285:        if (pcp->psem_hash.le_prev == 0)
                    286:                panic("psem namecache purge le_prev");
                    287:        if (pcp->psem_hash.le_next == pcp)
                    288:                panic("namecache purge le_next");
                    289: #endif /* DIAGNOSTIC */
                    290:        LIST_REMOVE(pcp, psem_hash);
                    291:        pcp->psem_hash.le_prev = 0;     
                    292:        psemnument--;
                    293: }
                    294: 
                    295: 
                    296: struct sem_open_args {
                    297: const char *name;
                    298: int oflag;
                    299: int mode;
                    300: int value;
                    301: };
                    302: 
                    303: int
                    304: sem_open(p, uap, retval)
                    305: struct proc *p;
                    306: register struct sem_open_args *uap;
                    307: register_t *retval;
                    308: {
                    309:        register struct filedesc *fdp = p->p_fd;
                    310:        register struct file *fp;
                    311:        register struct vnode *vp;
                    312:        int flags, i;
                    313:        struct file *nfp;
                    314:        int type, indx, error;
                    315:        struct psemname nd;
                    316:        struct pseminfo *pinfo;
                    317:        extern struct fileops psemops;
                    318:        char * pnbuf;
                    319:        char * nameptr;
                    320:        char * cp;
                    321:        size_t pathlen, plen;
                    322:        int fmode ;
                    323:        int cmode = uap->mode;
                    324:        int value = uap->value;
                    325:        int incache = 0;
                    326:        struct psemnode * pnode = PSEMNODE_NULL;
                    327:        struct psemcache * pcache = PSEMCACHE_NULL;
                    328:        kern_return_t kret = KERN_SUCCESS;
                    329: 
                    330:        if(!psem_init)
                    331:                psem_cache_init();
                    332: 
                    333:        pinfo = PSEMINFO_NULL;
                    334: 
                    335:        MALLOC_ZONE(pnbuf, caddr_t,
                    336:                        MAXPATHLEN, M_NAMEI, M_WAITOK);
                    337:        pathlen = MAXPATHLEN;
                    338:        error = copyinstr(uap->name, pnbuf,
                    339:                MAXPATHLEN, &pathlen);
                    340:        if (error) {
                    341:                goto bad;
                    342:        }
                    343:        if (pathlen > PSEMNAMLEN) {
                    344:                error = ENAMETOOLONG;
                    345:                goto bad;
                    346:        }
                    347: 
                    348: 
                    349: #ifdef PSXSEM_NAME_RESTRICT
                    350:        nameptr = pnbuf;
                    351:        if (*nameptr == '/') {
                    352:                while (*(nameptr++) == '/') {
                    353:                        plen--;
                    354:                        error = EINVAL;
                    355:                        goto bad;
                    356:                }
                    357:         } else {
                    358:                error = EINVAL;
                    359:                goto bad;
                    360:        }
                    361: #endif /* PSXSEM_NAME_RESTRICT */
                    362: 
                    363:        plen = pathlen;
                    364:        nameptr = pnbuf;
                    365:        nd.psem_nameptr = nameptr;
                    366:        nd.psem_namelen = plen;
                    367:        nd. psem_hash =0;
                    368: 
                    369:         for (cp = nameptr, i=1; *cp != 0 && i <= plen; i++, cp++) {
                    370:                nd.psem_hash += (unsigned char)*cp * i;
                    371:        }
                    372: 
                    373:        error = psem_cache_search(&pinfo, &nd, &pcache);
                    374: 
                    375:        if (error == ENOENT) {
                    376:                error = EINVAL;
                    377:                goto bad;
                    378: 
                    379:        }
                    380:        if (!error) {
                    381:                incache = 0;
                    382:        } else
                    383:                incache = 1;
                    384:        fmode = FFLAGS(uap->oflag);
                    385: 
                    386:        if (error = falloc(p, &nfp, &indx)) {
                    387:                goto bad;
                    388:        }
                    389: 
                    390:        fp = nfp;
                    391:        cmode &=  ALLPERMS;
                    392: 
                    393:        if (((fmode & (O_CREAT | O_EXCL))==(O_CREAT | O_EXCL)) &&  incache) {
                    394:                /* sem exists and opened O_EXCL */
                    395: #if notyet
                    396:                if (pinfo->psem_flags & PSEM_INDELETE) {
                    397:                }
                    398: #endif 
                    399:                error = EEXIST;
                    400:                goto bad1;
                    401:        }
                    402:        if (((fmode & (O_CREAT | O_EXCL))== O_CREAT) &&  incache) {
                    403:                /* As per POSIX, O_CREAT has no effect */
                    404:                fmode &= ~O_CREAT;
                    405:        }
                    406: 
                    407:        if (fmode & O_CREAT) {
                    408:                if((value < 0) && (value > SEM_VALUE_MAX)) {
                    409:                        error = EINVAL;
                    410:                        goto bad1;
                    411:                }
                    412:                pinfo = (struct pseminfo *)_MALLOC(sizeof(struct pseminfo), M_SHM, M_WAITOK);
                    413:                bzero(pinfo, sizeof(struct pseminfo));
                    414:                pinfo->psem_flags = PSEM_DEFINED | PSEM_INCREATE;
                    415:                pinfo->psem_usecount = 1;
                    416:                pinfo->psem_mode = cmode;
                    417:                pinfo->psem_uid = p->p_ucred->cr_uid;
                    418:                pinfo->psem_gid = p->p_ucred->cr_gid;
                    419:                kret = semaphore_create(kernel_task, &pinfo->psem_semobject,
                    420:                             SYNC_POLICY_FIFO, value);
                    421:                if(kret != KERN_SUCCESS) 
                    422:                        goto bad3;
                    423:                pinfo->psem_flags &= ~PSEM_DEFINED;
                    424:                pinfo->psem_flags |= PSEM_ALLOCATED;
                    425:                pinfo->sem_proc = p;
                    426:        } else {
                    427:                /* semaphore should exist as it is without  O_CREAT */
                    428:                if (!incache) {
                    429:                        error = ENOENT;
                    430:                        goto bad1;
                    431:                }
                    432:                if( pinfo->psem_flags & PSEM_INDELETE) {
                    433:                        error = ENOENT;
                    434:                        goto bad1;
                    435:                }       
                    436:                if (error = psem_access(pinfo, fmode, p->p_ucred, p))
                    437:                        goto bad1;
                    438:        }
                    439:        pnode = (struct psemnode *)_MALLOC(sizeof(struct psemnode), M_SHM, M_WAITOK);
                    440:        bzero(pnode, sizeof(struct psemnode));
                    441: 
                    442:        if (!incache) {
                    443:                if (error = psem_cache_add(pinfo, &nd)) {
                    444:                goto bad2;
                    445:                }
                    446:        }
                    447:        pinfo->psem_flags &= ~PSEM_INCREATE;
                    448:        pinfo->psem_usecount++;
                    449:        pnode->pinfo = pinfo;
                    450:        fp->f_flag = flags & FMASK;
                    451:        fp->f_type = DTYPE_PSXSEM;
                    452:        fp->f_ops = &psemops;
                    453:        fp->f_data = (caddr_t)pnode;
                    454:        *fdflags(p, indx) &= ~UF_RESERVED;
                    455:        *retval = indx;
                    456:        return (0);
                    457: 
                    458: bad3:
                    459:        switch (kret) {
                    460:        case KERN_RESOURCE_SHORTAGE:
                    461:                error = ENOMEM;
                    462:        case KERN_PROTECTION_FAILURE:
                    463:                error = EACCES;
                    464:        default:
                    465:                error = EINVAL;
                    466:        
                    467:        }
                    468:        goto bad1;
                    469: bad2:
                    470:        _FREE(pnode, M_SHM);
                    471:                
                    472: bad1:
                    473:        fdrelse(p, indx);
                    474:        ffree(nfp);
                    475:        _FREE(pinfo, M_SHM);
                    476:                
                    477: bad:
                    478:        _FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
                    479:        return (error);
                    480: }
                    481: 
                    482: 
                    483: 
                    484: int
                    485: psem_access(struct pseminfo *pinfo, int mode, struct ucred *cred, struct proc *p)
                    486: {
                    487:        mode_t mask;
                    488:        register gid_t *gp;
                    489:        int i, error;
                    490: 
                    491:        /* Otherwise, user id 0 always gets access. */
                    492:        if (cred->cr_uid == 0)
                    493:                return (0);
                    494: 
                    495:        mask = 0;
                    496: 
                    497:        /* Otherwise, check the owner. */
                    498:        if (cred->cr_uid == pinfo->psem_uid) {
                    499:                if (mode & FREAD)
                    500:                        mask |= S_IRUSR;
                    501:                if (mode & FWRITE)
                    502:                        mask |= S_IWUSR;
                    503:                return ((pinfo->psem_mode & mask) == mask ? 0 : EACCES);
                    504:        }
                    505: 
                    506:        /* Otherwise, check the groups. */
                    507:        for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
                    508:                if (pinfo->psem_gid == *gp) {
                    509:                        if (mode & FREAD)
                    510:                                mask |= S_IRGRP;
                    511:                        if (mode & FWRITE)
                    512:                                mask |= S_IWGRP;
                    513:                        return ((pinfo->psem_mode & mask) == mask ? 0 : EACCES);
                    514:                }
                    515: 
                    516:        /* Otherwise, check everyone else. */
                    517:        if (mode & FREAD)
                    518:                mask |= S_IROTH;
                    519:        if (mode & FWRITE)
                    520:                mask |= S_IWOTH;
                    521:        return ((pinfo->psem_mode & mask) == mask ? 0 : EACCES);
                    522: }
                    523: 
                    524: 
                    525: 
                    526: 
                    527: struct sem_unlink_args {
                    528: const char *name;
                    529: };
                    530: 
                    531: int
                    532: sem_unlink(p, uap, retval)
                    533: struct proc *p;
                    534: register struct sem_unlink_args *uap;
                    535: register_t *retval;
                    536: {
                    537:        register struct filedesc *fdp = p->p_fd;
                    538:        register struct file *fp;
                    539:        int flags, i;
                    540:        int error=0;
                    541:        struct psemname nd;
                    542:        struct pseminfo *pinfo;
                    543:        extern struct fileops psemops;
                    544:        char * pnbuf;
                    545:        char * nameptr;
                    546:        char * cp;
                    547:        size_t pathlen, plen;
                    548:        int fmode, cmode ;
                    549:        int incache = 0;
                    550:        struct psemnode * pnode = PSEMNODE_NULL;
                    551:        struct psemcache *pcache = PSEMCACHE_NULL;
                    552:        kern_return_t kret;
                    553: 
                    554:        pinfo = PSEMINFO_NULL;
                    555: 
                    556:        MALLOC_ZONE(pnbuf, caddr_t,
                    557:                        MAXPATHLEN, M_NAMEI, M_WAITOK);
                    558:        pathlen = MAXPATHLEN;
                    559:        error = copyinstr(uap->name, pnbuf,
                    560:                MAXPATHLEN, &pathlen);
                    561:        if (error) {
                    562:                goto bad;
                    563:        }
                    564:        if (pathlen > PSEMNAMLEN) {
                    565:                error = ENAMETOOLONG;
                    566:                goto bad;
                    567:        }
                    568: 
                    569: 
                    570: #ifdef PSXSEM_NAME_RESTRICT
                    571:        nameptr = pnbuf;
                    572:        if (*nameptr == '/') {
                    573:                while (*(nameptr++) == '/') {
                    574:                        plen--;
                    575:                        error = EINVAL;
                    576:                        goto bad;
                    577:                }
                    578:         } else {
                    579:                error = EINVAL;
                    580:                goto bad;
                    581:        }
                    582: #endif /* PSXSEM_NAME_RESTRICT */
                    583: 
                    584:        plen = pathlen;
                    585:        nameptr = pnbuf;
                    586:        nd.psem_nameptr = nameptr;
                    587:        nd.psem_namelen = plen;
                    588:        nd. psem_hash =0;
                    589: 
                    590:         for (cp = nameptr, i=1; *cp != 0 && i <= plen; i++, cp++) {
                    591:                nd.psem_hash += (unsigned char)*cp * i;
                    592:        }
                    593: 
                    594:        error = psem_cache_search(&pinfo, &nd, &pcache);
                    595: 
                    596:        if (error == ENOENT) {
                    597:                error = EINVAL;
                    598:                goto bad;
                    599: 
                    600:        }
                    601:        if (!error) {
                    602:                error = EINVAL;
                    603:                goto bad;
                    604:        } else
                    605:                incache = 1;
                    606:        if (error = psem_access(pinfo, pinfo->psem_mode, p->p_ucred, p))
                    607:                goto bad;
                    608: 
                    609:        if ((pinfo->psem_flags & (PSEM_DEFINED | PSEM_ALLOCATED))==0) {
                    610:                return (EINVAL);
                    611:        }
                    612: 
                    613:        if (pinfo->psem_flags & PSEM_INDELETE) {
                    614:                error = 0;
                    615:                goto bad;
                    616:        }
                    617:        pinfo->psem_flags |= PSEM_INDELETE;
                    618:        pinfo->psem_usecount--;
                    619: 
                    620:        if (!pinfo->psem_usecount) {
                    621:                psem_delete(pinfo);
                    622:                _FREE(pinfo,M_SHM);
                    623:        } else
                    624:                pinfo->psem_flags |= PSEM_REMOVED;
                    625: 
                    626:        psem_cache_delete(pcache);
                    627:        _FREE(pcache, M_SHM);
                    628:        error = 0;
                    629: bad:
                    630:        _FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
                    631:        return (error);
                    632: }
                    633: 
                    634: struct sem_close_args {
                    635: sem_t *sem;
                    636: };
                    637: 
                    638: int
                    639: sem_close(p, uap, retval)
                    640:        struct proc *p;
                    641:        struct sem_close_args *uap;
                    642:        register_t *retval;
                    643: {
                    644:        int fd = (int)uap->sem;
                    645:        register struct filedesc *fdp = p->p_fd;
                    646:        register struct file *fp;
                    647:        int error = 0;
                    648: 
                    649: 
                    650:        if ((u_int)fd >= fdp->fd_nfiles ||
                    651:                        (fp = fdp->fd_ofiles[fd]) == NULL ||
                    652:                        (fdp->fd_ofileflags[fd] & UF_RESERVED))
                    653:                return (EBADF);
                    654:        fdrelse(p, fd);
                    655:        if( error = closef(fp, p))
                    656:                return(error);
                    657:        return(0);
                    658:        
                    659:        
                    660: }
                    661: 
                    662: struct sem_wait_args {
                    663: sem_t *sem;
                    664: };
                    665: 
                    666: int
                    667: sem_wait(p, uap, retval)
                    668:        struct proc *p;
                    669:        struct sem_wait_args *uap;
                    670:        register_t *retval;
                    671: {
                    672:        int fd = (int)uap->sem;
                    673:        register struct filedesc *fdp = p->p_fd;
                    674:        struct file *fp;
                    675:        struct pseminfo * pinfo;
                    676:        struct psemnode * pnode ;
                    677:        kern_return_t kret;
                    678:        int error;
                    679: 
                    680:        if (error = fdgetf(p, (int)uap->sem, &fp))
                    681:                return (error);
                    682:        if (fp->f_type != DTYPE_PSXSEM)
                    683:                return(EBADF);
                    684:        if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL )
                    685:                return(EINVAL);
                    686:        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL)
                    687:                return(EINVAL);
                    688:        if ((pinfo->psem_flags & (PSEM_DEFINED | PSEM_ALLOCATED)) 
                    689:                        != PSEM_ALLOCATED) {
                    690:                return(EINVAL);
                    691:        }
                    692: 
                    693:        kret = semaphore_wait(pinfo->psem_semobject);
                    694:        switch (kret) {
                    695:        case KERN_INVALID_ADDRESS:
                    696:        case KERN_PROTECTION_FAILURE:
                    697:                return (EACCES);
                    698:        case KERN_ABORTED:
                    699:        case KERN_OPERATION_TIMED_OUT:
                    700:                return (EINTR);
                    701:        case KERN_SUCCESS:
                    702:                return(0);
                    703:        default:
                    704:                return (EINVAL);
                    705:        }
                    706: 
                    707: }
                    708: 
                    709: struct sem_trywait_args {
                    710: sem_t *sem;
                    711: };
                    712: 
                    713: int
                    714: sem_trywait(p, uap, retval)
                    715:        struct proc *p;
                    716:        struct sem_wait_args *uap;
                    717:        register_t *retval;
                    718: {
                    719:        int fd = (int)uap->sem;
                    720:        register struct filedesc *fdp = p->p_fd;
                    721:        struct file *fp;
                    722:        struct pseminfo * pinfo;
                    723:        struct psemnode * pnode ;
                    724:        kern_return_t kret;
                    725:        mach_timespec_t wait_time;
                    726:        int error;
                    727:        
                    728:        if (error = fdgetf(p, (int)uap->sem, &fp))
                    729:                return (error);
                    730:        if (fp->f_type != DTYPE_PSXSEM)
                    731:                return(EBADF);
                    732:        if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL )
                    733:                return(EINVAL);
                    734:        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL)
                    735:                return(EINVAL);
                    736:        if ((pinfo->psem_flags & (PSEM_DEFINED | PSEM_ALLOCATED)) 
                    737:                        != PSEM_ALLOCATED) {
                    738:                return(EINVAL);
                    739:        }
                    740: 
                    741:        wait_time.tv_sec = 0;
                    742:        wait_time.tv_nsec = 0;
                    743: 
                    744:        kret = semaphore_timedwait(pinfo->psem_semobject, MACH_TIMESPEC_ZERO);
                    745:        switch (kret) {
                    746:        case KERN_INVALID_ADDRESS:
                    747:        case KERN_PROTECTION_FAILURE:
                    748:                return (EINVAL);
                    749:        case KERN_ABORTED:
                    750:                return (EINTR);
                    751:        case KERN_OPERATION_TIMED_OUT:
                    752:                return (EAGAIN);
                    753:        case KERN_SUCCESS:
                    754:                return(0);
                    755:        default:
                    756:                return (EINVAL);
                    757:        }
                    758: 
                    759: }
                    760: 
                    761: struct sem_post_args {
                    762: sem_t *sem;
                    763: };
                    764: 
                    765: int
                    766: sem_post(p, uap, retval)
                    767:        struct proc *p;
                    768:        struct sem_wait_args *uap;
                    769:        register_t *retval;
                    770: {
                    771:        int fd = (int)uap->sem;
                    772:        register struct filedesc *fdp = p->p_fd;
                    773:        struct file *fp;
                    774:        struct pseminfo * pinfo;
                    775:        struct psemnode * pnode ;
                    776:        kern_return_t kret;
                    777:        int error;
                    778: 
                    779:        if (error = fdgetf(p, (int)uap->sem, &fp))
                    780:                return (error);
                    781:        if (fp->f_type != DTYPE_PSXSEM)
                    782:                return(EBADF);
                    783:        if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL )
                    784:                return(EINVAL);
                    785:        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL)
                    786:                return(EINVAL);
                    787:        if ((pinfo->psem_flags & (PSEM_DEFINED | PSEM_ALLOCATED)) 
                    788:                        != PSEM_ALLOCATED) {
                    789:                return(EINVAL);
                    790:        }
                    791: 
                    792:        kret = semaphore_signal(pinfo->psem_semobject);
                    793:        switch (kret) {
                    794:        case KERN_INVALID_ADDRESS:
                    795:        case KERN_PROTECTION_FAILURE:
                    796:                return (EINVAL);
                    797:        case KERN_ABORTED:
                    798:        case KERN_OPERATION_TIMED_OUT:
                    799:                return (EINTR);
                    800:        case KERN_SUCCESS:
                    801:                return(0);
                    802:        default:
                    803:                return (EINVAL);
                    804:        }
                    805: 
                    806: }
                    807: 
                    808: struct sem_init_args {
                    809: sem_t *sem;
                    810: int phsared;
                    811: unsigned int value;
                    812: };
                    813: 
                    814: int
                    815: sem_init(p, uap, retval)
                    816:        struct proc *p;
                    817:        struct sem_init_args *uap;
                    818:        register_t *retval;
                    819: {
                    820:        return(ENOSYS);
                    821: }
                    822: 
                    823: struct sem_destroy_args {
                    824: sem_t *sem;
                    825: };
                    826: 
                    827: int
                    828: sem_destroy(p, uap, retval)
                    829:        struct proc *p;
                    830:        struct sem_destroy_args *uap;
                    831:        register_t *retval;
                    832: {
                    833:        return(ENOSYS);
                    834: }
                    835: 
                    836: struct sem_getvalue_args {
                    837: sem_t *sem;
                    838: int * sval;
                    839: };
                    840: 
                    841: int
                    842: sem_getvalue(p, uap, retval)
                    843:        struct proc *p;
                    844:        struct sem_getvalue_args *uap;
                    845:        register_t *retval;
                    846: {
                    847:        return(ENOSYS);
                    848: }
                    849: 
                    850: int
                    851: psem_closefile(fp, p)
                    852:        struct file *fp;
                    853:        struct proc *p;
                    854: {
                    855: 
                    856:        return (psem_close(((struct psemnode *)fp->f_data), fp->f_flag,
                    857:                fp->f_cred, p));
                    858: }
                    859: 
                    860: 
                    861: int
                    862: psem_close(pnode, flags, cred, p)
                    863:        register struct psemnode *pnode;
                    864:        int flags;
                    865:        struct ucred *cred;
                    866:        struct proc *p;
                    867: {
                    868:        int error=0;
                    869:        kern_return_t kret;
                    870:        register struct pseminfo *pinfo;
                    871: 
                    872:        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL)
                    873:                return(EINVAL);
                    874: 
                    875:        if ((pinfo->psem_flags & PSEM_ALLOCATED) != PSEM_ALLOCATED) {
                    876:                return(EINVAL);
                    877:        }
                    878: #if DIAGNOSTIC
                    879:        if(!pinfo->psem_usecount) {
                    880:                kprintf("negative usecount in psem_close\n");
                    881:        }
                    882: #endif /* DIAGNOSTIC */
                    883:        pinfo->psem_usecount--;
                    884: 
                    885:        if ((pinfo->psem_flags & PSEM_REMOVED) && !pinfo->psem_usecount) {
                    886:                error = psem_delete(pinfo);
                    887:                _FREE(pinfo,M_SHM);
                    888:        }
                    889:        _FREE(pnode, M_SHM);
                    890:        return (error);
                    891: }
                    892: 
                    893: int 
                    894: psem_delete(struct pseminfo * pinfo)
                    895: {
                    896:        kern_return_t kret;
                    897: 
                    898:        kret = semaphore_destroy(kernel_task, pinfo->psem_semobject);
                    899: 
                    900:        switch (kret) {
                    901:        case KERN_INVALID_ADDRESS:
                    902:        case KERN_PROTECTION_FAILURE:
                    903:                return (EINVAL);
                    904:        case KERN_ABORTED:
                    905:        case KERN_OPERATION_TIMED_OUT:
                    906:                return (EINTR);
                    907:        case KERN_SUCCESS:
                    908:                return(0);
                    909:        default:
                    910:                return (EINVAL);
                    911:        }
                    912:        
                    913: }
                    914: 
                    915: 
                    916: int
                    917: psem_read(struct file *fp, struct uio *uio, struct ucred *cred) 
                    918: {
                    919:        return(EOPNOTSUPP);
                    920: }
                    921: int
                    922: psem_write(struct file *fp, struct uio *uio, struct ucred *cred)
                    923: {
                    924:        return(EOPNOTSUPP);
                    925: }
                    926: int
                    927: psem_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
                    928: {
                    929:        return(EOPNOTSUPP);
                    930: }
                    931: int
                    932: psem_select(struct file *fp, int which, struct proc *p)
                    933: {
                    934:        return(EOPNOTSUPP);
                    935: }

unix.superglobalmegacorp.com

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