1. 程式人生 > >A memery management interface---Source code_except.c

A memery management interface---Source code_except.c

/*
 *checking implementation of mem interface
 * */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include "except.h"
#include "mem.h"

#define hash(p,t) (((unsigned long)(p)>>3)%( sizeof(t)/sizeof((t)[0])-1 ) )
#define NDESCRIPTORS 512
#define NALLOC 4096

Except_T Mem_failed = {"failed to allocate memery"};
static FILE * log=NULL;
union align
{
    int i;
    long l;
    long * lp;
    void *p;
    void (*fp)(void);
    float f;
    double d;
    long double ld;
};


#define HTAB_LEN 2048
/* memery allocator */
static  struct  descriptor
{
    struct descriptor * free;
    struct descriptor * link;
    const void * ptr;
    long size;
    const char * file;
    int line;
} * htab[HTAB_LEN];

static struct descriptor freelist={&freelist};


/*return the descriptor*/
static struct descriptor * find(const void * ptr)  
{    struct descriptor *bp=htab[hash(ptr,htab)];
    while(bp &&bp->ptr!=ptr)
        bp = bp->link;   
    return(bp);
};       

static struct descriptor * avail = NULL;
static int nleft=-1;
static struct descriptor * dalloc(void * ptr,long size,const char * file,int line)
{
    if (nleft<0)
    {    avail = malloc(NDESCRIPTORS*sizeof(*avail));   
        if (avail==NULL)
            return(NULL);   
        nleft = NDESCRIPTORS;
    }       
    avail->ptr = ptr;
    avail->size = size;
    avail->file = file;
    avail->line = line;
    avail->free = avail->link = NULL;
    nleft--;
    return(avail++);
};

/* free descriptor  */
static void dfree(struct descriptor *bp)
{
    if (bp)
    {       
        unsigned long h =hash(bp->ptr,htab);
        struct descriptor * prev = htab[h];
        while(prev &&prev->link!=bp)
            prev= prev->link;   
        assert(prev);
        prev->link = bp->link;
        free(bp);
    }       
};       

void Mem_free(void * ptr,const char * file,int line)
{
#define FREE_MEM(bp) (bp)->free = freelist.free;    /
        freelist.free = (bp)           
    void *next;   
    if (ptr)
    {    struct descriptor *bp,*tmp;   
        if (  (bp = find(ptr))==NULL || bp->free)
            Except_raise(&Mem_failed,file,line);   
        next = (char *)bp->ptr+(bp->size/sizeof(union align)+1)*sizeof(union align);
        tmp = freelist.free;   
        while(1)
        {    // merge free blocks    
            long nbytes;   
            if (tmp->ptr==next)
            {    bp->size += tmp->size;    
                dfree(tmp);
                FREE_MEM(bp);
                return;
            }   
            else if (   nbytes=(tmp->size/sizeof(union align)+1)*sizeof(union align), ((char *)tmp->ptr+nbytes) == bp->ptr)
            {    tmp->size += bp->size;   
                dfree(bp);
                FREE_MEM(tmp);
                return;
            }   
            if (tmp==&freelist)   
            {    FREE_MEM(bp);
                return;   
            }       
            tmp = tmp->free;
        };       
    }           
};       

void * Mem_resize(void * ptr,long nbytes,const char * file,int line)
{
    struct descriptor * bp;
    void * newptr;

    assert(ptr);
    assert(nbytes>0);
    if ( ((unsigned long)ptr) %sizeof(union align) !=0  || (bp = find(ptr))==NULL || bp->free  )
        RAISE(Mem_failed);   
    newptr = Mem_alloc(nbytes,file,line);
    memcpy(newptr,ptr,nbytes < bp->size ? nbytes : bp->size);
    Mem_free(ptr,file,line);

    return(newptr);
};       

void * Mem_calloc(long count,long nbytes,const char * file,int line )
{
    void *ptr;

    assert(count>0);
    assert(nbytes>0);
    ptr = Mem_alloc(count*nbytes,file,line);

    memset(ptr,'/0',count*nbytes);

    return (ptr);
};       



static void free_align(struct descriptor *bp)
{
    unsigned long h = hash(bp->ptr,htab);
    struct descriptor *prev,*next;

    prev = htab[h];

    while(prev && prev->link != bp)
        prev = prev->link;    
    if (prev==NULL)    return;

    next = bp->link;
    prev->link = next;
    free((char *)bp->ptr);
    free(bp);
};       

void * Mem_alloc(long nbytes,const char * file,int line)
{
    struct descriptor * bp;
    void * ptr;
    assert(nbytes>0);
    /* modify nbytes */
    nbytes = (nbytes/sizeof(union align)+1) *sizeof(union align);

    for(bp=freelist.free;bp;bp = bp->free)
    {
        if (bp->size>nbytes)
        {
            bp->size -= nbytes;
            ptr = (char *)bp->ptr + bp->size;

            /*     *This space can't be used by Mem_alloc,so,we give it the operating system* */
            if (bp->size==sizeof(union align))
                free_align(bp);       
           
            if ( (bp=dalloc(ptr,nbytes,file,line))!=NULL )
            {   
                unsigned long h = hash(ptr,htab);
                htab[h]->link;
                if (htab[h]!=NULL)   
                {       
                    bp->link=htab[h]->link;
                    htab[h]->link = bp;
                }
                else    htab[h] = bp;
                return (ptr);
            }       
            else
                RAISE(Mem_failed);   
        }       
        if (bp==&freelist)
        {
            struct descriptor * newptr;   
            if ( (ptr=malloc(nbytes+NALLOC))==NULL || (newptr=dalloc(ptr,nbytes+NALLOC,__FILE__,__LINE__))==NULL )
                RAISE(Mem_failed);   
            newptr->free = freelist.free;       
            freelist.free = newptr;
        }       
    }
    return (NULL);
};       

void Mem_init(FILE *log)
{
    int i;
    for(i=0;i<HTAB_LEN;i++)
        htab[i] = NULL;
};