The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/posix_sem.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8b6808d24c58f28198d326967e8666c1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.