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