|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.