head 1.25; access; symbols MM_1_4_2:1.24 MM_1_4_1:1.24 MM_1_4_0:1.23 MM_1_3_1:1.22 MM_1_3_0:1.21 MM_1_2_2:1.19 MM_1_2_1:1.16 MM_1_2_0:1.16 MM_1_1_3:1.10 MM_1_1_2:1.10 MM_1_1_1:1.10 MM_1_1_0:1.10 MM_1_0_12:1.8 MM_1_0_11:1.8 MM_1_0_10:1.7 MM_1_0_9:1.7 MM_1_0_8:1.7 MM_1_0_7:1.7 MM_1_0_6:1.6 MM_1_0_5:1.6 MM_1_0_4:1.6 MM_1_0_3:1.5 MM_1_0_1:1.4 MM_1_0_0:1.3 MM_1_0b6:1.3 MM_1_0b5:1.3 MM_1_0b4:1.3 MM_1_0b3:1.3 MM_1_0b2plus:1.1.1.1 RSE:1.1.1; locks; strict; comment @ * @; 1.25 date 2007.01.01.18.26.34; author rse; state Exp; branches; next 1.24; commitid xbmVq17WhC8zJP0s; 1.24 date 2006.08.10.19.00.33; author rse; state Exp; branches; next 1.23; commitid zS8gipIRuG1bykIr; 1.23 date 2005.09.02.20.00.46; author rse; state Exp; branches; next 1.22; 1.22 date 2004.09.12.18.35.01; author rse; state Exp; branches; next 1.21; 1.21 date 2003.03.07.15.04.50; author rse; state Exp; branches; next 1.20; 1.20 date 2003.03.07.14.59.15; author rse; state Exp; branches; next 1.19; 1.19 date 2002.12.19.09.25.24; author rse; state Exp; branches; next 1.18; 1.18 date 2002.12.19.09.14.58; author rse; state Exp; branches; next 1.17; 1.17 date 2002.12.19.09.11.51; author rse; state Exp; branches; next 1.16; 1.16 date 2002.07.26.13.48.38; author rse; state Exp; branches; next 1.15; 1.15 date 2002.07.26.13.34.53; author rse; state Exp; branches; next 1.14; 1.14 date 2002.07.26.13.04.40; author rse; state Exp; branches; next 1.13; 1.13 date 2002.07.26.09.59.34; author rse; state Exp; branches; next 1.12; 1.12 date 2001.01.29.20.27.22; author rse; state Exp; branches; next 1.11; 1.11 date 2001.01.29.20.00.43; author rse; state Exp; branches; next 1.10; 1.10 date 2000.03.17.16.54.08; author rse; state Exp; branches; next 1.9; 1.9 date 2000.01.09.20.19.40; author rse; state Exp; branches; next 1.8; 1.8 date 99.09.06.10.38.26; author rse; state Exp; branches; next 1.7; 1.7 date 99.06.22.13.19.02; author rse; state Exp; branches; next 1.6; 1.6 date 99.05.21.21.20.09; author rse; state Exp; branches; next 1.5; 1.5 date 99.05.15.11.45.22; author rse; state Exp; branches; next 1.4; 1.4 date 99.04.18.10.39.51; author rse; state Exp; branches; next 1.3; 1.3 date 99.03.15.13.25.48; author rse; state Exp; branches; next 1.2; 1.2 date 99.03.15.12.58.49; author rse; state Exp; branches; next 1.1; 1.1 date 99.03.15.11.12.50; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 99.03.15.11.12.50; author rse; state Exp; branches; next ; desc @@ 1.25 log @Updated all copyright messages for year 2007 @ text @/* ==================================================================== * Copyright (c) 1999-2007 Ralf S. Engelschall * Copyright (c) 1999-2007 The OSSP Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by * Ralf S. Engelschall ." * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by * Ralf S. Engelschall ." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ /* ** ** mm_core.c -- Low-level Shared Memory API ** */ #define MM_PRIVATE #include "mm.h" /* * Some global variables */ #if defined(MM_SEMT_FCNTL) /* lock/unlock structures for fcntl() */ static struct flock mm_core_dolock_rd; static struct flock mm_core_dolock_rw; static struct flock mm_core_dounlock; #endif #if defined(MM_SEMT_IPCSEM) /* lock/unlock structures for semop() */ static union semun mm_core_semctlarg; static struct sembuf mm_core_dolock[2]; static struct sembuf mm_core_dounlock[1]; #endif #if defined(MM_SHMT_MMFILE) || defined(MM_SHMT_MMPOSX) static size_t mm_core_mapoffset = 0; /* we use own file */ #elif defined(MM_SHMT_MMZERO) static size_t mm_core_mapoffset = 1024*1024*1; /* we share with other apps */ #endif static void mm_core_init(void) { static int initialized = FALSE; if (!initialized) { #if defined(MM_SEMT_FCNTL) mm_core_dolock_rd.l_whence = SEEK_SET; /* from current point */ mm_core_dolock_rd.l_start = 0; /* -"- */ mm_core_dolock_rd.l_len = 0; /* until end of file */ mm_core_dolock_rd.l_type = F_RDLCK; /* set shard/read lock */ mm_core_dolock_rd.l_pid = 0; /* pid not actually interesting */ mm_core_dolock_rw.l_whence = SEEK_SET; /* from current point */ mm_core_dolock_rw.l_start = 0; /* -"- */ mm_core_dolock_rw.l_len = 0; /* until end of file */ mm_core_dolock_rw.l_type = F_WRLCK; /* set exclusive/read-write lock */ mm_core_dolock_rw.l_pid = 0; /* pid not actually interesting */ mm_core_dounlock.l_whence = SEEK_SET; /* from current point */ mm_core_dounlock.l_start = 0; /* -"- */ mm_core_dounlock.l_len = 0; /* until end of file */ mm_core_dounlock.l_type = F_UNLCK; /* unlock */ mm_core_dounlock.l_pid = 0; /* pid not actually interesting */ #endif #if defined(MM_SEMT_IPCSEM) mm_core_dolock[0].sem_num = 0; mm_core_dolock[0].sem_op = 0; mm_core_dolock[0].sem_flg = 0; mm_core_dolock[1].sem_num = 0; mm_core_dolock[1].sem_op = 1; mm_core_dolock[1].sem_flg = SEM_UNDO; mm_core_dounlock[0].sem_num = 0; mm_core_dounlock[0].sem_op = -1; mm_core_dounlock[0].sem_flg = SEM_UNDO; #endif initialized = TRUE; } return; } #if defined(MM_SEMT_FLOCK) /* * Determine per-process fd for semaphore * (needed only for flock() based semaphore) */ static int mm_core_getfdsem(mem_core *mc) { int fd = -1; pid_t pid; int i; pid = getpid(); for (i = 0; i < MM_MAXCHILD && mc->mc_fdsem[i].pid != 0 && mc->mc_fdsem[i].fd != -1; i++) { if (mc->mc_fdsem[i].pid == pid) { fd = mc->mc_fdsem[i].fd; break; } } if (fd == -1 && i < MM_MAXCHILD) { fd = open(mc->mc_fnsem, O_WRONLY, MM_CORE_FILEMODE); #if defined(F_SETFD) && defined(FD_CLOEXEC) fcntl(fd, F_SETFD, FD_CLOEXEC); #endif mc->mc_fdsem[i].pid = getpid(); mc->mc_fdsem[i].fd = fd; } return fd; } #endif /* MM_SEMT_FLOCK */ /* * Determine memory page size of OS */ static size_t mm_core_pagesize(void) { static int pagesize = 0; if (pagesize == 0) #if defined(MM_VMPS_GETPAGESIZE) pagesize = getpagesize(); #elif defined(MM_VMPS_SYSCONF) pagesize = sysconf(_SC_PAGESIZE); #elif defined(MM_VMPS_BEOS) pagesize = B_PAGE_SIZE; #else pagesize = MM_CORE_DEFAULT_PAGESIZE; #endif return pagesize; } /* * Align a size to the next page or word boundary */ size_t mm_core_align2page(size_t size) { int psize = mm_core_pagesize(); return ((size)%(psize) > 0 ? ((size)/(psize)+1)*(psize) : (size)); } size_t mm_core_align2word(size_t size) { return ((1+((size-1) / SIZEOF_mem_word)) * SIZEOF_mem_word); } size_t mm_core_maxsegsize(void) { return mm_core_align2page((MM_SHM_MAXSEGSIZE-SIZEOF_mem_core)-mm_core_pagesize()); } /* * Create a shared memory area */ void *mm_core_create(size_t usersize, const char *file) { mem_core *mc; void *area = ((void *)-1); #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) || defined(MM_SHMT_IPCSHM) int fdmem = -1; #endif int fdsem = -1; #if defined(MM_SEMT_IPCSEM) int fdsem_rd = -1; #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) char *fnmem; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char *fnsem; #endif size_t size; #if defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) int zero = 0; #endif #if defined(MM_SHMT_IPCSHM) struct shmid_ds shmbuf; #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) char shmfilename[MM_MAXPATH]; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char semfilename[MM_MAXPATH]; #endif #if defined(MM_SHMT_BEOS) area_id temparea; #endif char filename[MM_MAXPATH]; if (usersize <= 0 || usersize > mm_core_maxsegsize()) { errno = EINVAL; return NULL; } if (file == NULL) { sprintf(filename, MM_CORE_DEFAULT_FILE, (int)getpid()); file = filename; } mm_core_init(); size = mm_core_align2page(usersize+SIZEOF_mem_core); #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) sprintf(shmfilename, "%s.mem", file); fnmem = shmfilename; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) sprintf(semfilename, "%s.sem", file); fnsem = semfilename; #endif #if defined(MM_SHMT_MMANON) if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map anonymous area"); #endif /* MM_SHMT_MMANON */ #if defined(MM_SHMT_BEOS) if ((temparea = create_area("mm", (void*)&area, B_ANY_ADDRESS, size, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA)) < 0) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to create the memory area"); #endif /* MM_SHMT_BEOS */ #if defined(MM_SHMT_MMPOSX) shm_unlink(fnmem); /* Ok when it fails */ if ((fdmem = shm_open(fnmem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open tempfile"); if (ftruncate(fdmem, mm_core_mapoffset+size) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate tempfile"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map tempfile"); shm_unlink(fnmem); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMPOSX */ #if defined(MM_SHMT_MMZERO) if ((fdmem = open("/dev/zero", O_RDWR, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open /dev/zero"); if (lseek(fdmem, mm_core_mapoffset+size, SEEK_SET) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to seek in /dev/zero"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map /dev/zero"); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMZERO */ #if defined(MM_SHMT_MMFILE) unlink(fnmem); if ((fdmem = open(fnmem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open memory file"); if (ftruncate(fdmem, mm_core_mapoffset+size) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate memory file"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map memory file"); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMFILE */ #if defined(MM_SHMT_IPCSHM) if ((fdmem = shmget(IPC_PRIVATE, size, (SHM_R|SHM_W|IPC_CREAT))) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire shared memory segment"); if ((area = (void *)shmat(fdmem, NULL, 0)) == ((void *)-1)) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to attach shared memory"); if (shmctl(fdmem, IPC_STAT, &shmbuf) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to get status of shared memory"); shmbuf.shm_perm.uid = getuid(); shmbuf.shm_perm.gid = getgid(); if (shmctl(fdmem, IPC_SET, &shmbuf) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set status of shared memory"); if (shmctl(fdmem, IPC_RMID, NULL) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to remove shared memory in advance"); #endif /* MM_SHMT_IPCSHM */ #if defined(MM_SEMT_FLOCK) unlink(fnsem); if ((fdsem = open(fnsem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file"); #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdsem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif #endif /* MM_SEMT_FLOCK */ #if defined(MM_SEMT_FCNTL) unlink(fnsem); if ((fdsem = open(fnsem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file"); #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdsem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif #endif /* MM_SEMT_FCNTL */ #if defined(MM_SEMT_IPCSEM) fdsem = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem == -1 && errno == EEXIST) fdsem = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); mm_core_semctlarg.val = 0; semctl(fdsem, 0, SETVAL, mm_core_semctlarg); fdsem_rd = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem_rd == -1 && errno == EEXIST) fdsem_rd = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem_rd == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); mm_core_semctlarg.val = 0; semctl(fdsem_rd, 0, SETVAL, mm_core_semctlarg); #endif /* MM_SEMT_IPCSEM */ /* * Configure the memory core parameters */ mc = (mem_core *)area; mc->mc_size = size; mc->mc_usize = usersize; mc->mc_pid = getpid(); #if defined(MM_SHMT_IPCSHM) mc->mc_fdmem = fdmem; #endif #if defined(MM_SEMT_FLOCK) mc->mc_fdsem[0].pid = getpid(); mc->mc_fdsem[0].fd = fdsem; mc->mc_fdsem[1].pid = 0; mc->mc_fdsem[1].fd = -1; #else mc->mc_fdsem = fdsem; #endif #if defined(MM_SEMT_BEOS) mc->mc_semid = create_sem(0, "mm_semid"); mc->mc_ben = 0; #endif #if defined(MM_SHMT_BEOS) mc->mc_areaid = temparea; #endif #if defined(MM_SEMT_IPCSEM) mc->mc_fdsem_rd = fdsem_rd; mc->mc_readers = 0; #endif #if defined(MM_SHMT_MMFILE) memcpy(mc->mc_fnmem, fnmem, MM_MAXPATH); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) memcpy(mc->mc_fnsem, fnsem, MM_MAXPATH); #endif /* * Return successfully established core */ return ((void *)&(mc->mc_base.mw_cp)); /* * clean-up sequence (CUS) for error situation */ BEGIN_FAILURE #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) if (area != ((void *)-1)) munmap((caddr_t)area, size); #endif #if defined(MM_SHMT_IPCSHM) if (area != ((void *)-1)) shmdt(area); #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) if (fdmem != -1) close(fdmem); #endif #if defined(MM_SEMT_BEOS) delete_sem(mc->mc_semid); #endif #if defined(MM_SHMT_BEOS) delete_area(mc->mc_areaid); #endif #if defined(MM_SHMT_IPCSHM) if (fdmem != -1) shmctl(fdmem, IPC_RMID, NULL); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) if (fdsem != -1) close(fdsem); #endif #if defined(MM_SEMT_IPCSEM) if (fdsem != -1) semctl(fdsem, 0, IPC_RMID, 0); if (fdsem_rd != -1) semctl(fdsem_rd, 0, IPC_RMID, 0); #endif #if defined(MM_SHMT_MMFILE) unlink(fnmem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) unlink(fnsem); #endif return NULL; END_FAILURE } int mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group) { int rc; mem_core *mc; #if defined(MM_SEMT_IPCSEM) union semun ick; struct semid_ds buf; int sems[2], i; #endif if (core == NULL) return -1; mc = (mem_core *)((char *)core-SIZEOF_mem_core); rc = 0; #if defined(MM_SHMT_MMFILE) if (rc == 0 && chmod(mc->mc_fnmem, mode) < 0) rc = -1; if (rc == 0 && chown(mc->mc_fnmem, owner, group) < 0) rc = -1; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) if (rc == 0 && chmod(mc->mc_fnsem, mode) < 0) rc = -1; if (rc == 0 && chown(mc->mc_fnsem, owner, group) < 0) rc = -1; #endif #if defined(MM_SEMT_IPCSEM) if (rc == 0) { sems[0] = mc->mc_fdsem; sems[1] = mc->mc_fdsem_rd; ick.buf = &buf; for (i = 0; i < 2; i++) { if (semctl(sems[i], 0, IPC_STAT, ick) < 0) { rc = -1; break; } if ((int)owner != -1) buf.sem_perm.uid = owner; if ((int)group != -1) buf.sem_perm.gid = group; buf.sem_perm.mode = mode; if (semctl(sems[i], 0, IPC_SET, ick) < 0) { rc = -1; break; } } } #endif return rc; } void mm_core_delete(void *core) { mem_core *mc; #if defined(MM_SHMT_IPCSHM) int fdmem; #endif int fdsem; #if defined(MM_SEMT_IPCSEM) int fdsem_rd; #endif size_t size; #if defined(MM_SHMT_MMFILE) char fnmem[MM_MAXPATH]; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char fnsem[MM_MAXPATH]; #endif if (core == NULL) return; mc = (mem_core *)((char *)core-SIZEOF_mem_core); size = mc->mc_size; #if defined(MM_SHMT_IPCSHM) fdmem = mc->mc_fdmem; #endif #if !defined(MM_SEMT_FLOCK) fdsem = mc->mc_fdsem; #endif #if defined(MM_SEMT_IPCSEM) fdsem_rd = mc->mc_fdsem_rd; #endif #if defined(MM_SEMT_FLOCK) fdsem = mm_core_getfdsem(mc); #endif #if defined(MM_SHMT_MMFILE) memcpy(fnmem, mc->mc_fnmem, MM_MAXPATH); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) memcpy(fnsem, mc->mc_fnsem, MM_MAXPATH); #endif #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) munmap((caddr_t)mc, size); #endif #if defined(MM_SHMT_IPCSHM) shmdt((void *)mc); shmctl(fdmem, IPC_RMID, NULL); #endif #if defined(MM_SHMT_MMFILE) unlink(fnmem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) close(fdsem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) unlink(fnsem); #endif #if defined(MM_SEMT_IPCSEM) semctl(fdsem, 0, IPC_RMID, 0); semctl(fdsem_rd, 0, IPC_RMID, 0); #endif return; } size_t mm_core_size(const void *core) { mem_core *mc; if (core == NULL) return 0; mc = (mem_core *)((char *)core-SIZEOF_mem_core); return (mc->mc_usize); } int mm_core_lock(const void *core, mm_lock_mode mode) { mem_core *mc; int rc = 0; int fdsem; if (core == NULL) return FALSE; mc = (mem_core *)((char *)core-SIZEOF_mem_core); #if !defined(MM_SEMT_FLOCK) fdsem = mc->mc_fdsem; #endif #if defined(MM_SEMT_FLOCK) fdsem = mm_core_getfdsem(mc); #endif #if defined(MM_SEMT_FCNTL) if (mode == MM_LOCK_RD) while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rd)) < 0) && (errno == EINTR)) ; else while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rw)) < 0) && (errno == EINTR)) ; #endif #if defined(MM_SEMT_FLOCK) if (mode == MM_LOCK_RD) while (((rc = flock(fdsem, LOCK_SH)) < 0) && (errno == EINTR)) ; else while (((rc = flock(fdsem, LOCK_EX)) < 0) && (errno == EINTR)) ; #endif #if defined(MM_SEMT_IPCSEM) if (mode == MM_LOCK_RD) { while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ; mc->mc_readers++; if (mc->mc_readers == 1) while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ; while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ; } else { while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ; } mc->mc_lockmode = mode; #endif #if defined(MM_SEMT_BEOS) rc = 0; if (atomic_add(&mc->mc_ben, 1) > 0) { /* someone already in lock... acquire sem and wait */ if (acquire_sem(mc->mc_semid) != B_NO_ERROR) { atomic_add(&mc->mc_ben, -1); rc = -1; } } #endif if (rc < 0) { ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to lock"); rc = FALSE; } else rc = TRUE; return rc; } int mm_core_unlock(const void *core) { mem_core *mc; int rc = 0; int fdsem; if (core == NULL) return FALSE; mc = (mem_core *)((char *)core-SIZEOF_mem_core); #if !defined(MM_SEMT_FLOCK) fdsem = mc->mc_fdsem; #endif #if defined(MM_SEMT_FLOCK) fdsem = mm_core_getfdsem(mc); #endif #if defined(MM_SEMT_FCNTL) while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dounlock)) < 0) && (errno == EINTR)) ; #endif #if defined(MM_SEMT_FLOCK) while (((rc = flock(fdsem, LOCK_UN)) < 0) && (errno == EINTR)) ; #endif #if defined(MM_SEMT_IPCSEM) if (mc->mc_lockmode == MM_LOCK_RD) { while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ; mc->mc_readers--; if (mc->mc_readers == 0) while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ; while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ; } else { while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ; } #endif #if defined(MM_SEMT_BEOS) rc = 0; if (atomic_add(&mc->mc_ben, -1) > 1) release_sem(mc->mc_semid); #endif if (rc < 0) { ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to unlock"); rc = FALSE; } else rc = TRUE; return rc; } /*EOF*/ @ 1.24 log @bump copyright for year 2006 @ text @d2 2 a3 2 * Copyright (c) 1999-2006 Ralf S. Engelschall * Copyright (c) 1999-2006 The OSSP Project @ 1.23 log @adjust copyright year @ text @d2 2 a3 2 * Copyright (c) 1999-2005 Ralf S. Engelschall * Copyright (c) 1999-2005 The OSSP Project @ 1.22 log @adjust year in copyright messages @ text @d2 2 a3 2 * Copyright (c) 1999-2004 Ralf S. Engelschall * Copyright (c) 1999-2004 The OSSP Project @ 1.21 log @Now that we immediately close the fd on MM_SHMT_MMZERO and MM_SHMT_MMFILE, we can avoid setting the FD_CLOEXEC just two calls before close(2). @ text @d2 2 a3 2 * Copyright (c) 1999-2003 Ralf S. Engelschall * Copyright (c) 1999-2003 The OSSP Project @ 1.20 log @1. Correctly cleanup under MM_SHMT_MMZERO in case of a shared memory segment creation error. 2. Close the filedescriptor of the underlying object immediately after mmap(2)'ing it in case of MM_SHMT_MMPOSX, MM_SHMT_MMZERO and MM_SHMT_MMFILE. Hints by: Joe Orton @ text @a273 4 #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdmem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif a287 4 #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdmem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif @ 1.19 log @Updated all copyright messages with forthcoming year 2003, added OSSP project as secondary copyright holder, added standard OSSP ASCII-art logo to documents, etc. @ text @d192 1 d194 1 d267 1 d284 1 d302 1 d365 1 d367 1 d411 1 a411 1 #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) d499 1 d501 1 d518 1 d520 1 a542 3 #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) close(fdmem); @ 1.18 log @Stripped trailing whitespaces from all files in source tree. @ text @d2 2 a3 1 * Copyright (c) 1999-2002 Ralf S. Engelschall. All rights reserved. @ 1.17 log @Use "close-on-exec" semantic on internal file descriptors if underlying platform supports this feature. This makes sure the file descriptors are closed by the kernel upon execution of exec(3) by the application. Hints by: Martin Kraemer @ text @d9 1 a9 1 * notice, this list of conditions and the following disclaimer. d121 1 a121 1 d123 2 a124 2 for (i = 0; i < MM_MAXCHILD && mc->mc_fdsem[i].pid != 0 && d242 1 a242 1 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, d260 1 a260 1 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, d277 1 a277 1 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, d294 1 a294 1 if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, d612 1 a612 1 @ 1.16 log @Fixed race condition in temporary file creation. Submitted by: Sebastian Krahmer, SuSE Security @ text @d133 3 d270 4 d287 4 d319 4 d329 4 @ 1.15 log @Make sure that under MM_SEMT_IPCSEM (mutex implementation method is SysV IPC semget) the {mm,MM}_permission() also changes the owner of the semaphore. Submitted by: Jonathan Kamens @ text @d252 1 a252 1 if ((fdmem = shm_open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1) d278 1 a278 1 if ((fdmem = open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1) d306 1 a306 1 if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1) d312 1 a312 1 if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1) @ 1.14 log @major source tree overhauling @ text @d422 5 d443 22 @ 1.13 log @bump copyright year @ text @d518 1 a518 1 int rc; d579 1 a579 1 int rc; @ 1.12 log @*** empty log message *** @ text @d2 1 a2 1 * Copyright (c) 1999-2001 Ralf S. Engelschall. All rights reserved. @ 1.11 log @*** empty log message *** @ text @d2 1 a2 1 * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. @ 1.10 log @*** empty log message *** @ text @d188 2 a189 2 int fdmem = 0; int fdsem = 0; d191 1 a191 1 int fdsem_rd = 0; d320 2 a321 2 if (fdsem == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); d327 2 a328 2 if (fdsem_rd == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); @ 1.9 log @*** empty log message *** @ text @d152 2 d212 3 d244 6 d347 8 a354 1 mc->mc_fdsem = fdsem; d358 1 a358 1 mc->mc_readers = 0; d388 6 d556 11 d610 6 @ 1.8 log @*** empty log message *** @ text @d2 1 a2 1 * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved. @ 1.7 log @*** empty log message *** @ text @d235 1 a235 1 MAP_ANON|MAP_SHARED, -1, 0)) == MAP_FAILED) d247 1 a247 1 MAP_SHARED, fdmem, mm_core_mapoffset)) == MAP_FAILED) d260 1 a260 1 MAP_SHARED, fdmem, mm_core_mapoffset)) == MAP_FAILED) d273 1 a273 1 MAP_SHARED, fdmem, mm_core_mapoffset)) == MAP_FAILED) @ 1.6 log @*** empty log message *** @ text @d295 1 a295 1 if ((fdsem = open(fnsem, O_WRONLY|O_CREAT, MM_CORE_FILEMODE)) == -1) d301 1 a301 1 if ((fdsem = open(fnsem, O_WRONLY|O_CREAT, MM_CORE_FILEMODE)) == -1) @ 1.5 log @*** empty log message *** @ text @d175 1 a175 1 return MM_SHM_MAXSEGSIZE; d212 4 a215 3 mm_core_init(); if (usersize <= 0 || usersize >= mm_core_maxsegsize()) usersize = mm_core_maxsegsize(); d220 2 @ 1.4 log @*** empty log message *** @ text @d391 24 @ 1.3 log @*** empty log message *** @ text @d182 1 a182 1 void *mm_core_create(size_t usersize, char *file) d454 1 a454 1 size_t mm_core_size(void *core) d464 1 a464 1 int mm_core_lock(void *core, mm_lock_mode mode) d514 1 a514 1 int mm_core_unlock(void *core) @ 1.2 log @*** empty log message *** @ text @d464 1 a464 1 int mm_core_lock(void *core, unsigned int mode) @ 1.1 log @Initial revision @ text @d56 2 a57 1 static struct flock mm_core_dolock; d79 15 a93 10 mm_core_dolock.l_whence = SEEK_SET; /* from current point */ mm_core_dolock.l_start = 0; /* -"- */ mm_core_dolock.l_len = 0; /* until end of file */ mm_core_dolock.l_type = F_WRLCK; /* set exclusive/write lock */ mm_core_dolock.l_pid = 0; /* pid not actually interesting */ mm_core_dounlock.l_whence = SEEK_SET; /* from current point */ mm_core_dounlock.l_start = 0; /* -"- */ mm_core_dounlock.l_len = 0; /* until end of file */ mm_core_dounlock.l_type = F_UNLCK; /* unlock */ mm_core_dounlock.l_pid = 0; /* pid not actually interesting */ d188 3 d240 1 a240 1 if (ftruncate(fdmem, size) == -1) d253 2 d266 1 a266 1 if (ftruncate(fdmem, size) == -1) d310 7 d335 4 d378 2 d396 3 d415 3 d449 1 d464 1 a464 1 int mm_core_lock(void *core) d481 4 a484 2 errno = 0; while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock)) < 0) && (errno == EINTR)) ; d487 4 a490 2 errno = 0; while (((rc = flock(fdsem, LOCK_EX)) < 0) && (errno == EINTR)) ; d493 11 a503 2 errno = 0; while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ; a530 1 errno = 0; a533 1 errno = 0; d537 10 a546 2 errno = 0; while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ; @ 1.1.1.1 log @Import into CVS @ text @@