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