shm_mem.c

Go to the documentation of this file.
00001 /* $Id: shm_mem.c 5035 2008-10-06 11:01:24Z henningw $
00002  *
00003  * Shared memory functions
00004  *
00005  * Copyright (C) 2001-2003 FhG Fokus
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * --------
00025  *  2003-03-12  split shm_mem_init in shm_getmem & shm_mem_init_mallocs
00026  *               (andrei)
00027  *  2004-07-27  ANON mmap support, needed on darwin (andrei)
00028  *  2004-09-19  shm_mem_destroy: destroy first the lock & then unmap (andrei)
00029  */
00030 
00031 
00032 #include <stdlib.h>
00033 
00034 #include "shm_mem.h"
00035 #include "../config.h"
00036 #include "../globals.h"
00037 
00038 #ifdef  SHM_MMAP
00039 
00040 #include <unistd.h>
00041 #include <sys/mman.h>
00042 #include <sys/types.h> /*open*/
00043 #include <sys/stat.h>
00044 #include <fcntl.h>
00045 
00046 #endif
00047 
00048 
00049 #ifdef STATISTICS
00050 stat_export_t shm_stats[] = {
00051    {"total_size" ,     STAT_IS_FUNC,    (stat_var**)shm_get_size     },
00052    {"used_size" ,      STAT_IS_FUNC,    (stat_var**)shm_get_used     },
00053    {"real_used_size" , STAT_IS_FUNC,    (stat_var**)shm_get_rused    },
00054    {"max_used_size" ,  STAT_IS_FUNC,    (stat_var**)shm_get_mused    },
00055    {"free_size" ,      STAT_IS_FUNC,    (stat_var**)shm_get_free     },
00056    {"fragments" ,      STAT_IS_FUNC,    (stat_var**)shm_get_frags    },
00057    {0,0,0}
00058 };
00059 #endif
00060 
00061 
00062 
00063 #ifndef SHM_MMAP
00064 static int shm_shmid=-1; /*shared memory id*/
00065 #endif
00066 
00067 gen_lock_t* mem_lock=0;
00068 
00069 static void* shm_mempool=(void*)-1;
00070 #ifdef F_MALLOC
00071    struct fm_block* shm_block;
00072 #else
00073    struct qm_block* shm_block;
00074 #endif
00075 
00076 
00077 inline static void* sh_realloc(void* p, unsigned int size)
00078 {
00079    void *r;
00080    shm_lock(); 
00081    shm_free_unsafe(p);
00082    r=shm_malloc_unsafe(size);
00083    shm_unlock();
00084    return r;
00085 }
00086 
00087 /* look at a buffer if there is perhaps enough space for the new size
00088    (It is beneficial to do so because vq_malloc is pretty stateful
00089     and if we ask for a new buffer size, we can still make it happy
00090     with current buffer); if so, we return current buffer again;
00091     otherwise, we free it, allocate a new one and return it; no
00092     guarantee for buffer content; if allocation fails, we return
00093     NULL
00094 */
00095 
00096 #ifdef DBG_QM_MALLOC
00097 void* _shm_resize( void* p, unsigned int s, const char* file, const char* func,
00098                      int line)
00099 #else
00100 void* _shm_resize( void* p , unsigned int s)
00101 #endif
00102 {
00103    if (p==0) {
00104       LM_DBG("resize(0) called\n");
00105       return shm_malloc( s );
00106    }
00107    return sh_realloc( p, s ); 
00108 }
00109 
00110 
00111 
00112 
00113 
00114 int shm_getmem(void)
00115 {
00116 
00117 #ifdef SHM_MMAP
00118    int fd;
00119 #else
00120    struct shmid_ds shm_info;
00121 #endif
00122 
00123 #ifdef SHM_MMAP
00124    if (shm_mempool && (shm_mempool!=(void*)-1)){
00125 #else
00126    if ((shm_shmid!=-1)||(shm_mempool!=(void*)-1)){
00127 #endif
00128       LM_CRIT("shm already initialized\n");
00129       return -1;
00130    }
00131    
00132 #ifdef SHM_MMAP
00133 #ifdef USE_ANON_MMAP
00134    shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE,
00135                 MAP_ANON|MAP_SHARED, -1 ,0);
00136 #else
00137    fd=open("/dev/zero", O_RDWR);
00138    if (fd==-1){
00139       LM_CRIT("could not open /dev/zero: %s\n", strerror(errno));
00140       return -1;
00141    }
00142    shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
00143    /* close /dev/zero */
00144    close(fd);
00145 #endif /* USE_ANON_MMAP */
00146 #else
00147    
00148    shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700);
00149    if (shm_shmid==-1){
00150       LM_CRIT("could not allocate shared memory segment: %s\n",
00151             strerror(errno));
00152       return -1;
00153    }
00154    shm_mempool=shmat(shm_shmid, 0, 0);
00155 #endif
00156    if (shm_mempool==(void*)-1){
00157       LM_CRIT("could not attach shared memory segment: %s\n",
00158             strerror(errno));
00159       /* destroy segment*/
00160       shm_mem_destroy();
00161       return -1;
00162    }
00163    return 0;
00164 }
00165 
00166 
00167 
00168 int shm_mem_init_mallocs(void* mempool, unsigned long pool_size)
00169 {
00170    /* init it for malloc*/
00171    shm_block=shm_malloc_init(mempool, pool_size);
00172    if (shm_block==0){
00173       LM_CRIT("could not initialize shared malloc\n");
00174       shm_mem_destroy();
00175       return -1;
00176    }
00177    mem_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc, 
00178                                           race cond*/
00179    if (mem_lock==0){
00180       LM_CRIT("could not allocate lock\n");
00181       shm_mem_destroy();
00182       return -1;
00183    }
00184    if (lock_init(mem_lock)==0){
00185       LM_CRIT("could not initialize lock\n");
00186       shm_mem_destroy();
00187       return -1;
00188    }
00189    
00190    LM_DBG("success\n");
00191    
00192    return 0;
00193 }
00194 
00195 
00196 int shm_mem_init(void)
00197 {
00198    int ret;
00199    
00200    ret=shm_getmem();
00201    if (ret<0) return ret;
00202    return shm_mem_init_mallocs(shm_mempool, shm_mem_size);
00203 }
00204 
00205 
00206 void shm_mem_destroy(void)
00207 {
00208 #ifndef SHM_MMAP
00209    struct shmid_ds shm_info;
00210 #endif
00211    
00212    LM_DBG("\n");
00213    if (mem_lock){
00214       LM_DBG("destroying the shared memory lock\n");
00215       lock_destroy(mem_lock); /* we don't need to dealloc it*/
00216    }
00217    if (shm_mempool && (shm_mempool!=(void*)-1)) {
00218 #ifdef SHM_MMAP
00219       munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
00220 #else
00221       shmdt(shm_mempool);
00222 #endif
00223       shm_mempool=(void*)-1;
00224    }
00225 #ifndef SHM_MMAP
00226    if (shm_shmid!=-1) {
00227       shmctl(shm_shmid, IPC_RMID, &shm_info);
00228       shm_shmid=-1;
00229    }
00230 #endif
00231 }

Generated on Thu May 24 12:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6