You are on page 1of 11

/* Simple memory manager that implements classes of memory.

This is handy when you want to do a lot of memory allocation for an operation, and at the end, free everythingall without having to keep track of your individual pointers. Just get a new memory class with getclass(), use falloc or clralc with that memory class to get your memory buffers, and call freeclass() on the class you got from getclass() when you are done. Also uses a handy do-it-yourself hashtable to keep track of the allocated buffer s. */ #define GLOBAL #define #define #define #define #define #define #define #define #define SGMEM_FOREIGN SGMEM_GLOBAL SGMEM_SSCREEN SGMEM_TEMP SGMEM_QLIST SGMEM_USER SGMEM_PARSE SGMEM_DYNAMIC SGMEM_FREE 0 1 /* 2 3 4 5 99 100 /* 0xFFFF /* Memory not usable */ User-level globals */ /* Used for temporary operations */ /* Used to construct QLIST */ Base of dynamic memory */ /* Available memory */

#define MAXSYSALLOCS 200 struct mheader { struct mheader *next; /* Doubly linked */ struct mheader *previous; unsigned int mclass; /* Memory mclass */ };

struct SysAlc { unsigned char *sysmemptr; unsigned int size; struct mheader *tail; }; typedef unsigned char Memory; /*---------Global Vars-----------*/ GLOBAL long nballoc = 0; /* Non-foreign bytes allocated */ GLOBAL char outofmem[] = "Out of memory ... %ld bytes already allocated"; /*---------Static Vars-----------*/ /* Head and tail of linked list, initialized in initmem(). */ static struct mheader *mp_head = (struct mheader *)0; static struct mheader *mp_tail = (struct mheader *)0; static Memory *lallocp = (Memory *)0; /* Highest allocated byte */ static unsigned *classtab = (unsigned *)0; static int nextsysalloc = 0;

static struct SysAlc sysmemallocs[MAXSYSALLOCS]; #define #define #define #define HASHNO 101 // should always be a prime number MAXCLASS 900 EXTRACLASS 30 HASHTABLE struct hashtable_s *

unsigned long global_quantity = 0; struct helement { unsigned long key; struct helement *nxt; unsigned long value; }; typedef struct hashtable_s { struct helement *elements[HASHNO]; } HASH; short check4mclasscorruption( unsigned int mclass ); HASHTABLE get_hash() { HASHTABLE r; r = malloc(sizeof(HASH)); memset(r, 0, sizeof(HASH)); return (HASHTABLE)r; } void install_in_hash( HASHTABLE hash, unsigned long key, unsigned long value ) { int i; struct helement *hp; struct helement **hashp = hash->elements; i = key % HASHNO; hp = (struct helement *)malloc(sizeof(struct helement)); memset(hp, 0, sizeof(struct helement)); hp->key hp->value hp->nxt hashp[i] } unsigned long lookup_hashval( HASHTABLE hash, unsigned long key ) { int i; struct helement *hp; struct helement **hashp = hash->elements; i = key % HASHNO; for (hp = hashp[i]; hp; hp = hp->nxt) if (hp->key == key) break; = key; = value; = hashp[i]; = hp;

if (hp) return hp->value; return 0; } void delete_hashval( HASHTABLE hash, unsigned long key ) { int i; struct helement *hp; struct helement **hashp = hash->elements; struct helement *hp_prev = 0; i = key % HASHNO; for (hp = hashp[i]; hp; hp = hp->nxt) { if (hp->key == key) { if (hp_prev) hp_prev->nxt = hp->nxt; else hashp[i] = hp->nxt; free(hp); break; } else hp_prev = hp; } return; } void delete_hash(HASHTABLE hash) { free(hash); } struct memory_class { unsigned int mclass; struct memory_pointer *first; struct memory_pointer *last; }; struct memory_pointer { unsigned char *ptr; unsigned int sz; struct memory_pointer *nxt; struct memory_pointer *prv; struct memory_class *mcp; }; struct threadmem_stuff { HASHTABLE hash; struct memory_class statics[16]; struct memory_class *dynamics[MAXCLASS + EXTRACLASS];

unsigned long quantity; unsigned long quantity_of_allocations; }; // call once for each thread int e_wfalloc_init(void) { struct threadmem_stuff *ptr; ptr = malloc(sizeof(struct threadmem_stuff)); memset(ptr, 0, sizeof(struct threadmem_stuff)); ptr->hash = get_hash(); mp_head = ptr; return 1; }; int clear_memory_manager() { struct threadmem_stuff *tsp = mp_head; int i; struct memory_class *mcp; for (i = 0; i < (sizeof(tsp->statics) / sizeof(tsp->statics[0])); i++) { freeclass(i); } free_special_classes(); freedyn(); mp_head = 0; delete_hash(tsp->hash); free(tsp); return 0; } struct memory_class *find_memory_class(unsigned int mclass) { struct threadmem_stuff *tsp = mp_head; int mclass_index; if (mclass == 99) { tsp->statics[15].mclass = mclass; return &(tsp->statics[15]); } if (mclass < 100) { tsp->statics[mclass].mclass = mclass; return &(tsp->statics[mclass]); } mclass_index = mclass - 100; if (!tsp->dynamics[mclass_index]) { tsp->dynamics[mclass_index] = malloc(sizeof(struct memory_class) ); memset(tsp->dynamics[mclass_index], 0, sizeof(struct memory_clas

s)); tsp->dynamics[mclass_index]->mclass = mclass; } return tsp->dynamics[mclass_index]; } Memory * falloc(unsigned int size, unsigned int memclass) { struct threadmem_stuff *tsp = mp_head; Memory *ptr = malloc(size); struct memory_pointer *mp = malloc(sizeof(struct memory_pointer)); struct memory_class *mcp = find_memory_class(memclass); memset(mp, 0, sizeof(*mp)); tsp->quantity += size; tsp->quantity_of_allocations++; global_quantity += size; mp->sz = size; mp->mcp = mcp; mp->ptr = ptr; if (mp->nxt = mcp->first) // intentionally not == mcp->first->prv = mp; mcp->first = mp; if (!mcp->last) mcp->last = mp; install_in_hash(tsp->hash, ptr, mp); return ptr; } void free_mp(struct memory_pointer *mp) { struct threadmem_stuff *tsp = mp_head; if (!mp) return; delete_hashval(tsp->hash, mp->ptr); if (mp->prv) mp->prv->nxt = mp->nxt; else mp->mcp->first = mp->nxt; if (mp->nxt) { if (mp->nxt->prv != mp) MessageBox(NULL, "linked list error", "uhoh", MB_OK); mp->nxt->prv = mp->prv; } else mp->mcp->last = mp->prv; // It's handy to have free memory marked with a signature byte memset(mp->ptr, '%', mp->sz); tsp->quantity -= mp->sz;

// //

tsp->quantity_of_allocations--; global_quantity -= mp->sz; free(mp->ptr); free(mp); return 1; } int get_thread_mem_quantity() { struct threadmem_stuff *tsp = mp_head; if (tsp) return tsp->quantity; else return 0; } int get_global_quantity() { return global_quantity; } int { freemem( void *p ) struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, p); if (!mp || (mp->ptr != p)) { MessageBox(NULL, "UHOH", "", MB_OK); return 0; } free_mp(mp); return 1; }

short check4mclasscorruption( unsigned int mclass ) { struct threadmem_stuff *tsp = mp_head; struct memory_class *mcp = find_memory_class(mclass); struct memory_pointer *mp; mp = mcp->first; while (mp) { if (mcp != mp->mcp) return TRUE; if (mp->nxt) { if (mp->nxt->prv != mp) return TRUE;

} else { if (mp != mcp->last) return TRUE; } if (mp->prv) { if (mp->prv->nxt != mp) return TRUE; } else { if (mp != mcp->first) return TRUE; } mp = mp->nxt; } return FALSE; } int { freeclass( unsigned int mclass ) struct threadmem_stuff *tsp = mp_head; struct memory_class *mcp = find_memory_class(mclass); unsigned int idx; while (mcp && mcp->first) { free_mp(mcp->first); }

if (mcp->mclass >= 100) { idx = mcp->mclass - 100; free(tsp->dynamics[idx]); tsp->dynamics[idx] = 0; } return 1; } int { freedyn(void) /* Free all dynamic memory classes */

struct threadmem_stuff *tsp = mp_head; int i; for (i = 0; i < MAXCLASS; i++) { if (tsp->dynamics[i]) freeclass(i+100); } return 1; } unsigned get_special_class(char *cl_name)

{ struct threadmem_stuff *tsp = mp_head; int i; struct memory_class *mcp; for (i = MAXCLASS; i < (MAXCLASS + EXTRACLASS); i++) { if (!tsp->dynamics[i]) { mcp = find_memory_class(i+100); return (i+100); } } MessageBox(NULL, "too many classes", "dd", MB_OK); return 0; } void { } void { free_special_classes(void) struct threadmem_stuff *tsp = mp_head; int i; struct memory_class *mcp; for (i = MAXCLASS; i < (MAXCLASS + EXTRACLASS); i++) { if (tsp->dynamics[i]) free_special_class(i+100); } } unsigned getclass(void) { struct threadmem_stuff *tsp = mp_head; int i; struct memory_class *mcp; for (i = 0; i < MAXCLASS; i++) { if (!tsp->dynamics[i]) { mcp = find_memory_class(i+100); return (i+100); } } MessageBox(NULL, "too many classes", "dd", MB_OK); return 0; } void { mapclass( unsigned int oldclass, unsigned int newclass ) struct struct struct struct threadmem_stuff *tsp = mp_head; memory_class *old_mcp = find_memory_class(oldclass); memory_class *new_mcp = find_memory_class(newclass); memory_pointer *mp; free_special_class(unsigned int mclass) freeclass(mclass);

mp = old_mcp->first; while (mp)

{ mp->mcp = new_mcp; mp = mp->nxt; } if (old_mcp->last) { old_mcp->last->nxt = new_mcp->first; if (new_mcp->first) new_mcp->first->prv = old_mcp->last; else new_mcp->last = old_mcp->last; new_mcp->first = old_mcp->first; } old_mcp->last = old_mcp->first = NULL; freeclass(oldclass); } Memory * clralc( unsigned int count, unsigned int mclass ) { fast Memory *p; if(p = falloc(count, mclass)) { memset((Memory *)p, 0, count); } return(p); } /* clralc() */ Memory * ralloc( void *gp, unsigned int nbytes ) { struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, gp); if (!mp || (mp->ptr != gp)) { MessageBox(NULL, "UHOH", "", MB_OK); return 0; } tsp->quantity -= mp->sz; global_quantity -= mp->sz; mp->sz = nbytes; tsp->quantity += mp->sz; global_quantity += mp->sz; delete_hashval(tsp->hash, mp->ptr); mp->ptr = realloc(mp->ptr, nbytes); install_in_hash(tsp->hash, mp->ptr, mp); return mp->ptr; } unsigned int sizemem( byte *p ) { struct threadmem_stuff *tsp = mp_head;

struct memory_pointer *mp = lookup_hashval(tsp->hash, p); if (!mp || (mp->ptr != p)) { MessageBox(NULL, "UHOH", "", MB_OK); return 0; } return mp->sz / 10; } unsigned int sizememinbytes( void *p ) { struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, p); if (!mp || (mp->ptr != p)) { MessageBox(NULL, "UHOH", "", MB_OK); return 0; } return mp->sz; } byte * { zero_ralloc( byte *gp, unsigned int nbytes ) struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, gp); unsigned int oldsize; if (!mp || (mp->ptr != gp)) { MessageBox(NULL, "UHOH", "", MB_OK); return 0; } oldsize = mp->sz; tsp->quantity -= mp->sz; global_quantity -= mp->sz; mp->sz = nbytes; tsp->quantity += mp->sz; global_quantity += mp->sz; delete_hashval(tsp->hash, mp->ptr); mp->ptr = realloc(mp->ptr, nbytes); install_in_hash(tsp->hash, mp->ptr, mp); if (oldsize < nbytes) memset(mp->ptr + oldsize, 0, nbytes - oldsize); install_in_hash(tsp->hash, mp->ptr, mp); return mp->ptr; } void { newclass( unsigned mclass, void *p ) struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, p); struct memory_class *mcp = find_memory_class(mclass); if (!mp || (mp->ptr != p) || mp->mcp == mcp) return;

if (mp->prv) mp->prv->nxt = mp->nxt; else mp->mcp->first = mp->nxt; if (mp->nxt) mp->nxt->prv = mp->prv; else mp->mcp->last = mp->prv; mp->nxt = mp->prv = 0; mp->mcp = mcp; if (mp->nxt = mcp->first) // intentionally not == mcp->first->prv = mp; mcp->first = mp; if (!mcp->last) mcp->last = mp; } unsigned classof( void *p ) { struct threadmem_stuff *tsp = mp_head; struct memory_pointer *mp = lookup_hashval(tsp->hash, p); if (!mp || (mp->ptr != p)) return 0; return mp->mcp->mclass; }

You might also like