1 #if HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 /** @file
6 *
7 * $Header: /tmp/hpctools/ga/tcgmsg/ipcv5.0/shmem.c,v 1.4 2002-01-24 22:07:27 d3h325 Exp $
8 *
9 * This stuff attempts to provide a simple interface to temporary shared
10 * memory regions, loosely modelled after that of Alliant Concentrix 5.0
11 *
12 *
13 * Note that the input arguments switch between integers and pointers
14 * to integers depending on if they are modified on return.
15 *
16 *
17 * Create a shared region of at least size bytes, returning the actual size,
18 * the id associated with the region. The return value is a pointer to the
19 * the region. Any error is a hard fail.
20 *
21 * (char *) CreateSharedRegion((long *) id, (long *) size)
22 *
23 *
24 * Detach a process from a shared memory region. 0 is returned on success,
25 * -1 for failure. id, size, and addr must match exactly those items returned
26 * from CreateSharedRegion
27 *
28 * long DetachSharedRegion((long) id, (long) size, (char *) addr)
29 *
30 *
31 * Delete a shared region from the system. This has to be done on the SUN
32 * to remove it from the system. On the Alliant the shared region disappears
33 * when the last process dies or detaches. Returns 0 on success, -1 on error.
34 *
35 * long DeleteSharedRegion((long) id)
36 *
37 *
38 * Delete all the shared regions associated with this process.
39 *
40 * long DeleteSharedAll()
41 *
42 *
43 * Attach to a shared memory region of known id and size. Returns the
44 * address of the mapped memory. Size must exactly match the size returned
45 * from CreateSharedRegion (which in turn is the requested size rounded
46 * up to a multiple of 4096). Any error is a hard fail.
47 *
48 * (char *) AttachSharedRegion((long) id, (long) size))
49 */
50
51 extern void Error(const char *, long);
52
53 #if !defined(MMAP) || defined(MACX)
54
55 #if HAVE_STDIO_H
56 # include <stdio.h>
57 #endif
58 #if HAVE_SYS_TYPES_H
59 # include <sys/types.h>
60 #endif
61 #if HAVE_SYS_IPC_H
62 # include <sys/ipc.h>
63 #endif
64 #if HAVE_SYS_SHM_H
65 # include <sys/shm.h>
66 #endif
67
68 #ifdef SUN
69 extern int shmget(key_t, int, int);
70 extern int shmdt(void *);
71 extern int shmctl(int, int, struct shmid_ds *);
72 extern void *shmat(int, const void *, int);
73 #endif
74
75
CreateSharedRegion(long * id,long * size)76 char *CreateSharedRegion(long *id, long *size)
77 {
78 char *temp;
79
80 /* Create the region */
81
82 if ( (*id = shmget(IPC_PRIVATE, (int) *size,
83 (int) (IPC_CREAT | 00600))) < 0 )
84 Error("CreateSharedRegion: failed to create shared region", (long) *id);
85
86 /* Attach to the region */
87
88 if ( (long) (temp = shmat((int) *id, (char *) NULL, 0)) == -1L)
89 Error("CreateSharedRegion: failed to attach to shared region", 0L);
90
91 return temp;
92 }
93
94
DetachSharedRegion(long id,long size,char * addr)95 long DetachSharedRegion(long id, long size, char *addr)
96 {
97 return shmdt(addr);
98 }
99
100
DeleteSharedRegion(long id)101 long DeleteSharedRegion(long id)
102 {
103 return shmctl((int) id, IPC_RMID, (struct shmid_ds *) NULL);
104 }
105
106
AttachSharedRegion(long id,long size)107 char *AttachSharedRegion(long id, long size)
108 {
109 char *temp;
110
111 if ( (long) (temp = shmat((int) id, (char *) NULL, 0)) == -1L)
112 Error("AttachSharedRegion: failed to attach to shared region", 0L);
113
114 return temp;
115 }
116
117 #else /* MMAP */
118
119 #if HAVE_STDIO_H
120 # include <stdio.h>
121 #endif
122 #if HAVE_SYS_TIME_H
123 # include <sys/time.h>
124 #endif
125 #if HAVE_SYS_TYPES_H
126 # include <sys/types.h>
127 #endif
128 #if HAVE_SYS_FILE_H
129 # include <sys/file.h>
130 #endif
131 #if HAVE_SYS_MMAN_H
132 # include <sys/mman.h>
133 #endif
134
135 extern char *strdup();
136 extern char *mktemp();
137
138 #define MAX_ID 20
139 static struct id_list_struct {
140 char *addr; /* pointer to shmem region */
141 unsigned size; /* size of region */
142 char *filename; /* associated file name */
143 int fd; /* file descriptor */
144 int status; /* = 1 if in use */
145 } id_list[MAX_ID];
146
147 static int next_id = 0;
148 static char template[] = "/tmp/SHMEM.XXXXXX";
149
CreateSharedRegion(id,size)150 char *CreateSharedRegion(id, size)
151 long *size, *id;
152 {
153 char *temp;
154
155 if (next_id == MAX_ID)
156 Error("CreateSharedRegion: MAX_ID exceeded ", MAX_ID);
157 *id = next_id;
158
159 if ( (temp = strdup(template)) == (char *) NULL)
160 Error("CreateSharedRegion: failed to get space for filename", 0);
161
162 /* Generate scratch file to identify region ... need to know this
163 name to attach to the region so need to establish some policy
164 before AttachtoSharedRegion can work */
165
166 id_list[*id].filename = mktemp(temp);
167 if ( (id_list[*id].fd = open(id_list[*id].filename,
168 O_RDWR|O_CREAT, 0666)) < 0)
169 Error("CreateSharedRegion: failed to open temporary file",0);
170
171 id_list[*id].addr = mmap((caddr_t) 0, (size_t)*size,
172 PROT_READ|PROT_WRITE,
173 MAP_ANON|MAP_SHARED, id_list[*id].fd, 0);
174 if (id_list[*id].addr == (char *) -1)
175 Error("CreateSharedRegion: mmap failed",-1);
176
177 id_list[*id].size = *size;
178 id_list[*id].status = 1;
179
180 next_id++;
181 return id_list[*id].addr;
182 }
183
184
DetachSharedRegion(long id,long size,char * addr)185 long DetachSharedRegion(long id, long size, char *addr)
186 {
187 if ( (id < 0) || (id > next_id))
188 return (long) -1;
189
190 if (id_list[id].status != 1)
191 return (long) -1;
192
193 id_list[id].status = 0;
194
195 return (long) munmap(id_list[id].addr, 0);
196 }
197
198
DeleteSharedRegion(long id)199 long DeleteSharedRegion(long id)
200 {
201 if ( (id < 0) || (id > next_id) )
202 return (long) -1;
203
204 if (id_list[id].status != 1)
205 return (long) -1;
206
207 (void) DetachSharedRegion(id, 0, (char *) 0);
208
209 if (id_list[id].fd >= 0) {
210 (void) close(id_list[id].fd);
211 (void) unlink(id_list[id].filename);
212 }
213
214 return (long) 0;
215 }
216
217
AttachSharedRegion(long id,long size)218 char *AttachSharedRegion(long id, long size)
219 {
220 Error("AttachSharedRegion: need mods for this to work on CONVEX",
221 (long) -1);
222 }
223
224
DeleteSharedAll()225 long DeleteSharedAll()
226 {
227 long id;
228 long status = 0;
229
230 for (id=0; id<next_id; id++)
231 if (id_list[id].status == 1)
232 status += DeleteSharedRegion(id);
233
234 if (status)
235 return (long) -1;
236 else
237 return (long) 0;
238 }
239
240 #endif /* MMAP */
241