Annotation of XNU/bsd/kern/posix_sem.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:  *     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.