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