Deleted Added
full compact
sysv_sem.c (77461) sysv_sem.c (82607)
1/* $FreeBSD: head/sys/kern/sysv_sem.c 77461 2001-05-30 03:28:59Z dd $ */
1/* $FreeBSD: head/sys/kern/sysv_sem.c 82607 2001-08-31 00:02:18Z dillon $ */
2
3/*
4 * Implementation of SVID semaphores
5 *
6 * Author: Daniel Boulet
7 *
8 * This software is provided ``AS IS'' without any warranties of any kind.
9 */
10
11#include "opt_sysvipc.h"
12
13#include <sys/param.h>
14#include <sys/systm.h>
15#include <sys/sysproto.h>
16#include <sys/kernel.h>
17#include <sys/proc.h>
2
3/*
4 * Implementation of SVID semaphores
5 *
6 * Author: Daniel Boulet
7 *
8 * This software is provided ``AS IS'' without any warranties of any kind.
9 */
10
11#include "opt_sysvipc.h"
12
13#include <sys/param.h>
14#include <sys/systm.h>
15#include <sys/sysproto.h>
16#include <sys/kernel.h>
17#include <sys/proc.h>
18#include <sys/lock.h>
19#include <sys/mutex.h>
18#include <sys/sem.h>
19#include <sys/syscall.h>
20#include <sys/sysent.h>
21#include <sys/sysctl.h>
22#include <sys/malloc.h>
23#include <sys/jail.h>
24
25static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores");

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

239SYSCALL_MODULE_HELPER(semop, 3);
240
241DECLARE_MODULE(sysvsem, sysvsem_mod,
242 SI_SUB_SYSV_SEM, SI_ORDER_FIRST);
243MODULE_VERSION(sysvsem, 1);
244
245/*
246 * Entry point for all SEM calls
20#include <sys/sem.h>
21#include <sys/syscall.h>
22#include <sys/sysent.h>
23#include <sys/sysctl.h>
24#include <sys/malloc.h>
25#include <sys/jail.h>
26
27static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores");

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

241SYSCALL_MODULE_HELPER(semop, 3);
242
243DECLARE_MODULE(sysvsem, sysvsem_mod,
244 SI_SUB_SYSV_SEM, SI_ORDER_FIRST);
245MODULE_VERSION(sysvsem, 1);
246
247/*
248 * Entry point for all SEM calls
249 *
250 * MPSAFE
247 */
248int
249semsys(p, uap)
250 struct proc *p;
251 /* XXX actually varargs. */
252 struct semsys_args /* {
253 u_int which;
254 int a2;
255 int a3;
256 int a4;
257 int a5;
258 } */ *uap;
259{
251 */
252int
253semsys(p, uap)
254 struct proc *p;
255 /* XXX actually varargs. */
256 struct semsys_args /* {
257 u_int which;
258 int a2;
259 int a3;
260 int a4;
261 int a5;
262 } */ *uap;
263{
264 int error;
260
265
261 if (!jail_sysvipc_allowed && jailed(p->p_ucred))
262 return (ENOSYS);
266 mtx_lock(&Giant);
263
267
264 if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
265 return (EINVAL);
266 return ((*semcalls[uap->which])(p, &uap->a2));
268 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
269 error = ENOSYS;
270 goto done2;
271 }
272
273 if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) {
274 error = EINVAL;
275 goto done2;
276 }
277 error = (*semcalls[uap->which])(p, &uap->a2);
278done2:
279 mtx_unlock(&Giant);
280 return (error);
267}
268
269/*
270 * Allocate a new sem_undo structure for a process
271 * (returns ptr to structure or NULL if no more room)
272 */
273
274static struct sem_undo *

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

443struct __semctl_args {
444 int semid;
445 int semnum;
446 int cmd;
447 union semun *arg;
448};
449#endif
450
281}
282
283/*
284 * Allocate a new sem_undo structure for a process
285 * (returns ptr to structure or NULL if no more room)
286 */
287
288static struct sem_undo *

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

457struct __semctl_args {
458 int semid;
459 int semnum;
460 int cmd;
461 union semun *arg;
462};
463#endif
464
465/*
466 * MPSAFE
467 */
451int
452__semctl(p, uap)
453 struct proc *p;
454 register struct __semctl_args *uap;
455{
456 int semid = uap->semid;
457 int semnum = uap->semnum;
458 int cmd = uap->cmd;
459 union semun *arg = uap->arg;
460 union semun real_arg;
461 struct ucred *cred = p->p_ucred;
468int
469__semctl(p, uap)
470 struct proc *p;
471 register struct __semctl_args *uap;
472{
473 int semid = uap->semid;
474 int semnum = uap->semnum;
475 int cmd = uap->cmd;
476 union semun *arg = uap->arg;
477 union semun real_arg;
478 struct ucred *cred = p->p_ucred;
462 int i, rval, eval;
479 int i, rval, error;
463 struct semid_ds sbuf;
464 register struct semid_ds *semaptr;
465
466#ifdef SEM_DEBUG
467 printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
468#endif
480 struct semid_ds sbuf;
481 register struct semid_ds *semaptr;
482
483#ifdef SEM_DEBUG
484 printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
485#endif
486 mtx_lock(&Giant);
469
487
470 if (!jail_sysvipc_allowed && jailed(p->p_ucred))
471 return (ENOSYS);
488 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
489 error = ENOSYS;
490 goto done2;
491 }
472
473 semid = IPCID_TO_IX(semid);
492
493 semid = IPCID_TO_IX(semid);
474 if (semid < 0 || semid >= seminfo.semmsl)
475 return(EINVAL);
494 if (semid < 0 || semid >= seminfo.semmsl) {
495 error = EINVAL;
496 goto done2;
497 }
476
477 semaptr = &sema[semid];
478 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
498
499 semaptr = &sema[semid];
500 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
479 semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
480 return(EINVAL);
501 semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
502 error = EINVAL;
503 goto done2;
504 }
481
505
482 eval = 0;
506 error = 0;
483 rval = 0;
484
485 switch (cmd) {
486 case IPC_RMID:
507 rval = 0;
508
509 switch (cmd) {
510 case IPC_RMID:
487 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M)))
488 return(eval);
511 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M)))
512 goto done2;
489 semaptr->sem_perm.cuid = cred->cr_uid;
490 semaptr->sem_perm.uid = cred->cr_uid;
491 semtot -= semaptr->sem_nsems;
492 for (i = semaptr->sem_base - sem; i < semtot; i++)
493 sem[i] = sem[i + semaptr->sem_nsems];
494 for (i = 0; i < seminfo.semmni; i++) {
495 if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
496 sema[i].sem_base > semaptr->sem_base)
497 sema[i].sem_base -= semaptr->sem_nsems;
498 }
499 semaptr->sem_perm.mode = 0;
500 semundo_clear(semid, -1);
501 wakeup((caddr_t)semaptr);
502 break;
503
504 case IPC_SET:
513 semaptr->sem_perm.cuid = cred->cr_uid;
514 semaptr->sem_perm.uid = cred->cr_uid;
515 semtot -= semaptr->sem_nsems;
516 for (i = semaptr->sem_base - sem; i < semtot; i++)
517 sem[i] = sem[i + semaptr->sem_nsems];
518 for (i = 0; i < seminfo.semmni; i++) {
519 if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
520 sema[i].sem_base > semaptr->sem_base)
521 sema[i].sem_base -= semaptr->sem_nsems;
522 }
523 semaptr->sem_perm.mode = 0;
524 semundo_clear(semid, -1);
525 wakeup((caddr_t)semaptr);
526 break;
527
528 case IPC_SET:
505 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M)))
506 return(eval);
507 if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
508 return(eval);
509 if ((eval = copyin(real_arg.buf, (caddr_t)&sbuf,
510 sizeof(sbuf))) != 0)
511 return(eval);
529 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M)))
530 goto done2;
531 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
532 goto done2;
533 if ((error = copyin(real_arg.buf, (caddr_t)&sbuf,
534 sizeof(sbuf))) != 0) {
535 goto done2;
536 }
512 semaptr->sem_perm.uid = sbuf.sem_perm.uid;
513 semaptr->sem_perm.gid = sbuf.sem_perm.gid;
514 semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
515 (sbuf.sem_perm.mode & 0777);
516 semaptr->sem_ctime = time_second;
517 break;
518
519 case IPC_STAT:
537 semaptr->sem_perm.uid = sbuf.sem_perm.uid;
538 semaptr->sem_perm.gid = sbuf.sem_perm.gid;
539 semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
540 (sbuf.sem_perm.mode & 0777);
541 semaptr->sem_ctime = time_second;
542 break;
543
544 case IPC_STAT:
520 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
521 return(eval);
522 if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
523 return(eval);
524 eval = copyout((caddr_t)semaptr, real_arg.buf,
525 sizeof(struct semid_ds));
545 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
546 goto done2;
547 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
548 goto done2;
549 error = copyout((caddr_t)semaptr, real_arg.buf,
550 sizeof(struct semid_ds));
526 break;
527
528 case GETNCNT:
551 break;
552
553 case GETNCNT:
529 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
530 return(eval);
531 if (semnum < 0 || semnum >= semaptr->sem_nsems)
532 return(EINVAL);
554 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
555 goto done2;
556 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
557 error = EINVAL;
558 goto done2;
559 }
533 rval = semaptr->sem_base[semnum].semncnt;
534 break;
535
536 case GETPID:
560 rval = semaptr->sem_base[semnum].semncnt;
561 break;
562
563 case GETPID:
537 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
538 return(eval);
539 if (semnum < 0 || semnum >= semaptr->sem_nsems)
540 return(EINVAL);
564 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
565 goto done2;
566 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
567 error = EINVAL;
568 goto done2;
569 }
541 rval = semaptr->sem_base[semnum].sempid;
542 break;
543
544 case GETVAL:
570 rval = semaptr->sem_base[semnum].sempid;
571 break;
572
573 case GETVAL:
545 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
546 return(eval);
547 if (semnum < 0 || semnum >= semaptr->sem_nsems)
548 return(EINVAL);
574 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
575 goto done2;
576 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
577 error = EINVAL;
578 goto done2;
579 }
549 rval = semaptr->sem_base[semnum].semval;
550 break;
551
552 case GETALL:
580 rval = semaptr->sem_base[semnum].semval;
581 break;
582
583 case GETALL:
553 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
554 return(eval);
555 if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
556 return(eval);
584 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
585 goto done2;
586 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
587 goto done2;
557 for (i = 0; i < semaptr->sem_nsems; i++) {
588 for (i = 0; i < semaptr->sem_nsems; i++) {
558 eval = copyout((caddr_t)&semaptr->sem_base[i].semval,
589 error = copyout((caddr_t)&semaptr->sem_base[i].semval,
559 &real_arg.array[i], sizeof(real_arg.array[0]));
590 &real_arg.array[i], sizeof(real_arg.array[0]));
560 if (eval != 0)
591 if (error != 0)
561 break;
562 }
563 break;
564
565 case GETZCNT:
592 break;
593 }
594 break;
595
596 case GETZCNT:
566 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R)))
567 return(eval);
568 if (semnum < 0 || semnum >= semaptr->sem_nsems)
569 return(EINVAL);
597 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
598 goto done2;
599 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
600 error = EINVAL;
601 goto done2;
602 }
570 rval = semaptr->sem_base[semnum].semzcnt;
571 break;
572
573 case SETVAL:
603 rval = semaptr->sem_base[semnum].semzcnt;
604 break;
605
606 case SETVAL:
574 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W)))
575 return(eval);
576 if (semnum < 0 || semnum >= semaptr->sem_nsems)
577 return(EINVAL);
578 if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
579 return(eval);
607 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W)))
608 goto done2;
609 if (semnum < 0 || semnum >= semaptr->sem_nsems) {
610 error = EINVAL;
611 goto done2;
612 }
613 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
614 goto done2;
580 semaptr->sem_base[semnum].semval = real_arg.val;
581 semundo_clear(semid, semnum);
582 wakeup((caddr_t)semaptr);
583 break;
584
585 case SETALL:
615 semaptr->sem_base[semnum].semval = real_arg.val;
616 semundo_clear(semid, semnum);
617 wakeup((caddr_t)semaptr);
618 break;
619
620 case SETALL:
586 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W)))
587 return(eval);
588 if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
589 return(eval);
621 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W)))
622 goto done2;
623 if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
624 goto done2;
590 for (i = 0; i < semaptr->sem_nsems; i++) {
625 for (i = 0; i < semaptr->sem_nsems; i++) {
591 eval = copyin(&real_arg.array[i],
626 error = copyin(&real_arg.array[i],
592 (caddr_t)&semaptr->sem_base[i].semval,
593 sizeof(real_arg.array[0]));
627 (caddr_t)&semaptr->sem_base[i].semval,
628 sizeof(real_arg.array[0]));
594 if (eval != 0)
629 if (error != 0)
595 break;
596 }
597 semundo_clear(semid, -1);
598 wakeup((caddr_t)semaptr);
599 break;
600
601 default:
630 break;
631 }
632 semundo_clear(semid, -1);
633 wakeup((caddr_t)semaptr);
634 break;
635
636 default:
602 return(EINVAL);
637 error = EINVAL;
638 break;
603 }
604
639 }
640
605 if (eval == 0)
641 if (error == 0)
606 p->p_retval[0] = rval;
642 p->p_retval[0] = rval;
607 return(eval);
643done2:
644 mtx_unlock(&Giant);
645 return(error);
608}
609
610#ifndef _SYS_SYSPROTO_H_
611struct semget_args {
612 key_t key;
613 int nsems;
614 int semflg;
615};
616#endif
617
646}
647
648#ifndef _SYS_SYSPROTO_H_
649struct semget_args {
650 key_t key;
651 int nsems;
652 int semflg;
653};
654#endif
655
656/*
657 * MPSAFE
658 */
618int
619semget(p, uap)
620 struct proc *p;
621 register struct semget_args *uap;
622{
659int
660semget(p, uap)
661 struct proc *p;
662 register struct semget_args *uap;
663{
623 int semid, eval;
664 int semid, error = 0;
624 int key = uap->key;
625 int nsems = uap->nsems;
626 int semflg = uap->semflg;
627 struct ucred *cred = p->p_ucred;
628
629#ifdef SEM_DEBUG
630 printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
631#endif
665 int key = uap->key;
666 int nsems = uap->nsems;
667 int semflg = uap->semflg;
668 struct ucred *cred = p->p_ucred;
669
670#ifdef SEM_DEBUG
671 printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
672#endif
673 mtx_lock(&Giant);
632
674
633 if (!jail_sysvipc_allowed && jailed(p->p_ucred))
634 return (ENOSYS);
675 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
676 error = ENOSYS;
677 goto done2;
678 }
635
636 if (key != IPC_PRIVATE) {
637 for (semid = 0; semid < seminfo.semmni; semid++) {
638 if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
639 sema[semid].sem_perm.key == key)
640 break;
641 }
642 if (semid < seminfo.semmni) {
643#ifdef SEM_DEBUG
644 printf("found public key\n");
645#endif
679
680 if (key != IPC_PRIVATE) {
681 for (semid = 0; semid < seminfo.semmni; semid++) {
682 if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
683 sema[semid].sem_perm.key == key)
684 break;
685 }
686 if (semid < seminfo.semmni) {
687#ifdef SEM_DEBUG
688 printf("found public key\n");
689#endif
646 if ((eval = ipcperm(p, &sema[semid].sem_perm,
647 semflg & 0700)))
648 return(eval);
690 if ((error = ipcperm(p, &sema[semid].sem_perm,
691 semflg & 0700))) {
692 goto done2;
693 }
649 if (nsems > 0 && sema[semid].sem_nsems < nsems) {
650#ifdef SEM_DEBUG
651 printf("too small\n");
652#endif
694 if (nsems > 0 && sema[semid].sem_nsems < nsems) {
695#ifdef SEM_DEBUG
696 printf("too small\n");
697#endif
653 return(EINVAL);
698 error = EINVAL;
699 goto done2;
654 }
655 if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
656#ifdef SEM_DEBUG
657 printf("not exclusive\n");
658#endif
700 }
701 if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
702#ifdef SEM_DEBUG
703 printf("not exclusive\n");
704#endif
659 return(EEXIST);
705 error = EEXIST;
706 goto done2;
660 }
661 goto found;
662 }
663 }
664
665#ifdef SEM_DEBUG
666 printf("need to allocate the semid_ds\n");
667#endif
668 if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
669 if (nsems <= 0 || nsems > seminfo.semmsl) {
670#ifdef SEM_DEBUG
671 printf("nsems out of range (0<%d<=%d)\n", nsems,
672 seminfo.semmsl);
673#endif
707 }
708 goto found;
709 }
710 }
711
712#ifdef SEM_DEBUG
713 printf("need to allocate the semid_ds\n");
714#endif
715 if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
716 if (nsems <= 0 || nsems > seminfo.semmsl) {
717#ifdef SEM_DEBUG
718 printf("nsems out of range (0<%d<=%d)\n", nsems,
719 seminfo.semmsl);
720#endif
674 return(EINVAL);
721 error = EINVAL;
722 goto done2;
675 }
676 if (nsems > seminfo.semmns - semtot) {
677#ifdef SEM_DEBUG
678 printf("not enough semaphores left (need %d, got %d)\n",
679 nsems, seminfo.semmns - semtot);
680#endif
723 }
724 if (nsems > seminfo.semmns - semtot) {
725#ifdef SEM_DEBUG
726 printf("not enough semaphores left (need %d, got %d)\n",
727 nsems, seminfo.semmns - semtot);
728#endif
681 return(ENOSPC);
729 error = ENOSPC;
730 goto done2;
682 }
683 for (semid = 0; semid < seminfo.semmni; semid++) {
684 if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
685 break;
686 }
687 if (semid == seminfo.semmni) {
688#ifdef SEM_DEBUG
689 printf("no more semid_ds's available\n");
690#endif
731 }
732 for (semid = 0; semid < seminfo.semmni; semid++) {
733 if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
734 break;
735 }
736 if (semid == seminfo.semmni) {
737#ifdef SEM_DEBUG
738 printf("no more semid_ds's available\n");
739#endif
691 return(ENOSPC);
740 error = ENOSPC;
741 goto done2;
692 }
693#ifdef SEM_DEBUG
694 printf("semid %d is available\n", semid);
695#endif
696 sema[semid].sem_perm.key = key;
697 sema[semid].sem_perm.cuid = cred->cr_uid;
698 sema[semid].sem_perm.uid = cred->cr_uid;
699 sema[semid].sem_perm.cgid = cred->cr_gid;

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

711#ifdef SEM_DEBUG
712 printf("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base,
713 &sem[semtot]);
714#endif
715 } else {
716#ifdef SEM_DEBUG
717 printf("didn't find it and wasn't asked to create it\n");
718#endif
742 }
743#ifdef SEM_DEBUG
744 printf("semid %d is available\n", semid);
745#endif
746 sema[semid].sem_perm.key = key;
747 sema[semid].sem_perm.cuid = cred->cr_uid;
748 sema[semid].sem_perm.uid = cred->cr_uid;
749 sema[semid].sem_perm.cgid = cred->cr_gid;

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

761#ifdef SEM_DEBUG
762 printf("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base,
763 &sem[semtot]);
764#endif
765 } else {
766#ifdef SEM_DEBUG
767 printf("didn't find it and wasn't asked to create it\n");
768#endif
719 return(ENOENT);
769 error = ENOENT;
770 goto done2;
720 }
721
722found:
723 p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
771 }
772
773found:
774 p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
724 return(0);
775done2:
776 mtx_unlock(&Giant);
777 return (error);
725}
726
727#ifndef _SYS_SYSPROTO_H_
728struct semop_args {
729 int semid;
730 struct sembuf *sops;
731 int nsops;
732};
733#endif
734
778}
779
780#ifndef _SYS_SYSPROTO_H_
781struct semop_args {
782 int semid;
783 struct sembuf *sops;
784 int nsops;
785};
786#endif
787
788/*
789 * MPSAFE
790 */
735int
736semop(p, uap)
737 struct proc *p;
738 register struct semop_args *uap;
739{
740 int semid = uap->semid;
741 int nsops = uap->nsops;
742 struct sembuf sops[MAX_SOPS];
743 register struct semid_ds *semaptr;
744 register struct sembuf *sopptr;
745 register struct sem *semptr;
746 struct sem_undo *suptr = NULL;
791int
792semop(p, uap)
793 struct proc *p;
794 register struct semop_args *uap;
795{
796 int semid = uap->semid;
797 int nsops = uap->nsops;
798 struct sembuf sops[MAX_SOPS];
799 register struct semid_ds *semaptr;
800 register struct sembuf *sopptr;
801 register struct sem *semptr;
802 struct sem_undo *suptr = NULL;
747 int i, j, eval;
803 int i, j, error = 0;
748 int do_wakeup, do_undos;
749
750#ifdef SEM_DEBUG
751 printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
752#endif
753
804 int do_wakeup, do_undos;
805
806#ifdef SEM_DEBUG
807 printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
808#endif
809
754 if (!jail_sysvipc_allowed && jailed(p->p_ucred))
755 return (ENOSYS);
810 mtx_lock(&Giant);
756
811
812 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
813 error = ENOSYS;
814 goto done2;
815 }
816
757 semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
758
817 semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
818
759 if (semid < 0 || semid >= seminfo.semmsl)
760 return(EINVAL);
819 if (semid < 0 || semid >= seminfo.semmsl) {
820 error = EINVAL;
821 goto done2;
822 }
761
762 semaptr = &sema[semid];
823
824 semaptr = &sema[semid];
763 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
764 return(EINVAL);
765 if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
766 return(EINVAL);
825 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
826 error = EINVAL;
827 goto done2;
828 }
829 if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
830 error = EINVAL;
831 goto done2;
832 }
767
833
768 if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) {
834 if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W))) {
769#ifdef SEM_DEBUG
835#ifdef SEM_DEBUG
770 printf("eval = %d from ipaccess\n", eval);
836 printf("error = %d from ipaccess\n", error);
771#endif
837#endif
772 return(eval);
838 goto done2;
773 }
774
775 if (nsops > MAX_SOPS) {
776#ifdef SEM_DEBUG
777 printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops);
778#endif
839 }
840
841 if (nsops > MAX_SOPS) {
842#ifdef SEM_DEBUG
843 printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops);
844#endif
779 return(E2BIG);
845 error = E2BIG;
846 goto done2;
780 }
781
847 }
848
782 if ((eval = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) {
849 if ((error = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) {
783#ifdef SEM_DEBUG
850#ifdef SEM_DEBUG
784 printf("eval = %d from copyin(%08x, %08x, %d)\n", eval,
851 printf("error = %d from copyin(%08x, %08x, %d)\n", error,
785 uap->sops, &sops, nsops * sizeof(sops[0]));
786#endif
852 uap->sops, &sops, nsops * sizeof(sops[0]));
853#endif
787 return(eval);
854 goto done2;
788 }
789
790 /*
791 * Loop trying to satisfy the vector of requests.
792 * If we reach a point where we must wait, any requests already
793 * performed are rolled back and we go to sleep until some other
794 * process wakes us up. At this point, we start all over again.
795 *
796 * This ensures that from the perspective of other tasks, a set
797 * of requests is atomic (never partially satisfied).
798 */
799 do_undos = 0;
800
801 for (;;) {
802 do_wakeup = 0;
803
804 for (i = 0; i < nsops; i++) {
805 sopptr = &sops[i];
806
855 }
856
857 /*
858 * Loop trying to satisfy the vector of requests.
859 * If we reach a point where we must wait, any requests already
860 * performed are rolled back and we go to sleep until some other
861 * process wakes us up. At this point, we start all over again.
862 *
863 * This ensures that from the perspective of other tasks, a set
864 * of requests is atomic (never partially satisfied).
865 */
866 do_undos = 0;
867
868 for (;;) {
869 do_wakeup = 0;
870
871 for (i = 0; i < nsops; i++) {
872 sopptr = &sops[i];
873
807 if (sopptr->sem_num >= semaptr->sem_nsems)
808 return(EFBIG);
874 if (sopptr->sem_num >= semaptr->sem_nsems) {
875 error = EFBIG;
876 goto done2;
877 }
809
810 semptr = &semaptr->sem_base[sopptr->sem_num];
811
812#ifdef SEM_DEBUG
813 printf("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
814 semaptr, semaptr->sem_base, semptr,
815 sopptr->sem_num, semptr->semval, sopptr->sem_op,
816 (sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait");

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

861 for (j = 0; j < i; j++)
862 semaptr->sem_base[sops[j].sem_num].semval -=
863 sops[j].sem_op;
864
865 /*
866 * If the request that we couldn't satisfy has the
867 * NOWAIT flag set then return with EAGAIN.
868 */
878
879 semptr = &semaptr->sem_base[sopptr->sem_num];
880
881#ifdef SEM_DEBUG
882 printf("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
883 semaptr, semaptr->sem_base, semptr,
884 sopptr->sem_num, semptr->semval, sopptr->sem_op,
885 (sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait");

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

930 for (j = 0; j < i; j++)
931 semaptr->sem_base[sops[j].sem_num].semval -=
932 sops[j].sem_op;
933
934 /*
935 * If the request that we couldn't satisfy has the
936 * NOWAIT flag set then return with EAGAIN.
937 */
869 if (sopptr->sem_flg & IPC_NOWAIT)
870 return(EAGAIN);
938 if (sopptr->sem_flg & IPC_NOWAIT) {
939 error = EAGAIN;
940 goto done2;
941 }
871
872 if (sopptr->sem_op == 0)
873 semptr->semzcnt++;
874 else
875 semptr->semncnt++;
876
877#ifdef SEM_DEBUG
878 printf("semop: good night!\n");
879#endif
942
943 if (sopptr->sem_op == 0)
944 semptr->semzcnt++;
945 else
946 semptr->semncnt++;
947
948#ifdef SEM_DEBUG
949 printf("semop: good night!\n");
950#endif
880 eval = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH,
951 error = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH,
881 "semwait", 0);
882#ifdef SEM_DEBUG
952 "semwait", 0);
953#ifdef SEM_DEBUG
883 printf("semop: good morning (eval=%d)!\n", eval);
954 printf("semop: good morning (error=%d)!\n", error);
884#endif
885
886 suptr = NULL; /* sem_undo may have been reallocated */
887
955#endif
956
957 suptr = NULL; /* sem_undo may have been reallocated */
958
888 if (eval != 0)
889 return(EINTR);
959 if (error != 0) {
960 error = EINTR;
961 goto done2;
962 }
890#ifdef SEM_DEBUG
891 printf("semop: good morning!\n");
892#endif
893
894 /*
895 * Make sure that the semaphore still exists
896 */
897 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
963#ifdef SEM_DEBUG
964 printf("semop: good morning!\n");
965#endif
966
967 /*
968 * Make sure that the semaphore still exists
969 */
970 if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
898 semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
899 return(EIDRM);
971 semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
972 error = EIDRM;
973 goto done2;
974 }
900
901 /*
902 * The semaphore is still alive. Readjust the count of
903 * waiting processes.
904 */
905 if (sopptr->sem_op == 0)
906 semptr->semzcnt--;
907 else

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

920 */
921 int adjval;
922
923 if ((sops[i].sem_flg & SEM_UNDO) == 0)
924 continue;
925 adjval = sops[i].sem_op;
926 if (adjval == 0)
927 continue;
975
976 /*
977 * The semaphore is still alive. Readjust the count of
978 * waiting processes.
979 */
980 if (sopptr->sem_op == 0)
981 semptr->semzcnt--;
982 else

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

995 */
996 int adjval;
997
998 if ((sops[i].sem_flg & SEM_UNDO) == 0)
999 continue;
1000 adjval = sops[i].sem_op;
1001 if (adjval == 0)
1002 continue;
928 eval = semundo_adjust(p, &suptr, semid,
1003 error = semundo_adjust(p, &suptr, semid,
929 sops[i].sem_num, -adjval);
1004 sops[i].sem_num, -adjval);
930 if (eval == 0)
1005 if (error == 0)
931 continue;
932
933 /*
934 * Oh-Oh! We ran out of either sem_undo's or undo's.
935 * Rollback the adjustments to this point and then
936 * rollback the semaphore ups and down so we can return
937 * with an error with all structures restored. We
938 * rollback the undo's in the exact reverse order that

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

950 panic("semop - can't undo undos");
951 }
952
953 for (j = 0; j < nsops; j++)
954 semaptr->sem_base[sops[j].sem_num].semval -=
955 sops[j].sem_op;
956
957#ifdef SEM_DEBUG
1006 continue;
1007
1008 /*
1009 * Oh-Oh! We ran out of either sem_undo's or undo's.
1010 * Rollback the adjustments to this point and then
1011 * rollback the semaphore ups and down so we can return
1012 * with an error with all structures restored. We
1013 * rollback the undo's in the exact reverse order that

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

1025 panic("semop - can't undo undos");
1026 }
1027
1028 for (j = 0; j < nsops; j++)
1029 semaptr->sem_base[sops[j].sem_num].semval -=
1030 sops[j].sem_op;
1031
1032#ifdef SEM_DEBUG
958 printf("eval = %d from semundo_adjust\n", eval);
1033 printf("error = %d from semundo_adjust\n", error);
959#endif
1034#endif
960 return(eval);
1035 goto done2;
961 } /* loop through the sops */
962 } /* if (do_undos) */
963
964 /* We're definitely done - set the sempid's */
965 for (i = 0; i < nsops; i++) {
966 sopptr = &sops[i];
967 semptr = &semaptr->sem_base[sopptr->sem_num];
968 semptr->sempid = p->p_pid;

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

977#ifdef SEM_DEBUG
978 printf("semop: back from wakeup\n");
979#endif
980 }
981#ifdef SEM_DEBUG
982 printf("semop: done\n");
983#endif
984 p->p_retval[0] = 0;
1036 } /* loop through the sops */
1037 } /* if (do_undos) */
1038
1039 /* We're definitely done - set the sempid's */
1040 for (i = 0; i < nsops; i++) {
1041 sopptr = &sops[i];
1042 semptr = &semaptr->sem_base[sopptr->sem_num];
1043 semptr->sempid = p->p_pid;

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

1052#ifdef SEM_DEBUG
1053 printf("semop: back from wakeup\n");
1054#endif
1055 }
1056#ifdef SEM_DEBUG
1057 printf("semop: done\n");
1058#endif
1059 p->p_retval[0] = 0;
985 return(0);
1060done2:
1061 mtx_unlock(&Giant);
1062 return (error);
986}
987
988/*
989 * Go through the undo structures for this process and apply the adjustments to
990 * semaphores.
991 */
992static void
993semexit_myhook(p)

--- 86 unchanged lines hidden ---
1063}
1064
1065/*
1066 * Go through the undo structures for this process and apply the adjustments to
1067 * semaphores.
1068 */
1069static void
1070semexit_myhook(p)

--- 86 unchanged lines hidden ---