Пример #1
0
void fm_free(struct fm_block* qm, void* p)
#endif
{
	struct fm_frag* f,*n;

	#ifdef DBG_F_MALLOC
	LM_DBG("params(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line);
	if (p>(void*)qm->last_frag || p<(void*)qm->first_frag){
		LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
		abort();
	}
	#endif
	if (p==0) {
		LM_DBG("free(0) called\n");
		return;
	}
	f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag));

	#ifdef DBG_F_MALLOC
	LM_DBG("freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func,
			f->line);
	f->file=file;
	f->func=func;
	f->line=line;
	#endif

join:

	if( qm->large_limit < qm->large_space )
		goto no_join;

	n = FRAG_NEXT(f);

	if (((char*)n < (char*)qm->last_frag) &&  n->prev )
	{

		fm_remove_free(qm, n);
		/* join */
		f->size += n->size + FRAG_OVERHEAD;

		#if defined(DBG_F_MALLOC) || defined(STATISTICS)
		//qm->real_used -= FRAG_OVERHEAD;
		qm->used += FRAG_OVERHEAD;
		#endif

		goto join;
	}

no_join:

	fm_insert_free(qm, f);
#if defined(DBG_F_MALLOC) || defined(STATISTICS)
	qm->fragments -= 1;
#endif
	pkg_threshold_check();
}
Пример #2
0
void* fm_malloc(struct fm_block* qm, unsigned long size)
#endif
{
	struct fm_frag* frag,*n;
	unsigned int hash;
		
	#ifdef DBG_F_MALLOC
	LM_DBG("params (%p, %lu), called from %s: %s(%d)\n", qm, size, file, func,
			line);
	#endif
	
	/*size must be a multiple of 8*/
	size=ROUNDUP(size);
	
	/*search for a suitable free frag*/

	for(hash=GET_HASH(size);hash<F_HASH_SIZE;hash++){
		frag=qm->free_hash[hash].first;
		for( ; frag; frag = frag->u.nxt_free )
			if ( frag->size >= size ) goto found;
		/* try in a bigger bucket */
	}
	/* not found, bad! */

	LM_WARN("Not enough free memory, will atempt defragmenation\n");

	for( frag = qm->first_frag; (char*)frag < (char*)qm->last_frag;  )
	{
		n = FRAG_NEXT(frag);

		if ( ((char*)n < (char*)qm->last_frag) &&  n->prev && frag->prev )
		{
			/* detach frag*/
			fm_remove_free(qm, frag);
			
			do
			{
				fm_remove_free(qm, n);
				frag->size += n->size + FRAG_OVERHEAD;

				#if defined(DBG_F_MALLOC) || defined(STATISTICS)
				//qm->real_used -= FRAG_OVERHEAD;
				qm->used += FRAG_OVERHEAD;
				#endif

				if( frag->size >size )
					goto solved;
				
				n = FRAG_NEXT(frag);
			}
			while
			( ((char*)n < (char*)qm->last_frag) &&  n->prev);

			fm_insert_free(qm,frag);
			
		}

		frag = n;
	}

	pkg_threshold_check();
	return 0;


		

found:
	/* we found it!*/
	
	fm_remove_free(qm,frag);
	
	/*see if we'll use full frag, or we'll split it in 2*/
	
	#ifdef DBG_F_MALLOC
	fm_split_frag(qm, frag, size, file, func, line);

	frag->file=file;
	frag->func=func;
	frag->line=line;
	frag->check=ST_CHECK_PATTERN;
	LM_DBG("params(%p, %lu), returns address %p \n", qm, size,
		(char*)frag+sizeof(struct fm_frag));
	#else
	fm_split_frag(qm, frag, size);
	#endif

solved:

	#if defined(DBG_F_MALLOC) || defined(STATISTICS)
	if (qm->max_real_used<qm->real_used)
		qm->max_real_used=qm->real_used;
	#endif

	pkg_threshold_check();
	return (char*)frag+sizeof(struct fm_frag);
}
Пример #3
0
void fm_split_frag(struct fm_block* qm, struct fm_frag* frag,
					unsigned long size)
#endif
{
	unsigned long rest;
	struct fm_frag* n;

	rest=frag->size-size;
	#ifdef MEM_FRAG_AVOIDANCE
	if ((rest> (FRAG_OVERHEAD+F_MALLOC_OPTIMIZE))||
		(rest>=(FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/
	#else
	if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){
	#endif
		frag->size=size;
		/*split the fragment*/
		n=FRAG_NEXT(frag);
		n->size=rest-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_F_MALLOC) || defined(STATISTICS)
		qm->real_used+=FRAG_OVERHEAD;
		#endif

		 */
		#if defined(DBG_F_MALLOC) || defined(STATISTICS)
		qm->used-=FRAG_OVERHEAD;
		#endif

		#ifdef DBG_F_MALLOC
		/* frag created by malloc, mark it*/
		n->file=file;
		n->func="frag. from fm_malloc";
		n->line=line;
		n->check=ST_CHECK_PATTERN;
		#endif
		/* reinsert n in free list*/
		fm_insert_free(qm, n);
	}else{
		/* we cannot split this fragment any more => alloc all of it*/
	}
}



/* init malloc and return a fm_block*/
struct fm_block* fm_malloc_init(char* address, unsigned long size)
{
	char* start;
	char* end;
	struct fm_block* qm;
	unsigned long init_overhead;
	
	/* make address and size multiple of 8*/
	start=(char*)ROUNDUP((unsigned long) address);
	LM_DBG("F_OPTIMIZE=%lu, /ROUNDTO=%lu\n",
			F_MALLOC_OPTIMIZE, F_MALLOC_OPTIMIZE/ROUNDTO);
	LM_DBG("F_HASH_SIZE=%lu, fm_block size=%lu\n",
			F_HASH_SIZE, (long)sizeof(struct fm_block));
	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+FRAG_OVERHEAD)) return 0;
	size=ROUNDDOWN(size);

	init_overhead=(ROUNDUP(sizeof(struct fm_block))+ 2 * FRAG_OVERHEAD);
	
	
	if (size < init_overhead)
	{
		/* not enough mem to create our control structures !!!*/
		return 0;
	}
	end=start+size;
	qm=(struct fm_block*)start;
	memset(qm, 0, sizeof(struct fm_block));
	qm->size=size;

	#if defined(DBG_F_MALLOC) || defined(STATISTICS)

	qm->used=size-init_overhead;
	qm->real_used=size;
	qm->max_real_used=init_overhead;
	#endif
	
	qm->first_frag=(struct fm_frag*)(start+ROUNDUP(sizeof(struct fm_block)));
	qm->last_frag=(struct fm_frag*)(end-sizeof(struct fm_frag));
	/* init initial fragment*/
	qm->first_frag->size=size-init_overhead;
	qm->last_frag->size=0;

	qm->last_frag->prev=NULL;
	qm->first_frag->prev=NULL;
	
	#ifdef DBG_F_MALLOC
	qm->first_frag->check=ST_CHECK_PATTERN;
	qm->last_frag->check=END_CHECK_PATTERN1;
	#endif
	
	/* link initial fragment into the free list*/

	qm->large_space = 0;
	qm->large_limit = qm->size / 100 * F_MALLOC_DEFRAG_PERCENT;

	if( qm->large_limit < F_MALLOC_DEFRAG_LIMIT )
		qm->large_limit = F_MALLOC_DEFRAG_LIMIT;

	fm_insert_free(qm, qm->first_frag);
	
	
	return qm;
}
Пример #4
0
void* fm_malloc(struct fm_block* qm, unsigned long size)
#endif
{
    struct fm_frag* frag,*n;
    unsigned int hash;

#ifdef DBG_MALLOC
    LM_GEN1(memlog, "%s_malloc(%lu), called from %s: %s(%d)\n", qm->name, size, file, func,
            line);
#endif

    /*size must be a multiple of 8*/
    size=ROUNDUP(size);

    /*search for a suitable free frag*/

    for(hash=GET_HASH(size); hash<F_HASH_SIZE; hash++) {
        frag=qm->free_hash[hash].first;
        for( ; frag; frag = frag->u.nxt_free )
            if ( frag->size >= size ) goto found;
        /* try in a bigger bucket */
    }
    /* not found, bad! */

#if defined(DBG_MALLOC) || defined(STATISTICS)
    LM_ERR(oom_errorf, qm->name, qm->size - qm->real_used,
           qm->name[0] == 'p' ? "M" : "m");
    LM_INFO("attempting defragmentation... (need %lu bytes)\n", size);
#else
    LM_ERR(oom_nostats_errorf, qm->name, qm->name[0] == 'p' ? "M" : "m");
    LM_INFO("attempting defragmentation... (need %lu bytes)\n", size);
#endif

    for( frag = qm->first_frag; (char*)frag < (char*)qm->last_frag;  )
    {
        n = FRAG_NEXT(frag);

        if ( ((char*)n < (char*)qm->last_frag) &&  n->prev && frag->prev )
        {
            /* detach frag*/
            fm_remove_free(qm, frag);

            do
            {
                fm_remove_free(qm, n);
                frag->size += n->size + FRAG_OVERHEAD;

#if defined(DBG_MALLOC) || defined(STATISTICS)
                //qm->real_used -= FRAG_OVERHEAD;
                qm->used += FRAG_OVERHEAD;
#endif

                if( frag->size >size ) {
#ifdef DBG_MALLOC
                    /* mark it as "busy" */
                    frag->is_free = 0;
#endif

                    goto solved;
                }

                n = FRAG_NEXT(frag);
            }
            while
            ( ((char*)n < (char*)qm->last_frag) &&  n->prev);

            fm_insert_free(qm,frag);

        }

        frag = n;
    }

    LM_INFO("unable to alloc a big enough fragment!\n");
    pkg_threshold_check();
    return 0;


found:
    /* we found it!*/

    fm_remove_free(qm,frag);

#ifdef DBG_MALLOC
    /* mark it as "busy" */
    frag->is_free = 0;
#endif

    /*see if we'll use full frag, or we'll split it in 2*/

#ifdef DBG_MALLOC
    fm_split_frag(qm, frag, size, file, func, line);

    frag->file=file;
    frag->func=func;
    frag->line=line;
    frag->check=ST_CHECK_PATTERN;
    LM_GEN1(memlog, "%s_malloc(%lu), returns address %p\n", qm->name, size,
            (char*)frag+sizeof(struct fm_frag));
#else
    fm_split_frag(qm, frag, size);
#endif

solved:

#if defined(DBG_MALLOC) || defined(STATISTICS)
    if (qm->max_real_used<qm->real_used)
        qm->max_real_used=qm->real_used;
    qm->fragments += 1;
#endif

    pkg_threshold_check();
    return (char*)frag+sizeof(struct fm_frag);
}