|
@@ -0,0 +1,272 @@
|
|
|
+/*
|
|
|
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
|
|
|
+ *
|
|
|
+ * This file is part of Kamailio, a free SIP server.
|
|
|
+ *
|
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
|
+ *
|
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+
|
|
|
+#include "../config.h"
|
|
|
+#include "../globals.h"
|
|
|
+#include "memdbg.h"
|
|
|
+#include "shm.h"
|
|
|
+
|
|
|
+#ifdef SHM_MMAP
|
|
|
+
|
|
|
+#include <unistd.h>
|
|
|
+#include <sys/mman.h>
|
|
|
+#include <sys/types.h> /*open*/
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <fcntl.h>
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "memcore.h"
|
|
|
+
|
|
|
+#define _ROUND2TYPE(s, type) \
|
|
|
+ (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
|
|
|
+#define _ROUND_LONG(s) _ROUND2TYPE(s, long)
|
|
|
+
|
|
|
+
|
|
|
+void shm_core_destroy(void);
|
|
|
+
|
|
|
+#ifndef SHM_MMAP
|
|
|
+static int _shm_core_shmid = -1; /*shared memory id*/
|
|
|
+#endif
|
|
|
+
|
|
|
+gen_lock_t* _shm_lock=0;
|
|
|
+
|
|
|
+static void* _shm_core_pool = (void*)-1;
|
|
|
+
|
|
|
+sr_shm_api_t _shm_root = {0};
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+int shm_getmem(void)
|
|
|
+{
|
|
|
+
|
|
|
+#ifdef SHM_MMAP
|
|
|
+#ifndef USE_ANON_MMAP
|
|
|
+ int fd;
|
|
|
+#endif
|
|
|
+#else
|
|
|
+ struct shmid_ds shm_info;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef SHM_MMAP
|
|
|
+ if (_shm_core_pool && (_shm_core_pool!=(void*)-1)){
|
|
|
+#else
|
|
|
+ if ((_shm_core_shmid!=-1)||(_shm_core_pool!=(void*)-1)){
|
|
|
+#endif
|
|
|
+ LOG(L_CRIT, "shm already initialized\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef SHM_MMAP
|
|
|
+#ifdef USE_ANON_MMAP
|
|
|
+ _shm_core_pool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE,
|
|
|
+ MAP_ANON|MAP_SHARED, -1 ,0);
|
|
|
+#else
|
|
|
+ fd=open("/dev/zero", O_RDWR);
|
|
|
+ if (fd==-1){
|
|
|
+ LOG(L_CRIT, "could not open /dev/zero: %s\n",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ _shm_core_pool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
|
|
|
+ /* close /dev/zero */
|
|
|
+ close(fd);
|
|
|
+#endif /* USE_ANON_MMAP */
|
|
|
+#else
|
|
|
+
|
|
|
+ _shm_core_shmid=shmget(IPC_PRIVATE, shm_mem_size , 0700);
|
|
|
+ if (_shm_core_shmid==-1){
|
|
|
+ LOG(L_CRIT, "could not allocate shared memory"
|
|
|
+ " segment: %s\n", strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ _shm_core_pool=shmat(_shm_core_shmid, 0, 0);
|
|
|
+#endif
|
|
|
+ if (_shm_core_pool==(void*)-1){
|
|
|
+ LOG(L_CRIT, "could not attach shared memory"
|
|
|
+ " segment: %s\n", strerror(errno));
|
|
|
+ /* destroy segment*/
|
|
|
+ shm_core_destroy();
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void* shm_core_get_pool(void)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ long sz;
|
|
|
+ long* p;
|
|
|
+ long* end;
|
|
|
+
|
|
|
+ ret=shm_getmem();
|
|
|
+ if (ret<0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (shm_force_alloc){
|
|
|
+ sz=sysconf(_SC_PAGESIZE);
|
|
|
+ DBG("%ld bytes/page\n", sz);
|
|
|
+ if ((sz<sizeof(*p)) || (_ROUND_LONG(sz)!=sz)){
|
|
|
+ LOG(L_WARN, "invalid page size %ld, using 4096\n",
|
|
|
+ sz);
|
|
|
+ sz=4096; /* invalid page size, use 4096 */
|
|
|
+ }
|
|
|
+ end=_shm_core_pool+shm_mem_size-sizeof(*p);
|
|
|
+ /* touch one word in every page */
|
|
|
+ for(p=(long*)_ROUND_LONG((long)_shm_core_pool); p<=end;
|
|
|
+ p=(long*)((char*)p+sz))
|
|
|
+ *p=0;
|
|
|
+ }
|
|
|
+ return _shm_core_pool;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * init the core lock
|
|
|
+ */
|
|
|
+int shm_core_lock_init(void)
|
|
|
+{
|
|
|
+ if (_shm_lock) {
|
|
|
+ LM_DBG("shared memory lock initialized\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ _shm_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc,
|
|
|
+ race cond*/
|
|
|
+ if (_shm_lock==0){
|
|
|
+ LOG(L_CRIT, "could not allocate lock\n");
|
|
|
+ shm_core_destroy();
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (lock_init(_shm_lock)==0){
|
|
|
+ LOG(L_CRIT, "could not initialize lock\n");
|
|
|
+ shm_core_destroy();
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void shm_core_lock_destroy(void)
|
|
|
+{
|
|
|
+ if (_shm_lock){
|
|
|
+ DBG("destroying the shared memory lock\n");
|
|
|
+ lock_destroy(_shm_lock); /* we don't need to dealloc it*/
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void shm_core_destroy(void)
|
|
|
+{
|
|
|
+#ifndef SHM_MMAP
|
|
|
+ struct shmid_ds shm_info;
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (_shm_core_pool && (_shm_core_pool!=(void*)-1)) {
|
|
|
+#ifdef SHM_MMAP
|
|
|
+ munmap(_shm_core_pool, /* SHM_MEM_SIZE */ shm_mem_size );
|
|
|
+#else
|
|
|
+ shmdt(_shm_core_pool);
|
|
|
+#endif
|
|
|
+ _shm_core_pool=(void*)-1;
|
|
|
+ }
|
|
|
+#ifndef SHM_MMAP
|
|
|
+ if (shm_shmid!=-1) {
|
|
|
+ shmctl(shm_shmid, IPC_RMID, &shm_info);
|
|
|
+ shm_shmid=-1;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+int shm_init_api(sr_shm_api_t *ap)
|
|
|
+{
|
|
|
+ memset(&_shm_root, 0, sizeof(sr_shm_api_t));
|
|
|
+ _shm_root.mname = ap->mname;
|
|
|
+ _shm_root.mem_pool = ap->mem_pool;
|
|
|
+ _shm_root.mem_block = ap->mem_block;
|
|
|
+ _shm_root.xmalloc = ap->xmalloc;
|
|
|
+ _shm_root.xmalloc_unsafe = ap->xmalloc_unsafe;
|
|
|
+ _shm_root.xfree = ap->xfree;
|
|
|
+ _shm_root.xfree_unsafe = ap->xfree_unsafe;
|
|
|
+ _shm_root.xrealloc = ap->xrealloc;
|
|
|
+ _shm_root.xresize = ap->xresize;
|
|
|
+ _shm_root.xstatus = ap->xstatus;
|
|
|
+ _shm_root.xinfo = ap->xinfo;
|
|
|
+ _shm_root.xavailable = ap->xavailable;
|
|
|
+ _shm_root.xsums = ap->xsums;
|
|
|
+ _shm_root.xdestroy = ap->xdestroy;
|
|
|
+ return 0;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+int shm_init_manager(char *name)
|
|
|
+{
|
|
|
+ if(strcmp(name, "fm")==0
|
|
|
+ || strcmp(name, "f_malloc")==0
|
|
|
+ || strcmp(name, "fmalloc")==0) {
|
|
|
+ /*fast malloc*/
|
|
|
+ return fm_malloc_init_shm_manager();
|
|
|
+ } else if(strcmp(name, "qm")==0
|
|
|
+ || strcmp(name, "q_malloc")==0
|
|
|
+ || strcmp(name, "qmalloc")==0) {
|
|
|
+ /*quick malloc*/
|
|
|
+ return qm_malloc_init_shm_manager();
|
|
|
+ } else if(strcmp(name, "sm")==0) {
|
|
|
+ /*system malloc*/
|
|
|
+ } else {
|
|
|
+ /*custom malloc - module*/
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void shm_destroy_manager(void)
|
|
|
+{
|
|
|
+ shm_core_lock_destroy();
|
|
|
+ if(_shm_root.xdestroy) {
|
|
|
+ _shm_root.xdestroy();
|
|
|
+ LM_DBG("destroying memory manager: %s\n",
|
|
|
+ (_shm_root.mname)?_shm_root.mname:"unknown");
|
|
|
+ }
|
|
|
+ shm_core_destroy();
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void shm_print_manager(void)
|
|
|
+{
|
|
|
+ LM_DBG("shm - using memory manager: %s\n",
|
|
|
+ (_pkg_root.mname)?_pkg_root.mname:"unknown");
|
|
|
+}
|