Deleted Added
full compact
sysv_shm.c (134675) sysv_shm.c (137613)
1/* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */
2/*
3 * Copyright (c) 1994 Adam Glass and Charles Hannum. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
1/* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */
2/*
3 * Copyright (c) 1994 Adam Glass and Charles Hannum. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/sysv_shm.c 134675 2004-09-03 05:11:32Z alc $");
33__FBSDID("$FreeBSD: head/sys/kern/sysv_shm.c 137613 2004-11-12 13:23:47Z rwatson $");
34
35#include "opt_compat.h"
36#include "opt_sysvipc.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>

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

80};
81
82#define SHMSEG_FREE 0x0200
83#define SHMSEG_REMOVED 0x0400
84#define SHMSEG_ALLOCATED 0x0800
85#define SHMSEG_WANTED 0x1000
86
87static int shm_last_free, shm_nused, shm_committed, shmalloced;
34
35#include "opt_compat.h"
36#include "opt_sysvipc.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>

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

80};
81
82#define SHMSEG_FREE 0x0200
83#define SHMSEG_REMOVED 0x0400
84#define SHMSEG_ALLOCATED 0x0800
85#define SHMSEG_WANTED 0x1000
86
87static int shm_last_free, shm_nused, shm_committed, shmalloced;
88static struct shmid_ds *shmsegs;
88static struct shmid_kernel *shmsegs;
89
90struct shmmap_state {
91 vm_offset_t va;
92 int shmid;
93};
94
89
90struct shmmap_state {
91 vm_offset_t va;
92 int shmid;
93};
94
95static void shm_deallocate_segment(struct shmid_ds *);
95static void shm_deallocate_segment(struct shmid_kernel *);
96static int shm_find_segment_by_key(key_t);
96static int shm_find_segment_by_key(key_t);
97static struct shmid_ds *shm_find_segment_by_shmid(int);
98static struct shmid_ds *shm_find_segment_by_shmidx(int);
97static struct shmid_kernel *shm_find_segment_by_shmid(int);
98static struct shmid_kernel *shm_find_segment_by_shmidx(int);
99static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
100static void shmrealloc(void);
101static void shminit(void);
102static int sysvshm_modload(struct module *, int, void *);
103static int shmunload(void);
104static void shmexit_myhook(struct vmspace *vm);
105static void shmfork_myhook(struct proc *p1, struct proc *p2);
106static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);

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

153
154static int
155shm_find_segment_by_key(key)
156 key_t key;
157{
158 int i;
159
160 for (i = 0; i < shmalloced; i++)
99static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
100static void shmrealloc(void);
101static void shminit(void);
102static int sysvshm_modload(struct module *, int, void *);
103static int shmunload(void);
104static void shmexit_myhook(struct vmspace *vm);
105static void shmfork_myhook(struct proc *p1, struct proc *p2);
106static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);

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

153
154static int
155shm_find_segment_by_key(key)
156 key_t key;
157{
158 int i;
159
160 for (i = 0; i < shmalloced; i++)
161 if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
162 shmsegs[i].shm_perm.key == key)
161 if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) &&
162 shmsegs[i].u.shm_perm.key == key)
163 return (i);
164 return (-1);
165}
166
163 return (i);
164 return (-1);
165}
166
167static struct shmid_ds *
167static struct shmid_kernel *
168shm_find_segment_by_shmid(int shmid)
169{
170 int segnum;
168shm_find_segment_by_shmid(int shmid)
169{
170 int segnum;
171 struct shmid_ds *shmseg;
171 struct shmid_kernel *shmseg;
172
173 segnum = IPCID_TO_IX(shmid);
174 if (segnum < 0 || segnum >= shmalloced)
175 return (NULL);
176 shmseg = &shmsegs[segnum];
172
173 segnum = IPCID_TO_IX(shmid);
174 if (segnum < 0 || segnum >= shmalloced)
175 return (NULL);
176 shmseg = &shmsegs[segnum];
177 if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
177 if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
178 (!shm_allow_removed &&
178 (!shm_allow_removed &&
179 (shmseg->shm_perm.mode & SHMSEG_REMOVED) != 0) ||
180 shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid))
179 (shmseg->u.shm_perm.mode & SHMSEG_REMOVED) != 0) ||
180 shmseg->u.shm_perm.seq != IPCID_TO_SEQ(shmid))
181 return (NULL);
182 return (shmseg);
183}
184
181 return (NULL);
182 return (shmseg);
183}
184
185static struct shmid_ds *
185static struct shmid_kernel *
186shm_find_segment_by_shmidx(int segnum)
187{
186shm_find_segment_by_shmidx(int segnum)
187{
188 struct shmid_ds *shmseg;
188 struct shmid_kernel *shmseg;
189
190 if (segnum < 0 || segnum >= shmalloced)
191 return (NULL);
192 shmseg = &shmsegs[segnum];
189
190 if (segnum < 0 || segnum >= shmalloced)
191 return (NULL);
192 shmseg = &shmsegs[segnum];
193 if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
193 if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
194 (!shm_allow_removed &&
194 (!shm_allow_removed &&
195 (shmseg->shm_perm.mode & SHMSEG_REMOVED) != 0))
195 (shmseg->u.shm_perm.mode & SHMSEG_REMOVED) != 0))
196 return (NULL);
197 return (shmseg);
198}
199
200static void
201shm_deallocate_segment(shmseg)
196 return (NULL);
197 return (shmseg);
198}
199
200static void
201shm_deallocate_segment(shmseg)
202 struct shmid_ds *shmseg;
202 struct shmid_kernel *shmseg;
203{
204 size_t size;
205
206 GIANT_REQUIRED;
207
203{
204 size_t size;
205
206 GIANT_REQUIRED;
207
208 vm_object_deallocate(shmseg->shm_internal);
209 shmseg->shm_internal = NULL;
210 size = round_page(shmseg->shm_segsz);
208 vm_object_deallocate(shmseg->u.shm_internal);
209 shmseg->u.shm_internal = NULL;
210 size = round_page(shmseg->u.shm_segsz);
211 shm_committed -= btoc(size);
212 shm_nused--;
211 shm_committed -= btoc(size);
212 shm_nused--;
213 shmseg->shm_perm.mode = SHMSEG_FREE;
213 shmseg->u.shm_perm.mode = SHMSEG_FREE;
214}
215
216static int
217shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
218{
214}
215
216static int
217shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
218{
219 struct shmid_ds *shmseg;
219 struct shmid_kernel *shmseg;
220 int segnum, result;
221 size_t size;
222
223 GIANT_REQUIRED;
224
225 segnum = IPCID_TO_IX(shmmap_s->shmid);
226 shmseg = &shmsegs[segnum];
220 int segnum, result;
221 size_t size;
222
223 GIANT_REQUIRED;
224
225 segnum = IPCID_TO_IX(shmmap_s->shmid);
226 shmseg = &shmsegs[segnum];
227 size = round_page(shmseg->shm_segsz);
227 size = round_page(shmseg->u.shm_segsz);
228 result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
229 if (result != KERN_SUCCESS)
230 return (EINVAL);
231 shmmap_s->shmid = -1;
228 result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
229 if (result != KERN_SUCCESS)
230 return (EINVAL);
231 shmmap_s->shmid = -1;
232 shmseg->shm_dtime = time_second;
233 if ((--shmseg->shm_nattch <= 0) &&
234 (shmseg->shm_perm.mode & SHMSEG_REMOVED)) {
232 shmseg->u.shm_dtime = time_second;
233 if ((--shmseg->u.shm_nattch <= 0) &&
234 (shmseg->u.shm_perm.mode & SHMSEG_REMOVED)) {
235 shm_deallocate_segment(shmseg);
236 shm_last_free = segnum;
237 }
238 return (0);
239}
240
241#ifndef _SYS_SYSPROTO_H_
242struct shmdt_args {

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

296kern_shmat(td, shmid, shmaddr, shmflg)
297 struct thread *td;
298 int shmid;
299 const void *shmaddr;
300 int shmflg;
301{
302 struct proc *p = td->td_proc;
303 int i, flags;
235 shm_deallocate_segment(shmseg);
236 shm_last_free = segnum;
237 }
238 return (0);
239}
240
241#ifndef _SYS_SYSPROTO_H_
242struct shmdt_args {

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

296kern_shmat(td, shmid, shmaddr, shmflg)
297 struct thread *td;
298 int shmid;
299 const void *shmaddr;
300 int shmflg;
301{
302 struct proc *p = td->td_proc;
303 int i, flags;
304 struct shmid_ds *shmseg;
304 struct shmid_kernel *shmseg;
305 struct shmmap_state *shmmap_s = NULL;
306 vm_offset_t attach_va;
307 vm_prot_t prot;
308 vm_size_t size;
309 int rv;
310 int error = 0;
311
312 if (!jail_sysvipc_allowed && jailed(td->td_ucred))

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

320 shmmap_s[i].shmid = -1;
321 p->p_vmspace->vm_shm = shmmap_s;
322 }
323 shmseg = shm_find_segment_by_shmid(shmid);
324 if (shmseg == NULL) {
325 error = EINVAL;
326 goto done2;
327 }
305 struct shmmap_state *shmmap_s = NULL;
306 vm_offset_t attach_va;
307 vm_prot_t prot;
308 vm_size_t size;
309 int rv;
310 int error = 0;
311
312 if (!jail_sysvipc_allowed && jailed(td->td_ucred))

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

320 shmmap_s[i].shmid = -1;
321 p->p_vmspace->vm_shm = shmmap_s;
322 }
323 shmseg = shm_find_segment_by_shmid(shmid);
324 if (shmseg == NULL) {
325 error = EINVAL;
326 goto done2;
327 }
328 error = ipcperm(td, &shmseg->shm_perm,
328 error = ipcperm(td, &shmseg->u.shm_perm,
329 (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
330 if (error)
331 goto done2;
332 for (i = 0; i < shminfo.shmseg; i++) {
333 if (shmmap_s->shmid == -1)
334 break;
335 shmmap_s++;
336 }
337 if (i >= shminfo.shmseg) {
338 error = EMFILE;
339 goto done2;
340 }
329 (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
330 if (error)
331 goto done2;
332 for (i = 0; i < shminfo.shmseg; i++) {
333 if (shmmap_s->shmid == -1)
334 break;
335 shmmap_s++;
336 }
337 if (i >= shminfo.shmseg) {
338 error = EMFILE;
339 goto done2;
340 }
341 size = round_page(shmseg->shm_segsz);
341 size = round_page(shmseg->u.shm_segsz);
342#ifdef VM_PROT_READ_IS_EXEC
343 prot = VM_PROT_READ | VM_PROT_EXECUTE;
344#else
345 prot = VM_PROT_READ;
346#endif
347 if ((shmflg & SHM_RDONLY) == 0)
348 prot |= VM_PROT_WRITE;
349 flags = MAP_ANON | MAP_SHARED;

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

363 * put it.
364 */
365 PROC_LOCK(p);
366 attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
367 lim_max(p, RLIMIT_DATA));
368 PROC_UNLOCK(p);
369 }
370
342#ifdef VM_PROT_READ_IS_EXEC
343 prot = VM_PROT_READ | VM_PROT_EXECUTE;
344#else
345 prot = VM_PROT_READ;
346#endif
347 if ((shmflg & SHM_RDONLY) == 0)
348 prot |= VM_PROT_WRITE;
349 flags = MAP_ANON | MAP_SHARED;

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

363 * put it.
364 */
365 PROC_LOCK(p);
366 attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
367 lim_max(p, RLIMIT_DATA));
368 PROC_UNLOCK(p);
369 }
370
371 vm_object_reference(shmseg->shm_internal);
372 rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->shm_internal,
371 vm_object_reference(shmseg->u.shm_internal);
372 rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->u.shm_internal,
373 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0);
374 if (rv != KERN_SUCCESS) {
373 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0);
374 if (rv != KERN_SUCCESS) {
375 vm_object_deallocate(shmseg->shm_internal);
375 vm_object_deallocate(shmseg->u.shm_internal);
376 error = ENOMEM;
377 goto done2;
378 }
379 vm_map_inherit(&p->p_vmspace->vm_map,
380 attach_va, attach_va + size, VM_INHERIT_SHARE);
381
382 shmmap_s->va = attach_va;
383 shmmap_s->shmid = shmid;
376 error = ENOMEM;
377 goto done2;
378 }
379 vm_map_inherit(&p->p_vmspace->vm_map,
380 attach_va, attach_va + size, VM_INHERIT_SHARE);
381
382 shmmap_s->va = attach_va;
383 shmmap_s->shmid = shmid;
384 shmseg->shm_lpid = p->p_pid;
385 shmseg->shm_atime = time_second;
386 shmseg->shm_nattch++;
384 shmseg->u.shm_lpid = p->p_pid;
385 shmseg->u.shm_atime = time_second;
386 shmseg->u.shm_nattch++;
387 td->td_retval[0] = attach_va;
388done2:
389 mtx_unlock(&Giant);
390 return (error);
391}
392
393int
394shmat(td, uap)

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

421 */
422static int
423oshmctl(td, uap)
424 struct thread *td;
425 struct oshmctl_args *uap;
426{
427#ifdef COMPAT_43
428 int error = 0;
387 td->td_retval[0] = attach_va;
388done2:
389 mtx_unlock(&Giant);
390 return (error);
391}
392
393int
394shmat(td, uap)

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

421 */
422static int
423oshmctl(td, uap)
424 struct thread *td;
425 struct oshmctl_args *uap;
426{
427#ifdef COMPAT_43
428 int error = 0;
429 struct shmid_ds *shmseg;
429 struct shmid_kernel *shmseg;
430 struct oshmid_ds outbuf;
431
432 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
433 return (ENOSYS);
434 mtx_lock(&Giant);
435 shmseg = shm_find_segment_by_shmid(uap->shmid);
436 if (shmseg == NULL) {
437 error = EINVAL;
438 goto done2;
439 }
440 switch (uap->cmd) {
441 case IPC_STAT:
430 struct oshmid_ds outbuf;
431
432 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
433 return (ENOSYS);
434 mtx_lock(&Giant);
435 shmseg = shm_find_segment_by_shmid(uap->shmid);
436 if (shmseg == NULL) {
437 error = EINVAL;
438 goto done2;
439 }
440 switch (uap->cmd) {
441 case IPC_STAT:
442 error = ipcperm(td, &shmseg->shm_perm, IPC_R);
442 error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
443 if (error)
444 goto done2;
443 if (error)
444 goto done2;
445 outbuf.shm_perm = shmseg->shm_perm;
446 outbuf.shm_segsz = shmseg->shm_segsz;
447 outbuf.shm_cpid = shmseg->shm_cpid;
448 outbuf.shm_lpid = shmseg->shm_lpid;
449 outbuf.shm_nattch = shmseg->shm_nattch;
450 outbuf.shm_atime = shmseg->shm_atime;
451 outbuf.shm_dtime = shmseg->shm_dtime;
452 outbuf.shm_ctime = shmseg->shm_ctime;
453 outbuf.shm_handle = shmseg->shm_internal;
445 outbuf.shm_perm = shmseg->u.shm_perm;
446 outbuf.shm_segsz = shmseg->u.shm_segsz;
447 outbuf.shm_cpid = shmseg->u.shm_cpid;
448 outbuf.shm_lpid = shmseg->u.shm_lpid;
449 outbuf.shm_nattch = shmseg->u.shm_nattch;
450 outbuf.shm_atime = shmseg->u.shm_atime;
451 outbuf.shm_dtime = shmseg->u.shm_dtime;
452 outbuf.shm_ctime = shmseg->u.shm_ctime;
453 outbuf.shm_handle = shmseg->u.shm_internal;
454 error = copyout(&outbuf, uap->ubuf, sizeof(outbuf));
455 if (error)
456 goto done2;
457 break;
458 default:
459 error = shmctl(td, (struct shmctl_args *)uap);
460 break;
461 }

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

482kern_shmctl(td, shmid, cmd, buf, bufsz)
483 struct thread *td;
484 int shmid;
485 int cmd;
486 void *buf;
487 size_t *bufsz;
488{
489 int error = 0;
454 error = copyout(&outbuf, uap->ubuf, sizeof(outbuf));
455 if (error)
456 goto done2;
457 break;
458 default:
459 error = shmctl(td, (struct shmctl_args *)uap);
460 break;
461 }

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

482kern_shmctl(td, shmid, cmd, buf, bufsz)
483 struct thread *td;
484 int shmid;
485 int cmd;
486 void *buf;
487 size_t *bufsz;
488{
489 int error = 0;
490 struct shmid_ds *shmseg;
490 struct shmid_kernel *shmseg;
491
492 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
493 return (ENOSYS);
494
495 mtx_lock(&Giant);
496 switch (cmd) {
497 case IPC_INFO:
498 memcpy(buf, &shminfo, sizeof(shminfo));

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

521 shmseg = shm_find_segment_by_shmid(shmid);
522 if (shmseg == NULL) {
523 error = EINVAL;
524 goto done2;
525 }
526 switch (cmd) {
527 case SHM_STAT:
528 case IPC_STAT:
491
492 if (!jail_sysvipc_allowed && jailed(td->td_ucred))
493 return (ENOSYS);
494
495 mtx_lock(&Giant);
496 switch (cmd) {
497 case IPC_INFO:
498 memcpy(buf, &shminfo, sizeof(shminfo));

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

521 shmseg = shm_find_segment_by_shmid(shmid);
522 if (shmseg == NULL) {
523 error = EINVAL;
524 goto done2;
525 }
526 switch (cmd) {
527 case SHM_STAT:
528 case IPC_STAT:
529 error = ipcperm(td, &shmseg->shm_perm, IPC_R);
529 error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
530 if (error)
531 goto done2;
530 if (error)
531 goto done2;
532 memcpy(buf, shmseg, sizeof(struct shmid_ds));
532 memcpy(buf, &shmseg->u, sizeof(struct shmid_ds));
533 if (bufsz)
534 *bufsz = sizeof(struct shmid_ds);
535 if (cmd == SHM_STAT)
533 if (bufsz)
534 *bufsz = sizeof(struct shmid_ds);
535 if (cmd == SHM_STAT)
536 td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->shm_perm);
536 td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->u.shm_perm);
537 break;
538 case IPC_SET: {
539 struct shmid_ds *shmid;
540
541 shmid = (struct shmid_ds *)buf;
537 break;
538 case IPC_SET: {
539 struct shmid_ds *shmid;
540
541 shmid = (struct shmid_ds *)buf;
542 error = ipcperm(td, &shmseg->shm_perm, IPC_M);
542 error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
543 if (error)
544 goto done2;
543 if (error)
544 goto done2;
545 shmseg->shm_perm.uid = shmid->shm_perm.uid;
546 shmseg->shm_perm.gid = shmid->shm_perm.gid;
547 shmseg->shm_perm.mode =
548 (shmseg->shm_perm.mode & ~ACCESSPERMS) |
545 shmseg->u.shm_perm.uid = shmid->shm_perm.uid;
546 shmseg->u.shm_perm.gid = shmid->shm_perm.gid;
547 shmseg->u.shm_perm.mode =
548 (shmseg->u.shm_perm.mode & ~ACCESSPERMS) |
549 (shmid->shm_perm.mode & ACCESSPERMS);
549 (shmid->shm_perm.mode & ACCESSPERMS);
550 shmseg->shm_ctime = time_second;
550 shmseg->u.shm_ctime = time_second;
551 break;
552 }
553 case IPC_RMID:
551 break;
552 }
553 case IPC_RMID:
554 error = ipcperm(td, &shmseg->shm_perm, IPC_M);
554 error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
555 if (error)
556 goto done2;
555 if (error)
556 goto done2;
557 shmseg->shm_perm.key = IPC_PRIVATE;
558 shmseg->shm_perm.mode |= SHMSEG_REMOVED;
559 if (shmseg->shm_nattch <= 0) {
557 shmseg->u.shm_perm.key = IPC_PRIVATE;
558 shmseg->u.shm_perm.mode |= SHMSEG_REMOVED;
559 if (shmseg->u.shm_nattch <= 0) {
560 shm_deallocate_segment(shmseg);
561 shm_last_free = IPCID_TO_IX(shmid);
562 }
563 break;
564#if 0
565 case SHM_LOCK:
566 case SHM_UNLOCK:
567#endif

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

622
623static int
624shmget_existing(td, uap, mode, segnum)
625 struct thread *td;
626 struct shmget_args *uap;
627 int mode;
628 int segnum;
629{
560 shm_deallocate_segment(shmseg);
561 shm_last_free = IPCID_TO_IX(shmid);
562 }
563 break;
564#if 0
565 case SHM_LOCK:
566 case SHM_UNLOCK:
567#endif

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

622
623static int
624shmget_existing(td, uap, mode, segnum)
625 struct thread *td;
626 struct shmget_args *uap;
627 int mode;
628 int segnum;
629{
630 struct shmid_ds *shmseg;
630 struct shmid_kernel *shmseg;
631 int error;
632
633 shmseg = &shmsegs[segnum];
631 int error;
632
633 shmseg = &shmsegs[segnum];
634 if (shmseg->shm_perm.mode & SHMSEG_REMOVED) {
634 if (shmseg->u.shm_perm.mode & SHMSEG_REMOVED) {
635 /*
636 * This segment is in the process of being allocated. Wait
637 * until it's done, and look the key up again (in case the
638 * allocation failed or it was freed).
639 */
635 /*
636 * This segment is in the process of being allocated. Wait
637 * until it's done, and look the key up again (in case the
638 * allocation failed or it was freed).
639 */
640 shmseg->shm_perm.mode |= SHMSEG_WANTED;
640 shmseg->u.shm_perm.mode |= SHMSEG_WANTED;
641 error = tsleep(shmseg, PLOCK | PCATCH, "shmget", 0);
642 if (error)
643 return (error);
644 return (EAGAIN);
645 }
646 if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL))
647 return (EEXIST);
641 error = tsleep(shmseg, PLOCK | PCATCH, "shmget", 0);
642 if (error)
643 return (error);
644 return (EAGAIN);
645 }
646 if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL))
647 return (EEXIST);
648 error = ipcperm(td, &shmseg->shm_perm, mode);
648 error = ipcperm(td, &shmseg->u.shm_perm, mode);
649 if (error)
650 return (error);
649 if (error)
650 return (error);
651 if (uap->size && uap->size > shmseg->shm_segsz)
651 if (uap->size && uap->size > shmseg->u.shm_segsz)
652 return (EINVAL);
652 return (EINVAL);
653 td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
653 td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
654 return (0);
655}
656
657static int
658shmget_allocate_segment(td, uap, mode)
659 struct thread *td;
660 struct shmget_args *uap;
661 int mode;
662{
663 int i, segnum, shmid, size;
664 struct ucred *cred = td->td_ucred;
654 return (0);
655}
656
657static int
658shmget_allocate_segment(td, uap, mode)
659 struct thread *td;
660 struct shmget_args *uap;
661 int mode;
662{
663 int i, segnum, shmid, size;
664 struct ucred *cred = td->td_ucred;
665 struct shmid_ds *shmseg;
665 struct shmid_kernel *shmseg;
666 vm_object_t shm_object;
667
668 GIANT_REQUIRED;
669
670 if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax)
671 return (EINVAL);
672 if (shm_nused >= shminfo.shmmni) /* Any shmids left? */
673 return (ENOSPC);
674 size = round_page(uap->size);
675 if (shm_committed + btoc(size) > shminfo.shmall)
676 return (ENOMEM);
677 if (shm_last_free < 0) {
678 shmrealloc(); /* Maybe expand the shmsegs[] array. */
679 for (i = 0; i < shmalloced; i++)
666 vm_object_t shm_object;
667
668 GIANT_REQUIRED;
669
670 if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax)
671 return (EINVAL);
672 if (shm_nused >= shminfo.shmmni) /* Any shmids left? */
673 return (ENOSPC);
674 size = round_page(uap->size);
675 if (shm_committed + btoc(size) > shminfo.shmall)
676 return (ENOMEM);
677 if (shm_last_free < 0) {
678 shmrealloc(); /* Maybe expand the shmsegs[] array. */
679 for (i = 0; i < shmalloced; i++)
680 if (shmsegs[i].shm_perm.mode & SHMSEG_FREE)
680 if (shmsegs[i].u.shm_perm.mode & SHMSEG_FREE)
681 break;
682 if (i == shmalloced)
683 return (ENOSPC);
684 segnum = i;
685 } else {
686 segnum = shm_last_free;
687 shm_last_free = -1;
688 }
689 shmseg = &shmsegs[segnum];
690 /*
691 * In case we sleep in malloc(), mark the segment present but deleted
692 * so that noone else tries to create the same key.
693 */
681 break;
682 if (i == shmalloced)
683 return (ENOSPC);
684 segnum = i;
685 } else {
686 segnum = shm_last_free;
687 shm_last_free = -1;
688 }
689 shmseg = &shmsegs[segnum];
690 /*
691 * In case we sleep in malloc(), mark the segment present but deleted
692 * so that noone else tries to create the same key.
693 */
694 shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
695 shmseg->shm_perm.key = uap->key;
696 shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff;
697 shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
694 shmseg->u.shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
695 shmseg->u.shm_perm.key = uap->key;
696 shmseg->u.shm_perm.seq = (shmseg->u.shm_perm.seq + 1) & 0x7fff;
697 shmid = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
698
699 /*
700 * We make sure that we have allocated a pager before we need
701 * to.
702 */
703 if (shm_use_phys) {
704 shm_object =
705 vm_pager_allocate(OBJT_PHYS, 0, size, VM_PROT_DEFAULT, 0);
706 } else {
707 shm_object =
708 vm_pager_allocate(OBJT_SWAP, 0, size, VM_PROT_DEFAULT, 0);
709 }
710 VM_OBJECT_LOCK(shm_object);
711 vm_object_clear_flag(shm_object, OBJ_ONEMAPPING);
712 vm_object_set_flag(shm_object, OBJ_NOSPLIT);
713 VM_OBJECT_UNLOCK(shm_object);
714
698
699 /*
700 * We make sure that we have allocated a pager before we need
701 * to.
702 */
703 if (shm_use_phys) {
704 shm_object =
705 vm_pager_allocate(OBJT_PHYS, 0, size, VM_PROT_DEFAULT, 0);
706 } else {
707 shm_object =
708 vm_pager_allocate(OBJT_SWAP, 0, size, VM_PROT_DEFAULT, 0);
709 }
710 VM_OBJECT_LOCK(shm_object);
711 vm_object_clear_flag(shm_object, OBJ_ONEMAPPING);
712 vm_object_set_flag(shm_object, OBJ_NOSPLIT);
713 VM_OBJECT_UNLOCK(shm_object);
714
715 shmseg->shm_internal = shm_object;
716 shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid;
717 shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid;
718 shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) |
715 shmseg->u.shm_internal = shm_object;
716 shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
717 shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
718 shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) |
719 (mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
719 (mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
720 shmseg->shm_segsz = uap->size;
721 shmseg->shm_cpid = td->td_proc->p_pid;
722 shmseg->shm_lpid = shmseg->shm_nattch = 0;
723 shmseg->shm_atime = shmseg->shm_dtime = 0;
724 shmseg->shm_ctime = time_second;
720 shmseg->u.shm_segsz = uap->size;
721 shmseg->u.shm_cpid = td->td_proc->p_pid;
722 shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0;
723 shmseg->u.shm_atime = shmseg->u.shm_dtime = 0;
724 shmseg->u.shm_ctime = time_second;
725 shm_committed += btoc(size);
726 shm_nused++;
725 shm_committed += btoc(size);
726 shm_nused++;
727 if (shmseg->shm_perm.mode & SHMSEG_WANTED) {
727 if (shmseg->u.shm_perm.mode & SHMSEG_WANTED) {
728 /*
729 * Somebody else wanted this key while we were asleep. Wake
730 * them up now.
731 */
728 /*
729 * Somebody else wanted this key while we were asleep. Wake
730 * them up now.
731 */
732 shmseg->shm_perm.mode &= ~SHMSEG_WANTED;
732 shmseg->u.shm_perm.mode &= ~SHMSEG_WANTED;
733 wakeup(shmseg);
734 }
735 td->td_retval[0] = shmid;
736 return (0);
737}
738
739/*
740 * MPSAFE

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

808
809 mtx_lock(&Giant);
810 size = shminfo.shmseg * sizeof(struct shmmap_state);
811 shmmap_s = malloc(size, M_SHM, M_WAITOK);
812 bcopy(p1->p_vmspace->vm_shm, shmmap_s, size);
813 p2->p_vmspace->vm_shm = shmmap_s;
814 for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
815 if (shmmap_s->shmid != -1)
733 wakeup(shmseg);
734 }
735 td->td_retval[0] = shmid;
736 return (0);
737}
738
739/*
740 * MPSAFE

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

808
809 mtx_lock(&Giant);
810 size = shminfo.shmseg * sizeof(struct shmmap_state);
811 shmmap_s = malloc(size, M_SHM, M_WAITOK);
812 bcopy(p1->p_vmspace->vm_shm, shmmap_s, size);
813 p2->p_vmspace->vm_shm = shmmap_s;
814 for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
815 if (shmmap_s->shmid != -1)
816 shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
816 shmsegs[IPCID_TO_IX(shmmap_s->shmid)].u.shm_nattch++;
817 mtx_unlock(&Giant);
818}
819
820static void
821shmexit_myhook(struct vmspace *vm)
822{
823 struct shmmap_state *base, *shm;
824 int i;

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

834 free(base, M_SHM);
835 }
836}
837
838static void
839shmrealloc(void)
840{
841 int i;
817 mtx_unlock(&Giant);
818}
819
820static void
821shmexit_myhook(struct vmspace *vm)
822{
823 struct shmmap_state *base, *shm;
824 int i;

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

834 free(base, M_SHM);
835 }
836}
837
838static void
839shmrealloc(void)
840{
841 int i;
842 struct shmid_ds *newsegs;
842 struct shmid_kernel *newsegs;
843
844 if (shmalloced >= shminfo.shmmni)
845 return;
846
847 newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
848 if (newsegs == NULL)
849 return;
850 for (i = 0; i < shmalloced; i++)
851 bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
852 for (; i < shminfo.shmmni; i++) {
843
844 if (shmalloced >= shminfo.shmmni)
845 return;
846
847 newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
848 if (newsegs == NULL)
849 return;
850 for (i = 0; i < shmalloced; i++)
851 bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
852 for (; i < shminfo.shmmni; i++) {
853 shmsegs[i].shm_perm.mode = SHMSEG_FREE;
854 shmsegs[i].shm_perm.seq = 0;
853 shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
854 shmsegs[i].u.shm_perm.seq = 0;
855 }
856 free(shmsegs, M_SHM);
857 shmsegs = newsegs;
858 shmalloced = shminfo.shmmni;
859}
860
861static void
862shminit()

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

874 TUNABLE_INT_FETCH("kern.ipc.shmseg", &shminfo.shmseg);
875 TUNABLE_INT_FETCH("kern.ipc.shm_use_phys", &shm_use_phys);
876
877 shmalloced = shminfo.shmmni;
878 shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK);
879 if (shmsegs == NULL)
880 panic("cannot allocate initial memory for sysvshm");
881 for (i = 0; i < shmalloced; i++) {
855 }
856 free(shmsegs, M_SHM);
857 shmsegs = newsegs;
858 shmalloced = shminfo.shmmni;
859}
860
861static void
862shminit()

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

874 TUNABLE_INT_FETCH("kern.ipc.shmseg", &shminfo.shmseg);
875 TUNABLE_INT_FETCH("kern.ipc.shm_use_phys", &shm_use_phys);
876
877 shmalloced = shminfo.shmmni;
878 shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK);
879 if (shmsegs == NULL)
880 panic("cannot allocate initial memory for sysvshm");
881 for (i = 0; i < shmalloced; i++) {
882 shmsegs[i].shm_perm.mode = SHMSEG_FREE;
883 shmsegs[i].shm_perm.seq = 0;
882 shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
883 shmsegs[i].u.shm_perm.seq = 0;
884 }
885 shm_last_free = 0;
886 shm_nused = 0;
887 shm_committed = 0;
888 shmexit_hook = &shmexit_myhook;
889 shmfork_hook = &shmfork_myhook;
890}
891

--- 56 unchanged lines hidden ---
884 }
885 shm_last_free = 0;
886 shm_nused = 0;
887 shm_committed = 0;
888 shmexit_hook = &shmexit_myhook;
889 shmfork_hook = &shmfork_myhook;
890}
891

--- 56 unchanged lines hidden ---