/*
*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;
};
*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;
};