shm_mem.c

Go to the documentation of this file.
00001 /*
00002 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of sip-router, a free SIP server.
00007  *
00008  * Permission to use, copy, modify, and distribute this software for any
00009  * purpose with or without fee is hereby granted, provided that the above
00010  * copyright notice and this permission notice appear in all copies.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00013  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00014  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00015  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00016  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00017  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00018  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00019  */
00020 
00021 /*
00022  * History:
00023  * --------
00024  *  2003-03-12  split shm_mem_init in shm_getmem & shm_mem_init_mallocs
00025  *               (andrei)
00026  *  2004-07-27  ANON mmap support, needed on darwin (andrei)
00027  *  2004-09-19  shm_mem_destroy: destroy first the lock & then unmap (andrei)
00028  *  2007-06-10   support for sfm_malloc & shm_malloc_destroy() (andrei)
00029  */
00030 
00038 #ifdef SHM_MEM
00039 
00040 #include <stdlib.h>
00041 
00042 #include "shm_mem.h"
00043 #include "../config.h"
00044 #include "../globals.h"
00045 #include "memdbg.h"
00046 
00047 #ifdef  SHM_MMAP
00048 
00049 #include <unistd.h>
00050 #include <sys/mman.h>
00051 #include <sys/types.h> /*open*/
00052 #include <sys/stat.h>
00053 #include <fcntl.h>
00054 
00055 #endif
00056 
00057 #define _ROUND2TYPE(s, type) \
00058         (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
00059 #define _ROUND_LONG(s) _ROUND2TYPE(s, long)
00060 
00061 
00062 #ifndef SHM_MMAP
00063 static int shm_shmid=-1; /*shared memory id*/
00064 #endif
00065 
00066 #ifndef SHM_SAFE_MALLOC
00067 gen_lock_t* mem_lock=0;
00068 #endif
00069 
00070 static void* shm_mempool=(void*)-1;
00071 #ifdef LL_MALLOC
00072         struct sfm_block* shm_block;
00073 #elif SF_MALLOC
00074         struct sfm_block* shm_block;
00075 #elif F_MALLOC
00076         struct fm_block* shm_block;
00077 #elif DL_MALLOC
00078         mspace shm_block;
00079 #else
00080         struct qm_block* shm_block;
00081 #endif
00082 
00083 
00084 inline static void* sh_realloc(void* p, unsigned int size)
00085 {
00086         void *r;
00087         shm_lock(); 
00088         shm_free_unsafe(p);
00089         r=shm_malloc_unsafe(size);
00090         shm_unlock();
00091         return r;
00092 }
00093 
00094 /* look at a buffer if there is perhaps enough space for the new size
00095    (It is beneficial to do so because vq_malloc is pretty stateful
00096     and if we ask for a new buffer size, we can still make it happy
00097     with current buffer); if so, we return current buffer again;
00098     otherwise, we free it, allocate a new one and return it; no
00099     guarantee for buffer content; if allocation fails, we return
00100     NULL
00101 */
00102 
00103 #ifdef DBG_QM_MALLOC
00104 void* _shm_resize( void* p, unsigned int s, const char* file, const char* func,
00105                                                         int line)
00106 #else
00107 void* _shm_resize( void* p , unsigned int s)
00108 #endif
00109 {
00110         if (p==0) {
00111                 DBG("WARNING:vqm_resize: resize(0) called\n");
00112                 return shm_malloc( s );
00113         }
00114         return sh_realloc( p, s ); 
00115 }
00116 
00117 
00118 
00119 
00120 
00121 int shm_getmem(void)
00122 {
00123 
00124 #ifdef SHM_MMAP
00125 #ifndef USE_ANON_MMAP
00126         int fd;
00127 #endif
00128 #else
00129         struct shmid_ds shm_info;
00130 #endif
00131 
00132 #ifdef SHM_MMAP
00133         if (shm_mempool && (shm_mempool!=(void*)-1)){
00134 #else
00135         if ((shm_shmid!=-1)||(shm_mempool!=(void*)-1)){
00136 #endif
00137                 LOG(L_CRIT, "BUG: shm_mem_init: shm already initialized\n");
00138                 return -1;
00139         }
00140         
00141 #ifdef SHM_MMAP
00142 #ifdef USE_ANON_MMAP
00143         shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE,
00144                                          MAP_ANON|MAP_SHARED, -1 ,0);
00145 #else
00146         fd=open("/dev/zero", O_RDWR);
00147         if (fd==-1){
00148                 LOG(L_CRIT, "ERROR: shm_mem_init: could not open /dev/zero: %s\n",
00149                                 strerror(errno));
00150                 return -1;
00151         }
00152         shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
00153         /* close /dev/zero */
00154         close(fd);
00155 #endif /* USE_ANON_MMAP */
00156 #else
00157         
00158         shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700);
00159         if (shm_shmid==-1){
00160                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate shared memory"
00161                                 " segment: %s\n", strerror(errno));
00162                 return -1;
00163         }
00164         shm_mempool=shmat(shm_shmid, 0, 0);
00165 #endif
00166         if (shm_mempool==(void*)-1){
00167                 LOG(L_CRIT, "ERROR: shm_mem_init: could not attach shared memory"
00168                                 " segment: %s\n", strerror(errno));
00169                 /* destroy segment*/
00170                 shm_mem_destroy();
00171                 return -1;
00172         }
00173         return 0;
00174 }
00175 
00176 
00177 
00178 int shm_mem_init_mallocs(void* mempool, unsigned long pool_size)
00179 {
00180         /* init it for malloc*/
00181         shm_block=shm_malloc_init(mempool, pool_size);
00182         if (shm_block==0){
00183                 LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared"
00184                                 " malloc\n");
00185                 shm_mem_destroy();
00186                 return -1;
00187         }
00188 #ifndef SHM_SAFE_MALLOC
00189         mem_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc, 
00190                                                                                                            race cond*/
00191         if (mem_lock==0){
00192                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate lock\n");
00193                 shm_mem_destroy();
00194                 return -1;
00195         }
00196         if (lock_init(mem_lock)==0){
00197                 LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize lock\n");
00198                 shm_mem_destroy();
00199                 return -1;
00200         }
00201 #endif  /*SHM SAFE_MALLOC */
00202         
00203         DBG("shm_mem_init: success\n");
00204         
00205         return 0;
00206 }
00207 
00208 
00209 int shm_mem_init(int force_alloc)
00210 {
00211         int ret;
00212         long sz;
00213         long* p;
00214         long* end;
00215         
00216         ret=shm_getmem();
00217         if (ret<0) return ret;
00218         if (force_alloc){
00219                 sz=sysconf(_SC_PAGESIZE);
00220                 DBG("shm_mem_init: %ld bytes/page\n", sz);
00221                 if ((sz<sizeof(*p)) || (_ROUND_LONG(sz)!=sz)){
00222                         LOG(L_WARN, "shm_mem_init: invalid page size %ld, using 4096\n",
00223                                         sz);
00224                         sz=4096; /* invalid page size, use 4096 */
00225                 }
00226                 end=shm_mempool+shm_mem_size-sizeof(*p);
00227                 /* touch one word in every page */
00228                 for(p=(long*)_ROUND_LONG((long)shm_mempool); p<=end;
00229                                                                                 p=(long*)((char*)p+sz))
00230                         *p=0; 
00231         }
00232         return shm_mem_init_mallocs(shm_mempool, shm_mem_size);
00233 }
00234 
00235 
00236 void shm_mem_destroy(void)
00237 {
00238 #ifndef SHM_MMAP
00239         struct shmid_ds shm_info;
00240 #endif
00241         
00242         DBG("shm_mem_destroy\n");
00243 #ifndef SHM_SAFE_MALLOC
00244         if (mem_lock){
00245                 DBG("destroying the shared memory lock\n");
00246                 lock_destroy(mem_lock); /* we don't need to dealloc it*/
00247         }
00248 #endif  /*SHM SAFE_MALLOC */
00249         if (shm_block){
00250                 shm_malloc_destroy(shm_block);
00251                 shm_block=0;
00252         }
00253         if (shm_mempool && (shm_mempool!=(void*)-1)) {
00254 #ifdef SHM_MMAP
00255                 munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
00256 #else
00257                 shmdt(shm_mempool);
00258 #endif
00259                 shm_mempool=(void*)-1;
00260         }
00261 #ifndef SHM_MMAP
00262         if (shm_shmid!=-1) {
00263                 shmctl(shm_shmid, IPC_RMID, &shm_info);
00264                 shm_shmid=-1;
00265         }
00266 #endif
00267 }
00268 
00269 
00270 #endif