]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/posix_sem.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / kern / posix_sem.c
index b1119d15381f0860b6e3dea3c44e2a56d45ee342..38106d0430f4e59151a3e028cd66c352be1a0b8a 100644 (file)
 #include <kern/clock.h>
 #include <mach/kern_return.h>
 
+#define f_flag fp_glob->fg_flag
+#define f_ops fp_glob->fg_ops
+#define f_data fp_glob->fg_data
 
-#define f_flag f_fglob->fg_flag
-#define f_type f_fglob->fg_ops->fo_type
-#define f_msgcount f_fglob->fg_msgcount
-#define f_cred f_fglob->fg_cred
-#define f_ops f_fglob->fg_ops
-#define f_offset f_fglob->fg_offset
-#define f_data f_fglob->fg_data
 #define PSEMNAMLEN      31      /* maximum name segment length we bother with */
 
 struct pseminfo {
@@ -119,7 +115,7 @@ struct pseminfo {
 struct  psemcache {
        LIST_ENTRY(psemcache) psem_hash;        /* hash chain */
        struct  pseminfo *pseminfo;             /* vnode the name refers to */
-       int     psem_nlen;              /* length of name */
+       size_t  psem_nlen;              /* length of name */
        char    psem_name[PSEMNAMLEN + 1];      /* segment name */
 };
 #define PSEMCACHE_NULL (struct psemcache *)0
@@ -139,7 +135,7 @@ struct  psemstats {
 
 struct psemname {
        char    *psem_nameptr;  /* pointer to looked up name */
-       long    psem_namelen;   /* length of looked up component */
+       size_t  psem_namelen;   /* length of looked up component */
        u_int32_t       psem_hash;      /* hash value of looked up name */
 };
 
@@ -166,7 +162,7 @@ SYSCTL_LONG(_kern_posix_sem, OID_AUTO, max, CTLFLAG_RW | CTLFLAG_LOCKED, &posix_
 
 struct psemstats psemstats;             /* cache effectiveness statistics */
 
-static int psem_access(struct pseminfo *pinfo, int mode, kauth_cred_t cred);
+static int psem_access(struct pseminfo *pinfo, mode_t mode, kauth_cred_t cred);
 static int psem_cache_search(struct pseminfo **,
     struct psemname *, struct psemcache **);
 static int psem_delete(struct pseminfo * pinfo);
@@ -238,7 +234,7 @@ psem_cache_search(struct pseminfo **psemp, struct psemname *pnp,
        for (pcp = pcpp->lh_first; pcp != 0; pcp = nnp) {
                nnp = pcp->psem_hash.le_next;
                if (pcp->psem_nlen == pnp->psem_namelen &&
-                   !bcmp(pcp->psem_name, pnp->psem_nameptr, (u_int)pcp->psem_nlen)) {
+                   !bcmp(pcp->psem_name, pnp->psem_nameptr, pcp->psem_nlen)) {
                        break;
                }
        }
@@ -298,7 +294,7 @@ psem_cache_add(struct pseminfo *psemp, struct psemname *pnp, struct psemcache *p
         */
        pcp->pseminfo = psemp;
        pcp->psem_nlen = pnp->psem_namelen;
-       bcopy(pnp->psem_nameptr, pcp->psem_name, (unsigned)pcp->psem_nlen);
+       bcopy(pnp->psem_nameptr, pcp->psem_name, pcp->psem_nlen);
        pcpp = PSEMHASH(pnp);
 #if DIAGNOSTIC
        {
@@ -321,7 +317,7 @@ psem_cache_add(struct pseminfo *psemp, struct psemname *pnp, struct psemcache *p
 void
 psem_cache_init(void)
 {
-       psemhashtbl = hashinit(posix_sem_max / 2, M_SHM, &psemhash);
+       psemhashtbl = hashinit((int)(posix_sem_max / 2), M_SHM, &psemhash);
 }
 
 static void
@@ -381,6 +377,16 @@ out:
        return error;
 }
 
+/*
+ *             In order to support unnamed POSIX semaphores, the named
+ *             POSIX semaphores will have to move out of the per-process
+ *             open filetable, and into a global table that is shared with
+ *             unnamed POSIX semaphores, since unnamed POSIX semaphores
+ *             are typically used by declaring instances in shared memory,
+ *             and there's no other way to do this without changing the
+ *             underlying type, which would introduce binary compatibility
+ *             issues.
+ */
 int
 sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval)
 {
@@ -396,15 +402,15 @@ sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval)
        char * nameptr;
        char * cp;
        size_t pathlen, plen;
-       int fmode;
-       int cmode = uap->mode;
+       mode_t fmode;
+       mode_t cmode = (mode_t)uap->mode;
        int value = uap->value;
        int incache = 0;
        struct psemcache *pcp = PSEMCACHE_NULL;
        kern_return_t kret = KERN_INVALID_ADDRESS;      /* default fail */
 
        AUDIT_ARG(fflags, uap->oflag);
-       AUDIT_ARG(mode, uap->mode);
+       AUDIT_ARG(mode, (mode_t)uap->mode);
        AUDIT_ARG(value32, uap->value);
 
        pinfo = PSEMINFO_NULL;
@@ -413,11 +419,7 @@ sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval)
         * Preallocate everything we might need up front to avoid taking
         * and dropping the lock, opening us up to race conditions.
         */
-       MALLOC_ZONE(pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK | M_ZERO);
-       if (pnbuf == NULL) {
-               error = ENOSPC;
-               goto bad;
-       }
+       pnbuf = zalloc_flags(ZV_NAMEI, Z_WAITOK | Z_ZERO);
 
        pathlen = MAXPATHLEN;
        error = copyinstr(uap->name, pnbuf, MAXPATHLEN, &pathlen);
@@ -490,7 +492,7 @@ sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval)
         * to KERN_INVALID_ADDRESS, above.
         */
 
-       fmode = FFLAGS(uap->oflag);
+       fmode = (mode_t)FFLAGS(uap->oflag);
 
        if ((fmode & O_CREAT)) {
                if ((value < 0) || (value > SEM_VALUE_MAX)) {
@@ -636,7 +638,7 @@ sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval)
        proc_fdunlock(p);
 
        *retval = CAST_USER_ADDR_T(indx);
-       FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
+       zfree(ZV_NAMEI, pnbuf);
        return 0;
 
 bad_locked:
@@ -671,7 +673,7 @@ bad:
        }
 
        if (pnbuf != NULL) {
-               FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
+               zfree(ZV_NAMEI, pnbuf);
        }
        return error;
 }
@@ -680,9 +682,9 @@ bad:
  * XXX This code is repeated in several places
  */
 static int
-psem_access(struct pseminfo *pinfo, int mode, kauth_cred_t cred)
+psem_access(struct pseminfo *pinfo, mode_t mode, kauth_cred_t cred)
 {
-       int mode_req = ((mode & FREAD) ? S_IRUSR : 0) |
+       mode_t mode_req = ((mode & FREAD) ? S_IRUSR : 0) |
            ((mode & FWRITE) ? S_IWUSR : 0);
 
        /* Otherwise, user id 0 always gets access. */
@@ -744,10 +746,8 @@ sem_unlink(__unused proc_t p, struct sem_unlink_args *uap, __unused int32_t *ret
 
        pinfo = PSEMINFO_NULL;
 
-       MALLOC_ZONE(pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
-       if (pnbuf == NULL) {
-               return ENOSPC;         /* XXX non-standard */
-       }
+       pnbuf = zalloc(ZV_NAMEI);
+
        pathlen = MAXPATHLEN;
        error = copyinstr(uap->name, pnbuf, MAXPATHLEN, &pathlen);
        if (error) {
@@ -807,7 +807,7 @@ sem_unlink(__unused proc_t p, struct sem_unlink_args *uap, __unused int32_t *ret
        PSEM_SUBSYS_UNLOCK();
 
 bad:
-       FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
+       zfree(ZV_NAMEI, pnbuf);
        return error;
 }
 
@@ -816,30 +816,19 @@ sem_close(proc_t p, struct sem_close_args *uap, __unused int32_t *retval)
 {
        int fd = CAST_DOWN_EXPLICIT(int, uap->sem);
        struct fileproc *fp;
-       int error = 0;
 
        AUDIT_ARG(fd, fd); /* XXX This seems wrong; uap->sem is a pointer */
 
        proc_fdlock(p);
-       error = fp_lookup(p, fd, &fp, 1);
-       if (error) {
+       if ((fp = fp_get_noref_locked(p, fd)) == NULL) {
                proc_fdunlock(p);
-               return error;
+               return EBADF;
        }
-       if (fp->f_type != DTYPE_PSXSEM) {
-               fp_drop(p, fd, fp, 1);
+       if (FILEGLOB_DTYPE(fp->fp_glob) != DTYPE_PSXSEM) {
                proc_fdunlock(p);
                return EBADF;
        }
-       procfdtbl_markclosefd(p, fd);
-       /* release the ref returned from fp_lookup before calling drain */
-       (void) os_ref_release_locked(&fp->f_iocount);
-       fileproc_drain(p, fp);
-       fdrelse(p, fd);
-       error = closef_locked(fp, fp->f_fglob, p);
-       fileproc_free(fp);
-       proc_fdunlock(p);
-       return error;
+       return fp_close_and_unlock(p, fd, fp, 0);
 }
 
 int
@@ -859,14 +848,12 @@ sem_wait_nocancel(proc_t p, struct sem_wait_nocancel_args *uap, __unused int32_t
        kern_return_t kret;
        int error;
 
-       error = fp_getfpsem(p, fd, &fp, &pnode);
+       error = fp_get_ftype(p, fd, DTYPE_PSXSEM, EBADF, &fp);
        if (error) {
                return error;
        }
-       if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL) {
-               error = EINVAL;
-               goto out;
-       }
+       pnode = (struct psemnode *)fp->f_data;
+
        PSEM_SUBSYS_LOCK();
        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL) {
                PSEM_SUBSYS_UNLOCK();
@@ -920,14 +907,12 @@ sem_trywait(proc_t p, struct sem_trywait_args *uap, __unused int32_t *retval)
        mach_timespec_t wait_time;
        int error;
 
-       error = fp_getfpsem(p, fd, &fp, &pnode);
+       error = fp_get_ftype(p, fd, DTYPE_PSXSEM, EBADF, &fp);
        if (error) {
                return error;
        }
-       if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL) {
-               error = EINVAL;
-               goto out;
-       }
+       pnode = (struct psemnode *)fp->f_data;
+
        PSEM_SUBSYS_LOCK();
        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL) {
                PSEM_SUBSYS_UNLOCK();
@@ -985,14 +970,12 @@ sem_post(proc_t p, struct sem_post_args *uap, __unused int32_t *retval)
        kern_return_t kret;
        int error;
 
-       error = fp_getfpsem(p, fd, &fp, &pnode);
+       error = fp_get_ftype(p, fd, DTYPE_PSXSEM, EBADF, &fp);
        if (error) {
                return error;
        }
-       if (((pnode = (struct psemnode *)fp->f_data)) == PSEMNODE_NULL) {
-               error = EINVAL;
-               goto out;
-       }
+       pnode = (struct psemnode *)fp->f_data;
+
        PSEM_SUBSYS_LOCK();
        if ((pinfo = pnode->pinfo) == PSEMINFO_NULL) {
                PSEM_SUBSYS_UNLOCK();
@@ -1036,7 +1019,7 @@ out:
 }
 
 static int
-psem_close(struct psemnode *pnode, __unused int flags)
+psem_close(struct psemnode *pnode)
 {
        int error = 0;
        struct pseminfo *pinfo;
@@ -1074,15 +1057,11 @@ psem_close(struct psemnode *pnode, __unused int flags)
 static int
 psem_closefile(struct fileglob *fg, __unused vfs_context_t ctx)
 {
-       int error;
-
        /*
         * Not locked as psem_close is called only from here and is locked
         * properly
         */
-       error =  psem_close(((struct psemnode *)fg->fg_data), fg->fg_flag);
-
-       return error;
+       return psem_close((struct psemnode *)fg->fg_data);
 }
 
 static int
@@ -1149,7 +1128,7 @@ psem_label_associate(struct fileproc *fp, struct vnode *vp, vfs_context_t ctx)
        struct pseminfo *psem;
 
        PSEM_SUBSYS_LOCK();
-       pnode = (struct psemnode *)fp->f_fglob->fg_data;
+       pnode = (struct psemnode *)fp->fp_glob->fg_data;
        if (pnode != NULL) {
                psem = pnode->pinfo;
                if (psem != NULL) {