|
|
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.