mem/shm_mem.c
628e3a5a
 /* $Id$
  *
  * Shared memory functions
7dd0b342
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
628e3a5a
  */
fd92af47
 /*
  * History:
  * --------
  *  2003-03-12  splited shm_mem_init in shm_getmem & shm_mem_init_mallocs
  *               (andrei)
  */
628e3a5a
 
7dd0b342
 
628e3a5a
 #ifdef SHM_MEM
 
caf80ae6
 #include <stdlib.h>
 
628e3a5a
 #include "shm_mem.h"
dda9dab1
 #include "../config.h"
4e2fdd79
 #include "../globals.h"
628e3a5a
 
dcb5f364
 #ifdef  SHM_MMAP
 
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/types.h> /*open*/
 #include <sys/stat.h>
 #include <fcntl.h>
 
 #endif
 
628e3a5a
 
 
dcb5f364
 #ifndef SHM_MMAP
628e3a5a
 static int shm_shmid=-1; /*shared memory id*/
dcb5f364
 #endif
dda9dab1
 
0bd53297
 gen_lock_t* mem_lock=0;
eca7f442
 
628e3a5a
 static void* shm_mempool=(void*)-1;
dda9dab1
 #ifdef VQ_MALLOC
 	struct vqm_block* shm_block;
b2dec9c6
 #elif F_MALLOC
 	struct fm_block* shm_block;
dda9dab1
 #else
 	struct qm_block* shm_block;
 #endif
628e3a5a
 
51eadd0c
 
 inline static void* sh_realloc(void* p, unsigned int size)
 {
 	void *r;
 	shm_lock(); 
 	shm_free_unsafe(p);
 	r=shm_malloc_unsafe(size);
 	shm_unlock();
 	return r;
 }
ea6721d7
 
 /* look at a buffer if there is perhaps enough space for the new size
    (It is benefitial to do so because vq_malloc is pretty stateful
     and if we ask for a new buffer size, we can still make it happy
     with current buffer); if so, we return current buffer again;
     otherwise, we free it, allocate a new one and return it; no
     guarantee for buffer content; if allocation fails, we return
     NULL
 */
caf80ae6
 
 #ifdef DBG_QM_MALLOC
0e70fc1b
 void* _shm_resize( void* p, unsigned int s, char* file, char* func, int line)
caf80ae6
 #else
 void* _shm_resize( void* p , unsigned int s)
 #endif
 {
 #ifdef VQ_MALLOC
 	struct vqm_frag *f;
 #endif
 	if (p==0) {
 		DBG("WARNING:vqm_resize: resize(0) called\n");
 		return shm_malloc( s );
 	}
 #	ifdef DBG_QM_MALLOC
 #	ifdef VQ_MALLOC
 	f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
 	DBG("_shm_resize(%p, %d), called from %s: %s(%d)\n",  
 		p, s, file, func, line);
 	VQM_DEBUG_FRAG(shm_block, f);
 	if (p>(void *)shm_block->core_end || p<(void*)shm_block->init_core){
 		LOG(L_CRIT, "BUG: vqm_free: bad pointer %p (out of memory block!) - "
 				"aborting\n", p);
 		abort();
 	}
 #endif
 #	endif
 	return sh_realloc( p, s ); 
 }
 
628e3a5a
 
ea6721d7
 
fd92af47
 
 
 int shm_getmem()
628e3a5a
 {
 
dcb5f364
 #ifdef SHM_MMAP
 	int fd;
 #else
 	struct shmid_ds shm_info;
 #endif
628e3a5a
 
dcb5f364
 #ifdef SHM_MMAP
 	if (shm_mempool && (shm_mempool!=(void*)-1)){
 #else
a7ce1229
 	if ((shm_shmid!=-1)||(shm_mempool!=(void*)-1)){
dcb5f364
 #endif
628e3a5a
 		LOG(L_CRIT, "BUG: shm_mem_init: shm already initialized\n");
 		return -1;
 	}
 	
dcb5f364
 #ifdef SHM_MMAP
454ef89a
 	fd=open("/dev/zero", O_RDWR);
dcb5f364
 	if (fd==-1){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not open /dev/zero: %s\n",
 				strerror(errno));
 		return -1;
 	}
e3fc93f4
 	shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
dcb5f364
 	/* close /dev/zero */
 	close(fd);
 #else
 	
40a8d9dd
 	shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700);
628e3a5a
 	if (shm_shmid==-1){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate shared memory"
 				" segment: %s\n", strerror(errno));
 		return -1;
 	}
 	shm_mempool=shmat(shm_shmid, 0, 0);
dcb5f364
 #endif
628e3a5a
 	if (shm_mempool==(void*)-1){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not attach shared memory"
 				" segment: %s\n", strerror(errno));
 		/* destroy segment*/
 		shm_mem_destroy();
 		return -1;
 	}
fd92af47
 	return 0;
 }
 
eca7f442
 
fd92af47
 
 int shm_mem_init_mallocs(void* mempool, int pool_size)
 {
628e3a5a
 	/* init it for malloc*/
fd92af47
 	shm_block=shm_malloc_init(mempool, pool_size);
628e3a5a
 	if (shm_block==0){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared"
 				" malloc\n");
 		shm_mem_destroy();
 		return -1;
 	}
0bd53297
 	mem_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc, 
 													   race cond*/
e0135488
 	if (mem_lock==0){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate lock\n");
 		shm_mem_destroy();
 		return -1;
 	}
 	if (lock_init(mem_lock)==0){
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize lock\n");
 		shm_mem_destroy();
 		return -1;
 	}
eca7f442
 	
628e3a5a
 	DBG("shm_mem_init: success\n");
 	
 	return 0;
 }
 
 
fd92af47
 int shm_mem_init()
 {
 	int ret;
 	
 	ret=shm_getmem();
 	if (ret<0) return ret;
 	return shm_mem_init_mallocs(shm_mempool, shm_mem_size);
 }
 
628e3a5a
 
 void shm_mem_destroy()
 {
dcb5f364
 #ifndef SHM_MMAP
628e3a5a
 	struct shmid_ds shm_info;
dcb5f364
 #endif
628e3a5a
 	
 	DBG("shm_mem_destroy\n");
 	if (shm_mempool && (shm_mempool!=(void*)-1)) {
dcb5f364
 #ifdef SHM_MMAP
40a8d9dd
 		munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
dcb5f364
 #else
628e3a5a
 		shmdt(shm_mempool);
dcb5f364
 #endif
628e3a5a
 		shm_mempool=(void*)-1;
 	}
dcb5f364
 #ifndef SHM_MMAP
628e3a5a
 	if (shm_shmid!=-1) {
 		shmctl(shm_shmid, IPC_RMID, &shm_info);
 		shm_shmid=-1;
 	}
dcb5f364
 #endif
c751da14
 	if (mem_lock){
 		DBG("destroying the shared memory lock\n");
 		lock_destroy(mem_lock); /* we don't need to dealloc it*/
 	}
628e3a5a
 }
 
 
 #endif