home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / exec / freemem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-10  |  5.3 KB  |  228 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: freemem.c,v 1.16 1997/01/10 04:06:49 ldp Exp $
  4.  
  5.     Desc: Exec function FreeMem()
  6.     Lang: english
  7. */
  8. #include <exec/alerts.h>
  9. #include <exec/execbase.h>
  10. #include <aros/machine.h>
  11. #include <aros/libcall.h>
  12. #include "memory.h"
  13. #include <aros/rt.h>
  14. #include <exec/memory.h>
  15. #include <proto/exec.h>
  16.  
  17. #include "exec_debug.h"
  18. #ifndef DEBUG_FreeMem
  19. #   define DEBUG_FreeMem 0
  20. #endif
  21. #if DEBUG_FreeMem
  22. #   undef DEBUG
  23. #   define DEBUG 1
  24. #endif
  25. #include <aros/debug.h>
  26.  
  27. #define NASTY_FREEMEM    0    /* Delete contents of free'd memory ? */
  28.  
  29. #if NASTY_FREEMEM
  30. extern void PurgeChunk (ULONG *, ULONG);
  31. #endif
  32.  
  33. /*****************************************************************************
  34.  
  35.     NAME */
  36.  
  37.     AROS_LH2(void, FreeMem,
  38.  
  39. /*  SYNOPSIS */
  40.     AROS_LHA(APTR,  memoryBlock, A1),
  41.     AROS_LHA(ULONG, byteSize,    D0),
  42.  
  43. /*  LOCATION */
  44.     struct ExecBase *, SysBase, 35, Exec)
  45.  
  46. /*  FUNCTION
  47.     Give a block of memory back to the system pool.
  48.  
  49.     INPUTS
  50.     memoryBlock - Pointer to the memory to be freed
  51.     byteSize    - Size of the block
  52.  
  53.     RESULT
  54.  
  55.     NOTES
  56.  
  57.     EXAMPLE
  58.  
  59.     BUGS
  60.  
  61.     SEE ALSO
  62.     AllocMem()
  63.  
  64.     INTERNALS
  65.  
  66.     HISTORY
  67.     8-10-95    created by m. fleischer
  68.        16-10-95    increased portability
  69.  
  70. ******************************************************************************/
  71. {
  72.     AROS_LIBFUNC_INIT
  73.  
  74.     struct MemHeader *mh;
  75.     struct MemChunk *p1, *p2, *p3;
  76.     UBYTE *p4;
  77.  
  78.     D(bug("Call FreeMem (%08lx, %ld)\n", memoryBlock, byteSize));
  79.  
  80.     /* If there is no memory free nothing */
  81.     if(!byteSize)
  82.     ReturnVoid ("FreeMem");
  83.  
  84.     RT_Free (RTT_MEMORY, memoryBlock, byteSize);
  85.  
  86.     /* Align size to the requirements */
  87.     byteSize+=(IPTR)memoryBlock&(MEMCHUNK_TOTAL-1);
  88.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  89.  
  90.     /* Align the block as well */
  91.     memoryBlock=(APTR)((IPTR)memoryBlock&~(MEMCHUNK_TOTAL-1));
  92.  
  93.     /* Start and end(+1) of the block */
  94.     p3=(struct MemChunk *)memoryBlock;
  95.     p4=(UBYTE *)p3+byteSize;
  96.  
  97.     /* Protect the memory list from access by other tasks. */
  98.     Forbid();
  99.  
  100.     /* Loop over MemHeader structures */
  101.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  102.     while(mh->mh_Node.ln_Succ)
  103.     {
  104.     /* Test if the memory belongs to this MemHeader. */
  105.     if(mh->mh_Lower<=memoryBlock&&mh->mh_Upper>memoryBlock)
  106.     {
  107. #if !defined(NO_CONSISTENCY_CHECKS)
  108.         /* Test if it really fits into this MemHeader. */
  109.         if((APTR)p4>mh->mh_Upper)
  110.         /* Something is completely wrong. */
  111.         Alert(AN_MemCorrupt|AT_DeadEnd);
  112. #endif
  113.         /*
  114.         The free memory list is only single linked, i.e. to insert
  115.         elements into the list I need the node as well as it's
  116.         predessor. For the first element I can use freeList->mh_First
  117.         instead of a real predessor.
  118.         */
  119.         p1=(struct MemChunk *)&mh->mh_First;
  120.         p2=p1->mc_Next;
  121.  
  122.         /* No chunk in list? Just insert the current one and return. */
  123.         if(p2==NULL)
  124.         {
  125. #if NASTY_FREEMEM
  126.         PurgeChunk ((ULONG *)p3, byteSize);
  127. #endif
  128.         p3->mc_Bytes=byteSize;
  129.         p3->mc_Next=NULL;
  130.         p1->mc_Next=p3;
  131.         mh->mh_Free+=byteSize;
  132.         Permit ();
  133.         ReturnVoid ("FreeMem");
  134.         }
  135.  
  136.         /* Follow the list to find a place where to insert our memory. */
  137.         do
  138.         {
  139. #if !defined(NO_CONSISTENCY_CHECKS)
  140.         /*
  141.             Do some constistency checks:
  142.             1. All MemChunks must be aligned to
  143.                MEMCHUNK_TOTAL.
  144.             2. The end (+1) of the current MemChunk
  145.                must be lower than the start of the next one.
  146.         */
  147.         if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  148.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  149.             &&p2->mc_Next!=NULL))
  150.             Alert(AN_MemCorrupt|AT_DeadEnd);
  151. #endif
  152.         /* Found a block with a higher address? */
  153.         if(p2>=p3)
  154.         {
  155. #if !defined(NO_CONSISTENCY_CHECKS)
  156.             /*
  157.             If the memory to be freed overlaps with the current
  158.             block something must be wrong.
  159.             */
  160.             if(p4>(UBYTE *)p2)
  161.             Alert(AN_FreeTwice|AT_DeadEnd);
  162. #endif
  163.             /* End the loop with p2 non-zero */
  164.             break;
  165.         }
  166.         /* goto next block */
  167.         p1=p2;
  168.         p2=p2->mc_Next;
  169.  
  170.         /* If the loop ends with p2 zero add it at the end. */
  171.         }while(p2!=NULL);
  172.  
  173.         /* If there was a previous block merge with it. */
  174.         if(p1!=(struct MemChunk *)&mh->mh_First)
  175.         {
  176. #if !defined(NO_CONSISTENCY_CHECKS)
  177.         /* Check if they overlap. */
  178.         if((UBYTE *)p1+p1->mc_Bytes>(UBYTE *)p3)
  179.             Alert(AN_FreeTwice|AT_DeadEnd);
  180. #endif
  181.         /* Merge if possible */
  182.         if((UBYTE *)p1+p1->mc_Bytes==(UBYTE *)p3)
  183.             p3=p1;
  184.         else
  185.             /* Not possible to merge */
  186.             p1->mc_Next=p3;
  187.         }else
  188.         /*
  189.             There was no previous block. Just insert the memory at
  190.             the start of the list.
  191.         */
  192.         p1->mc_Next=p3;
  193.  
  194.         /* Try to merge with next block (if there is one ;-) ). */
  195.         if(p4==(UBYTE *)p2&&p2!=NULL)
  196.         {
  197.         /*
  198.             Overlap checking already done. Doing it here after
  199.             the list potentially changed would be a bad idea.
  200.         */
  201.         p4+=p2->mc_Bytes;
  202.         p2=p2->mc_Next;
  203.         }
  204.         /* relink the list and return. */
  205. #if NASTY_FREEMEM
  206.         PurgeChunk ((ULONG *)p3, p4-(UBYTE *)p3);
  207. #endif
  208.         p3->mc_Next=p2;
  209.         p3->mc_Bytes=p4-(UBYTE *)p3;
  210.         mh->mh_Free+=byteSize;
  211.         Permit();
  212.         ReturnVoid ("FreeMem");
  213.     }
  214.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  215.     }
  216.  
  217. #if !defined(NO_CONSISTENCY_CHECKS)
  218.     /* Some memory that didn't fit into any MemHeader? */
  219.     Alert(AN_MemCorrupt|AT_DeadEnd);
  220. #else
  221.     Permit();
  222. #endif
  223.  
  224.     ReturnVoid ("FreeMem");
  225.     AROS_LIBFUNC_EXIT
  226. } /* FreeMem */
  227.  
  228.