Skip to content

Commit

Permalink
paralel alloc - wip
Browse files Browse the repository at this point in the history
  • Loading branch information
vladpaiu committed Jan 3, 2025
1 parent a27db64 commit ea018b0
Show file tree
Hide file tree
Showing 9 changed files with 1,468 additions and 32 deletions.
1 change: 1 addition & 0 deletions Makefile.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions mem/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
26 changes: 20 additions & 6 deletions mem/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down
286 changes: 286 additions & 0 deletions mem/f_parallel_malloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
#ifdef F_PARALLEL_MALLOC

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#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
Loading

0 comments on commit ea018b0

Please sign in to comment.