📄 mm_core.c
字号:
/* ==================================================================== * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. * * 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 <rse@engelschall.com>." * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by * Ralf S. Engelschall <rse@engelschall.com>." * * 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 */#endifstatic 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); 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); int fdmem = 0; int fdsem = 0;#if defined(MM_SEMT_IPCSEM) int fdsem_rd = 0;#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, 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); 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"); mm_core_mapoffset += size;#endif /* MM_SHMT_MMZERO */#if defined(MM_SHMT_MMFILE) unlink(fnmem); if ((fdmem = open(fnmem, O_RDWR|O_CREAT, 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"); 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, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");#endif /* MM_SEMT_FLOCK */#if defined(MM_SEMT_FCNTL) unlink(fnsem); if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -