home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / dnet / dnet2.3.2 / amiga / lib / memory.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  6.9 KB  |  269 lines

  1. /* 
  2. ** memory.c
  3. **
  4. ** useful functions to deal with some of the crap that goes
  5. ** on in amigados's memory management
  6. **
  7. ** keep memory in a list
  8. **
  9. ** no doubt, AmigaDOS does some of this for us, but we can't really
  10. ** debug that, or handle things like freeing all allocated resources
  11. ** (i.e. at end of a process) like we can doing things this way.
  12. **
  13. **  Note, also, relying on amigados means we risk disastrous results when 
  14. **  things never allocated are freed.
  15. **  Of course, the problem with this scheme is that if things overwrites its
  16. **  memory and/or corrupts its list somehow, it can be really hosed. This 
  17. **  has the perhaps stupidly optimistic assumption that there isn't much 
  18. **  thrashing of memory going on.
  19. */
  20.  
  21. #define MEM_DEBUG
  22.  
  23. #ifdef MEM_DEBUG
  24.  
  25. #include <stdio.h>
  26. #include <exec/memory.h>
  27.  
  28. #ifndef IFDEBUG
  29. #ifdef DEBUG
  30. #define IFDEBUG(foo) foo
  31. #else
  32. #define IFDEBUG(foo) 
  33. #endif  /* DEBUG */
  34. #endif  /* IFDEBUG */
  35.  
  36. void * AllocVec(unsigned long, unsigned long);
  37.  
  38. struct MemSeg {
  39.    void * Addr;
  40.    unsigned long Size;
  41. };
  42.  
  43. /* here we store our data on memory allocated in a big array of 
  44. MemSeg structures */
  45.  
  46. static struct MemSeg * AllocatedMemList = NULL;
  47. static unsigned long MemListSize = 0;  /* space for mem entries in MemList */
  48. static unsigned long NumMemEntries = 0;
  49.  
  50. /* allocate a larger space for AllocatedMemList, transfer data over to it */
  51. ExpandAllocatedMemList(){
  52.     struct MemSeg * NewMemList = NULL;
  53.     unsigned long NewMemListSize = MemListSize + 50;
  54.     unsigned long count;
  55.     unsigned long countcheck = 0;
  56.  
  57.     IFDEBUG(printf("Expanding AllocatedMemList to %d\n", NewMemListSize);)
  58.  
  59.     /* get space for memory allocation records */
  60.     NewMemList = AllocVec(sizeof(struct MemSeg) * NewMemListSize, MEMF_CLEAR);
  61.     if(NewMemList == NULL){
  62.         /* this is way bad.  catastrophically die */
  63.     fprintf(stderr, "ERROR: ExpandMemList(): out of memory!\n");
  64.     return;
  65.     }
  66.  
  67.     /* copy over the old data  from old space, if it is used */
  68.     if(AllocatedMemList != NULL){
  69.     IFDEBUG(printf("Transferring AllocatedMemList\n");)
  70.     for(count=0,countcheck =0;count< MemListSize;count++){
  71.         if(AllocatedMemList[count].Addr != NULL){
  72.         NewMemList[count].Addr = AllocatedMemList[count].Addr;
  73.         NewMemList[count].Size = AllocatedMemList[count].Size;
  74.         countcheck++;
  75.         } 
  76.     }
  77.     if(countcheck != NumMemEntries){
  78.         fprintf(stderr,"WARNING:Possible corruption of AllocatedMemList!\n");
  79.     }
  80.     }
  81.     NumMemEntries = countcheck;
  82.  
  83.     if(AllocatedMemList != NULL ) FreeVec(AllocatedMemList);
  84.     AllocatedMemList = NewMemList;
  85.     MemListSize = NewMemListSize;
  86.  
  87.     IFDEBUG(printf("Done Expanding AllocatedMemList to %lx %d entries\n", AllocatedMemList, MemListSize);)
  88. }
  89.  
  90. /* return pointer to MemSeg containing data for called pointer */
  91. struct MemSeg * GetMemEntry(void * ptr){
  92.     unsigned long count;
  93.  
  94.     IFDEBUG(printf("GetMemEntry(%lx)\n", ptr);)
  95.     if(AllocatedMemList == NULL) {
  96.     fprintf(stderr, "GetMemEntry() fail: no memlist\n");
  97.         return NULL;
  98.     }
  99.  
  100.     for(count=0;count < MemListSize;count++){
  101.         if(AllocatedMemList[count].Addr == ptr) 
  102.         return &AllocatedMemList[count];
  103.     }
  104.  
  105.     return NULL;
  106. }
  107.  
  108. /* allocate a chunk of memory */
  109. void * MemAlloc( size_t size , int flags ){
  110.     void * NewAddr = AllocVec(size, flags);
  111.     struct MemSeg * MemEntryData = NULL;
  112.  
  113.     IFDEBUG(printf("doing MemAlloc(%d)\n", size);)
  114.  
  115.     if(NewAddr == NULL) {
  116.     fprintf(stderr, "MemAlloc fail -- no mem!\n");
  117.         return NULL;
  118.     }
  119.  
  120.     if(AllocatedMemList == NULL || MemListSize <= NumMemEntries){
  121.        ExpandAllocatedMemList();
  122.     }
  123.  
  124.     MemEntryData = GetMemEntry( NULL ); /* find an unused slot in MemList */
  125.  
  126.     if(MemEntryData == NULL){
  127.     /* Ack, this is bad. indicates corrupted AllocatedMemList 
  128.     ** or an out of memory situation (couldn't expand Allocated list )
  129.     */
  130.     FreeVec(NewAddr);
  131.     fprintf(stderr, "Error:MemAlloc fail: no MemEntry\n");
  132.     return NULL;
  133.     }
  134.  
  135.     MemEntryData->Addr  = NewAddr;
  136.     MemEntryData->Size  = size;
  137.     NumMemEntries++;
  138.  
  139.     IFDEBUG(printf("done MemAlloc(%d)\n", size);)
  140.     return NewAddr;
  141. }
  142.  
  143. /* 
  144. **  free a chunk of memory 
  145. **
  146. **  Make up some warning if wasn't allocated, or we're freeing up the wrong
  147. **  size.
  148. **
  149. */
  150. MemFree(void * ptr, unsigned long size ){
  151.    unsigned long count;
  152.    struct MemSeg * memptr;
  153.  
  154.    IFDEBUG(printf("doing MemFree(%d %d )\n", ptr, size);)
  155.  
  156.    if(AllocatedMemList == NULL) {
  157.        fprintf(stderr, "ERROR: MemFree'd before any allocation!\n");
  158.        return;
  159.    }
  160.  
  161.    memptr = GetMemEntry(ptr);
  162.  
  163.    if(memptr == NULL){
  164.       fprintf(stderr, "WARNING: tried to free unallocated pointer, sz %d!\n", 
  165.           size);
  166.       return;
  167.    }
  168.  
  169.    if(memptr->Addr != ptr){
  170.       fprintf(stderr, "ERROR: GetMemEntry failed!  got wrong memptr!\n");
  171.    }
  172.  
  173.    if(size > 0 && memptr->Size != size){
  174.       fprintf(stderr, 
  175.           "Warning: allocated size (%d) and  freed size (%d) disagree\n", 
  176.     memptr->Size, size);
  177.    }
  178.  
  179.    FreeVec(ptr);
  180.    memptr->Size = 0;
  181.    memptr->Addr = NULL;
  182.    NumMemEntries--;
  183.  
  184.    /* look for multiple entries? */
  185.     if(ptr != 0)
  186.     while((memptr = GetMemEntry(ptr)) != NULL){
  187.         fprintf(stderr, 
  188.             "WARNING: multiply allocated memory? size (%d)\n", 
  189.             memptr->Size);
  190.         memptr->Addr = NULL;
  191.         memptr->Size = 0;
  192.     }
  193.     IFDEBUG(printf("Done MemFree\n");)
  194. }
  195.  
  196. /* free up anything that was left allocated */
  197. AllFree(){
  198.     unsigned long count;
  199.     unsigned long countcheck = NumMemEntries;
  200.  
  201.     IFDEBUG(puts("doing AllFree");)
  202.  
  203.     if(NumMemEntries != 0 )
  204.     fprintf(stderr, "AllFree(): %d entries to free\n", NumMemEntries);
  205.  
  206.     if(AllocatedMemList == NULL){
  207.     fprintf(stderr, "No memory list to AllFree!\n");
  208.     return;
  209.     }
  210.  
  211.     for(count = 0;count < MemListSize ;count++){
  212.        if(AllocatedMemList[count].Addr != NULL){
  213.            fprintf(stderr,"Block %d bytes to free at %lx\n", 
  214.            AllocatedMemList[count].Size, AllocatedMemList[count].Addr);
  215.            FreeVec(AllocatedMemList[count].Addr);
  216.        countcheck--;
  217.        }
  218.     }
  219.  
  220.     if(countcheck != 0){
  221.        fprintf(stderr, "AllClean: %d unaccounted memory allocations!\n", countcheck);
  222.     } 
  223.     IFDEBUG(else fprintf(stderr, "AllClean: no unaccounted memory allocations!\n");)
  224.  
  225.     FreeVec(AllocatedMemList);
  226.     AllocatedMemList = NULL;
  227.  
  228.     IFDEBUG(fprintf(stderr, "AllFree done\n");)
  229. }
  230.  
  231.  
  232. /* function definitions to cause things here to replace ordinary function 
  233. ** calls */
  234.  
  235. void * AllocMem(size_t size, unsigned long flags){
  236.    return MemAlloc( size, flags);
  237. }
  238. void FreeMem( void * ptr, size_t size){
  239.    MemFree(ptr, size);
  240. }
  241.  
  242. void * malloc(size_t size){
  243.    return MemAlloc( size, MEMF_CLEAR);
  244. }
  245. void * calloc(int nmemb, size_t size){
  246.    return MemAlloc( nmemb * size, MEMF_CLEAR);
  247. }
  248. void free(void * ptr){
  249.    MemFree(ptr, 0);
  250. }
  251.  
  252. char * strdup( char * string){
  253.    int lenstr;
  254.    char * newptr;
  255.    if(string == NULL) return;
  256.  
  257.    lenstr = strlen(string)+1;  /* plus 1 for null terminator! */
  258.  
  259.    newptr = (char *) malloc( lenstr );
  260.  
  261.    if(newptr != NULL) strcpy(newptr, string);
  262.  
  263.    return newptr;
  264. }
  265.  
  266. /* have to macro define AllocVec/FreeVec, as they're used in this! */
  267.  
  268. #endif
  269.