| 684 | } |
| 685 | |
| 686 | static int |
| 687 | shmget_allocate_segment(struct thread *td, key_t key, size_t size, int mode) |
| 688 | { |
| 689 | struct ucred *cred = td->td_ucred; |
| 690 | struct shmid_kernel *shmseg; |
| 691 | vm_object_t shm_object; |
| 692 | int i, segnum; |
| 693 | |
| 694 | SYSVSHM_ASSERT_LOCKED(); |
| 695 | |
| 696 | if (size < shminfo.shmmin || size > shminfo.shmmax) |
| 697 | return (EINVAL); |
| 698 | if (shm_nused >= shminfo.shmmni) /* Any shmids left? */ |
| 699 | return (ENOSPC); |
| 700 | size = round_page(size); |
| 701 | if (shm_committed + btoc(size) > shminfo.shmall) |
| 702 | return (ENOMEM); |
| 703 | if (shm_last_free < 0) { |
| 704 | shmrealloc(); /* Maybe expand the shmsegs[] array. */ |
| 705 | for (i = 0; i < shmalloced; i++) |
| 706 | if (shmsegs[i].u.shm_perm.mode & SHMSEG_FREE) |
| 707 | break; |
| 708 | if (i == shmalloced) |
| 709 | return (ENOSPC); |
| 710 | segnum = i; |
| 711 | } else { |
| 712 | segnum = shm_last_free; |
| 713 | shm_last_free = -1; |
| 714 | } |
| 715 | KASSERT(segnum >= 0 && segnum < shmalloced, |
| 716 | ("segnum %d shmalloced %d", segnum, shmalloced)); |
| 717 | shmseg = &shmsegs[segnum]; |
| 718 | #ifdef RACCT |
| 719 | if (racct_enable) { |
| 720 | PROC_LOCK(td->td_proc); |
| 721 | if (racct_add(td->td_proc, RACCT_NSHM, 1)) { |
| 722 | PROC_UNLOCK(td->td_proc); |
| 723 | return (ENOSPC); |
| 724 | } |
| 725 | if (racct_add(td->td_proc, RACCT_SHMSIZE, size)) { |
| 726 | racct_sub(td->td_proc, RACCT_NSHM, 1); |
| 727 | PROC_UNLOCK(td->td_proc); |
| 728 | return (ENOMEM); |
| 729 | } |
| 730 | PROC_UNLOCK(td->td_proc); |
| 731 | } |
| 732 | #endif |
| 733 | |
| 734 | /* |
| 735 | * We make sure that we have allocated a pager before we need |
| 736 | * to. |
| 737 | */ |
| 738 | shm_object = vm_pager_allocate(shm_use_phys ? OBJT_PHYS : OBJT_SWAP, |
| 739 | 0, size, VM_PROT_DEFAULT, 0, cred); |
| 740 | if (shm_object == NULL) { |
| 741 | #ifdef RACCT |
| 742 | if (racct_enable) { |
| 743 | PROC_LOCK(td->td_proc); |
no test coverage detected