1 /* ====================================================================
2 * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by
19 * Ralf S. Engelschall <rse@engelschall.com>."
20 *
21 * 4. Redistributions of any form whatsoever must retain the following
22 * acknowledgment:
23 * "This product includes software developed by
24 * Ralf S. Engelschall <rse@engelschall.com>."
25 *
26 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
27 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
30 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37 * OF THE POSSIBILITY OF SUCH DAMAGE.
38 * ====================================================================
39 */
40
41 /*
42 **
43 ** mm_core.c -- Low-level Shared Memory API
44 **
45 */
46
47 #define MM_PRIVATE
48 #include "mm.h"
49
50 /*
51 * Some global variables
52 */
53
54 #if defined(MM_SEMT_FCNTL)
55 /* lock/unlock structures for fcntl() */
56 static struct flock mm_core_dolock_rd;
57 static struct flock mm_core_dolock_rw;
58 static struct flock mm_core_dounlock;
59 #endif
60
61 #if defined(MM_SEMT_IPCSEM)
62 /* lock/unlock structures for semop() */
63 static union semun mm_core_semctlarg;
64 static struct sembuf mm_core_dolock[2];
65 static struct sembuf mm_core_dounlock[1];
66 #endif
67
68 #if defined(MM_SHMT_MMFILE) || defined(MM_SHMT_MMPOSX)
69 static size_t mm_core_mapoffset = 0; /* we use own file */
70 #elif defined(MM_SHMT_MMZERO)
71 static size_t mm_core_mapoffset = 1024*1024*1; /* we share with other apps */
72 #endif
73
mm_core_init(void)74 static void mm_core_init(void)
75 {
76 static int initialized = FALSE;
77 if (!initialized) {
78 #if defined(MM_SEMT_FCNTL)
79 mm_core_dolock_rd.l_whence = SEEK_SET; /* from current point */
80 mm_core_dolock_rd.l_start = 0; /* -"- */
81 mm_core_dolock_rd.l_len = 0; /* until end of file */
82 mm_core_dolock_rd.l_type = F_RDLCK; /* set shard/read lock */
83 mm_core_dolock_rd.l_pid = 0; /* pid not actually interesting */
84 mm_core_dolock_rw.l_whence = SEEK_SET; /* from current point */
85 mm_core_dolock_rw.l_start = 0; /* -"- */
86 mm_core_dolock_rw.l_len = 0; /* until end of file */
87 mm_core_dolock_rw.l_type = F_WRLCK; /* set exclusive/read-write lock */
88 mm_core_dolock_rw.l_pid = 0; /* pid not actually interesting */
89 mm_core_dounlock.l_whence = SEEK_SET; /* from current point */
90 mm_core_dounlock.l_start = 0; /* -"- */
91 mm_core_dounlock.l_len = 0; /* until end of file */
92 mm_core_dounlock.l_type = F_UNLCK; /* unlock */
93 mm_core_dounlock.l_pid = 0; /* pid not actually interesting */
94 #endif
95 #if defined(MM_SEMT_IPCSEM)
96 mm_core_dolock[0].sem_num = 0;
97 mm_core_dolock[0].sem_op = 0;
98 mm_core_dolock[0].sem_flg = 0;
99 mm_core_dolock[1].sem_num = 0;
100 mm_core_dolock[1].sem_op = 1;
101 mm_core_dolock[1].sem_flg = SEM_UNDO;
102 mm_core_dounlock[0].sem_num = 0;
103 mm_core_dounlock[0].sem_op = -1;
104 mm_core_dounlock[0].sem_flg = SEM_UNDO;
105 #endif
106 initialized = TRUE;
107 }
108 return;
109 }
110
111 #if defined(MM_SEMT_FLOCK)
112 /*
113 * Determine per-process fd for semaphore
114 * (needed only for flock() based semaphore)
115 */
mm_core_getfdsem(mem_core * mc)116 static int mm_core_getfdsem(mem_core *mc)
117 {
118 int fd = -1;
119 pid_t pid;
120 int i;
121
122 pid = getpid();
123 for (i = 0; i < MM_MAXCHILD &&
124 mc->mc_fdsem[i].pid != 0 &&
125 mc->mc_fdsem[i].fd != -1; i++) {
126 if (mc->mc_fdsem[i].pid == pid) {
127 fd = mc->mc_fdsem[i].fd;
128 break;
129 }
130 }
131 if (fd == -1 && i < MM_MAXCHILD) {
132 fd = open(mc->mc_fnsem, O_WRONLY, MM_CORE_FILEMODE);
133 mc->mc_fdsem[i].pid = getpid();
134 mc->mc_fdsem[i].fd = fd;
135 }
136 return fd;
137 }
138 #endif /* MM_SEMT_FLOCK */
139
140 /*
141 * Determine memory page size of OS
142 */
143
mm_core_pagesize(void)144 static size_t mm_core_pagesize(void)
145 {
146 static int pagesize = 0;
147 if (pagesize == 0)
148 #if defined(MM_VMPS_GETPAGESIZE)
149 pagesize = getpagesize();
150 #elif defined(MM_VMPS_SYSCONF)
151 pagesize = sysconf(_SC_PAGESIZE);
152 #elif defined(MM_VMPS_BEOS)
153 pagesize = B_PAGE_SIZE;
154 #else
155 pagesize = MM_CORE_DEFAULT_PAGESIZE;
156 #endif
157 return pagesize;
158 }
159
160 /*
161 * Align a size to the next page or word boundary
162 */
163
mm_core_align2page(size_t size)164 size_t mm_core_align2page(size_t size)
165 {
166 int psize = mm_core_pagesize();
167 return ((size)%(psize) > 0 ? ((size)/(psize)+1)*(psize) : (size));
168 }
169
mm_core_align2word(size_t size)170 size_t mm_core_align2word(size_t size)
171 {
172 return ((1+((size-1) / SIZEOF_mem_word)) * SIZEOF_mem_word);
173 }
174
mm_core_maxsegsize(void)175 size_t mm_core_maxsegsize(void)
176 {
177 return mm_core_align2page((MM_SHM_MAXSEGSIZE-SIZEOF_mem_core)-mm_core_pagesize());
178 }
179
180 #if defined(MM_SHMT_IPCSHM) || defined(MM_SEMT_IPCSEM)
181 /*
182 * will return either a normal key value or IPC_PRIVATE
183 * used for attaching to existing shared memorys
184 */
__mm_get_key_value(const char * file,char suffix)185 static key_t __mm_get_key_value ( const char *file, char suffix )
186 {
187 key_t key;
188 key = ftok(file, suffix);
189
190 if ( key < 0 ) return IPC_PRIVATE;
191 else return key;
192 }
193 #endif
194
195 /*
196 * Create a shared memory area
197 *
198 * *initialize = 1 - the allocated memory will be initialized on ANY case
199 * *initialize = 0 - the allocated memory will NOT be initialized
200 */
201
mm_core_create(size_t usersize,const char * file,int * initialize)202 void *mm_core_create(size_t usersize, const char *file, int *initialize)
203 {
204 mem_core *mc;
205 void *area = ((void *)-1);
206 int fdmem = 0;
207 int fdsem = 0;
208 #if defined(MM_SEMT_IPCSEM)
209 int fdsem_rd = 0;
210 #endif
211 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
212 char *fnmem;
213 #endif
214 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
215 char *fnsem;
216 #endif
217 size_t size;
218 #if defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
219 int zero = 0;
220 #endif
221 #if defined(MM_SHMT_IPCSHM)
222 struct shmid_ds shmbuf;
223 key_t key = -1;
224 #endif
225 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
226 char shmfilename[MM_MAXPATH];
227 #endif
228 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
229 char semfilename[MM_MAXPATH];
230 #endif
231 #if defined(MM_SHMT_BEOS)
232 area_id temparea;
233 #endif
234 char filename[MM_MAXPATH];
235
236 if ( initialize != NULL )
237 *initialize = 1;
238
239 if (usersize <= 0 || usersize > mm_core_maxsegsize()) {
240 errno = EINVAL;
241 return NULL;
242 }
243 if (file == NULL) {
244 sprintf(filename, MM_CORE_DEFAULT_FILE, (int)getpid());
245 file = filename;
246 }
247
248 mm_core_init();
249 size = mm_core_align2page(usersize+SIZEOF_mem_core);
250
251 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
252 sprintf(shmfilename, "%s.mem", file);
253 fnmem = shmfilename;
254 #endif
255 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
256 sprintf(semfilename, "%s.sem", file);
257 fnsem = semfilename;
258 #endif
259
260 #if defined(MM_SHMT_MMANON)
261 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
262 MAP_ANON|MAP_SHARED, -1, 0)) == (void *)MAP_FAILED)
263 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map anonymous area");
264 #endif /* MM_SHMT_MMANON */
265
266 #if defined(MM_SHMT_BEOS)
267 if ((temparea = create_area("mm", (void*)&area, B_ANY_ADDRESS,
268 size, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA)) < 0)
269 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to create the memory area");
270 #endif /* MM_SHMT_BEOS */
271
272 #if defined(MM_SHMT_MMPOSX)
273 shm_unlink(fnmem); /* Ok when it fails */
274 if ((fdmem = shm_open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
275 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open tempfile");
276 if (ftruncate(fdmem, mm_core_mapoffset+size) == -1)
277 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate tempfile");
278 write(fdmem, &zero, sizeof(zero));
279 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
280 MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
281 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map tempfile");
282 shm_unlink(fnmem);
283 mm_core_mapoffset += size;
284 #endif /* MM_SHMT_MMPOSX */
285
286 #if defined(MM_SHMT_MMZERO)
287 if ((fdmem = open("/dev/zero", O_RDWR, MM_CORE_FILEMODE)) == -1)
288 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open /dev/zero");
289 if (lseek(fdmem, mm_core_mapoffset+size, SEEK_SET) == -1)
290 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to seek in /dev/zero");
291 write(fdmem, &zero, sizeof(zero));
292 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
293 MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
294 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map /dev/zero");
295 mm_core_mapoffset += size;
296 #endif /* MM_SHMT_MMZERO */
297
298 #if defined(MM_SHMT_MMFILE)
299 unlink(fnmem);
300 if ((fdmem = open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
301 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open memory file");
302 if (ftruncate(fdmem, mm_core_mapoffset+size) == -1)
303 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate memory file");
304 write(fdmem, &zero, sizeof(zero));
305 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE,
306 MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
307 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map memory file");
308 mm_core_mapoffset += size;
309 #endif /* MM_SHMT_MMFILE */
310
311 #if defined(MM_SHMT_IPCSHM)
312 key = __mm_get_key_value(file, 'm');
313 if ((fdmem = shmget(key, size, (SHM_R|SHM_W|IPC_CREAT|IPC_EXCL))) == -1)
314 {
315 *initialize = 0;
316 if ((fdmem = shmget(key, size, (SHM_R|SHM_W|IPC_CREAT))) == -1)
317 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire shared memory segment");
318 }
319 if ((area = (void *)shmat(fdmem, NULL, 0)) == ((void *)-1))
320 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to attach shared memory");
321 if (shmctl(fdmem, IPC_STAT, &shmbuf) == -1)
322 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to get status of shared memory");
323 shmbuf.shm_perm.uid = getuid();
324 shmbuf.shm_perm.gid = getgid();
325 if (shmctl(fdmem, IPC_SET, &shmbuf) == -1)
326 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set status of shared memory");
327 if (key==IPC_PRIVATE && shmctl(fdmem, IPC_RMID, NULL) == -1)
328 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to remove shared memory in advance");
329 #endif /* MM_SHMT_IPCSHM */
330
331 #if defined(MM_SEMT_FLOCK)
332 unlink(fnsem);
333 if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
334 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");
335 #endif /* MM_SEMT_FLOCK */
336
337 #if defined(MM_SEMT_FCNTL)
338 unlink(fnsem);
339 if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
340 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");
341 #endif /* MM_SEMT_FCNTL */
342
343 #if defined(MM_SEMT_IPCSEM)
344 key = __mm_get_key_value(file, 'w');
345 fdsem = semget(key, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
346 if (fdsem == -1 && errno == EEXIST)
347 fdsem = semget(key, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
348 if (fdsem == -1)
349 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore");
350 mm_core_semctlarg.val = 0;
351 semctl(fdsem, 0, SETVAL, mm_core_semctlarg);
352 key = __mm_get_key_value(file, 'r');
353 fdsem_rd = semget(key, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
354 if (fdsem_rd == -1 && errno == EEXIST)
355 fdsem_rd = semget(key, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
356 if (fdsem_rd == -1)
357 FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore");
358 mm_core_semctlarg.val = 0;
359 semctl(fdsem_rd, 0, SETVAL, mm_core_semctlarg);
360 #endif /* MM_SEMT_IPCSEM */
361
362 /*
363 * Configure the memory core parameters
364 */
365 mc = (mem_core *)area;
366 if ( !*initialize && !getenv("MM_INIT_MEMORY") )
367 goto return_success;
368 mc->mc_size = size;
369 mc->mc_usize = usersize;
370 mc->mc_pid = getpid();
371 mc->mc_fdmem = fdmem;
372 mc->mc_mapcount = 0;
373 #if defined(MM_SEMT_FLOCK)
374 mc->mc_fdsem[0].pid = getpid();
375 mc->mc_fdsem[0].fd = fdsem;
376 mc->mc_fdsem[1].pid = 0;
377 mc->mc_fdsem[1].fd = -1;
378 #else
379 mc->mc_fdsem = fdsem;
380 #endif
381 #if defined(MM_SEMT_BEOS)
382 mc->mc_semid = create_sem(0, "mm_semid");
383 mc->mc_ben = 0;
384 #endif
385 #if defined(MM_SHMT_BEOS)
386 mc->mc_areaid = temparea;
387 #endif
388 #if defined(MM_SEMT_IPCSEM)
389 mc->mc_fdsem_rd = fdsem_rd;
390 mc->mc_readers = 0;
391 #endif
392 #if defined(MM_SHMT_MMFILE)
393 memcpy(mc->mc_fnmem, fnmem, MM_MAXPATH);
394 #endif
395 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
396 memcpy(mc->mc_fnsem, fnsem, MM_MAXPATH);
397 #endif
398
399 /*
400 * Return successfully established core
401 */
402 return_success:
403 return ((void *)&(mc->mc_base.mw_cp));
404
405 /*
406 * clean-up sequence (CUS) for error situation
407 */
408 BEGIN_FAILURE
409 #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
410 if (area != ((void *)-1))
411 munmap((caddr_t)area, size);
412 #endif
413 #if defined(MM_SHMT_IPCSHM)
414 if (area != ((void *)-1))
415 shmdt(area);
416 #endif
417 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
418 if (fdmem != -1)
419 close(fdmem);
420 #endif
421 #if defined(MM_SEMT_BEOS)
422 delete_sem(mc->mc_semid);
423 #endif
424 #if defined(MM_SHMT_BEOS)
425 delete_area(mc->mc_areaid);
426 #endif
427 #if defined(MM_SHMT_IPCSHM)
428 if (fdmem != -1)
429 shmctl(fdmem, IPC_RMID, NULL);
430 #endif
431 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
432 if (fdsem != -1)
433 close(fdsem);
434 #endif
435 #if defined(MM_SEMT_IPCSEM)
436 if (fdsem != -1)
437 semctl(fdsem, 0, IPC_RMID, 0);
438 if (fdsem_rd != -1)
439 semctl(fdsem_rd, 0, IPC_RMID, 0);
440 #endif
441 #if defined(MM_SHMT_MMFILE)
442 unlink(fnmem);
443 #endif
444 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
445 unlink(fnsem);
446 #endif
447 return NULL;
448 END_FAILURE
449 }
450
mm_core_permission(void * core,mode_t mode,uid_t owner,gid_t group)451 int mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group)
452 {
453 int rc;
454 mem_core *mc;
455
456 if (core == NULL)
457 return -1;
458 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
459 rc = 0;
460 #if defined(MM_SHMT_MMFILE)
461 if (rc == 0 && chmod(mc->mc_fnmem, mode) < 0)
462 rc = -1;
463 if (rc == 0 && chown(mc->mc_fnmem, owner, group) < 0)
464 rc = -1;
465 #endif
466 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
467 if (rc == 0 && chmod(mc->mc_fnsem, mode) < 0)
468 rc = -1;
469 if (rc == 0 && chown(mc->mc_fnsem, owner, group) < 0)
470 rc = -1;
471 #endif
472 return rc;
473 }
474
mm_core_delete(void * core,int destroy)475 void mm_core_delete(void *core, int destroy)
476 {
477 mem_core *mc;
478 int fdmem;
479 int fdsem;
480 #if defined(MM_SEMT_IPCSEM)
481 int fdsem_rd;
482 #endif
483 size_t size;
484 #if defined(MM_SHMT_MMFILE)
485 char fnmem[MM_MAXPATH];
486 #endif
487 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
488 char fnsem[MM_MAXPATH];
489 #endif
490
491 if (core == NULL)
492 return;
493 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
494 size = mc->mc_size;
495 fdmem = mc->mc_fdmem;
496 #if !defined(MM_SEMT_FLOCK)
497 fdsem = mc->mc_fdsem;
498 #endif
499 #if defined(MM_SEMT_IPCSEM)
500 fdsem_rd = mc->mc_fdsem_rd;
501 #endif
502 #if defined(MM_SEMT_FLOCK)
503 fdsem = mm_core_getfdsem(mc);
504 #endif
505 #if defined(MM_SHMT_MMFILE)
506 memcpy(fnmem, mc->mc_fnmem, MM_MAXPATH);
507 #endif
508 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
509 memcpy(fnsem, mc->mc_fnsem, MM_MAXPATH);
510 #endif
511
512 #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
513 munmap((caddr_t)mc, size);
514 #endif
515 #if defined(MM_SHMT_IPCSHM)
516 shmdt((void *)mc);
517 if ( destroy )
518 shmctl(fdmem, IPC_RMID, NULL);
519 #endif
520 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
521 close(fdmem);
522 #endif
523 #if defined(MM_SHMT_MMFILE)
524 if ( destroy )
525 unlink(fnmem);
526 #endif
527 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
528 close(fdsem);
529 #endif
530 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
531 unlink(fnsem);
532 #endif
533 #if defined(MM_SEMT_IPCSEM)
534 if ( destroy )
535 {
536 semctl(fdsem, 0, IPC_RMID, 0);
537 semctl(fdsem_rd, 0, IPC_RMID, 0);
538 }
539 #endif
540 return;
541 }
542
mm_core_detach(const void * core)543 void mm_core_detach (const void *core)
544 {
545 mem_core *mc;
546 int fdmem;
547 int fdsem;
548 size_t size;
549
550 if (core == NULL)
551 return;
552 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
553 size = mc->mc_size;
554 fdmem = mc->mc_fdmem;
555 #if !defined(MM_SEMT_FLOCK)
556 fdsem = mc->mc_fdsem;
557 #endif
558 #if defined(MM_SEMT_FLOCK)
559 fdsem = mm_core_getfdsem(mc);
560 #endif
561
562 #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
563 munmap((caddr_t)mc, size);
564 #endif
565 #if defined(MM_SHMT_IPCSHM)
566 shmdt((void *)mc);
567 #endif
568 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
569 close(fdmem);
570 #endif
571 #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
572 close(fdsem);
573 #endif
574 return;
575 }
576
mm_core_size(const void * core)577 size_t mm_core_size(const void *core)
578 {
579 mem_core *mc;
580
581 if (core == NULL)
582 return 0;
583 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
584 return (mc->mc_usize);
585 }
586
mm_core_lock(const void * core,mm_lock_mode mode)587 int mm_core_lock(const void *core, mm_lock_mode mode)
588 {
589 mem_core *mc;
590 int rc;
591 int fdsem;
592
593 if (core == NULL)
594 return FALSE;
595 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
596 #if !defined(MM_SEMT_FLOCK)
597 fdsem = mc->mc_fdsem;
598 #endif
599 #if defined(MM_SEMT_FLOCK)
600 fdsem = mm_core_getfdsem(mc);
601 #endif
602
603 #if defined(MM_SEMT_FCNTL)
604 if (mode == MM_LOCK_RD)
605 while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rd)) < 0) && (errno == EINTR)) ;
606 else
607 while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rw)) < 0) && (errno == EINTR)) ;
608 #endif
609 #if defined(MM_SEMT_FLOCK)
610 if (mode == MM_LOCK_RD)
611 while (((rc = flock(fdsem, LOCK_SH)) < 0) && (errno == EINTR)) ;
612 else
613 while (((rc = flock(fdsem, LOCK_EX)) < 0) && (errno == EINTR)) ;
614 #endif
615 #if defined(MM_SEMT_IPCSEM)
616 if (mode == MM_LOCK_RD) {
617 while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
618 mc->mc_readers++;
619 if (mc->mc_readers == 1)
620 while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
621 while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
622 }
623 else {
624 while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
625 }
626 mc->mc_lockmode = mode;
627 #endif
628 #if defined(MM_SEMT_BEOS)
629 rc = 0;
630 if (atomic_add(&mc->mc_ben, 1) > 0) {
631 /* someone already in lock... acquire sem and wait */
632 if (acquire_sem(mc->mc_semid) != B_NO_ERROR) {
633 atomic_add(&mc->mc_ben, -1);
634 rc = -1;
635 }
636 }
637 #endif
638
639 if (rc < 0) {
640 ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to lock");
641 rc = FALSE;
642 }
643 else
644 rc = TRUE;
645 return rc;
646 }
647
mm_core_unlock(const void * core)648 int mm_core_unlock(const void *core)
649 {
650 mem_core *mc;
651 int rc;
652 int fdsem;
653
654 if (core == NULL)
655 return FALSE;
656 mc = (mem_core *)((char *)core-SIZEOF_mem_core);
657 #if !defined(MM_SEMT_FLOCK)
658 fdsem = mc->mc_fdsem;
659 #endif
660 #if defined(MM_SEMT_FLOCK)
661 fdsem = mm_core_getfdsem(mc);
662 #endif
663
664 #if defined(MM_SEMT_FCNTL)
665 while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dounlock)) < 0) && (errno == EINTR)) ;
666 #endif
667 #if defined(MM_SEMT_FLOCK)
668 while (((rc = flock(fdsem, LOCK_UN)) < 0) && (errno == EINTR)) ;
669 #endif
670 #if defined(MM_SEMT_IPCSEM)
671 if (mc->mc_lockmode == MM_LOCK_RD) {
672 while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
673 mc->mc_readers--;
674 if (mc->mc_readers == 0)
675 while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
676 while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
677 }
678 else {
679 while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
680 }
681 #endif
682 #if defined(MM_SEMT_BEOS)
683 rc = 0;
684 if (atomic_add(&mc->mc_ben, -1) > 1)
685 release_sem(mc->mc_semid);
686 #endif
687
688 if (rc < 0) {
689 ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to unlock");
690 rc = FALSE;
691 }
692 else
693 rc = TRUE;
694 return rc;
695 }
696
697 /*
698 returns the ID (file descriptior, ipc id ... etc) of the shared memory segment
699 */
mm_core_shmid(const void * core)700 int mm_core_shmid (const void *core)
701 {
702 mem_core *mc = (mem_core *)((char *)core-SIZEOF_mem_core);
703
704 return mc->mc_fdmem;
705 }
706
707 /*
708 returns the amount of maps located in this shared memory segment
709 */
mm_core_mapcount(const void * core)710 int mm_core_mapcount(const void *core)
711 {
712 mem_core *mc = (mem_core *)((char *)core-SIZEOF_mem_core);
713
714 return mc->mc_mapcount;
715 }
716
717 /*
718 increases the map count on this shared memory
719 segment and returns the new count
720 */
mm_core_addmap(const void * core)721 int mm_core_addmap(const void *core)
722 {
723 mem_core *mc = (mem_core *)((char *)core-SIZEOF_mem_core);
724
725 return ++mc->mc_mapcount;
726 }
727
728 /*
729 decreases the map count on this shared
730 memory segment and returns the new count
731 */
mm_core_remmap(const void * core)732 int mm_core_remmap(const void *core)
733 {
734 mem_core *mc = (mem_core *)((char *)core-SIZEOF_mem_core);
735
736 return --mc->mc_mapcount;
737 }
738
mm_core_stat(const void * core,int * uid,int * gid,int * mode)739 int mm_core_stat(const void *core, int *uid, int *gid, int *mode)
740 {
741 struct shmid_ds buf;
742 mem_core *mc = (mem_core *)((char *)core-SIZEOF_mem_core);
743
744 if ( shmctl(mc->mc_fdmem, IPC_STAT, &buf) != 0 )
745 return -1;
746
747 if(uid)
748 *uid = buf.shm_perm.uid;
749
750 if(gid)
751 *gid = buf.shm_perm.gid;
752
753 if(mode)
754 *mode = buf.shm_perm.mode;
755
756 return 0;
757 }
758
759 /*EOF*/
760