1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma weak _shmat = shmat 31 #pragma weak _shmctl = shmctl 32 #pragma weak _shmctl64 = shmctl64 33 #pragma weak _shmdt = shmdt 34 #pragma weak _shmget = shmget 35 #pragma weak _shmids = shmids 36 37 #include "lint.h" 38 #include "thr_uberdata.h" 39 #include <sys/types.h> 40 #include <sys/ipc.h> 41 #include <sys/ipc_impl.h> 42 #include <sys/shm.h> 43 #include <sys/shm_impl.h> 44 #include <sys/syscall.h> 45 #include <errno.h> 46 47 /* 48 * List of all shared memory segments. 49 * We need this to keep track of the sizes so that we can unregister 50 * any robust locks that are contained in a segment that is detached. 51 */ 52 static struct shm_size { 53 void *shm_addr; 54 size_t shm_size; 55 struct shm_size *shm_next; 56 } *shm_list = NULL; 57 58 static mutex_t shm_lock = DEFAULTMUTEX; /* protects shm_list */ 59 60 extern void unregister_locks(caddr_t, size_t); 61 62 /* 63 * Add a shared memory address and size to the remembered list. 64 */ 65 static void 66 add_shm_size(void *addr, size_t size) 67 { 68 struct shm_size **list; 69 struct shm_size *elem; 70 71 lmutex_lock(&shm_lock); 72 73 for (list = &shm_list; (elem = *list) != NULL; list = &elem->shm_next) { 74 if (elem->shm_addr == addr) { /* won't happen? */ 75 elem->shm_size = size; 76 lmutex_unlock(&shm_lock); 77 return; 78 } 79 } 80 elem = lmalloc(sizeof (*elem)); 81 elem->shm_addr = addr; 82 elem->shm_size = size; 83 elem->shm_next = NULL; 84 *list = elem; 85 86 lmutex_unlock(&shm_lock); 87 } 88 89 /* 90 * Delete the shared memory address from the remembered list 91 * and unregister all of the robust locks contained therein. 92 */ 93 static void 94 delete_shm_size(void *addr) 95 { 96 struct shm_size **list; 97 struct shm_size *elem; 98 size_t size = 0; 99 100 lmutex_lock(&shm_lock); 101 102 for (list = &shm_list; (elem = *list) != NULL; list = &elem->shm_next) { 103 if (elem->shm_addr == addr) { 104 size = elem->shm_size; 105 *list = elem->shm_next; 106 lfree(elem, sizeof (*elem)); 107 break; 108 } 109 } 110 111 lmutex_unlock(&shm_lock); 112 113 if (size != 0) 114 unregister_locks(addr, size); 115 } 116 117 void * 118 shmat(int shmid, const void *shmaddr, int shmflg) 119 { 120 sysret_t rval; 121 int error; 122 void *addr; 123 struct shmid_ds shmds; 124 125 error = __systemcall(&rval, SYS_shmsys, SHMAT, shmid, shmaddr, shmflg); 126 addr = (void *)rval.sys_rval1; 127 if (error) { 128 (void) __set_errno(error); 129 } else if (shmctl(shmid, IPC_STAT, &shmds) == 0) { 130 add_shm_size(addr, shmds.shm_segsz); 131 } 132 return (addr); 133 } 134 135 int 136 shmctl(int shmid, int cmd, struct shmid_ds *buf) 137 { 138 if (cmd == IPC_SET64 || cmd == IPC_STAT64) { 139 (void) __set_errno(EINVAL); 140 return (-1); 141 } 142 return (syscall(SYS_shmsys, SHMCTL, shmid, cmd, buf)); 143 } 144 145 int 146 shmctl64(int shmid, int cmd, struct shmid_ds64 *buf) 147 { 148 if (cmd != IPC_SET64 && cmd != IPC_STAT64) { 149 (void) __set_errno(EINVAL); 150 return (-1); 151 } 152 return (syscall(SYS_shmsys, SHMCTL, shmid, cmd, buf)); 153 } 154 155 int 156 shmdt(char *shmaddr) 157 { 158 int rval = syscall(SYS_shmsys, SHMDT, shmaddr); 159 if (rval == 0) 160 delete_shm_size(shmaddr); 161 return (rval); 162 } 163 164 int 165 shmget(key_t key, size_t size, int shmflg) 166 { 167 return (syscall(SYS_shmsys, SHMGET, key, size, shmflg)); 168 } 169 170 int 171 shmids(int *buf, uint_t nids, uint_t *pnids) 172 { 173 return (syscall(SYS_shmsys, SHMIDS, buf, nids, pnids)); 174 } 175