xref: /titanic_50/usr/src/lib/libc/port/sys/shmsys.c (revision 09ce0d4acf1a79c720d7e54b60e87cbfa0f1b2d6)
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