home *** CD-ROM | disk | FTP | other *** search
- /*
- ** memory.c
- **
- ** useful functions to deal with some of the crap that goes
- ** on in amigados's memory management
- **
- ** keep memory in a list
- **
- ** no doubt, AmigaDOS does some of this for us, but we can't really
- ** debug that, or handle things like freeing all allocated resources
- ** (i.e. at end of a process) like we can doing things this way.
- **
- ** Note, also, relying on amigados means we risk disastrous results when
- ** things never allocated are freed.
- ** Of course, the problem with this scheme is that if things overwrites its
- ** memory and/or corrupts its list somehow, it can be really hosed. This
- ** has the perhaps stupidly optimistic assumption that there isn't much
- ** thrashing of memory going on.
- */
-
- #define MEM_DEBUG
-
- #ifdef MEM_DEBUG
-
- #include <stdio.h>
- #include <exec/memory.h>
-
- #ifndef IFDEBUG
- #ifdef DEBUG
- #define IFDEBUG(foo) foo
- #else
- #define IFDEBUG(foo)
- #endif /* DEBUG */
- #endif /* IFDEBUG */
-
- void * AllocVec(unsigned long, unsigned long);
-
- struct MemSeg {
- void * Addr;
- unsigned long Size;
- };
-
- /* here we store our data on memory allocated in a big array of
- MemSeg structures */
-
- static struct MemSeg * AllocatedMemList = NULL;
- static unsigned long MemListSize = 0; /* space for mem entries in MemList */
- static unsigned long NumMemEntries = 0;
-
- /* allocate a larger space for AllocatedMemList, transfer data over to it */
- ExpandAllocatedMemList(){
- struct MemSeg * NewMemList = NULL;
- unsigned long NewMemListSize = MemListSize + 50;
- unsigned long count;
- unsigned long countcheck = 0;
-
- IFDEBUG(printf("Expanding AllocatedMemList to %d\n", NewMemListSize);)
-
- /* get space for memory allocation records */
- NewMemList = AllocVec(sizeof(struct MemSeg) * NewMemListSize, MEMF_CLEAR);
- if(NewMemList == NULL){
- /* this is way bad. catastrophically die */
- fprintf(stderr, "ERROR: ExpandMemList(): out of memory!\n");
- return;
- }
-
- /* copy over the old data from old space, if it is used */
- if(AllocatedMemList != NULL){
- IFDEBUG(printf("Transferring AllocatedMemList\n");)
- for(count=0,countcheck =0;count< MemListSize;count++){
- if(AllocatedMemList[count].Addr != NULL){
- NewMemList[count].Addr = AllocatedMemList[count].Addr;
- NewMemList[count].Size = AllocatedMemList[count].Size;
- countcheck++;
- }
- }
- if(countcheck != NumMemEntries){
- fprintf(stderr,"WARNING:Possible corruption of AllocatedMemList!\n");
- }
- }
- NumMemEntries = countcheck;
-
- if(AllocatedMemList != NULL ) FreeVec(AllocatedMemList);
- AllocatedMemList = NewMemList;
- MemListSize = NewMemListSize;
-
- IFDEBUG(printf("Done Expanding AllocatedMemList to %lx %d entries\n", AllocatedMemList, MemListSize);)
- }
-
- /* return pointer to MemSeg containing data for called pointer */
- struct MemSeg * GetMemEntry(void * ptr){
- unsigned long count;
-
- IFDEBUG(printf("GetMemEntry(%lx)\n", ptr);)
- if(AllocatedMemList == NULL) {
- fprintf(stderr, "GetMemEntry() fail: no memlist\n");
- return NULL;
- }
-
- for(count=0;count < MemListSize;count++){
- if(AllocatedMemList[count].Addr == ptr)
- return &AllocatedMemList[count];
- }
-
- return NULL;
- }
-
- /* allocate a chunk of memory */
- void * MemAlloc( size_t size , int flags ){
- void * NewAddr = AllocVec(size, flags);
- struct MemSeg * MemEntryData = NULL;
-
- IFDEBUG(printf("doing MemAlloc(%d)\n", size);)
-
- if(NewAddr == NULL) {
- fprintf(stderr, "MemAlloc fail -- no mem!\n");
- return NULL;
- }
-
- if(AllocatedMemList == NULL || MemListSize <= NumMemEntries){
- ExpandAllocatedMemList();
- }
-
- MemEntryData = GetMemEntry( NULL ); /* find an unused slot in MemList */
-
- if(MemEntryData == NULL){
- /* Ack, this is bad. indicates corrupted AllocatedMemList
- ** or an out of memory situation (couldn't expand Allocated list )
- */
- FreeVec(NewAddr);
- fprintf(stderr, "Error:MemAlloc fail: no MemEntry\n");
- return NULL;
- }
-
- MemEntryData->Addr = NewAddr;
- MemEntryData->Size = size;
- NumMemEntries++;
-
- IFDEBUG(printf("done MemAlloc(%d)\n", size);)
- return NewAddr;
- }
-
- /*
- ** free a chunk of memory
- **
- ** Make up some warning if wasn't allocated, or we're freeing up the wrong
- ** size.
- **
- */
- MemFree(void * ptr, unsigned long size ){
- unsigned long count;
- struct MemSeg * memptr;
-
- IFDEBUG(printf("doing MemFree(%d %d )\n", ptr, size);)
-
- if(AllocatedMemList == NULL) {
- fprintf(stderr, "ERROR: MemFree'd before any allocation!\n");
- return;
- }
-
- memptr = GetMemEntry(ptr);
-
- if(memptr == NULL){
- fprintf(stderr, "WARNING: tried to free unallocated pointer, sz %d!\n",
- size);
- return;
- }
-
- if(memptr->Addr != ptr){
- fprintf(stderr, "ERROR: GetMemEntry failed! got wrong memptr!\n");
- }
-
- if(size > 0 && memptr->Size != size){
- fprintf(stderr,
- "Warning: allocated size (%d) and freed size (%d) disagree\n",
- memptr->Size, size);
- }
-
- FreeVec(ptr);
- memptr->Size = 0;
- memptr->Addr = NULL;
- NumMemEntries--;
-
- /* look for multiple entries? */
- if(ptr != 0)
- while((memptr = GetMemEntry(ptr)) != NULL){
- fprintf(stderr,
- "WARNING: multiply allocated memory? size (%d)\n",
- memptr->Size);
- memptr->Addr = NULL;
- memptr->Size = 0;
- }
- IFDEBUG(printf("Done MemFree\n");)
- }
-
- /* free up anything that was left allocated */
- AllFree(){
- unsigned long count;
- unsigned long countcheck = NumMemEntries;
-
- IFDEBUG(puts("doing AllFree");)
-
- if(NumMemEntries != 0 )
- fprintf(stderr, "AllFree(): %d entries to free\n", NumMemEntries);
-
- if(AllocatedMemList == NULL){
- fprintf(stderr, "No memory list to AllFree!\n");
- return;
- }
-
- for(count = 0;count < MemListSize ;count++){
- if(AllocatedMemList[count].Addr != NULL){
- fprintf(stderr,"Block %d bytes to free at %lx\n",
- AllocatedMemList[count].Size, AllocatedMemList[count].Addr);
- FreeVec(AllocatedMemList[count].Addr);
- countcheck--;
- }
- }
-
- if(countcheck != 0){
- fprintf(stderr, "AllClean: %d unaccounted memory allocations!\n", countcheck);
- }
- IFDEBUG(else fprintf(stderr, "AllClean: no unaccounted memory allocations!\n");)
-
- FreeVec(AllocatedMemList);
- AllocatedMemList = NULL;
-
- IFDEBUG(fprintf(stderr, "AllFree done\n");)
- }
-
-
- /* function definitions to cause things here to replace ordinary function
- ** calls */
-
- void * AllocMem(size_t size, unsigned long flags){
- return MemAlloc( size, flags);
- }
- void FreeMem( void * ptr, size_t size){
- MemFree(ptr, size);
- }
-
- void * malloc(size_t size){
- return MemAlloc( size, MEMF_CLEAR);
- }
- void * calloc(int nmemb, size_t size){
- return MemAlloc( nmemb * size, MEMF_CLEAR);
- }
- void free(void * ptr){
- MemFree(ptr, 0);
- }
-
- char * strdup( char * string){
- int lenstr;
- char * newptr;
- if(string == NULL) return;
-
- lenstr = strlen(string)+1; /* plus 1 for null terminator! */
-
- newptr = (char *) malloc( lenstr );
-
- if(newptr != NULL) strcpy(newptr, string);
-
- return newptr;
- }
-
- /* have to macro define AllocVec/FreeVec, as they're used in this! */
-
- #endif
-