From ea018b000a1df0c9888a8248da63fd7cec3e284a Mon Sep 17 00:00:00 2001 From: Vlad Paiu Date: Fri, 3 Jan 2025 14:52:28 +0200 Subject: [PATCH] paralel alloc - wip --- Makefile.conf.template | 1 + mem/common.c | 10 + mem/common.h | 26 +- mem/f_parallel_malloc.c | 286 +++++++++++++++++ mem/f_parallel_malloc.h | 207 ++++++++++++ mem/f_parallel_malloc_dyn.h | 613 ++++++++++++++++++++++++++++++++++++ mem/shm_mem.c | 165 ++++++++-- mem/shm_mem.h | 184 ++++++++++- version.h | 8 +- 9 files changed, 1468 insertions(+), 32 deletions(-) create mode 100644 mem/f_parallel_malloc.c create mode 100644 mem/f_parallel_malloc.h create mode 100644 mem/f_parallel_malloc_dyn.h diff --git a/Makefile.conf.template b/Makefile.conf.template index 83765830130..e098195ba6b 100644 --- a/Makefile.conf.template +++ b/Makefile.conf.template @@ -86,6 +86,7 @@ DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors +DEFS+= -DF_PARALLEL_MALLOC #Fast memory allocator with paralel buckets #DEFS+= -DQM_DBG_MALLOC_HIST=3 #Size of debug history for Q_MALLOC (default is 1) #DEFS+= -DNO_DEBUG #Compile out all debug messages #DEFS+= -DNO_LOG #Compile out all logging diff --git a/mem/common.c b/mem/common.c index c13e76e4574..598b3516005 100644 --- a/mem/common.c +++ b/mem/common.c @@ -60,6 +60,11 @@ int parse_mm(const char *mm_name, enum osips_mm *mm) return 0; } + if (!strcasecmp(mm_name, "F_PARALLEL_MALLOC")) { + *mm = MM_F_PARALLEL_MALLOC; + return 0; + } + #ifdef DBG_MALLOC if (!strcasecmp(mm_name, "F_MALLOC_DBG")) { *mm = MM_F_MALLOC_DBG; @@ -75,6 +80,11 @@ int parse_mm(const char *mm_name, enum osips_mm *mm) *mm = MM_HP_MALLOC_DBG; return 0; } + + if (!strcasecmp(mm_name, "F_PARALLEL_MALLOC_DBG")) { + *mm = MM_F_PARALLEL_MALLOC_DBG; + return 0; + } #endif return -1; diff --git a/mem/common.h b/mem/common.h index 2cc467780be..e39c92c8687 100644 --- a/mem/common.h +++ b/mem/common.h @@ -23,30 +23,40 @@ #ifndef mem_common_h #define mem_common_h +#include "../lock_ops.h" + extern void *mem_block; extern void *shm_block; extern void *shm_dbg_block; extern void *rpm_block; +extern void **shm_blocks; +extern int init_done; +extern gen_lock_t *hash_locks[128]; #include "meminfo.h" -#if !defined(F_MALLOC) && !defined(Q_MALLOC) && !defined(HP_MALLOC) -#error "no memory allocator selected" -/* if exactly an allocator was selected, let's inline it! */ -#elif ((!defined Q_MALLOC && !defined HP_MALLOC) || \ - (!defined F_MALLOC && !defined HP_MALLOC) || \ - (!defined F_MALLOC && !defined Q_MALLOC)) +#if !defined(F_MALLOC) && !defined(Q_MALLOC) && !defined(HP_MALLOC) && !defined(F_PARALLEL_MALLOC) +#error "no memory allocator selected"b + +/* if exactly one allocator was selected, let's inline it! */ +#elif ((!defined(F_MALLOC) && !defined(Q_MALLOC) && !defined(HP_MALLOC)) || \ + (!defined(F_MALLOC) && !defined(Q_MALLOC) && !defined(F_PARALLEL_MALLOC)) || \ + (!defined(F_MALLOC) && !defined(HP_MALLOC) && !defined(F_PARALLEL_MALLOC)) || \ + (!defined(Q_MALLOC) && !defined(HP_MALLOC) && !defined(F_PARALLEL_MALLOC))) #define INLINE_ALLOC #endif + enum osips_mm { MM_NONE, MM_F_MALLOC, MM_Q_MALLOC, MM_HP_MALLOC, + MM_F_PARALLEL_MALLOC, MM_F_MALLOC_DBG, MM_Q_MALLOC_DBG, MM_HP_MALLOC_DBG, + MM_F_PARALLEL_MALLOC_DBG, }; #if defined F_MALLOC @@ -61,6 +71,10 @@ enum osips_mm { #include "hp_malloc.h" #endif +#if defined F_PARALLEL_MALLOC +#include "f_parallel_malloc.h" +#endif + extern int mem_warming_enabled; extern char *mem_warming_pattern_file; extern int mem_warming_percentage; diff --git a/mem/f_parallel_malloc.c b/mem/f_parallel_malloc.c new file mode 100644 index 00000000000..ec90a25cd3e --- /dev/null +++ b/mem/f_parallel_malloc.c @@ -0,0 +1,286 @@ +#ifdef F_PARALLEL_MALLOC + +#include +#include +#include + +#include "f_parallel_malloc.h" +#include "../dprint.h" +#include "../globals.h" +#include "../statistics.h" + +#ifdef DBG_MALLOC +#include "mem_dbg_hash.h" +#endif + +#include "../lib/dbg/struct_hist.h" + +#define MIN_FRAG_SIZE ROUNDTO +#define F_PARALLEL_FRAG_OVERHEAD (sizeof(struct parallel_frag)) +#define frag_is_free(_f) ((_f)->prev) + +#define F_PARALLEL_FRAG_NEXT(f) \ + ((struct parallel_frag *)((char *)(f) + sizeof(struct parallel_frag) + (f)->size)) + +#define max(a,b) ( (a)>(b)?(a):(b)) + +/* ROUNDTO= 2^k so the following works */ +#define ROUNDTO_MASK (~((unsigned long)ROUNDTO-1)) +#define ROUNDUP(s) (((s)+(ROUNDTO-1))&ROUNDTO_MASK) +#define ROUNDDOWN(s) ((s)&ROUNDTO_MASK) + +/* finds the hash value for s, s=ROUNDTO multiple*/ +#define F_PARALLEL_GET_HASH(s) ( ((unsigned long)(s)<=F_PARALLEL_MALLOC_OPTIMIZE)?\ + (unsigned long)(s)/ROUNDTO: \ + F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO+big_hash_idx((s))- \ + F_PARALLEL_MALLOC_OPTIMIZE_FACTOR+1 ) + +#define F_PARALLEL_UN_HASH(h) ( ((unsigned long)(h)<=(F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO))?\ + (unsigned long)(h)*ROUNDTO: \ + 1UL<<((unsigned long)(h)-F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO+\ + F_PARALLEL_MALLOC_OPTIMIZE_FACTOR-1)\ + ) + +static inline void parallel_free_minus(struct parallel_block *fm, unsigned long size) +{ + + #if defined(DBG_MALLOC) || defined(STATISTICS) + fm->real_used+=size; + fm->used+=size; + #endif +} + + +static inline void parallel_free_plus(struct parallel_block *fm, unsigned long size) +{ + + #if defined(DBG_MALLOC) || defined(STATISTICS) + fm->real_used-=size; + fm->used-=size; + #endif +} + + +/* computes hash number for big buckets*/ +inline static unsigned long big_hash_idx(unsigned long s) +{ + unsigned long idx; + /* s is rounded => s = k*2^n (ROUNDTO=2^n) + * index= i such that 2^i > s >= 2^(i-1) + * + * => index = number of the first non null bit in s*/ + idx=sizeof(long)*8-1; + for (; !(s&(1UL<<(sizeof(long)*8-1))) ; s<<=1, idx--); + return idx; +} + +#ifdef SHM_EXTRA_STATS +#include "module_info.h" +unsigned long parallel_stats_get_index(void *ptr) +{ + if (!ptr) + return GROUP_IDX_INVALID; + + return F_PARALLEL_FRAG(ptr)->statistic_index; +} + +void parallel_stats_set_index(void *ptr, unsigned long idx) +{ + if (!ptr) + return; + + F_PARALLEL_FRAG(ptr)->statistic_index = idx; +} +#endif + +static inline void parallel_insert_free(struct parallel_block *fm, struct parallel_frag *frag) +{ + struct parallel_frag **f; + int hash; + +// LM_ERR("Inserting free size frag %p in block %p, total size = %lu\n",frag,fm,frag->size); + + hash=F_PARALLEL_GET_HASH(frag->size); +// LM_ERR("Gos to hash %d\n",hash); + f=&(fm->free_hash[hash].first); + if (*f) + (*f)->block_ptr = fm; + if (frag->size > F_PARALLEL_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH, + (different from 0.8.1[24] on + purpose --andrei ) */ +// LM_ERR("We optimize it, first is %p!! \n",*f); + for(; *f; f=&((*f)->u.nxt_free)){ + //LM_ERR("Iterating over next free \n"); + (*f)->block_ptr = fm; + if (frag->size <= (*f)->size) break; + } + } + + /*insert it here*/ + if (*f) { + //LM_ERR("Setting back-pointer \n"); + (*f)->block_ptr = fm; + } + + frag->prev = f; + frag->u.nxt_free=*f; + frag->block_ptr = fm; + + //LM_ERR("Linking %p with %p \n",frag,*f); + + if( *f ) { + (*f)->block_ptr = fm; + (*f)->prev = &(frag->u.nxt_free); + frag->u.nxt_free->block_ptr = fm; + } + + //LM_ERR("Putting at %p\n",f); + *f=frag; + fm->free_hash[hash].no++; + //LM_ERR("Free hash no = %lu in block %p\n",fm->free_hash[hash].no,fm); + //LM_ERR("After insert, we are left with %lu \n",frag->size); + + frag->block_ptr = fm; + parallel_free_plus(fm, frag->size); +} + +static inline void parallel_remove_free(struct parallel_block *fm, struct parallel_frag *n) +{ + struct parallel_frag **pf; + int hash; + + pf = n->prev; + hash = F_PARALLEL_GET_HASH( n->size ); + + /* detach */ + if (*pf) + (*pf)->block_ptr=fm; + + *pf=n->u.nxt_free; + if (*pf) + (*pf)->block_ptr=fm; + + if( n->u.nxt_free ) + n->u.nxt_free->prev = pf; + + fm->free_hash[hash].no--; + + n->prev = NULL; + n->block_ptr = fm; + + //LM_ERR("Removing free size frag %p in block %p, total size = %lu\n",n,fm,n->size); + + parallel_free_minus(fm , n->size); + +}; + + + + + +/* init malloc and return a parallel_block*/ +struct parallel_block *parallel_malloc_init(char *address, unsigned long size, char *name, int idx) + +{ + char *start; + char *end; + struct parallel_block *fm; + unsigned long init_overhead; + + //LM_ERR("Init parallel block %p of size %lu\n", address,size); + + /* make address and size multiple of 8*/ + start=(char*)ROUNDUP((unsigned long) address); + LM_DBG("F_OPTIMIZE=%lu, /ROUNDTO=%lu, %lu-bytes aligned\n", + F_PARALLEL_MALLOC_OPTIMIZE, F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO, + (unsigned long)ROUNDTO); + LM_DBG("F_HASH_SIZE=%lu, parallel_block size=%zu, frag_size=%zu\n", + F_PARALLEL_HASH_SIZE, sizeof(struct parallel_block), sizeof(struct parallel_frag)); + LM_DBG("params (%p, %lu), start=%p\n", address, size, start); + + if (size<(unsigned long)(start-address)) return 0; + size-=(start-address); + if (size <(MIN_FRAG_SIZE+F_PARALLEL_FRAG_OVERHEAD)) return 0; + size=ROUNDDOWN(size); + + init_overhead=(ROUNDUP(sizeof(struct parallel_block))+ 2 * F_PARALLEL_FRAG_OVERHEAD); + + + if (size < init_overhead) + { + /* not enough mem to create our control structures !!!*/ + return 0; + } + end=start+size; + fm=(struct parallel_block *)start; + //LM_ERR("Actual parallel block is %p \n",fm); + memset(fm, 0, sizeof(struct parallel_block)); + fm->name = name; + fm->size=size; + + fm->idx = idx; + + #if defined(DBG_MALLOC) || defined(STATISTICS) + fm->used=size-init_overhead; + fm->real_used=size; + fm->max_real_used=init_overhead; + fm->fragments = 0; + #endif + + fm->first_frag=(struct parallel_frag *)(start+ROUNDUP(sizeof(struct parallel_block))); + fm->last_frag=(struct parallel_frag *)(end-sizeof(struct parallel_frag)); + + fm->first_frag->block_ptr = fm; + fm->last_frag->block_ptr = fm; + + /* init initial fragment*/ + fm->first_frag->size=size-init_overhead; + fm->last_frag->size=0; + + fm->last_frag->prev=NULL; + fm->first_frag->prev=NULL; + + /* link initial fragment into the free list*/ + + parallel_insert_free(fm, fm->first_frag); + + return fm; +} + +#include "f_parallel_malloc_dyn.h" + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +#undef DBG_MALLOC +#include "f_parallel_malloc_dyn.h" +#define DBG_MALLOC +#endif + +#ifdef SHM_EXTRA_STATS +void parallel_stats_core_init(struct parallel_block *fm, int core_index) +{ + struct parallel_frag *f; + + LM_ERR("Extra stats ?? \n"); + + for (f=fm->first_frag; (char *)f < (char *)fm->last_frag; f=F_PARALLEL_FRAG_NEXT(f)) + if (!frag_is_free(f)) + f->statistic_index = core_index; +} + +#endif + + + + +/* fills a malloc info structure with info about the block + * if a parameter is not supported, it will be filled with 0 */ +void parallel_info(struct parallel_block *fm, struct mem_info *info) +{ + memset(info,0, sizeof(*info)); + /* Not implemented, need an array here, no real use for it now */ + return; +} + + + +#endif diff --git a/mem/f_parallel_malloc.h b/mem/f_parallel_malloc.h new file mode 100644 index 00000000000..24a0c227f3d --- /dev/null +++ b/mem/f_parallel_malloc.h @@ -0,0 +1,207 @@ +#ifndef parallel_malloc_h +#define parallel_malloc_h + +#include +#include "meminfo.h" +#include "common.h" + +#undef ROUNDTO + +#if defined(__CPU_sparc64) || defined(__CPU_sparc) +/* tricky, on sun in 32 bits mode long long must be 64 bits aligned + * but long can be 32 bits aligned => malloc should return long long + * aligned memory */ + #define ROUNDTO sizeof(long long) +#else + #define ROUNDTO sizeof(void *) /* address alignment, in bytes (2^n) */ +#endif + +#define F_PARALLEL_MALLOC_OPTIMIZE_FACTOR 14UL /*used below */ + +/* size to optimize for, (most allocs <= this size), must be 2^k */ +#define F_PARALLEL_MALLOC_OPTIMIZE (1UL << F_PARALLEL_MALLOC_OPTIMIZE_FACTOR) + +#define F_PARALLEL_HASH_SIZE (F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO + \ + (sizeof(long)*8-F_PARALLEL_MALLOC_OPTIMIZE_FACTOR)+1) + +/* get the fragment which corresponds to a pointer */ +#define F_PARALLEL_FRAG(p) \ + ((struct parallel_frag *)((char *)(p) - sizeof(struct parallel_frag))) + +/* hash structure: + * 0 .... F_MALLOC_OPTIMIZE/ROUNDTO - small buckets, size increases with + * ROUNDTO from bucket to bucket + * +1 .... end - size = 2^k, big buckets */ + +struct parallel_frag { + unsigned long size; + union { + struct parallel_frag *nxt_free; + long reserved; + } u; + struct parallel_frag **prev; +#ifdef DBG_MALLOC + const char *file; + const char *func; + unsigned long line; +#endif + + /* we are hashing, need to know which is the big block for this allocation */ + struct parallel_block *block_ptr; + +#ifdef SHM_EXTRA_STATS + unsigned long statistic_index; +#endif +} __attribute__ ((aligned (ROUNDTO))); + +#define F_PARALLEL_FRAG_OVERHEAD (sizeof(struct parallel_frag)) + +struct parallel_frag_lnk { + struct parallel_frag *first; + unsigned long no; +}; + +struct parallel_block { + char *name; /* purpose of this memory block */ + + unsigned long size; /* total size */ + unsigned long fragments; /* number of fragments in use */ +#if defined(DBG_MALLOC) || defined(STATISTICS) + unsigned long used; /* alloc'ed size */ + unsigned long real_used; /* used + malloc overhead */ + unsigned long max_real_used; +#endif + + int idx; + + struct parallel_frag *first_frag; + struct parallel_frag *last_frag; + + struct parallel_frag_lnk free_hash[F_PARALLEL_HASH_SIZE]; +} __attribute__ ((aligned (ROUNDTO))); + +struct parallel_block *parallel_malloc_init(char *address, unsigned long size, char *name,int idx); + +#ifdef DBG_MALLOC +void *parallel_malloc(struct parallel_block *fm, unsigned long size, + const char *file, const char *func, unsigned int line); +void parallel_free(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line); +void *parallel_realloc(struct parallel_block *fm, void *p, unsigned long size, + const char *file, const char *func, unsigned int line); +#ifndef INLINE_ALLOC +void *parallel_malloc_dbg(struct parallel_block *fm, unsigned long size, + const char *file, const char *func, unsigned int line); +void parallel_free_dbg(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line); +void *parallel_realloc_dbg(struct parallel_block *fm, void *p, unsigned long size, + const char *file, const char *func, unsigned int line); +#endif +#else +void *parallel_malloc(struct parallel_block *fm, unsigned long size); +void parallel_free(struct parallel_block *fm, void *p); +void *parallel_realloc(struct parallel_block *fm, void *p, unsigned long size); +#endif + +void parallel_status(struct parallel_block *); +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void parallel_status_dbg(struct parallel_block *); +#endif +void parallel_info(struct parallel_block *, struct mem_info *); + +static inline unsigned long parallel_frag_size(void *p) +{ + if (!p) + return 0; + + return F_PARALLEL_FRAG(p)->size; +} + +#ifdef SHM_EXTRA_STATS +void parallel_stats_core_init(struct parallel_block *fm, int core_index); +unsigned long parallel_stats_get_index(void *ptr); +void parallel_stats_set_index(void *ptr, unsigned long idx); + +#ifdef DBG_MALLOC +static inline const char *parallel_frag_file(void *p) { return F_PARALLEL_FRAG(p)->file; } +static inline const char *parallel_frag_func(void *p) { return F_PARALLEL_FRAG(p)->func; } +static inline unsigned long parallel_frag_line(void *p) { return F_PARALLEL_FRAG(p)->line; } +#else +static inline const char *parallel_frag_file(void *p) { return NULL; } +static inline const char *parallel_frag_func(void *p) { return NULL; } +static inline unsigned long parallel_frag_line(void *p) { return 0; } +#endif +#endif + +#ifdef STATISTICS +static inline unsigned long parallel_get_size(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->size; + } + + return total_size; +} +static inline unsigned long parallel_get_used(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->used; + } + + return total_size; +} +static inline unsigned long parallel_get_free(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->size - + ((struct parallel_block *)shm_blocks[i])->real_used; + } + + return total_size; +} +static inline unsigned long parallel_get_real_used(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->real_used; + } + + return total_size; +} +static inline unsigned long parallel_get_max_real_used(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->max_real_used; + } + + return total_size; +} +static inline unsigned long parallel_get_frags(struct parallel_block *fm) +{ + int i; + unsigned long total_size=0; + + for (i=0;i<128;i++) { + total_size += ((struct parallel_block *)shm_blocks[i])->fragments; + } + + return total_size; +} + +#endif /*STATISTICS*/ + +#endif diff --git a/mem/f_parallel_malloc_dyn.h b/mem/f_parallel_malloc_dyn.h new file mode 100644 index 00000000000..c6c85265b01 --- /dev/null +++ b/mem/f_parallel_malloc_dyn.h @@ -0,0 +1,613 @@ +/* + * If you have to deal with the ifdef spaghetti, here are its requirements: + * - be able to compile an inlined allocator (fm_split_frag short) + * - be able to compile an inlined, dbg allocator (fm_split_frag long) + * - be able to compile multiple allocators (fm_split_frag short) + * - be able to compile multiple, dbg allocators + * (fm_split_frag_dbg + fm_split_frag long, + * requires x2 include, hence the "_dynamic" file suffix) + * + * The same idea applies to all below functions. + */ + +static inline +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void parallel_split_frag_dbg(struct parallel_block *fm, struct parallel_frag *frag, + unsigned long size, + const char *file, const char *func, unsigned int line) +#elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC +void parallel_split_frag(struct parallel_block *fm, struct parallel_frag *frag, + unsigned long size) +#else +void parallel_split_frag(struct parallel_block *fm, struct parallel_frag *frag, + unsigned long size, + const char *file, const char *func, unsigned int line) +#endif +{ + unsigned long rest; + struct parallel_frag *n; + + //LM_ERR("VLAD - F_PARALLEL split block %p for size %lu of frag %p \n",fm,size,frag); + frag->block_ptr = fm; + + rest=frag->size-size; + #ifdef MEM_FRAG_AVOIDANCE + //LM_ERR("FRAG avoidance \n"); + if ((rest> (F_PARALLEL_FRAG_OVERHEAD+F_PARALLEL_MALLOC_OPTIMIZE))|| + (rest>=(F_PARALLEL_FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/ + #else + if (rest>(F_PARALLEL_FRAG_OVERHEAD+MIN_FRAG_SIZE)){ + #endif + //LM_ERR("We-re splliting frag %p from block %p\n",frag,fm); + frag->size=size; + /*split the fragment*/ + n=F_PARALLEL_FRAG_NEXT(frag); + n->block_ptr=fm; + n->size=rest-F_PARALLEL_FRAG_OVERHEAD; + + + /* + * The real used memory does not increase, as the frag memory is not + * freed from real_used. On the other hand, the used size should + * decrease, because the new fragment is not "useful data" - razvanc + + #if defined(DBG_MALLOC) || defined(STATISTICS) + fm->real_used+=F_PARALLEL_FRAG_OVERHEAD; + #endif + + */ + #if defined(DBG_MALLOC) || defined(STATISTICS) + fm->used-=F_PARALLEL_FRAG_OVERHEAD; + #endif + + #ifdef DBG_MALLOC + /* frag created by malloc, mark it*/ + n->file=file; + n->func=func; + n->line=line; + #endif + /* reinsert n in free list*/ + parallel_insert_free(fm, n); + }else{ + /* we cannot split this fragment any more => alloc all of it*/ + } +} + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void *parallel_malloc_dbg(struct parallel_block *fm, unsigned long size, + const char *file, const char *func, unsigned int line) +#elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC +void *parallel_malloc(struct parallel_block *fm, unsigned long size) +#else +void *parallel_malloc(struct parallel_block *fm, unsigned long size, + const char *file, const char *func, unsigned int line) +#endif +{ + struct parallel_frag *frag, *n; + unsigned int hash; + + //LM_ERR("VLAD - F_PARALLEL malloc block %p for size %lu\n",fm,size); + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "%s_malloc(%lu), called from %s: %s(%d)\n", fm->name, size, file, func, + line); + #endif + + /*size must be a multiple of 8*/ + size=ROUNDUP(size); + + /*search for a suitable free frag*/ + + //LM_ERR("big Hash = %lu , current hash size = %lu\n",F_PARALLEL_HASH_SIZE,F_PARALLEL_GET_HASH(size)); + + for(hash=F_PARALLEL_GET_HASH(size);hashfree_hash[hash].first; + //LM_ERR("Checking in hash %d, first is frag %p\n",hash,frag); + for( ; frag; frag = frag->u.nxt_free ) { + //LM_ERR("Vlad searching %lu size, in frag %p size %lu , hash %d\n",size,frag,frag->size,hash); + if ( frag->size >= size ) goto found; + /* try in a bigger bucket */ + } + } + /* not found, bad! */ + +#if defined(DBG_MALLOC) || defined(STATISTICS) + LM_WARN("not enough contiguous free %s memory (%ld bytes left, need %lu), attempting " \ + "defragmentation... please increase the \"-%s\" command line parameter!\n", + fm->name, fm->size - fm->real_used, size, fm->name[0] == 'p' ? "M" : "m"); +#else + LM_WARN("not enough contiguous free %s memory (need %lu), attempting defragmentation... " \ + "please increase the \"-%s\" command line parameter!\n", + fm->name, fm->size - fm->real_used, size, fm->name[0] == 'p' ? "M" : "m"); +#endif + + for( frag = fm->first_frag; (char*)frag < (char*)fm->last_frag; ) + { + n = F_PARALLEL_FRAG_NEXT(frag); + + if (((char*)n < (char*)fm->last_frag) && + frag_is_free(n) && frag_is_free(frag)) + { + /* detach frag*/ + parallel_remove_free(fm, frag); + + do + { + parallel_remove_free(fm, n); + frag->size += n->size + F_PARALLEL_FRAG_OVERHEAD; + + #if defined(DBG_MALLOC) || defined(STATISTICS) + //fm->real_used -= F_PARALLEL_FRAG_OVERHEAD; + fm->used += F_PARALLEL_FRAG_OVERHEAD; + #endif + + if (frag->size >size) + goto solved; + + n = F_PARALLEL_FRAG_NEXT(frag); + } + while + ( ((char*)n < (char*)fm->last_frag) && frag_is_free(n)); + + parallel_insert_free(fm,frag); + + } + + frag = n; + } + +#if defined(DBG_MALLOC) || defined(STATISTICS) + LM_ERR(oom_errorf, fm->name, fm->size - fm->real_used, size, + fm->name[0] == 'p' ? "M" : "m"); +#else + LM_ERR(oom_nostats_errorf, fm->name, size, fm->name[0] == 'p' ? "M" : "m"); +#endif + pkg_threshold_check(); + return 0; + + +found: + /* we found it!*/ + //LM_ERR("We found it !!! \n"); + + parallel_remove_free(fm,frag); + + /*see if we'll use full frag, or we'll split it in 2*/ + + #if !defined INLINE_ALLOC && defined DBG_MALLOC + parallel_split_frag_dbg(fm, frag, size, file, "fm_malloc frag", line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + parallel_split_frag(fm, frag, size); + #else + parallel_split_frag(fm, frag, size, file, "fm_malloc frag", line); + #endif + + #ifdef DBG_MALLOC + frag->file=file; + frag->func=func; + frag->line=line; + LM_GEN1(memlog, "%s_malloc(%lu), returns address %p\n", fm->name, size, + (char*)frag+sizeof(struct parallel_frag)); + #endif + +solved: + + #if defined(DBG_MALLOC) || defined(STATISTICS) + if (fm->max_real_usedreal_used) + fm->max_real_used=fm->real_used; + fm->fragments += 1; + #endif + + frag->block_ptr = fm; + + pkg_threshold_check(); + + //LM_ERR("Alloc done ok ! - return frag %p with size %lu \n",frag,frag->size); + return (char*)frag+sizeof(struct parallel_frag); +} + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void parallel_free_dbg(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line) +#elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC +void parallel_free(struct parallel_block *fm, void *p) +#else +void parallel_free(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line) +#endif +{ + struct parallel_frag *f, *n; + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "%s_free(%p), called from %s: %s(%d)\n", fm->name, p, file, + func, line); + if (p && (p > (void *)fm->last_frag || p < (void *)fm->first_frag)) { + LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); + abort(); + } + #endif + if (!p) { + LM_GEN1(memlog, "free(NULL) called\n"); + return; + } + + f = F_PARALLEL_FRAG(p); + + fm = f->block_ptr; + + //LM_ERR("VLAD - F_PARALLEL free in block %p of %p with idx %d \n",fm,p,fm->idx); + + lock_get(hash_locks[fm->idx]); + + check_double_free(p, f, fm); + +#ifdef DBG_MALLOC + LM_GEN1(memlog, "freeing block alloc'ed from %s: %s(%ld)\n", + f->file, f->func, f->line); +#endif + + /* attempt to join with a next fragment that also happens to be free */ + n = F_PARALLEL_FRAG_NEXT(f); + if (((char*)n < (char*)fm->last_frag) && frag_is_free(n)) { + parallel_remove_free(fm, n); + /* join */ + f->size += n->size + F_PARALLEL_FRAG_OVERHEAD; + + #if defined(DBG_MALLOC) || defined(STATISTICS) + //fm->real_used -= F_PARALLEL_FRAG_OVERHEAD; + fm->used += F_PARALLEL_FRAG_OVERHEAD; + #endif + } + +#ifdef DBG_MALLOC + f->file = file; + f->func = func; + f->line = line; +#endif + + parallel_insert_free(fm, f); +#if defined(DBG_MALLOC) || defined(STATISTICS) + fm->fragments -= 1; +#endif + pkg_threshold_check(); + + //LM_ERR("Succes in freeing ! \n"); + + lock_release(hash_locks[fm->idx]); +} + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void parallel_free_dbg_unsafe(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line) +#elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC +void parallel_free_unsafe(struct parallel_block *fm, void *p) +#else +void parallel_free_unsafe(struct parallel_block *fm, void *p, const char *file, + const char *func, unsigned int line) +#endif +{ + struct parallel_frag *f, *n; + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "%s_free(%p), called from %s: %s(%d)\n", fm->name, p, file, + func, line); + if (p && (p > (void *)fm->last_frag || p < (void *)fm->first_frag)) { + LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); + abort(); + } + #endif + if (!p) { + LM_GEN1(memlog, "free(NULL) called\n"); + return; + } + + f = F_PARALLEL_FRAG(p); + + check_double_free(p, f, fm); + +#ifdef DBG_MALLOC + LM_GEN1(memlog, "freeing block alloc'ed from %s: %s(%ld)\n", + f->file, f->func, f->line); +#endif + + /* attempt to join with a next fragment that also happens to be free */ + n = F_PARALLEL_FRAG_NEXT(f); + if (((char*)n < (char*)fm->last_frag) && frag_is_free(n)) { + parallel_remove_free(fm, n); + /* join */ + f->size += n->size + F_PARALLEL_FRAG_OVERHEAD; + + #if defined(DBG_MALLOC) || defined(STATISTICS) + //fm->real_used -= F_PARALLEL_FRAG_OVERHEAD; + fm->used += F_PARALLEL_FRAG_OVERHEAD; + #endif + } + +#ifdef DBG_MALLOC + f->file = file; + f->func = func; + f->line = line; +#endif + + parallel_insert_free(fm, f); +#if defined(DBG_MALLOC) || defined(STATISTICS) + fm->fragments -= 1; +#endif + pkg_threshold_check(); + + //LM_ERR("Succes in freeing ! \n"); +} + + + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void *parallel_realloc_dbg(struct parallel_block *fm, void *p, unsigned long size, + const char *file, const char *func, unsigned int line) +#elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC +void *parallel_realloc(struct parallel_block *fm, void *p, unsigned long size) +#else +void *parallel_realloc(struct parallel_block *fm, void *p, unsigned long size, + const char *file, const char *func, unsigned int line) +#endif +{ + struct parallel_frag *f; + unsigned long diff; + unsigned long orig_size; + struct parallel_frag *n; + void *ptr,*input; + + //LM_ERR("VLAD - F_PARALLEL realloc in block %p of %p \n",fm,p); + + input = p; + + if (p) { + fm = F_PARALLEL_FRAG(p)->block_ptr; + + lock_get(hash_locks[fm->idx]); + + //LM_ERR("Vlad - forcing our way into the same block for realloc %p, idx = %d \n",fm,fm->idx); + } else { + //LM_ERR("Vlad - fresh realloc - we were allocated block %p \n",fm); + } + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "%s_realloc(%p, %lu->%lu), called from %s: %s(%d)\n", + fm->name, p, p ? F_PARALLEL_FRAG(p)->size : 0, size, file, func, line); + if (p && (p > (void *)fm->last_frag || p < (void *)fm->first_frag)) { + LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); + abort(); + } + #endif + + if (size == 0) { + if (p) { + #if !defined INLINE_ALLOC && defined DBG_MALLOC + parallel_free_dbg(fm, p, file, func, line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + parallel_free(fm, p); + #else + parallel_free(fm, p, file, func, line); + #endif + + lock_release(hash_locks[fm->idx]); + } + pkg_threshold_check(); + return 0; + } + + if (!p) + #if !defined INLINE_ALLOC && defined DBG_MALLOC + return parallel_malloc_dbg(fm, size, file, func, line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + return parallel_malloc(fm, size); + #else + return parallel_malloc(fm, size, file, func, line); + #endif + + f = F_PARALLEL_FRAG(p); + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", + f, f->file, f->func, f->line); + #endif + + size = ROUNDUP(size); + orig_size = f->size; + + if (f->size > size) { + //LM_ERR("Vlad - shrink realloc \n"); + /* shrink */ + #ifdef DBG_MALLOC + LM_GEN1(memlog, "shrinking from %lu to %lu\n", f->size, size); + #endif + + #if !defined INLINE_ALLOC && defined DBG_MALLOC + parallel_split_frag_dbg(fm, f, size, file, "fm_realloc frag", line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + parallel_split_frag(fm, f, size); + #else + parallel_split_frag(fm, f, size, file, "fm_realloc frag", line); + #endif + + } else if (f->size < size) { + //LM_ERR("Vlad - grow realloc \n"); + /* grow */ + #ifdef DBG_MALLOC + LM_GEN1(memlog, "growing from %lu to %lu\n", f->size, size); + #endif + + diff = size-f->size; + n = F_PARALLEL_FRAG_NEXT(f); + n->block_ptr = fm; + + if (((char*)n < (char*)fm->last_frag) && frag_is_free(n) && + ((n->size+F_PARALLEL_FRAG_OVERHEAD)>=diff)) { + //LM_ERR("Attempting join \n"); + + parallel_remove_free(fm,n); + /* join */ + f->size += n->size + F_PARALLEL_FRAG_OVERHEAD; + + #if defined(DBG_MALLOC) || defined(STATISTICS) + //fm->real_used -= F_PARALLEL_FRAG_OVERHEAD; + fm->used += F_PARALLEL_FRAG_OVERHEAD; + #endif + + /* split it if necessary */ + if (f->size > size){ + #if !defined INLINE_ALLOC && defined DBG_MALLOC + parallel_split_frag_dbg(fm, f, size, file, "fm_realloc frag", line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + parallel_split_frag(fm, f, size); + #else + parallel_split_frag(fm, f, size, file, "fm_realloc frag", line); + #endif + } + } else { + /* could not join => realloc */ + //LM_ERR("Attempting full realloc \n"); + + #if !defined INLINE_ALLOC && defined DBG_MALLOC + ptr = parallel_malloc_dbg(fm, size, file, func, line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + ptr = parallel_malloc(fm, size); + #else + ptr = parallel_malloc(fm, size, file, func, line); + #endif + + if (ptr) { + /* copy, need by libssl */ + memcpy(ptr, p, orig_size); + + //LM_ERR("Free inside of realloc !!! :( \n"); + + #if !defined INLINE_ALLOC && defined DBG_MALLOC + parallel_free_dbg_unsafe(fm, p, file, func, line); + #elif !defined F_PARALLEL_MALLOC_DYN && !defined DBG_MALLOC + parallel_free_unsafe(fm, p); + #else + parallel_free_unsafe(fm, p, file, func, line); + #endif + } + p = ptr; + } + } else { + /* do nothing */ + #ifdef DBG_MALLOC + LM_GEN1(memlog, "doing nothing, same size: %lu - %lu\n", f->size, size); + #endif + } + + #ifdef DBG_MALLOC + LM_GEN1(memlog, "returning %p\n", p); + #endif + + #if defined(DBG_MALLOC) || defined(STATISTICS) + if (fm->max_real_usedreal_used) + fm->max_real_used=fm->real_used; + #endif + + f->block_ptr = fm; + + if (input) + lock_release(hash_locks[fm->idx]); + + pkg_threshold_check(); + return p; +} + +#if !defined INLINE_ALLOC && defined DBG_MALLOC +void parallel_status_dbg(struct parallel_block *fm) +#else +void parallel_status(struct parallel_block *fm) +#endif +{ + struct parallel_frag *f; + unsigned int i,j,bucket; + unsigned int h; + int unused; + unsigned long size; + + //LM_ERR("VLAD - F_PARALLEL status in block %p \n",fm); + +#ifdef DBG_MALLOC + mem_dbg_htable_t allocd; + struct mem_dbg_entry *it; +#endif + + /* TODO - 128 hardcode */ + for (bucket=0;bucket<128;bucket++) { + fm = shm_blocks[bucket]; + lock_get(hash_locks[fm->idx]); + + LM_GEN1(memdump, "fm_status (%p):\n", fm); + if (!fm) return; + + LM_GEN1(memdump, " heap size= %ld\n", fm->size); +#if defined(DBG_MALLOC) || defined(STATISTICS) + LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n", + fm->used, fm->real_used, fm->size-fm->used); + LM_GEN1(memdump, " max used (+overhead)= %lu\n", fm->max_real_used); +#endif + +#if defined(DBG_MALLOC) + dbg_ht_init(allocd); + + for (f = fm->first_frag; f >= fm->first_frag && f < fm->last_frag; + f = F_PARALLEL_FRAG_NEXT(f)) { + if (!frag_is_free(f) && f->file) + if (dbg_ht_update(allocd, f->file, f->func, f->line, f->size) < 0) { + LM_ERR("Unable to update alloc'ed. memory summary\n"); + dbg_ht_free(allocd); + return; + } + } + + if (f != fm->last_frag) + LM_GEN1(memdump, "failed to walk through all fragments (%p %p %p)\n", + f, fm->first_frag, fm->last_frag); + + LM_GEN1(memdump, " dumping summary of all alloc'ed. fragments:\n"); + LM_GEN1(memdump, "------------+---------------------------------------\n"); + LM_GEN1(memdump, "total_bytes | num_allocations x [file: func, line]\n"); + LM_GEN1(memdump, "------------+---------------------------------------\n"); + for(i=0; i < DBG_HASH_SIZE; i++) { + it = allocd[i]; + while (it) { + LM_GEN1(memdump, " %10lu : %lu x [%s: %s, line %lu]\n", + it->size, it->no_fragments, it->file, it->func, it->line); + it = it->next; + } + } + LM_GEN1(memdump, "----------------------------------------------------\n"); + + dbg_ht_free(allocd); +#endif + + LM_GEN1(memdump, "dumping free list:\n"); + for(h=0,i=0,size=0;hfree_hash[h].first,j=0; f; + size+=f->size,f=f->u.nxt_free,i++,j++){ } + if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t" + " bucket size: %9lu - %9lu (first %9lu)\n", + h, j, unused, F_PARALLEL_UN_HASH(h), + ((h<=F_PARALLEL_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* F_PARALLEL_UN_HASH(h), + fm->free_hash[h].first->size + ); + if (j!=fm->free_hash[h].no){ + LM_CRIT("different free frag. count: %d!=%ld" + " for hash %3d\n", j, fm->free_hash[h].no, h); + } + + } + LM_GEN1(memdump, "TOTAL: %6d free fragments = %6lu free bytes\n", i, size); + LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)F_PARALLEL_FRAG_OVERHEAD ); + LM_GEN1(memdump, "-----------------------------\n"); + + lock_release(hash_locks[fm->idx]); + } +} + +#define F_PARALLEL_MALLOC_DYN + diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 376eeb04346..fab9c576cce 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -100,6 +100,10 @@ static int shm_shmid=-1; /*shared memory id*/ gen_lock_t *mem_lock; #endif +#if defined F_PARALLEL_MALLOC +gen_lock_t *hash_locks[128]; +#endif + #ifdef HP_MALLOC gen_lock_t *mem_locks; #endif @@ -107,6 +111,14 @@ gen_lock_t *mem_locks; static void* shm_mempool=INVALID_MAP; void *shm_block; +/* TODO - integrate to script */ +int total_pools = 128; +/* we allocated 128 * 250 ~= 32 GB for the split pool */ +static void** shm_mempools=NULL; +void **shm_blocks; + +int init_done=0; + #ifdef DBG_MALLOC gen_lock_t *mem_dbg_lock; unsigned long shm_dbg_pool_size; @@ -270,7 +282,7 @@ void *shm_getmem(int fd, void *force_addr, unsigned long size) int shm_use_global_lock; #endif -int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) +int shm_mem_init_mallocs(void* mempool, unsigned long pool_size,int idx) { #ifdef HP_MALLOC int i; @@ -339,6 +351,18 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) shm_frag_func = hp_frag_func; shm_frag_line = hp_frag_line; break; +#endif +#ifdef F_PARALLEL_MALLOC + case MM_F_PARALLEL_MALLOC: + case MM_F_PARALLEL_MALLOC_DBG: + shm_stats_core_init = (osips_shm_stats_init_f)parallel_stats_core_init; + shm_stats_get_index = parallel_stats_get_index; + shm_stats_set_index = parallel_stats_set_index; + shm_frag_overhead = F_PARALLEL_FRAG_OVERHEAD; + shm_frag_file = parallel_frag_file; + shm_frag_func = parallel_frag_func; + shm_frag_line = parallel_frag_line; + break; #endif default: LM_ERR("current build does not include support for " @@ -365,6 +389,12 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) case MM_HP_MALLOC_DBG: shm_frag_size = hp_frag_size; break; +#endif +#ifdef F_PARALLEL_MALLOC + case MM_F_PARALLEL_MALLOC: + case MM_F_PARALLEL_MALLOC_DBG: + shm_frag_size = parallel_frag_size; + break; #endif default: LM_ERR("current build does not include support for " @@ -373,6 +403,31 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) } switch (mem_allocator_shm) { +#ifdef F_PARALLEL_MALLOC + case MM_F_PARALLEL_MALLOC: + //LM_ERR("VLAD initializing block %d \n",idx); + shm_blocks[idx] = parallel_malloc_init(mempool, pool_size, "shm", idx); + if (!shm_blocks[idx]) { + LM_CRIT("parallel alloc init :( \n"); + goto err_destroy; + } + //LM_ERR("Done allocating - setting func pointers \n"); + gen_shm_malloc = (osips_block_malloc_f)parallel_malloc; + gen_shm_malloc_unsafe = (osips_block_malloc_f)parallel_malloc; + gen_shm_realloc = (osips_block_realloc_f)parallel_realloc; + gen_shm_realloc_unsafe = (osips_block_realloc_f)parallel_realloc; + gen_shm_free = (osips_block_free_f)parallel_free; + gen_shm_free_unsafe = (osips_block_free_f)parallel_free; + gen_shm_info = (osips_mem_info_f)parallel_info; + gen_shm_status = (osips_mem_status_f)parallel_status; + gen_shm_get_size = (osips_get_mmstat_f)parallel_get_size; + gen_shm_get_used = (osips_get_mmstat_f)parallel_get_used; + gen_shm_get_rused = (osips_get_mmstat_f)parallel_get_real_used; + gen_shm_get_mused = (osips_get_mmstat_f)parallel_get_max_real_used; + gen_shm_get_free = (osips_get_mmstat_f)parallel_get_free; + gen_shm_get_frags = (osips_get_mmstat_f)parallel_get_frags; + break; +#endif #ifdef F_MALLOC case MM_F_MALLOC: shm_block = fm_malloc_init(mempool, pool_size, "shm"); @@ -496,10 +551,15 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) } #endif - if (!shm_block){ - LM_CRIT("could not initialize shared malloc\n"); - shm_mem_destroy(); - return -1; + if (mem_allocator_shm != MM_F_PARALLEL_MALLOC) { + if (!shm_block){ +err_destroy: + LM_CRIT("could not initialize shared malloc\n"); + shm_mem_destroy(); + return -1; + } + } else { + //LM_ERR("VLAD - no global check for PARALLEL_ALLOC \n"); } #if defined(SHM_EXTRA_STATS) && defined(SHM_SHOW_DEFAULT_GROUP) @@ -576,7 +636,22 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) memset(shm_hash_usage, 0, HP_TOTAL_HASH_SIZE * sizeof *shm_hash_usage); #endif -#if defined F_MALLOC || defined Q_MALLOC +#if defined F_PARALLEL_MALLOC + //LM_ERR("Vlad - init multi locks here on idx %d \n",idx); + hash_locks[idx] = shm_malloc_unsafe(sizeof(gen_lock_t)); + if (!hash_locks[idx]) { + LM_CRIT("could not initialize lock on idx %d\n",idx); + shm_mem_destroy(); + return -1; + } + + if (!lock_init(hash_locks[idx])) { + LM_CRIT("could not initialize lock on idx %d\n",idx); + shm_mem_destroy(); + return -1; + } + +#elif defined F_MALLOC || defined Q_MALLOC mem_lock = shm_malloc_unsafe(sizeof *mem_lock); if (!mem_lock) { LM_CRIT("could not allocate the shm lock\n"); @@ -687,7 +762,8 @@ int shm_dbg_mem_init_mallocs(void* mempool, unsigned long pool_size) int shm_mem_init(void) { - int fd = -1; + int fd = -1,i=0; + unsigned long block_size; LM_INFO("allocating SHM block\n"); #ifdef SHM_MMAP @@ -699,27 +775,69 @@ int shm_mem_init(void) return -1; } -#ifndef USE_ANON_MMAP - fd=open("/dev/zero", O_RDWR); - if (fd==-1){ - LM_CRIT("could not open /dev/zero: %s\n", strerror(errno)); + /* TODO - full speed ahead, we don't care about allocator type, we will hardcode for testing */ + shm_mempools = malloc(total_pools * sizeof(void*)); + if (!shm_mempools) { + LM_ERR("Failed to init all the mempools \n"); return -1; } -#endif /* USE_ANON_MMAP */ + memset(shm_mempools,0,total_pools * sizeof(void *)); + + shm_blocks = malloc(total_pools * sizeof(void *)); + if (!shm_blocks) { + LM_ERR("Failed to init all the blocks \n"); + return -1; + } + memset(shm_blocks,0,total_pools * sizeof(void *)); - shm_mempool = shm_getmem(fd, NULL, shm_mem_size); #ifndef USE_ANON_MMAP - close(fd); + //LM_ERR("Anon mmap \n"); + fd=open("/dev/zero", O_RDWR); + if (fd==-1){ + LM_CRIT("could not open /dev/zero: %s\n", strerror(errno)); + return -1; + } #endif /* USE_ANON_MMAP */ - if (shm_mempool == INVALID_MAP) { - LM_CRIT("could not attach shared memory segment: %s\n", - strerror(errno)); - /* destroy segment*/ - shm_mem_destroy(); - return -1; + for (i=0;i