Deleted Added
full compact
sysv_sem.c (129882) sysv_sem.c (137613)
1/*
2 * Implementation of SVID semaphores
3 *
4 * Author: Daniel Boulet
5 *
6 * This software is provided ``AS IS'' without any warranties of any kind.
7 */
8
9#include <sys/cdefs.h>
1/*
2 * Implementation of SVID semaphores
3 *
4 * Author: Daniel Boulet
5 *
6 * This software is provided ``AS IS'' without any warranties of any kind.
7 */
8
9#include <sys/cdefs.h>
10__FBSDID("$FreeBSD: head/sys/kern/sysv_sem.c 129882 2004-05-30 20:34:58Z phk $");
10__FBSDID("$FreeBSD: head/sys/kern/sysv_sem.c 137613 2004-11-12 13:23:47Z rwatson $");
11
12#include "opt_sysvipc.h"
13
14#include <sys/param.h>
15#include <sys/systm.h>
16#include <sys/sysproto.h>
17#include <sys/eventhandler.h>
18#include <sys/kernel.h>

--- 16 unchanged lines hidden (view full) ---

35#define DPRINTF(a)
36#endif
37
38static void seminit(void);
39static int sysvsem_modload(struct module *, int, void *);
40static int semunload(void);
41static void semexit_myhook(void *arg, struct proc *p);
42static int sysctl_sema(SYSCTL_HANDLER_ARGS);
11
12#include "opt_sysvipc.h"
13
14#include <sys/param.h>
15#include <sys/systm.h>
16#include <sys/sysproto.h>
17#include <sys/eventhandler.h>
18#include <sys/kernel.h>

--- 16 unchanged lines hidden (view full) ---

35#define DPRINTF(a)
36#endif
37
38static void seminit(void);
39static int sysvsem_modload(struct module *, int, void *);
40static int semunload(void);
41static void semexit_myhook(void *arg, struct proc *p);
42static int sysctl_sema(SYSCTL_HANDLER_ARGS);
43static int semvalid(int semid, struct semid_ds *semaptr);
43static int semvalid(int semid, struct semid_kernel *semakptr);
44
45#ifndef _SYS_SYSPROTO_H_
46struct __semctl_args;
47int __semctl(struct thread *td, struct __semctl_args *uap);
48struct semget_args;
49int semget(struct thread *td, struct semget_args *uap);
50struct semop_args;
51int semop(struct thread *td, struct semop_args *uap);

--- 7 unchanged lines hidden (view full) ---

59/* XXX casting to (sy_call_t *) is bogus, as usual. */
60static sy_call_t *semcalls[] = {
61 (sy_call_t *)__semctl, (sy_call_t *)semget,
62 (sy_call_t *)semop
63};
64
65static struct mtx sem_mtx; /* semaphore global lock */
66static int semtot = 0;
44
45#ifndef _SYS_SYSPROTO_H_
46struct __semctl_args;
47int __semctl(struct thread *td, struct __semctl_args *uap);
48struct semget_args;
49int semget(struct thread *td, struct semget_args *uap);
50struct semop_args;
51int semop(struct thread *td, struct semop_args *uap);

--- 7 unchanged lines hidden (view full) ---

59/* XXX casting to (sy_call_t *) is bogus, as usual. */
60static sy_call_t *semcalls[] = {
61 (sy_call_t *)__semctl, (sy_call_t *)semget,
62 (sy_call_t *)semop
63};
64
65static struct mtx sem_mtx; /* semaphore global lock */
66static int semtot = 0;
67static struct semid_ds *sema; /* semaphore id pool */
67static struct semid_kernel *sema; /* semaphore id pool */
68static struct mtx *sema_mtx; /* semaphore id pool mutexes*/
69static struct sem *sem; /* semaphore pool */
70SLIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */
71static int *semu; /* undo structure pool */
72static eventhandler_tag semexit_tag;
73
74#define SEMUNDO_MTX sem_mtx
75#define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX);

--- 109 unchanged lines hidden (view full) ---

185 TUNABLE_INT_FETCH("kern.ipc.semmsl", &seminfo.semmsl);
186 TUNABLE_INT_FETCH("kern.ipc.semopm", &seminfo.semopm);
187 TUNABLE_INT_FETCH("kern.ipc.semume", &seminfo.semume);
188 TUNABLE_INT_FETCH("kern.ipc.semusz", &seminfo.semusz);
189 TUNABLE_INT_FETCH("kern.ipc.semvmx", &seminfo.semvmx);
190 TUNABLE_INT_FETCH("kern.ipc.semaem", &seminfo.semaem);
191
192 sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
68static struct mtx *sema_mtx; /* semaphore id pool mutexes*/
69static struct sem *sem; /* semaphore pool */
70SLIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */
71static int *semu; /* undo structure pool */
72static eventhandler_tag semexit_tag;
73
74#define SEMUNDO_MTX sem_mtx
75#define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX);

--- 109 unchanged lines hidden (view full) ---

185 TUNABLE_INT_FETCH("kern.ipc.semmsl", &seminfo.semmsl);
186 TUNABLE_INT_FETCH("kern.ipc.semopm", &seminfo.semopm);
187 TUNABLE_INT_FETCH("kern.ipc.semume", &seminfo.semume);
188 TUNABLE_INT_FETCH("kern.ipc.semusz", &seminfo.semusz);
189 TUNABLE_INT_FETCH("kern.ipc.semvmx", &seminfo.semvmx);
190 TUNABLE_INT_FETCH("kern.ipc.semaem", &seminfo.semaem);
191
192 sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
193 sema = malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM,
193 sema = malloc(sizeof(struct semid_kernel) * seminfo.semmni, M_SEM,
194 M_WAITOK);
195 sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM,
196 M_WAITOK | M_ZERO);
197 semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
198
199 for (i = 0; i < seminfo.semmni; i++) {
194 M_WAITOK);
195 sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM,
196 M_WAITOK | M_ZERO);
197 semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
198
199 for (i = 0; i < seminfo.semmni; i++) {
200 sema[i].sem_base = 0;
201 sema[i].sem_perm.mode = 0;
202 sema[i].sem_perm.seq = 0;
200 sema[i].u.sem_base = 0;
201 sema[i].u.sem_perm.mode = 0;
202 sema[i].u.sem_perm.seq = 0;
203 }
204 for (i = 0; i < seminfo.semmni; i++)
205 mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF);
206 for (i = 0; i < seminfo.semmnu; i++) {
207 struct sem_undo *suptr = SEMU(i);
208 suptr->un_proc = NULL;
209 }
210 SLIST_INIT(&semu_list);

--- 256 unchanged lines hidden (view full) ---

467 break;
468 }
469 i++, sunptr++;
470 }
471 }
472}
473
474static int
203 }
204 for (i = 0; i < seminfo.semmni; i++)
205 mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF);
206 for (i = 0; i < seminfo.semmnu; i++) {
207 struct sem_undo *suptr = SEMU(i);
208 suptr->un_proc = NULL;
209 }
210 SLIST_INIT(&semu_list);

--- 256 unchanged lines hidden (view full) ---

467 break;
468 }
469 i++, sunptr++;
470 }
471 }
472}
473
474static int
475semvalid(semid, semaptr)
475semvalid(semid, semakptr)
476 int semid;
476 int semid;
477 struct semid_ds *semaptr;
477 struct semid_kernel *semakptr;
478{
479
478{
479
480 return ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
481 semaptr->sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
480 return ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
481 semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
482}
483
484/*
485 * Note that the user-mode half of this passes a union, not a pointer
486 */
487#ifndef _SYS_SYSPROTO_H_
488struct __semctl_args {
489 int semid;

--- 15 unchanged lines hidden (view full) ---

505 int semnum = uap->semnum;
506 int cmd = uap->cmd;
507 u_short *array;
508 union semun *arg = uap->arg;
509 union semun real_arg;
510 struct ucred *cred = td->td_ucred;
511 int i, rval, error;
512 struct semid_ds sbuf;
482}
483
484/*
485 * Note that the user-mode half of this passes a union, not a pointer
486 */
487#ifndef _SYS_SYSPROTO_H_
488struct __semctl_args {
489 int semid;

--- 15 unchanged lines hidden (view full) ---

505 int semnum = uap->semnum;
506 int cmd = uap->cmd;
507 u_short *array;
508 union semun *arg = uap->arg;
509 union semun real_arg;
510 struct ucred *cred = td->td_ucred;
511 int i, rval, error;
512 struct semid_ds sbuf;
513 struct semid_ds *semaptr;
513 struct semid_kernel *semakptr;
514 struct mtx *sema_mtxp;
515 u_short usval, count;
516
517 DPRINTF(("call to semctl(%d, %d, %d, 0x%x)\n",
518 semid, semnum, cmd, arg));
519 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
520 return (ENOSYS);
521
522 array = NULL;
523
524 switch(cmd) {
525 case SEM_STAT:
526 if (semid < 0 || semid >= seminfo.semmni)
527 return (EINVAL);
528 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
529 return (error);
514 struct mtx *sema_mtxp;
515 u_short usval, count;
516
517 DPRINTF(("call to semctl(%d, %d, %d, 0x%x)\n",
518 semid, semnum, cmd, arg));
519 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
520 return (ENOSYS);
521
522 array = NULL;
523
524 switch(cmd) {
525 case SEM_STAT:
526 if (semid < 0 || semid >= seminfo.semmni)
527 return (EINVAL);
528 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
529 return (error);
530 semaptr = &sema[semid];
530 semakptr = &sema[semid];
531 sema_mtxp = &sema_mtx[semid];
532 mtx_lock(sema_mtxp);
531 sema_mtxp = &sema_mtx[semid];
532 mtx_lock(sema_mtxp);
533 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
533 if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) {
534 error = EINVAL;
535 goto done2;
536 }
534 error = EINVAL;
535 goto done2;
536 }
537 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
537 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
538 goto done2;
539 mtx_unlock(sema_mtxp);
538 goto done2;
539 mtx_unlock(sema_mtxp);
540 error = copyout(semaptr, real_arg.buf, sizeof(struct semid_ds));
541 rval = IXSEQ_TO_IPCID(semid,semaptr->sem_perm);
540 error = copyout(&semakptr->u, real_arg.buf,
541 sizeof(struct semid_ds));
542 rval = IXSEQ_TO_IPCID(semid, semakptr->u.sem_perm);
542 if (error == 0)
543 td->td_retval[0] = rval;
544 return (error);
545 }
546
547 semid = IPCID_TO_IX(semid);
548 if (semid < 0 || semid >= seminfo.semmni)
549 return (EINVAL);
550
543 if (error == 0)
544 td->td_retval[0] = rval;
545 return (error);
546 }
547
548 semid = IPCID_TO_IX(semid);
549 if (semid < 0 || semid >= seminfo.semmni)
550 return (EINVAL);
551
551 semaptr = &sema[semid];
552 semakptr = &sema[semid];
552 sema_mtxp = &sema_mtx[semid];
553
554 error = 0;
555 rval = 0;
556
557 switch (cmd) {
558 case IPC_RMID:
559 mtx_lock(sema_mtxp);
553 sema_mtxp = &sema_mtx[semid];
554
555 error = 0;
556 rval = 0;
557
558 switch (cmd) {
559 case IPC_RMID:
560 mtx_lock(sema_mtxp);
560 if ((error = semvalid(uap->semid, semaptr)) != 0)
561 if ((error = semvalid(uap->semid, semakptr)) != 0)
561 goto done2;
562 goto done2;
562 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M)))
563 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
563 goto done2;
564 goto done2;
564 semaptr->sem_perm.cuid = cred->cr_uid;
565 semaptr->sem_perm.uid = cred->cr_uid;
566 semtot -= semaptr->sem_nsems;
567 for (i = semaptr->sem_base - sem; i < semtot; i++)
568 sem[i] = sem[i + semaptr->sem_nsems];
565 semakptr->u.sem_perm.cuid = cred->cr_uid;
566 semakptr->u.sem_perm.uid = cred->cr_uid;
567 semtot -= semakptr->u.sem_nsems;
568 for (i = semakptr->u.sem_base - sem; i < semtot; i++)
569 sem[i] = sem[i + semakptr->u.sem_nsems];
569 for (i = 0; i < seminfo.semmni; i++) {
570 for (i = 0; i < seminfo.semmni; i++) {
570 if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
571 sema[i].sem_base > semaptr->sem_base)
572 sema[i].sem_base -= semaptr->sem_nsems;
571 if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
572 sema[i].u.sem_base > semakptr->u.sem_base)
573 sema[i].u.sem_base -= semakptr->u.sem_nsems;
573 }
574 }
574 semaptr->sem_perm.mode = 0;
575 semakptr->u.sem_perm.mode = 0;
575 SEMUNDO_LOCK();
576 semundo_clear(semid, -1);
577 SEMUNDO_UNLOCK();
576 SEMUNDO_LOCK();
577 semundo_clear(semid, -1);
578 SEMUNDO_UNLOCK();
578 wakeup(semaptr);
579 wakeup(semakptr);
579 break;
580
581 case IPC_SET:
582 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
583 goto done2;
584 if ((error = copyin(real_arg.buf, &sbuf, sizeof(sbuf))) != 0)
585 goto done2;
586 mtx_lock(sema_mtxp);
580 break;
581
582 case IPC_SET:
583 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
584 goto done2;
585 if ((error = copyin(real_arg.buf, &sbuf, sizeof(sbuf))) != 0)
586 goto done2;
587 mtx_lock(sema_mtxp);
587 if ((error = semvalid(uap->semid, semaptr)) != 0)
588 if ((error = semvalid(uap->semid, semakptr)) != 0)
588 goto done2;
589 goto done2;
589 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M)))
590 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
590 goto done2;
591 goto done2;
591 semaptr->sem_perm.uid = sbuf.sem_perm.uid;
592 semaptr->sem_perm.gid = sbuf.sem_perm.gid;
593 semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
594 (sbuf.sem_perm.mode & 0777);
595 semaptr->sem_ctime = time_second;
592 semakptr->u.sem_perm.uid = sbuf.sem_perm.uid;
593 semakptr->u.sem_perm.gid = sbuf.sem_perm.gid;
594 semakptr->u.sem_perm.mode = (semakptr->u.sem_perm.mode &
595 ~0777) | (sbuf.sem_perm.mode & 0777);
596 semakptr->u.sem_ctime = time_second;
596 break;
597
598 case IPC_STAT:
599 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
600 goto done2;
601 mtx_lock(sema_mtxp);
597 break;
598
599 case IPC_STAT:
600 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
601 goto done2;
602 mtx_lock(sema_mtxp);
602 if ((error = semvalid(uap->semid, semaptr)) != 0)
603 if ((error = semvalid(uap->semid, semakptr)) != 0)
603 goto done2;
604 goto done2;
604 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
605 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
605 goto done2;
606 goto done2;
606 sbuf = *semaptr;
607 sbuf = semakptr->u;
607 mtx_unlock(sema_mtxp);
608 mtx_unlock(sema_mtxp);
608 error = copyout(semaptr, real_arg.buf,
609 error = copyout(&semakptr->u, real_arg.buf,
609 sizeof(struct semid_ds));
610 break;
611
612 case GETNCNT:
613 mtx_lock(sema_mtxp);
610 sizeof(struct semid_ds));
611 break;
612
613 case GETNCNT:
614 mtx_lock(sema_mtxp);
614 if ((error = semvalid(uap->semid, semaptr)) != 0)
615 if ((error = semvalid(uap->semid, semakptr)) != 0)
615 goto done2;
616 goto done2;
616 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
617 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
617 goto done2;
618 goto done2;
618 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
619 if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
619 error = EINVAL;
620 goto done2;
621 }
620 error = EINVAL;
621 goto done2;
622 }
622 rval = semaptr->sem_base[semnum].semncnt;
623 rval = semakptr->u.sem_base[semnum].semncnt;
623 break;
624
625 case GETPID:
626 mtx_lock(sema_mtxp);
624 break;
625
626 case GETPID:
627 mtx_lock(sema_mtxp);
627 if ((error = semvalid(uap->semid, semaptr)) != 0)
628 if ((error = semvalid(uap->semid, semakptr)) != 0)
628 goto done2;
629 goto done2;
629 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
630 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
630 goto done2;
631 goto done2;
631 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
632 if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
632 error = EINVAL;
633 goto done2;
634 }
633 error = EINVAL;
634 goto done2;
635 }
635 rval = semaptr->sem_base[semnum].sempid;
636 rval = semakptr->u.sem_base[semnum].sempid;
636 break;
637
638 case GETVAL:
639 mtx_lock(sema_mtxp);
637 break;
638
639 case GETVAL:
640 mtx_lock(sema_mtxp);
640 if ((error = semvalid(uap->semid, semaptr)) != 0)
641 if ((error = semvalid(uap->semid, semakptr)) != 0)
641 goto done2;
642 goto done2;
642 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
643 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
643 goto done2;
644 goto done2;
644 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
645 if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
645 error = EINVAL;
646 goto done2;
647 }
646 error = EINVAL;
647 goto done2;
648 }
648 rval = semaptr->sem_base[semnum].semval;
649 rval = semakptr->u.sem_base[semnum].semval;
649 break;
650
651 case GETALL:
652 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
653 goto done2;
650 break;
651
652 case GETALL:
653 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
654 goto done2;
654 array = malloc(sizeof(*array) * semaptr->sem_nsems, M_TEMP,
655 array = malloc(sizeof(*array) * semakptr->u.sem_nsems, M_TEMP,
655 M_WAITOK);
656 mtx_lock(sema_mtxp);
656 M_WAITOK);
657 mtx_lock(sema_mtxp);
657 if ((error = semvalid(uap->semid, semaptr)) != 0)
658 if ((error = semvalid(uap->semid, semakptr)) != 0)
658 goto done2;
659 goto done2;
659 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
660 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
660 goto done2;
661 goto done2;
661 for (i = 0; i < semaptr->sem_nsems; i++)
662 array[i] = semaptr->sem_base[i].semval;
662 for (i = 0; i < semakptr->u.sem_nsems; i++)
663 array[i] = semakptr->u.sem_base[i].semval;
663 mtx_unlock(sema_mtxp);
664 error = copyout(array, real_arg.array,
665 i * sizeof(real_arg.array[0]));
666 break;
667
668 case GETZCNT:
669 mtx_lock(sema_mtxp);
664 mtx_unlock(sema_mtxp);
665 error = copyout(array, real_arg.array,
666 i * sizeof(real_arg.array[0]));
667 break;
668
669 case GETZCNT:
670 mtx_lock(sema_mtxp);
670 if ((error = semvalid(uap->semid, semaptr)) != 0)
671 if ((error = semvalid(uap->semid, semakptr)) != 0)
671 goto done2;
672 goto done2;
672 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
673 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
673 goto done2;
674 goto done2;
674 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
675 if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
675 error = EINVAL;
676 goto done2;
677 }
676 error = EINVAL;
677 goto done2;
678 }
678 rval = semaptr->sem_base[semnum].semzcnt;
679 rval = semakptr->u.sem_base[semnum].semzcnt;
679 break;
680
681 case SETVAL:
682 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
683 goto done2;
684 mtx_lock(sema_mtxp);
680 break;
681
682 case SETVAL:
683 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
684 goto done2;
685 mtx_lock(sema_mtxp);
685 if ((error = semvalid(uap->semid, semaptr)) != 0)
686 if ((error = semvalid(uap->semid, semakptr)) != 0)
686 goto done2;
687 goto done2;
687 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W)))
688 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
688 goto done2;
689 goto done2;
689 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
690 if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
690 error = EINVAL;
691 goto done2;
692 }
693 if (real_arg.val < 0 || real_arg.val > seminfo.semvmx) {
694 error = ERANGE;
695 goto done2;
696 }
691 error = EINVAL;
692 goto done2;
693 }
694 if (real_arg.val < 0 || real_arg.val > seminfo.semvmx) {
695 error = ERANGE;
696 goto done2;
697 }
697 semaptr->sem_base[semnum].semval = real_arg.val;
698 semakptr->u.sem_base[semnum].semval = real_arg.val;
698 SEMUNDO_LOCK();
699 semundo_clear(semid, semnum);
700 SEMUNDO_UNLOCK();
699 SEMUNDO_LOCK();
700 semundo_clear(semid, semnum);
701 SEMUNDO_UNLOCK();
701 wakeup(semaptr);
702 wakeup(semakptr);
702 break;
703
704 case SETALL:
705 mtx_lock(sema_mtxp);
706raced:
703 break;
704
705 case SETALL:
706 mtx_lock(sema_mtxp);
707raced:
707 if ((error = semvalid(uap->semid, semaptr)) != 0)
708 if ((error = semvalid(uap->semid, semakptr)) != 0)
708 goto done2;
709 goto done2;
709 count = semaptr->sem_nsems;
710 count = semakptr->u.sem_nsems;
710 mtx_unlock(sema_mtxp);
711 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
712 goto done2;
713 array = malloc(sizeof(*array) * count, M_TEMP, M_WAITOK);
714 copyin(real_arg.array, array, count * sizeof(*array));
715 if (error)
716 break;
717 mtx_lock(sema_mtxp);
711 mtx_unlock(sema_mtxp);
712 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
713 goto done2;
714 array = malloc(sizeof(*array) * count, M_TEMP, M_WAITOK);
715 copyin(real_arg.array, array, count * sizeof(*array));
716 if (error)
717 break;
718 mtx_lock(sema_mtxp);
718 if ((error = semvalid(uap->semid, semaptr)) != 0)
719 if ((error = semvalid(uap->semid, semakptr)) != 0)
719 goto done2;
720 /* we could have raced? */
720 goto done2;
721 /* we could have raced? */
721 if (count != semaptr->sem_nsems) {
722 if (count != semakptr->u.sem_nsems) {
722 free(array, M_TEMP);
723 array = NULL;
724 goto raced;
725 }
723 free(array, M_TEMP);
724 array = NULL;
725 goto raced;
726 }
726 if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W)))
727 if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
727 goto done2;
728 goto done2;
728 for (i = 0; i < semaptr->sem_nsems; i++) {
729 for (i = 0; i < semakptr->u.sem_nsems; i++) {
729 usval = array[i];
730 if (usval > seminfo.semvmx) {
731 error = ERANGE;
732 break;
733 }
730 usval = array[i];
731 if (usval > seminfo.semvmx) {
732 error = ERANGE;
733 break;
734 }
734 semaptr->sem_base[i].semval = usval;
735 semakptr->u.sem_base[i].semval = usval;
735 }
736 SEMUNDO_LOCK();
737 semundo_clear(semid, -1);
738 SEMUNDO_UNLOCK();
736 }
737 SEMUNDO_LOCK();
738 semundo_clear(semid, -1);
739 SEMUNDO_UNLOCK();
739 wakeup(semaptr);
740 wakeup(semakptr);
740 break;
741
742 default:
743 error = EINVAL;
744 break;
745 }
746
747 if (error == 0)

--- 30 unchanged lines hidden (view full) ---

778
779 DPRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg));
780 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
781 return (ENOSYS);
782
783 mtx_lock(&Giant);
784 if (key != IPC_PRIVATE) {
785 for (semid = 0; semid < seminfo.semmni; semid++) {
741 break;
742
743 default:
744 error = EINVAL;
745 break;
746 }
747
748 if (error == 0)

--- 30 unchanged lines hidden (view full) ---

779
780 DPRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg));
781 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
782 return (ENOSYS);
783
784 mtx_lock(&Giant);
785 if (key != IPC_PRIVATE) {
786 for (semid = 0; semid < seminfo.semmni; semid++) {
786 if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
787 sema[semid].sem_perm.key == key)
787 if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) &&
788 sema[semid].u.sem_perm.key == key)
788 break;
789 }
790 if (semid < seminfo.semmni) {
791 DPRINTF(("found public key\n"));
789 break;
790 }
791 if (semid < seminfo.semmni) {
792 DPRINTF(("found public key\n"));
792 if ((error = ipcperm(td, &sema[semid].sem_perm,
793 if ((error = ipcperm(td, &sema[semid].u.sem_perm,
793 semflg & 0700))) {
794 goto done2;
795 }
794 semflg & 0700))) {
795 goto done2;
796 }
796 if (nsems > 0 && sema[semid].sem_nsems < nsems) {
797 if (nsems > 0 && sema[semid].u.sem_nsems < nsems) {
797 DPRINTF(("too small\n"));
798 error = EINVAL;
799 goto done2;
800 }
801 if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
802 DPRINTF(("not exclusive\n"));
803 error = EEXIST;
804 goto done2;
805 }
806 goto found;
807 }
808 }
809
798 DPRINTF(("too small\n"));
799 error = EINVAL;
800 goto done2;
801 }
802 if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
803 DPRINTF(("not exclusive\n"));
804 error = EEXIST;
805 goto done2;
806 }
807 goto found;
808 }
809 }
810
810 DPRINTF(("need to allocate the semid_ds\n"));
811 DPRINTF(("need to allocate the semid_kernel\n"));
811 if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
812 if (nsems <= 0 || nsems > seminfo.semmsl) {
813 DPRINTF(("nsems out of range (0<%d<=%d)\n", nsems,
814 seminfo.semmsl));
815 error = EINVAL;
816 goto done2;
817 }
818 if (nsems > seminfo.semmns - semtot) {
819 DPRINTF((
820 "not enough semaphores left (need %d, got %d)\n",
821 nsems, seminfo.semmns - semtot));
822 error = ENOSPC;
823 goto done2;
824 }
825 for (semid = 0; semid < seminfo.semmni; semid++) {
812 if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
813 if (nsems <= 0 || nsems > seminfo.semmsl) {
814 DPRINTF(("nsems out of range (0<%d<=%d)\n", nsems,
815 seminfo.semmsl));
816 error = EINVAL;
817 goto done2;
818 }
819 if (nsems > seminfo.semmns - semtot) {
820 DPRINTF((
821 "not enough semaphores left (need %d, got %d)\n",
822 nsems, seminfo.semmns - semtot));
823 error = ENOSPC;
824 goto done2;
825 }
826 for (semid = 0; semid < seminfo.semmni; semid++) {
826 if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
827 if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0)
827 break;
828 }
829 if (semid == seminfo.semmni) {
828 break;
829 }
830 if (semid == seminfo.semmni) {
830 DPRINTF(("no more semid_ds's available\n"));
831 DPRINTF(("no more semid_kernel's available\n"));
831 error = ENOSPC;
832 goto done2;
833 }
834 DPRINTF(("semid %d is available\n", semid));
832 error = ENOSPC;
833 goto done2;
834 }
835 DPRINTF(("semid %d is available\n", semid));
835 sema[semid].sem_perm.key = key;
836 sema[semid].sem_perm.cuid = cred->cr_uid;
837 sema[semid].sem_perm.uid = cred->cr_uid;
838 sema[semid].sem_perm.cgid = cred->cr_gid;
839 sema[semid].sem_perm.gid = cred->cr_gid;
840 sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
841 sema[semid].sem_perm.seq =
842 (sema[semid].sem_perm.seq + 1) & 0x7fff;
843 sema[semid].sem_nsems = nsems;
844 sema[semid].sem_otime = 0;
845 sema[semid].sem_ctime = time_second;
846 sema[semid].sem_base = &sem[semtot];
836 sema[semid].u.sem_perm.key = key;
837 sema[semid].u.sem_perm.cuid = cred->cr_uid;
838 sema[semid].u.sem_perm.uid = cred->cr_uid;
839 sema[semid].u.sem_perm.cgid = cred->cr_gid;
840 sema[semid].u.sem_perm.gid = cred->cr_gid;
841 sema[semid].u.sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
842 sema[semid].u.sem_perm.seq =
843 (sema[semid].u.sem_perm.seq + 1) & 0x7fff;
844 sema[semid].u.sem_nsems = nsems;
845 sema[semid].u.sem_otime = 0;
846 sema[semid].u.sem_ctime = time_second;
847 sema[semid].u.sem_base = &sem[semtot];
847 semtot += nsems;
848 semtot += nsems;
848 bzero(sema[semid].sem_base,
849 sizeof(sema[semid].sem_base[0])*nsems);
850 DPRINTF(("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base,
851 &sem[semtot]));
849 bzero(sema[semid].u.sem_base,
850 sizeof(sema[semid].u.sem_base[0])*nsems);
851 DPRINTF(("sembase = 0x%x, next = 0x%x\n",
852 sema[semid].u.sem_base, &sem[semtot]));
852 } else {
853 DPRINTF(("didn't find it and wasn't asked to create it\n"));
854 error = ENOENT;
855 goto done2;
856 }
857
858found:
853 } else {
854 DPRINTF(("didn't find it and wasn't asked to create it\n"));
855 error = ENOENT;
856 goto done2;
857 }
858
859found:
859 td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
860 td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].u.sem_perm);
860done2:
861 mtx_unlock(&Giant);
862 return (error);
863}
864
865#ifndef _SYS_SYSPROTO_H_
866struct semop_args {
867 int semid;

--- 10 unchanged lines hidden (view full) ---

878 struct thread *td;
879 struct semop_args *uap;
880{
881#define SMALL_SOPS 8
882 struct sembuf small_sops[SMALL_SOPS];
883 int semid = uap->semid;
884 size_t nsops = uap->nsops;
885 struct sembuf *sops;
861done2:
862 mtx_unlock(&Giant);
863 return (error);
864}
865
866#ifndef _SYS_SYSPROTO_H_
867struct semop_args {
868 int semid;

--- 10 unchanged lines hidden (view full) ---

879 struct thread *td;
880 struct semop_args *uap;
881{
882#define SMALL_SOPS 8
883 struct sembuf small_sops[SMALL_SOPS];
884 int semid = uap->semid;
885 size_t nsops = uap->nsops;
886 struct sembuf *sops;
886 struct semid_ds *semaptr;
887 struct semid_kernel *semakptr;
887 struct sembuf *sopptr = 0;
888 struct sem *semptr = 0;
889 struct sem_undo *suptr;
890 struct mtx *sema_mtxp;
891 size_t i, j, k;
892 int error;
893 int do_wakeup, do_undos;
894
895 DPRINTF(("call to semop(%d, 0x%x, %u)\n", semid, sops, nsops));
896
897 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
898 return (ENOSYS);
899
900 semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
901
902 if (semid < 0 || semid >= seminfo.semmni)
888 struct sembuf *sopptr = 0;
889 struct sem *semptr = 0;
890 struct sem_undo *suptr;
891 struct mtx *sema_mtxp;
892 size_t i, j, k;
893 int error;
894 int do_wakeup, do_undos;
895
896 DPRINTF(("call to semop(%d, 0x%x, %u)\n", semid, sops, nsops));
897
898 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
899 return (ENOSYS);
900
901 semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
902
903 if (semid < 0 || semid >= seminfo.semmni)
903 return (EINVAL);
904 error = EINVAL;
904
905 /* Allocate memory for sem_ops */
906 if (nsops <= SMALL_SOPS)
907 sops = small_sops;
908 else if (nsops <= seminfo.semopm)
909 sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
910 else {
911 DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm,
912 nsops));
913 return (E2BIG);
914 }
915 if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) {
916 DPRINTF(("error = %d from copyin(%08x, %08x, %d)\n", error,
917 uap->sops, sops, nsops * sizeof(sops[0])));
918 if (sops != small_sops)
919 free(sops, M_SEM);
920 return (error);
921 }
922
905
906 /* Allocate memory for sem_ops */
907 if (nsops <= SMALL_SOPS)
908 sops = small_sops;
909 else if (nsops <= seminfo.semopm)
910 sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
911 else {
912 DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm,
913 nsops));
914 return (E2BIG);
915 }
916 if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) {
917 DPRINTF(("error = %d from copyin(%08x, %08x, %d)\n", error,
918 uap->sops, sops, nsops * sizeof(sops[0])));
919 if (sops != small_sops)
920 free(sops, M_SEM);
921 return (error);
922 }
923
923 semaptr = &sema[semid];
924 semakptr = &sema[semid];
924 sema_mtxp = &sema_mtx[semid];
925 mtx_lock(sema_mtxp);
925 sema_mtxp = &sema_mtx[semid];
926 mtx_lock(sema_mtxp);
926 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
927 if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) {
927 error = EINVAL;
928 goto done2;
929 }
928 error = EINVAL;
929 goto done2;
930 }
930 if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
931 if (semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
931 error = EINVAL;
932 goto done2;
933 }
934 /*
935 * Initial pass thru sops to see what permissions are needed.
936 * Also perform any checks that don't need repeating on each
937 * attempt to satisfy the request vector.
938 */
939 j = 0; /* permission needed */
940 do_undos = 0;
941 for (i = 0; i < nsops; i++) {
942 sopptr = &sops[i];
932 error = EINVAL;
933 goto done2;
934 }
935 /*
936 * Initial pass thru sops to see what permissions are needed.
937 * Also perform any checks that don't need repeating on each
938 * attempt to satisfy the request vector.
939 */
940 j = 0; /* permission needed */
941 do_undos = 0;
942 for (i = 0; i < nsops; i++) {
943 sopptr = &sops[i];
943 if (sopptr->sem_num >= semaptr->sem_nsems) {
944 if (sopptr->sem_num >= semakptr->u.sem_nsems) {
944 error = EFBIG;
945 goto done2;
946 }
947 if (sopptr->sem_flg & SEM_UNDO && sopptr->sem_op != 0)
948 do_undos = 1;
949 j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
950 }
951
945 error = EFBIG;
946 goto done2;
947 }
948 if (sopptr->sem_flg & SEM_UNDO && sopptr->sem_op != 0)
949 do_undos = 1;
950 j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
951 }
952
952 if ((error = ipcperm(td, &semaptr->sem_perm, j))) {
953 if ((error = ipcperm(td, &semakptr->u.sem_perm, j))) {
953 DPRINTF(("error = %d from ipaccess\n", error));
954 goto done2;
955 }
956
957 /*
958 * Loop trying to satisfy the vector of requests.
959 * If we reach a point where we must wait, any requests already
960 * performed are rolled back and we go to sleep until some other
961 * process wakes us up. At this point, we start all over again.
962 *
963 * This ensures that from the perspective of other tasks, a set
964 * of requests is atomic (never partially satisfied).
965 */
966 for (;;) {
967 do_wakeup = 0;
968 error = 0; /* error return if necessary */
969
970 for (i = 0; i < nsops; i++) {
971 sopptr = &sops[i];
954 DPRINTF(("error = %d from ipaccess\n", error));
955 goto done2;
956 }
957
958 /*
959 * Loop trying to satisfy the vector of requests.
960 * If we reach a point where we must wait, any requests already
961 * performed are rolled back and we go to sleep until some other
962 * process wakes us up. At this point, we start all over again.
963 *
964 * This ensures that from the perspective of other tasks, a set
965 * of requests is atomic (never partially satisfied).
966 */
967 for (;;) {
968 do_wakeup = 0;
969 error = 0; /* error return if necessary */
970
971 for (i = 0; i < nsops; i++) {
972 sopptr = &sops[i];
972 semptr = &semaptr->sem_base[sopptr->sem_num];
973 semptr = &semakptr->u.sem_base[sopptr->sem_num];
973
974 DPRINTF((
974
975 DPRINTF((
975 "semop: semaptr=%x, sem_base=%x, "
976 "semop: semakptr=%x, sem_base=%x, "
976 "semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
977 "semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
977 semaptr, semaptr->sem_base, semptr,
978 semakptr, semakptr->u.sem_base, semptr,
978 sopptr->sem_num, semptr->semval, sopptr->sem_op,
979 (sopptr->sem_flg & IPC_NOWAIT) ?
980 "nowait" : "wait"));
981
982 if (sopptr->sem_op < 0) {
983 if (semptr->semval + sopptr->sem_op < 0) {
984 DPRINTF(("semop: can't do it now\n"));
985 break;

--- 25 unchanged lines hidden (view full) ---

1011 if (i >= nsops)
1012 goto done;
1013
1014 /*
1015 * No ... rollback anything that we've already done
1016 */
1017 DPRINTF(("semop: rollback 0 through %d\n", i-1));
1018 for (j = 0; j < i; j++)
979 sopptr->sem_num, semptr->semval, sopptr->sem_op,
980 (sopptr->sem_flg & IPC_NOWAIT) ?
981 "nowait" : "wait"));
982
983 if (sopptr->sem_op < 0) {
984 if (semptr->semval + sopptr->sem_op < 0) {
985 DPRINTF(("semop: can't do it now\n"));
986 break;

--- 25 unchanged lines hidden (view full) ---

1012 if (i >= nsops)
1013 goto done;
1014
1015 /*
1016 * No ... rollback anything that we've already done
1017 */
1018 DPRINTF(("semop: rollback 0 through %d\n", i-1));
1019 for (j = 0; j < i; j++)
1019 semaptr->sem_base[sops[j].sem_num].semval -=
1020 semakptr->u.sem_base[sops[j].sem_num].semval -=
1020 sops[j].sem_op;
1021
1022 /* If we detected an error, return it */
1023 if (error != 0)
1024 goto done2;
1025
1026 /*
1027 * If the request that we couldn't satisfy has the

--- 5 unchanged lines hidden (view full) ---

1033 }
1034
1035 if (sopptr->sem_op == 0)
1036 semptr->semzcnt++;
1037 else
1038 semptr->semncnt++;
1039
1040 DPRINTF(("semop: good night!\n"));
1021 sops[j].sem_op;
1022
1023 /* If we detected an error, return it */
1024 if (error != 0)
1025 goto done2;
1026
1027 /*
1028 * If the request that we couldn't satisfy has the

--- 5 unchanged lines hidden (view full) ---

1034 }
1035
1036 if (sopptr->sem_op == 0)
1037 semptr->semzcnt++;
1038 else
1039 semptr->semncnt++;
1040
1041 DPRINTF(("semop: good night!\n"));
1041 error = msleep(semaptr, sema_mtxp, (PZERO - 4) | PCATCH,
1042 error = msleep(semakptr, sema_mtxp, (PZERO - 4) | PCATCH,
1042 "semwait", 0);
1043 DPRINTF(("semop: good morning (error=%d)!\n", error));
1044 /* return code is checked below, after sem[nz]cnt-- */
1045
1046 /*
1047 * Make sure that the semaphore still exists
1048 */
1043 "semwait", 0);
1044 DPRINTF(("semop: good morning (error=%d)!\n", error));
1045 /* return code is checked below, after sem[nz]cnt-- */
1046
1047 /*
1048 * Make sure that the semaphore still exists
1049 */
1049 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
1050 semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
1050 if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
1051 semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
1051 error = EIDRM;
1052 goto done2;
1053 }
1054
1055 /*
1056 * The semaphore is still alive. Readjust the count of
1057 * waiting processes.
1058 */

--- 55 unchanged lines hidden (view full) ---

1114 if (adjval == 0)
1115 continue;
1116 if (semundo_adjust(td, &suptr, semid,
1117 sops[k].sem_num, adjval) != 0)
1118 panic("semop - can't undo undos");
1119 }
1120
1121 for (j = 0; j < nsops; j++)
1052 error = EIDRM;
1053 goto done2;
1054 }
1055
1056 /*
1057 * The semaphore is still alive. Readjust the count of
1058 * waiting processes.
1059 */

--- 55 unchanged lines hidden (view full) ---

1115 if (adjval == 0)
1116 continue;
1117 if (semundo_adjust(td, &suptr, semid,
1118 sops[k].sem_num, adjval) != 0)
1119 panic("semop - can't undo undos");
1120 }
1121
1122 for (j = 0; j < nsops; j++)
1122 semaptr->sem_base[sops[j].sem_num].semval -=
1123 semakptr->u.sem_base[sops[j].sem_num].semval -=
1123 sops[j].sem_op;
1124
1125 DPRINTF(("error = %d from semundo_adjust\n", error));
1126 SEMUNDO_UNLOCK();
1127 goto done2;
1128 } /* loop through the sops */
1129 SEMUNDO_UNLOCK();
1130 } /* if (do_undos) */
1131
1132 /* We're definitely done - set the sempid's and time */
1133 for (i = 0; i < nsops; i++) {
1134 sopptr = &sops[i];
1124 sops[j].sem_op;
1125
1126 DPRINTF(("error = %d from semundo_adjust\n", error));
1127 SEMUNDO_UNLOCK();
1128 goto done2;
1129 } /* loop through the sops */
1130 SEMUNDO_UNLOCK();
1131 } /* if (do_undos) */
1132
1133 /* We're definitely done - set the sempid's and time */
1134 for (i = 0; i < nsops; i++) {
1135 sopptr = &sops[i];
1135 semptr = &semaptr->sem_base[sopptr->sem_num];
1136 semptr = &semakptr->u.sem_base[sopptr->sem_num];
1136 semptr->sempid = td->td_proc->p_pid;
1137 }
1137 semptr->sempid = td->td_proc->p_pid;
1138 }
1138 semaptr->sem_otime = time_second;
1139 semakptr->u.sem_otime = time_second;
1139
1140 /*
1141 * Do a wakeup if any semaphore was up'd whilst something was
1142 * sleeping on it.
1143 */
1144 if (do_wakeup) {
1145 DPRINTF(("semop: doing wakeup\n"));
1140
1141 /*
1142 * Do a wakeup if any semaphore was up'd whilst something was
1143 * sleeping on it.
1144 */
1145 if (do_wakeup) {
1146 DPRINTF(("semop: doing wakeup\n"));
1146 wakeup(semaptr);
1147 wakeup(semakptr);
1147 DPRINTF(("semop: back from wakeup\n"));
1148 }
1149 DPRINTF(("semop: done\n"));
1150 td->td_retval[0] = 0;
1151done2:
1152 mtx_unlock(sema_mtxp);
1153 if (sops != small_sops)
1154 free(sops, M_SEM);
1148 DPRINTF(("semop: back from wakeup\n"));
1149 }
1150 DPRINTF(("semop: done\n"));
1151 td->td_retval[0] = 0;
1152done2:
1153 mtx_unlock(sema_mtxp);
1154 if (sops != small_sops)
1155 free(sops, M_SEM);
1156 free(sops, M_SEM);
1155 return (error);
1156}
1157
1158/*
1159 * Go through the undo structures for this process and apply the adjustments to
1160 * semaphores.
1161 */
1162static void

--- 26 unchanged lines hidden (view full) ---

1189 */
1190 if (suptr->un_cnt > 0) {
1191 int ix;
1192
1193 for (ix = 0; ix < suptr->un_cnt; ix++) {
1194 int semid = suptr->un_ent[ix].un_id;
1195 int semnum = suptr->un_ent[ix].un_num;
1196 int adjval = suptr->un_ent[ix].un_adjval;
1157 return (error);
1158}
1159
1160/*
1161 * Go through the undo structures for this process and apply the adjustments to
1162 * semaphores.
1163 */
1164static void

--- 26 unchanged lines hidden (view full) ---

1191 */
1192 if (suptr->un_cnt > 0) {
1193 int ix;
1194
1195 for (ix = 0; ix < suptr->un_cnt; ix++) {
1196 int semid = suptr->un_ent[ix].un_id;
1197 int semnum = suptr->un_ent[ix].un_num;
1198 int adjval = suptr->un_ent[ix].un_adjval;
1197 struct semid_ds *semaptr;
1199 struct semid_kernel *semakptr;
1198 struct mtx *sema_mtxp;
1199
1200 struct mtx *sema_mtxp;
1201
1200 semaptr = &sema[semid];
1202 semakptr = &sema[semid];
1201 sema_mtxp = &sema_mtx[semid];
1202 mtx_lock(sema_mtxp);
1203 SEMUNDO_LOCK();
1203 sema_mtxp = &sema_mtx[semid];
1204 mtx_lock(sema_mtxp);
1205 SEMUNDO_LOCK();
1204 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
1206 if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0)
1205 panic("semexit - semid not allocated");
1207 panic("semexit - semid not allocated");
1206 if (semnum >= semaptr->sem_nsems)
1208 if (semnum >= semakptr->u.sem_nsems)
1207 panic("semexit - semnum out of range");
1208
1209 DPRINTF((
1210 "semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
1211 suptr->un_proc, suptr->un_ent[ix].un_id,
1212 suptr->un_ent[ix].un_num,
1213 suptr->un_ent[ix].un_adjval,
1209 panic("semexit - semnum out of range");
1210
1211 DPRINTF((
1212 "semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
1213 suptr->un_proc, suptr->un_ent[ix].un_id,
1214 suptr->un_ent[ix].un_num,
1215 suptr->un_ent[ix].un_adjval,
1214 semaptr->sem_base[semnum].semval));
1216 semakptr->u.sem_base[semnum].semval));
1215
1216 if (adjval < 0) {
1217
1218 if (adjval < 0) {
1217 if (semaptr->sem_base[semnum].semval < -adjval)
1218 semaptr->sem_base[semnum].semval = 0;
1219 if (semakptr->u.sem_base[semnum].semval <
1220 -adjval)
1221 semakptr->u.sem_base[semnum].semval = 0;
1219 else
1222 else
1220 semaptr->sem_base[semnum].semval +=
1223 semakptr->u.sem_base[semnum].semval +=
1221 adjval;
1222 } else
1224 adjval;
1225 } else
1223 semaptr->sem_base[semnum].semval += adjval;
1226 semakptr->u.sem_base[semnum].semval += adjval;
1224
1227
1225 wakeup(semaptr);
1228 wakeup(semakptr);
1226 DPRINTF(("semexit: back from wakeup\n"));
1227 mtx_unlock(sema_mtxp);
1228 SEMUNDO_UNLOCK();
1229 }
1230 }
1231
1232 /*
1233 * Deallocate the undo vector.
1234 */
1235 DPRINTF(("removing vector\n"));
1236 suptr->un_proc = NULL;
1237 *supptr = SLIST_NEXT(suptr, un_next);
1238}
1239
1240static int
1241sysctl_sema(SYSCTL_HANDLER_ARGS)
1242{
1243
1244 return (SYSCTL_OUT(req, sema,
1229 DPRINTF(("semexit: back from wakeup\n"));
1230 mtx_unlock(sema_mtxp);
1231 SEMUNDO_UNLOCK();
1232 }
1233 }
1234
1235 /*
1236 * Deallocate the undo vector.
1237 */
1238 DPRINTF(("removing vector\n"));
1239 suptr->un_proc = NULL;
1240 *supptr = SLIST_NEXT(suptr, un_next);
1241}
1242
1243static int
1244sysctl_sema(SYSCTL_HANDLER_ARGS)
1245{
1246
1247 return (SYSCTL_OUT(req, sema,
1245 sizeof(struct semid_ds) * seminfo.semmni));
1248 sizeof(struct semid_kernel) * seminfo.semmni));
1246}
1249}