]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/sysv_sem.c
b499764876b02e230ba9e0addbc9e11cf591bce7
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Implementation of SVID semaphores
25 * Author: Daniel Boulet
27 * This software is provided ``AS IS'' without any warranties of any kind.
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/sysproto.h>
33 #include <sys/kernel.h>
36 #include <sys/sysent.h>
38 static void seminit
__P((void *));
39 SYSINIT(sysv_sem
, SI_SUB_SYSV_SEM
, SI_ORDER_FIRST
, seminit
, NULL
)
41 #ifndef _SYS_SYSPROTO_H_
43 int __semctl
__P((struct proc
*p
, struct __semctl_args
*uap
));
45 int semget
__P((struct proc
*p
, struct semget_args
*uap
));
47 int semop
__P((struct proc
*p
, struct semop_args
*uap
));
48 struct semconfig_args
;
49 int semconfig
__P((struct proc
*p
, struct semconfig_args
*uap
));
52 static struct sem_undo
*semu_alloc
__P((struct proc
*p
));
53 static int semundo_adjust
__P((struct proc
*p
, struct sem_undo
**supptr
,
54 int semid
, int semnum
, int adjval
));
55 static void semundo_clear
__P((int semid
, int semnum
));
57 /* XXX casting to (sy_call_t *) is bogus, as usual. */
58 static sy_call_t
*semcalls
[] = {
59 (sy_call_t
*)__semctl
, (sy_call_t
*)semget
,
60 (sy_call_t
*)semop
, (sy_call_t
*)semconfig
63 static int semtot
= 0;
64 struct semid_ds
*sema
; /* semaphore id pool */
65 struct sem
*sem
; /* semaphore pool */
66 static struct sem_undo
*semu_list
; /* list of active undo structures */
67 int *semu
; /* undo structure pool */
69 static struct proc
*semlock_holder
= NULL
;
78 panic("sema is NULL");
80 panic("semu is NULL");
82 for (i
= 0; i
< seminfo
.semmni
; i
++) {
84 sema
[i
].sem_perm
.mode
= 0;
86 for (i
= 0; i
< seminfo
.semmnu
; i
++) {
87 register struct sem_undo
*suptr
= SEMU(i
);
88 suptr
->un_proc
= NULL
;
94 * Entry point for all SEM calls
99 /* XXX actually varargs. */
100 struct semsys_args
/* {
109 while (semlock_holder
!= NULL
&& semlock_holder
!= p
)
110 (void) tsleep((caddr_t
)&semlock_holder
, (PZERO
- 4), "semsys", 0);
112 if (uap
->which
>= sizeof(semcalls
)/sizeof(semcalls
[0]))
114 return ((*semcalls
[uap
->which
])(p
, &uap
->a2
));
118 * Lock or unlock the entire semaphore facility.
120 * This will probably eventually evolve into a general purpose semaphore
121 * facility status enquiry mechanism (I don't like the "read /dev/kmem"
122 * approach currently taken by ipcs and the amount of info that we want
123 * to be able to extract for ipcs is probably beyond what the capability
124 * of the getkerninfo facility.
126 * At the time that the current version of semconfig was written, ipcs is
127 * the only user of the semconfig facility. It uses it to ensure that the
128 * semaphore facility data structures remain static while it fishes around
132 #ifndef _SYS_SYSPROTO_H_
133 struct semconfig_args
{
134 semconfig_ctl_t flag
;
141 struct semconfig_args
*uap
;
146 case SEM_CONFIG_FREEZE
:
150 case SEM_CONFIG_THAW
:
151 semlock_holder
= NULL
;
152 wakeup((caddr_t
)&semlock_holder
);
156 printf("semconfig: unknown flag parameter value (%d) - ignored\n",
167 * Allocate a new sem_undo structure for a process
168 * (returns ptr to structure or NULL if no more room)
171 static struct sem_undo
*
176 register struct sem_undo
*suptr
;
177 register struct sem_undo
**supptr
;
181 * Try twice to allocate something.
182 * (we'll purge any empty structures after the first pass so
183 * two passes are always enough)
186 for (attempt
= 0; attempt
< 2; attempt
++) {
188 * Look for a free structure.
189 * Fill it in and return it if we find one.
192 for (i
= 0; i
< seminfo
.semmnu
; i
++) {
194 if (suptr
->un_proc
== NULL
) {
195 suptr
->un_next
= semu_list
;
204 * We didn't find a free one, if this is the first attempt
205 * then try to free some structures.
209 /* All the structures are in use - try to free some */
210 int did_something
= 0;
213 while ((suptr
= *supptr
) != NULL
) {
214 if (suptr
->un_cnt
== 0) {
215 suptr
->un_proc
= NULL
;
216 *supptr
= suptr
->un_next
;
219 supptr
= &(suptr
->un_next
);
222 /* If we didn't free anything then just give-up */
227 * The second pass failed even though we freed
228 * something after the first pass!
229 * This is IMPOSSIBLE!
231 panic("semu_alloc - second attempt failed");
238 * Adjust a particular entry for a particular proc
242 semundo_adjust(p
, supptr
, semid
, semnum
, adjval
)
243 register struct proc
*p
;
244 struct sem_undo
**supptr
;
248 register struct sem_undo
*suptr
;
249 register struct undo
*sunptr
;
252 /* Look for and remember the sem_undo if the caller doesn't provide
257 for (suptr
= semu_list
; suptr
!= NULL
;
258 suptr
= suptr
->un_next
) {
259 if (suptr
->un_proc
== p
) {
267 suptr
= semu_alloc(p
);
275 * Look for the requested entry and adjust it (delete if adjval becomes
278 sunptr
= &suptr
->un_ent
[0];
279 for (i
= 0; i
< suptr
->un_cnt
; i
++, sunptr
++) {
280 if (sunptr
->un_id
!= semid
|| sunptr
->un_num
!= semnum
)
283 sunptr
->un_adjval
= 0;
285 sunptr
->un_adjval
+= adjval
;
286 if (sunptr
->un_adjval
== 0) {
288 if (i
< suptr
->un_cnt
)
290 suptr
->un_ent
[suptr
->un_cnt
];
295 /* Didn't find the right entry - create it */
298 if (suptr
->un_cnt
!= seminfo
.semume
) {
299 sunptr
= &suptr
->un_ent
[suptr
->un_cnt
];
301 sunptr
->un_adjval
= adjval
;
302 sunptr
->un_id
= semid
; sunptr
->un_num
= semnum
;
309 semundo_clear(semid
, semnum
)
312 register struct sem_undo
*suptr
;
314 for (suptr
= semu_list
; suptr
!= NULL
; suptr
= suptr
->un_next
) {
315 register struct undo
*sunptr
= &suptr
->un_ent
[0];
318 while (i
< suptr
->un_cnt
) {
319 if (sunptr
->un_id
== semid
) {
320 if (semnum
== -1 || sunptr
->un_num
== semnum
) {
322 if (i
< suptr
->un_cnt
) {
324 suptr
->un_ent
[suptr
->un_cnt
];
337 * Note that the user-mode half of this passes a union, not a pointer
339 #ifndef _SYS_SYSPROTO_H_
340 struct __semctl_args
{
351 register struct __semctl_args
*uap
;
353 int semid
= uap
->semid
;
354 int semnum
= uap
->semnum
;
356 union semun
*arg
= uap
->arg
;
357 union semun real_arg
;
358 struct ucred
*cred
= p
->p_ucred
;
360 struct semid_ds sbuf
;
361 register struct semid_ds
*semaptr
;
364 printf("call to semctl(%d, %d, %d, 0x%x)\n", semid
, semnum
, cmd
, arg
);
367 semid
= IPCID_TO_IX(semid
);
368 if (semid
< 0 || semid
>= seminfo
.semmsl
)
371 semaptr
= &sema
[semid
];
372 if ((semaptr
->sem_perm
.mode
& SEM_ALLOC
) == 0 ||
373 semaptr
->sem_perm
.seq
!= IPCID_TO_SEQ(uap
->semid
))
381 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_M
)))
383 semaptr
->sem_perm
.cuid
= cred
->cr_uid
;
384 semaptr
->sem_perm
.uid
= cred
->cr_uid
;
385 semtot
-= semaptr
->sem_nsems
;
386 for (i
= semaptr
->sem_base
- sem
; i
< semtot
; i
++)
387 sem
[i
] = sem
[i
+ semaptr
->sem_nsems
];
388 for (i
= 0; i
< seminfo
.semmni
; i
++) {
389 if ((sema
[i
].sem_perm
.mode
& SEM_ALLOC
) &&
390 sema
[i
].sem_base
> semaptr
->sem_base
)
391 sema
[i
].sem_base
-= semaptr
->sem_nsems
;
393 semaptr
->sem_perm
.mode
= 0;
394 semundo_clear(semid
, -1);
395 wakeup((caddr_t
)semaptr
);
399 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_M
)))
401 if ((eval
= copyin(arg
, &real_arg
, sizeof(real_arg
))) != 0)
403 if ((eval
= copyin(real_arg
.buf
, (caddr_t
)&sbuf
,
406 semaptr
->sem_perm
.uid
= sbuf
.sem_perm
.uid
;
407 semaptr
->sem_perm
.gid
= sbuf
.sem_perm
.gid
;
408 semaptr
->sem_perm
.mode
= (semaptr
->sem_perm
.mode
& ~0777) |
409 (sbuf
.sem_perm
.mode
& 0777);
410 semaptr
->sem_ctime
= time_second
;
414 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
416 if ((eval
= copyin(arg
, &real_arg
, sizeof(real_arg
))) != 0)
418 eval
= copyout((caddr_t
)semaptr
, real_arg
.buf
,
419 sizeof(struct semid_ds
));
423 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
425 if (semnum
< 0 || semnum
>= semaptr
->sem_nsems
)
427 rval
= semaptr
->sem_base
[semnum
].semncnt
;
431 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
433 if (semnum
< 0 || semnum
>= semaptr
->sem_nsems
)
435 rval
= semaptr
->sem_base
[semnum
].sempid
;
439 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
441 if (semnum
< 0 || semnum
>= semaptr
->sem_nsems
)
443 rval
= semaptr
->sem_base
[semnum
].semval
;
447 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
449 if ((eval
= copyin(arg
, &real_arg
, sizeof(real_arg
))) != 0)
451 for (i
= 0; i
< semaptr
->sem_nsems
; i
++) {
452 eval
= copyout((caddr_t
)&semaptr
->sem_base
[i
].semval
,
453 &real_arg
.array
[i
], sizeof(real_arg
.array
[0]));
460 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_R
)))
462 if (semnum
< 0 || semnum
>= semaptr
->sem_nsems
)
464 rval
= semaptr
->sem_base
[semnum
].semzcnt
;
468 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_W
)))
470 if (semnum
< 0 || semnum
>= semaptr
->sem_nsems
)
472 if ((eval
= copyin(arg
, &real_arg
, sizeof(real_arg
))) != 0)
474 semaptr
->sem_base
[semnum
].semval
= real_arg
.val
;
475 semundo_clear(semid
, semnum
);
476 wakeup((caddr_t
)semaptr
);
480 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_W
)))
482 if ((eval
= copyin(arg
, &real_arg
, sizeof(real_arg
))) != 0)
484 for (i
= 0; i
< semaptr
->sem_nsems
; i
++) {
485 eval
= copyin(&real_arg
.array
[i
],
486 (caddr_t
)&semaptr
->sem_base
[i
].semval
,
487 sizeof(real_arg
.array
[0]));
491 semundo_clear(semid
, -1);
492 wakeup((caddr_t
)semaptr
);
500 p
->p_retval
[0] = rval
;
504 #ifndef _SYS_SYSPROTO_H_
515 register struct semget_args
*uap
;
519 int nsems
= uap
->nsems
;
520 int semflg
= uap
->semflg
;
521 struct ucred
*cred
= p
->p_ucred
;
524 printf("semget(0x%x, %d, 0%o)\n", key
, nsems
, semflg
);
527 if (key
!= IPC_PRIVATE
) {
528 for (semid
= 0; semid
< seminfo
.semmni
; semid
++) {
529 if ((sema
[semid
].sem_perm
.mode
& SEM_ALLOC
) &&
530 sema
[semid
].sem_perm
.key
== key
)
533 if (semid
< seminfo
.semmni
) {
535 printf("found public key\n");
537 if ((eval
= ipcperm(cred
, &sema
[semid
].sem_perm
,
540 if (nsems
> 0 && sema
[semid
].sem_nsems
< nsems
) {
542 printf("too small\n");
546 if ((semflg
& IPC_CREAT
) && (semflg
& IPC_EXCL
)) {
548 printf("not exclusive\n");
557 printf("need to allocate the semid_ds\n");
559 if (key
== IPC_PRIVATE
|| (semflg
& IPC_CREAT
)) {
560 if (nsems
<= 0 || nsems
> seminfo
.semmsl
) {
562 printf("nsems out of range (0<%d<=%d)\n", nsems
,
567 if (nsems
> seminfo
.semmns
- semtot
) {
569 printf("not enough semaphores left (need %d, got %d)\n",
570 nsems
, seminfo
.semmns
- semtot
);
574 for (semid
= 0; semid
< seminfo
.semmni
; semid
++) {
575 if ((sema
[semid
].sem_perm
.mode
& SEM_ALLOC
) == 0)
578 if (semid
== seminfo
.semmni
) {
580 printf("no more semid_ds's available\n");
585 printf("semid %d is available\n", semid
);
587 sema
[semid
].sem_perm
.key
= key
;
588 sema
[semid
].sem_perm
.cuid
= cred
->cr_uid
;
589 sema
[semid
].sem_perm
.uid
= cred
->cr_uid
;
590 sema
[semid
].sem_perm
.cgid
= cred
->cr_gid
;
591 sema
[semid
].sem_perm
.gid
= cred
->cr_gid
;
592 sema
[semid
].sem_perm
.mode
= (semflg
& 0777) | SEM_ALLOC
;
593 sema
[semid
].sem_perm
.seq
=
594 (sema
[semid
].sem_perm
.seq
+ 1) & 0x7fff;
595 sema
[semid
].sem_nsems
= nsems
;
596 sema
[semid
].sem_otime
= 0;
597 sema
[semid
].sem_ctime
= time_second
;
598 sema
[semid
].sem_base
= &sem
[semtot
];
600 bzero(sema
[semid
].sem_base
,
601 sizeof(sema
[semid
].sem_base
[0])*nsems
);
603 printf("sembase = 0x%x, next = 0x%x\n", sema
[semid
].sem_base
,
608 printf("didn't find it and wasn't asked to create it\n");
614 p
->p_retval
[0] = IXSEQ_TO_IPCID(semid
, sema
[semid
].sem_perm
);
618 #ifndef _SYS_SYSPROTO_H_
629 register struct semop_args
*uap
;
631 int semid
= uap
->semid
;
632 int nsops
= uap
->nsops
;
633 struct sembuf sops
[MAX_SOPS
];
634 register struct semid_ds
*semaptr
;
635 register struct sembuf
*sopptr
;
636 register struct sem
*semptr
;
637 struct sem_undo
*suptr
= NULL
;
638 struct ucred
*cred
= p
->p_ucred
;
640 int do_wakeup
, do_undos
;
643 printf("call to semop(%d, 0x%x, %d)\n", semid
, sops
, nsops
);
646 semid
= IPCID_TO_IX(semid
); /* Convert back to zero origin */
648 if (semid
< 0 || semid
>= seminfo
.semmsl
)
651 semaptr
= &sema
[semid
];
652 if ((semaptr
->sem_perm
.mode
& SEM_ALLOC
) == 0)
654 if (semaptr
->sem_perm
.seq
!= IPCID_TO_SEQ(uap
->semid
))
657 if ((eval
= ipcperm(cred
, &semaptr
->sem_perm
, IPC_W
))) {
659 printf("eval = %d from ipaccess\n", eval
);
664 if (nsops
> MAX_SOPS
) {
666 printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS
, nsops
);
671 if ((eval
= copyin(uap
->sops
, &sops
, nsops
* sizeof(sops
[0]))) != 0) {
673 printf("eval = %d from copyin(%08x, %08x, %d)\n", eval
,
674 uap
->sops
, &sops
, nsops
* sizeof(sops
[0]));
680 * Loop trying to satisfy the vector of requests.
681 * If we reach a point where we must wait, any requests already
682 * performed are rolled back and we go to sleep until some other
683 * process wakes us up. At this point, we start all over again.
685 * This ensures that from the perspective of other tasks, a set
686 * of requests is atomic (never partially satisfied).
693 for (i
= 0; i
< nsops
; i
++) {
696 if (sopptr
->sem_num
>= semaptr
->sem_nsems
)
699 semptr
= &semaptr
->sem_base
[sopptr
->sem_num
];
702 printf("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
703 semaptr
, semaptr
->sem_base
, semptr
,
704 sopptr
->sem_num
, semptr
->semval
, sopptr
->sem_op
,
705 (sopptr
->sem_flg
& IPC_NOWAIT
) ? "nowait" : "wait");
708 if (sopptr
->sem_op
< 0) {
709 if (semptr
->semval
+ sopptr
->sem_op
< 0) {
711 printf("semop: can't do it now\n");
715 semptr
->semval
+= sopptr
->sem_op
;
716 if (semptr
->semval
== 0 &&
720 if (sopptr
->sem_flg
& SEM_UNDO
)
722 } else if (sopptr
->sem_op
== 0) {
723 if (semptr
->semval
> 0) {
725 printf("semop: not zero now\n");
730 if (semptr
->semncnt
> 0)
732 semptr
->semval
+= sopptr
->sem_op
;
733 if (sopptr
->sem_flg
& SEM_UNDO
)
739 * Did we get through the entire vector?
745 * No ... rollback anything that we've already done
748 printf("semop: rollback 0 through %d\n", i
-1);
750 for (j
= 0; j
< i
; j
++)
751 semaptr
->sem_base
[sops
[j
].sem_num
].semval
-=
755 * If the request that we couldn't satisfy has the
756 * NOWAIT flag set then return with EAGAIN.
758 if (sopptr
->sem_flg
& IPC_NOWAIT
)
761 if (sopptr
->sem_op
== 0)
767 printf("semop: good night!\n");
769 eval
= tsleep((caddr_t
)semaptr
, (PZERO
- 4) | PCATCH
,
772 printf("semop: good morning (eval=%d)!\n", eval
);
775 suptr
= NULL
; /* sem_undo may have been reallocated */
780 printf("semop: good morning!\n");
784 * Make sure that the semaphore still exists
786 if ((semaptr
->sem_perm
.mode
& SEM_ALLOC
) == 0 ||
787 semaptr
->sem_perm
.seq
!= IPCID_TO_SEQ(uap
->semid
)) {
788 /* The man page says to return EIDRM. */
789 /* Unfortunately, BSD doesn't define that code! */
798 * The semaphore is still alive. Readjust the count of
801 if (sopptr
->sem_op
== 0)
809 * Process any SEM_UNDO requests.
812 for (i
= 0; i
< nsops
; i
++) {
814 * We only need to deal with SEM_UNDO's for non-zero
819 if ((sops
[i
].sem_flg
& SEM_UNDO
) == 0)
821 adjval
= sops
[i
].sem_op
;
824 eval
= semundo_adjust(p
, &suptr
, semid
,
825 sops
[i
].sem_num
, -adjval
);
830 * Oh-Oh! We ran out of either sem_undo's or undo's.
831 * Rollback the adjustments to this point and then
832 * rollback the semaphore ups and down so we can return
833 * with an error with all structures restored. We
834 * rollback the undo's in the exact reverse order that
835 * we applied them. This guarantees that we won't run
836 * out of space as we roll things back out.
838 for (j
= i
- 1; j
>= 0; j
--) {
839 if ((sops
[j
].sem_flg
& SEM_UNDO
) == 0)
841 adjval
= sops
[j
].sem_op
;
844 if (semundo_adjust(p
, &suptr
, semid
,
845 sops
[j
].sem_num
, adjval
) != 0)
846 panic("semop - can't undo undos");
849 for (j
= 0; j
< nsops
; j
++)
850 semaptr
->sem_base
[sops
[j
].sem_num
].semval
-=
854 printf("eval = %d from semundo_adjust\n", eval
);
857 } /* loop through the sops */
858 } /* if (do_undos) */
860 /* We're definitely done - set the sempid's */
861 for (i
= 0; i
< nsops
; i
++) {
863 semptr
= &semaptr
->sem_base
[sopptr
->sem_num
];
864 semptr
->sempid
= p
->p_pid
;
867 /* Do a wakeup if any semaphore was up'd. */
870 printf("semop: doing wakeup\n");
872 sem_wakeup((caddr_t
)semaptr
);
874 wakeup((caddr_t
)semaptr
);
876 printf("semop: back from wakeup\n");
878 wakeup((caddr_t
)semaptr
);
882 printf("semop: done\n");
889 * Go through the undo structures for this process and apply the adjustments to
896 register struct sem_undo
*suptr
;
897 register struct sem_undo
**supptr
;
901 * If somebody else is holding the global semaphore facility lock
902 * then sleep until it is released.
904 while (semlock_holder
!= NULL
&& semlock_holder
!= p
) {
906 printf("semaphore facility locked - sleeping ...\n");
908 (void) tsleep((caddr_t
)&semlock_holder
, (PZERO
- 4), "semext", 0);
914 * Go through the chain of undo vectors looking for one
915 * associated with this process.
918 for (supptr
= &semu_list
; (suptr
= *supptr
) != NULL
;
919 supptr
= &suptr
->un_next
) {
920 if (suptr
->un_proc
== p
)
928 printf("proc @%08x has undo structure with %d entries\n", p
,
933 * If there are any active undo elements then process them.
935 if (suptr
->un_cnt
> 0) {
938 for (ix
= 0; ix
< suptr
->un_cnt
; ix
++) {
939 int semid
= suptr
->un_ent
[ix
].un_id
;
940 int semnum
= suptr
->un_ent
[ix
].un_num
;
941 int adjval
= suptr
->un_ent
[ix
].un_adjval
;
942 struct semid_ds
*semaptr
;
944 semaptr
= &sema
[semid
];
945 if ((semaptr
->sem_perm
.mode
& SEM_ALLOC
) == 0)
946 panic("semexit - semid not allocated");
947 if (semnum
>= semaptr
->sem_nsems
)
948 panic("semexit - semnum out of range");
951 printf("semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
952 suptr
->un_proc
, suptr
->un_ent
[ix
].un_id
,
953 suptr
->un_ent
[ix
].un_num
,
954 suptr
->un_ent
[ix
].un_adjval
,
955 semaptr
->sem_base
[semnum
].semval
);
959 if (semaptr
->sem_base
[semnum
].semval
< -adjval
)
960 semaptr
->sem_base
[semnum
].semval
= 0;
962 semaptr
->sem_base
[semnum
].semval
+=
965 semaptr
->sem_base
[semnum
].semval
+= adjval
;
968 sem_wakeup((caddr_t
)semaptr
);
970 wakeup((caddr_t
)semaptr
);
973 printf("semexit: back from wakeup\n");
979 * Deallocate the undo vector.
982 printf("removing vector\n");
984 suptr
->un_proc
= NULL
;
985 *supptr
= suptr
->un_next
;
989 * If the exiting process is holding the global semaphore facility
990 * lock then release it.
992 if (semlock_holder
== p
) {
993 semlock_holder
= NULL
;
994 wakeup((caddr_t
)&semlock_holder
);