|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */ ! 23: ! 24: /* ! 25: * Copyright (c) 1994 Adam Glass and Charles Hannum. All rights reserved. ! 26: * ! 27: * Redistribution and use in source and binary forms, with or without ! 28: * modification, are permitted provided that the following conditions ! 29: * are met: ! 30: * 1. Redistributions of source code must retain the above copyright ! 31: * notice, this list of conditions and the following disclaimer. ! 32: * 2. Redistributions in binary form must reproduce the above copyright ! 33: * notice, this list of conditions and the following disclaimer in the ! 34: * documentation and/or other materials provided with the distribution. ! 35: * 3. All advertising materials mentioning features or use of this software ! 36: * must display the following acknowledgement: ! 37: * This product includes software developed by Adam Glass and Charles ! 38: * Hannum. ! 39: * 4. The names of the authors may not be used to endorse or promote products ! 40: * derived from this software without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR ! 43: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ! 44: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ! 45: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, ! 46: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ! 47: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ! 48: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ! 49: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ! 50: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ! 51: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! 52: */ ! 53: ! 54: ! 55: #include <sys/param.h> ! 56: #include <sys/systm.h> ! 57: #include <sys/kernel.h> ! 58: #include <sys/shm.h> ! 59: #include <sys/proc.h> ! 60: #include <sys/malloc.h> ! 61: #include <sys/mman.h> ! 62: #include <sys/stat.h> ! 63: ! 64: #include <mach/mach_types.h> ! 65: #include <mach/vm_inherit.h> ! 66: #include <vm/vm_map.h> ! 67: ! 68: struct shmat_args; ! 69: extern int shmat __P((struct proc *p, struct shmat_args *uap, int *retval)); ! 70: struct shmctl_args; ! 71: extern int shmctl __P((struct proc *p, struct shmctl_args *uap, int *retval)); ! 72: struct shmdt_args; ! 73: extern int shmdt __P((struct proc *p, struct shmdt_args *uap, int *retval)); ! 74: struct shmget_args; ! 75: extern int shmget __P((struct proc *p, struct shmget_args *uap, int *retval)); ! 76: ! 77: #if 0 ! 78: static void shminit __P((void *)); ! 79: SYSINIT(sysv_shm, SI_SUB_SYSV_SHM, SI_ORDER_FIRST, shminit, NULL) ! 80: #endif 0 ! 81: ! 82: struct oshmctl_args; ! 83: static int oshmctl __P((struct proc *p, struct oshmctl_args *uap, int * retval)); ! 84: static int shmget_allocate_segment __P((struct proc *p, struct shmget_args *uap, int mode, int * retval)); ! 85: static int shmget_existing __P((struct proc *p, struct shmget_args *uap, int mode, int segnum, int * retval)); ! 86: ! 87: typedef int sy_call_t __P((struct proc *, void *, int *)); ! 88: ! 89: /* XXX casting to (sy_call_t *) is bogus, as usual. */ ! 90: static sy_call_t *shmcalls[] = { ! 91: (sy_call_t *)shmat, (sy_call_t *)oshmctl, ! 92: (sy_call_t *)shmdt, (sy_call_t *)shmget, ! 93: (sy_call_t *)shmctl ! 94: }; ! 95: ! 96: #define SHMSEG_FREE 0x0200 ! 97: #define SHMSEG_REMOVED 0x0400 ! 98: #define SHMSEG_ALLOCATED 0x0800 ! 99: #define SHMSEG_WANTED 0x1000 ! 100: ! 101: static int shm_last_free, shm_nused, shm_committed; ! 102: struct shmid_ds *shmsegs; ! 103: ! 104: struct shm_handle { ! 105: /* vm_offset_t kva; */ ! 106: void * shm_object; ! 107: }; ! 108: ! 109: struct shmmap_state { ! 110: vm_offset_t va; ! 111: int shmid; ! 112: }; ! 113: ! 114: static void shm_deallocate_segment __P((struct shmid_ds *)); ! 115: static int shm_find_segment_by_key __P((key_t)); ! 116: static struct shmid_ds *shm_find_segment_by_shmid __P((int)); ! 117: static int shm_delete_mapping __P((struct proc *, struct shmmap_state *)); ! 118: ! 119: static int ! 120: shm_find_segment_by_key(key) ! 121: key_t key; ! 122: { ! 123: int i; ! 124: ! 125: for (i = 0; i < shminfo.shmmni; i++) ! 126: if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) && ! 127: shmsegs[i].shm_perm.key == key) ! 128: return i; ! 129: return -1; ! 130: } ! 131: ! 132: static struct shmid_ds * ! 133: shm_find_segment_by_shmid(shmid) ! 134: int shmid; ! 135: { ! 136: int segnum; ! 137: struct shmid_ds *shmseg; ! 138: ! 139: segnum = IPCID_TO_IX(shmid); ! 140: if (segnum < 0 || segnum >= shminfo.shmmni) ! 141: return NULL; ! 142: shmseg = &shmsegs[segnum]; ! 143: if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED)) ! 144: != SHMSEG_ALLOCATED || ! 145: shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid)) ! 146: return NULL; ! 147: return shmseg; ! 148: } ! 149: ! 150: static void ! 151: shm_deallocate_segment(shmseg) ! 152: struct shmid_ds *shmseg; ! 153: { ! 154: struct shm_handle *shm_handle; ! 155: struct shmmap_state *shmmap_s=NULL; ! 156: size_t size; ! 157: char * ptr; ! 158: ! 159: shm_handle = shmseg->shm_internal; ! 160: size = round_page(shmseg->shm_segsz); ! 161: mach_destroy_memory_entry(shm_handle->shm_object); ! 162: FREE((caddr_t)shm_handle, M_SHM); ! 163: shmseg->shm_internal = NULL; ! 164: shm_committed -= btoc(size); ! 165: shm_nused--; ! 166: shmseg->shm_perm.mode = SHMSEG_FREE; ! 167: } ! 168: ! 169: static int ! 170: shm_delete_mapping(p, shmmap_s) ! 171: struct proc *p; ! 172: struct shmmap_state *shmmap_s; ! 173: { ! 174: struct shmid_ds *shmseg; ! 175: int segnum, result; ! 176: size_t size; ! 177: ! 178: segnum = IPCID_TO_IX(shmmap_s->shmid); ! 179: shmseg = &shmsegs[segnum]; ! 180: size = round_page(shmseg->shm_segsz); ! 181: result = vm_deallocate(current_map(), shmmap_s->va, size); ! 182: if (result != KERN_SUCCESS) ! 183: return EINVAL; ! 184: shmmap_s->shmid = -1; ! 185: shmseg->shm_dtime = time_second; ! 186: if ((--shmseg->shm_nattch <= 0) && ! 187: (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { ! 188: shm_deallocate_segment(shmseg); ! 189: shm_last_free = segnum; ! 190: } ! 191: return 0; ! 192: } ! 193: ! 194: struct shmdt_args { ! 195: void *shmaddr; ! 196: }; ! 197: ! 198: int ! 199: shmdt(p, uap, retval) ! 200: struct proc *p; ! 201: struct shmdt_args *uap; ! 202: register_t *retval; ! 203: { ! 204: struct shmmap_state *shmmap_s; ! 205: int i; ! 206: ! 207: shmmap_s = (struct shmmap_state *)p->vm_shm; ! 208: if (shmmap_s == NULL) ! 209: return EINVAL; ! 210: for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) ! 211: if (shmmap_s->shmid != -1 && ! 212: shmmap_s->va == (vm_offset_t)uap->shmaddr) ! 213: break; ! 214: if (i == shminfo.shmseg) ! 215: return EINVAL; ! 216: return shm_delete_mapping(p, shmmap_s); ! 217: } ! 218: ! 219: #ifndef _SYS_SYSPROTO_H_ ! 220: struct shmat_args { ! 221: int shmid; ! 222: void *shmaddr; ! 223: int shmflg; ! 224: }; ! 225: #endif ! 226: ! 227: int ! 228: shmat(p, uap, retval) ! 229: struct proc *p; ! 230: struct shmat_args *uap; ! 231: register_t *retval; ! 232: { ! 233: int error, i, flags; ! 234: struct ucred *cred = p->p_ucred; ! 235: struct shmid_ds *shmseg; ! 236: struct shmmap_state *shmmap_s = NULL; ! 237: struct shm_handle *shm_handle; ! 238: vm_offset_t attach_va; ! 239: vm_prot_t prot; ! 240: vm_size_t size; ! 241: kern_return_t rv; ! 242: ! 243: shmmap_s = (struct shmmap_state *)p->vm_shm; ! 244: if (shmmap_s == NULL) { ! 245: size = shminfo.shmseg * sizeof(struct shmmap_state); ! 246: shmmap_s = (struct shmmap_state *)_MALLOC(size, M_SHM, M_WAITOK); ! 247: for (i = 0; i < shminfo.shmseg; i++) ! 248: shmmap_s[i].shmid = -1; ! 249: p->vm_shm = (caddr_t)shmmap_s; ! 250: } ! 251: shmseg = shm_find_segment_by_shmid(uap->shmid); ! 252: if (shmseg == NULL) ! 253: return EINVAL; ! 254: error = ipcperm(cred, &shmseg->shm_perm, ! 255: (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); ! 256: if (error) ! 257: return error; ! 258: for (i = 0; i < shminfo.shmseg; i++) { ! 259: if (shmmap_s->shmid == -1) ! 260: break; ! 261: shmmap_s++; ! 262: } ! 263: if (i >= shminfo.shmseg) ! 264: return EMFILE; ! 265: size = round_page(shmseg->shm_segsz); ! 266: prot = VM_PROT_READ; ! 267: if ((uap->shmflg & SHM_RDONLY) == 0) ! 268: prot |= VM_PROT_WRITE; ! 269: flags = MAP_ANON | MAP_SHARED; ! 270: if (uap->shmaddr) { ! 271: flags |= MAP_FIXED; ! 272: if (uap->shmflg & SHM_RND) ! 273: attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1); ! 274: else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0) ! 275: attach_va = (vm_offset_t)uap->shmaddr; ! 276: else ! 277: return EINVAL; ! 278: } else { ! 279: attach_va = round_page(uap->shmaddr); ! 280: } ! 281: ! 282: shm_handle = shmseg->shm_internal; ! 283: rv = vm_map(current_map(), &attach_va, size, 0, (flags & MAP_FIXED)? FALSE: TRUE, ! 284: shm_handle->shm_object, 0, FALSE, prot, prot, VM_INHERIT_DEFAULT); ! 285: if (rv != KERN_SUCCESS) ! 286: goto out; ! 287: rv = vm_inherit(current_map(), attach_va, size, ! 288: VM_INHERIT_SHARE); ! 289: if (rv != KERN_SUCCESS) { ! 290: (void) vm_deallocate(current_map(), attach_va, size); ! 291: goto out; ! 292: } ! 293: ! 294: shmmap_s->va = attach_va; ! 295: shmmap_s->shmid = uap->shmid; ! 296: shmseg->shm_lpid = p->p_pid; ! 297: shmseg->shm_atime = time_second; ! 298: shmseg->shm_nattch++; ! 299: *retval = attach_va; ! 300: return( 0); ! 301: out: ! 302: switch (rv) { ! 303: case KERN_INVALID_ADDRESS: ! 304: case KERN_NO_SPACE: ! 305: return (ENOMEM); ! 306: case KERN_PROTECTION_FAILURE: ! 307: return (EACCES); ! 308: default: ! 309: return (EINVAL); ! 310: } ! 311: ! 312: } ! 313: ! 314: struct oshmid_ds { ! 315: struct ipc_perm shm_perm; /* operation perms */ ! 316: int shm_segsz; /* size of segment (bytes) */ ! 317: ushort shm_cpid; /* pid, creator */ ! 318: ushort shm_lpid; /* pid, last operation */ ! 319: short shm_nattch; /* no. of current attaches */ ! 320: time_t shm_atime; /* last attach time */ ! 321: time_t shm_dtime; /* last detach time */ ! 322: time_t shm_ctime; /* last change time */ ! 323: void *shm_handle; /* internal handle for shm segment */ ! 324: }; ! 325: ! 326: struct oshmctl_args { ! 327: int shmid; ! 328: int cmd; ! 329: struct oshmid_ds *ubuf; ! 330: }; ! 331: ! 332: static int ! 333: oshmctl(p, uap, retval) ! 334: struct proc *p; ! 335: struct oshmctl_args *uap; ! 336: register_t *retval; ! 337: { ! 338: #ifdef COMPAT_43 ! 339: int error; ! 340: struct ucred *cred = p->p_ucred; ! 341: struct shmid_ds *shmseg; ! 342: struct oshmid_ds outbuf; ! 343: ! 344: shmseg = shm_find_segment_by_shmid(uap->shmid); ! 345: if (shmseg == NULL) ! 346: return EINVAL; ! 347: switch (uap->cmd) { ! 348: case IPC_STAT: ! 349: error = ipcperm(cred, &shmseg->shm_perm, IPC_R); ! 350: if (error) ! 351: return error; ! 352: outbuf.shm_perm = shmseg->shm_perm; ! 353: outbuf.shm_segsz = shmseg->shm_segsz; ! 354: outbuf.shm_cpid = shmseg->shm_cpid; ! 355: outbuf.shm_lpid = shmseg->shm_lpid; ! 356: outbuf.shm_nattch = shmseg->shm_nattch; ! 357: outbuf.shm_atime = shmseg->shm_atime; ! 358: outbuf.shm_dtime = shmseg->shm_dtime; ! 359: outbuf.shm_ctime = shmseg->shm_ctime; ! 360: outbuf.shm_handle = shmseg->shm_internal; ! 361: error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf)); ! 362: if (error) ! 363: return error; ! 364: break; ! 365: default: ! 366: /* XXX casting to (sy_call_t *) is bogus, as usual. */ ! 367: return ((sy_call_t *)shmctl)(p, uap, retval); ! 368: } ! 369: return 0; ! 370: #else ! 371: return EINVAL; ! 372: #endif ! 373: } ! 374: ! 375: #ifndef _SYS_SYSPROTO_H_ ! 376: struct shmctl_args { ! 377: int shmid; ! 378: int cmd; ! 379: struct shmid_ds *buf; ! 380: }; ! 381: #endif ! 382: ! 383: int ! 384: shmctl(p, uap, retval) ! 385: struct proc *p; ! 386: struct shmctl_args *uap; ! 387: register_t *retval; ! 388: { ! 389: int error; ! 390: struct ucred *cred = p->p_ucred; ! 391: struct shmid_ds inbuf; ! 392: struct shmid_ds *shmseg; ! 393: ! 394: shmseg = shm_find_segment_by_shmid(uap->shmid); ! 395: if (shmseg == NULL) ! 396: return EINVAL; ! 397: switch (uap->cmd) { ! 398: case IPC_STAT: ! 399: error = ipcperm(cred, &shmseg->shm_perm, IPC_R); ! 400: if (error) ! 401: return error; ! 402: error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf)); ! 403: if (error) ! 404: return error; ! 405: break; ! 406: case IPC_SET: ! 407: error = ipcperm(cred, &shmseg->shm_perm, IPC_M); ! 408: if (error) ! 409: return error; ! 410: error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf)); ! 411: if (error) ! 412: return error; ! 413: shmseg->shm_perm.uid = inbuf.shm_perm.uid; ! 414: shmseg->shm_perm.gid = inbuf.shm_perm.gid; ! 415: shmseg->shm_perm.mode = ! 416: (shmseg->shm_perm.mode & ~ACCESSPERMS) | ! 417: (inbuf.shm_perm.mode & ACCESSPERMS); ! 418: shmseg->shm_ctime = time_second; ! 419: break; ! 420: case IPC_RMID: ! 421: error = ipcperm(cred, &shmseg->shm_perm, IPC_M); ! 422: if (error) ! 423: return error; ! 424: shmseg->shm_perm.key = IPC_PRIVATE; ! 425: shmseg->shm_perm.mode |= SHMSEG_REMOVED; ! 426: if (shmseg->shm_nattch <= 0) { ! 427: shm_deallocate_segment(shmseg); ! 428: shm_last_free = IPCID_TO_IX(uap->shmid); ! 429: } ! 430: break; ! 431: #if 0 ! 432: case SHM_LOCK: ! 433: case SHM_UNLOCK: ! 434: #endif ! 435: default: ! 436: return EINVAL; ! 437: } ! 438: return 0; ! 439: } ! 440: ! 441: #ifndef _SYS_SYSPROTO_H_ ! 442: struct shmget_args { ! 443: key_t key; ! 444: size_t size; ! 445: int shmflg; ! 446: }; ! 447: #endif ! 448: ! 449: static int ! 450: shmget_existing(p, uap, mode, segnum, retval) ! 451: struct proc *p; ! 452: struct shmget_args *uap; ! 453: int mode; ! 454: int segnum; ! 455: int *retval; ! 456: { ! 457: struct shmid_ds *shmseg; ! 458: struct ucred *cred = p->p_ucred; ! 459: int error; ! 460: ! 461: shmseg = &shmsegs[segnum]; ! 462: if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { ! 463: /* ! 464: * This segment is in the process of being allocated. Wait ! 465: * until it's done, and look the key up again (in case the ! 466: * allocation failed or it was freed). ! 467: */ ! 468: shmseg->shm_perm.mode |= SHMSEG_WANTED; ! 469: error = tsleep((caddr_t)shmseg, PLOCK | PCATCH, "shmget", 0); ! 470: if (error) ! 471: return error; ! 472: return EAGAIN; ! 473: } ! 474: error = ipcperm(cred, &shmseg->shm_perm, mode); ! 475: if (error) ! 476: return error; ! 477: if (uap->size && uap->size > shmseg->shm_segsz) ! 478: return EINVAL; ! 479: if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) ! 480: return EEXIST; ! 481: *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); ! 482: return 0; ! 483: } ! 484: ! 485: static int ! 486: shmget_allocate_segment(p, uap, mode, retval) ! 487: struct proc *p; ! 488: struct shmget_args *uap; ! 489: int mode; ! 490: int * retval; ! 491: { ! 492: int i, segnum, shmid, size; ! 493: struct ucred *cred = p->p_ucred; ! 494: struct shmid_ds *shmseg; ! 495: struct shm_handle *shm_handle; ! 496: kern_return_t kret; ! 497: vm_offset_t user_addr; ! 498: void * mem_object; ! 499: ! 500: if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax) ! 501: return EINVAL; ! 502: if (shm_nused >= shminfo.shmmni) /* any shmids left? */ ! 503: return ENOSPC; ! 504: size = round_page(uap->size); ! 505: if (shm_committed + btoc(size) > shminfo.shmall) ! 506: return ENOMEM; ! 507: if (shm_last_free < 0) { ! 508: for (i = 0; i < shminfo.shmmni; i++) ! 509: if (shmsegs[i].shm_perm.mode & SHMSEG_FREE) ! 510: break; ! 511: if (i == shminfo.shmmni) ! 512: panic("shmseg free count inconsistent"); ! 513: segnum = i; ! 514: } else { ! 515: segnum = shm_last_free; ! 516: shm_last_free = -1; ! 517: } ! 518: shmseg = &shmsegs[segnum]; ! 519: /* ! 520: * In case we sleep in malloc(), mark the segment present but deleted ! 521: * so that noone else tries to create the same key. ! 522: */ ! 523: kret = vm_allocate(current_map(), &user_addr, size, TRUE); ! 524: if (kret != KERN_SUCCESS) ! 525: goto out; ! 526: ! 527: kret = mach_make_memory_entry (current_map(), &size, ! 528: user_addr, VM_PROT_DEFAULT, &mem_object, 0); ! 529: ! 530: if (kret != KERN_SUCCESS) ! 531: goto out; ! 532: shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; ! 533: shmseg->shm_perm.key = uap->key; ! 534: shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff; ! 535: shm_handle = (struct shm_handle *) ! 536: _MALLOC(sizeof(struct shm_handle), M_SHM, M_WAITOK); ! 537: shm_handle->shm_object = mem_object; ! 538: shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); ! 539: ! 540: shmseg->shm_internal = shm_handle; ! 541: shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid; ! 542: shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid; ! 543: shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) | ! 544: (mode & ACCESSPERMS) | SHMSEG_ALLOCATED; ! 545: shmseg->shm_segsz = uap->size; ! 546: shmseg->shm_cpid = p->p_pid; ! 547: shmseg->shm_lpid = shmseg->shm_nattch = 0; ! 548: shmseg->shm_atime = shmseg->shm_dtime = 0; ! 549: shmseg->shm_ctime = time_second; ! 550: shm_committed += btoc(size); ! 551: shm_nused++; ! 552: if (shmseg->shm_perm.mode & SHMSEG_WANTED) { ! 553: /* ! 554: * Somebody else wanted this key while we were asleep. Wake ! 555: * them up now. ! 556: */ ! 557: shmseg->shm_perm.mode &= ~SHMSEG_WANTED; ! 558: wakeup((caddr_t)shmseg); ! 559: } ! 560: *retval = shmid; ! 561: return 0; ! 562: out: ! 563: switch (kret) { ! 564: case KERN_INVALID_ADDRESS: ! 565: case KERN_NO_SPACE: ! 566: return (ENOMEM); ! 567: case KERN_PROTECTION_FAILURE: ! 568: return (EACCES); ! 569: default: ! 570: return (EINVAL); ! 571: } ! 572: ! 573: } ! 574: ! 575: int ! 576: shmget(p, uap, retval) ! 577: struct proc *p; ! 578: struct shmget_args *uap; ! 579: register_t *retval; ! 580: { ! 581: int segnum, mode, error; ! 582: ! 583: mode = uap->shmflg & ACCESSPERMS; ! 584: if (uap->key != IPC_PRIVATE) { ! 585: again: ! 586: segnum = shm_find_segment_by_key(uap->key); ! 587: if (segnum >= 0) { ! 588: error = shmget_existing(p, uap, mode, segnum, retval); ! 589: if (error == EAGAIN) ! 590: goto again; ! 591: return(error); ! 592: } ! 593: if ((uap->shmflg & IPC_CREAT) == 0) ! 594: return ENOENT; ! 595: } ! 596: return( shmget_allocate_segment(p, uap, mode, retval));; ! 597: /*NOTREACHED*/ ! 598: ! 599: } ! 600: ! 601: struct shmsys_args { ! 602: u_int which; ! 603: int a2; ! 604: int a3; ! 605: int a4; ! 606: }; ! 607: int ! 608: shmsys(p, uap, retval) ! 609: struct proc *p; ! 610: /* XXX actually varargs. */ ! 611: struct shmsys_args *uap; ! 612: register_t *retval; ! 613: { ! 614: ! 615: if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) ! 616: return EINVAL; ! 617: return ((*shmcalls[uap->which])(p, &uap->a2, retval)); ! 618: } ! 619: ! 620: void ! 621: shmfork(p1, p2) ! 622: struct proc *p1, *p2; ! 623: { ! 624: struct shmmap_state *shmmap_s; ! 625: size_t size; ! 626: int i; ! 627: ! 628: size = shminfo.shmseg * sizeof(struct shmmap_state); ! 629: shmmap_s = (struct shmmap_state *)_MALLOC(size, M_SHM, M_WAITOK); ! 630: bcopy((caddr_t)p1->vm_shm, (caddr_t)shmmap_s, size); ! 631: p2->vm_shm = (caddr_t)shmmap_s; ! 632: for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) ! 633: if (shmmap_s->shmid != -1) ! 634: shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++; ! 635: } ! 636: ! 637: void ! 638: shmexit(p) ! 639: struct proc *p; ! 640: { ! 641: struct shmmap_state *shmmap_s; ! 642: int i; ! 643: ! 644: shmmap_s = (struct shmmap_state *)p->vm_shm; ! 645: for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) ! 646: if (shmmap_s->shmid != -1) ! 647: shm_delete_mapping(p, shmmap_s); ! 648: FREE((caddr_t)p->vm_shm, M_SHM); ! 649: p->vm_shm = NULL; ! 650: } ! 651: ! 652: void ! 653: shminit(dummy) ! 654: void *dummy; ! 655: { ! 656: int i; ! 657: int s; ! 658: ! 659: s = sizeof(struct shmid_ds) * shminfo.shmmni; ! 660: ! 661: MALLOC(shmsegs, struct shmid_ds *, s, ! 662: M_SHM, M_WAITOK); ! 663: for (i = 0; i < shminfo.shmmni; i++) { ! 664: shmsegs[i].shm_perm.mode = SHMSEG_FREE; ! 665: shmsegs[i].shm_perm.seq = 0; ! 666: } ! 667: shm_last_free = 0; ! 668: shm_nused = 0; ! 669: shm_committed = 0; ! 670: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.