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

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: allocabs.c,v 1.10 1997/01/01 03:46:04 ldp Exp $
  4.  
  5.     Desc: Exec function AllocAbs()
  6.     Lang: english
  7. */
  8. #include <exec/alerts.h>
  9. #include <exec/execbase.h>
  10. #include <aros/machine.h>
  11. #include "memory.h"
  12. #include <exec/memory.h>
  13. #include <proto/exec.h>
  14.  
  15. /*****************************************************************************
  16.  
  17.     NAME */
  18.  
  19.     AROS_LH2(APTR, AllocAbs,
  20.  
  21. /*  SYNOPSIS */
  22.     AROS_LHA(ULONG, byteSize, D0),
  23.     AROS_LHA(APTR,  location, D1),
  24.  
  25. /*  LOCATION */
  26.     struct ExecBase *, SysBase, 34, Exec)
  27.  
  28. /*  FUNCTION
  29.     Allocate some memory from the system memory pool at a given address.
  30.  
  31.     INPUTS
  32.     byteSize - Number of bytes you want to get
  33.     location - Where you want to get the memory
  34.  
  35.     RESULT
  36.     A pointer to some memory including the requested bytes or NULL if
  37.     the memory couldn't be allocated
  38.  
  39.     NOTES
  40.  
  41.     EXAMPLE
  42.  
  43.     BUGS
  44.  
  45.     SEE ALSO
  46.     FreeMem()
  47.  
  48.     INTERNALS
  49.  
  50.     HISTORY
  51.        17-10-95    created by M. Fleischer
  52.  
  53. ******************************************************************************/
  54. {
  55.     AROS_LIBFUNC_INIT
  56.     struct MemChunk *p1,*p2,*p3,*p4;
  57.     struct MemHeader *mh;
  58.  
  59.     /* Zero bytes requested? May return everything ;-). */
  60.     if(!byteSize)
  61.     return NULL;
  62.  
  63.     /* Align size to the requirements */
  64.     byteSize+=(IPTR)location&(MEMCHUNK_TOTAL-1);
  65.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  66.  
  67.     /* Align the location as well */
  68.     location=(APTR)((IPTR)location&~(MEMCHUNK_TOTAL-1));
  69.  
  70.     /* Start and end(+1) of the block */
  71.     p3=(struct MemChunk *)location;
  72.     p4=(struct MemChunk *)((UBYTE *)p3+byteSize);
  73.  
  74.     /* Protect the memory list from access by other tasks. */
  75.     Forbid();
  76.  
  77.     /* Loop over MemHeader structures */
  78.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  79.     while(mh->mh_Node.ln_Succ)
  80.     {
  81.     /* Test if the memory belongs to this MemHeader. */
  82.     if(mh->mh_Lower<=location&&mh->mh_Upper>location)
  83.     {
  84.         /*
  85.         The free memory list is only single linked, i.e. to remove
  86.         elements from the list I need the node's predessor. For the
  87.         first element I can use freeList->mh_First instead of a real
  88.         predessor.
  89.         */
  90.         p1=(struct MemChunk *)&mh->mh_First;
  91.         p2=p1->mc_Next;
  92.  
  93.         /* Follow the list to find a chunk with our memory. */
  94.         while(p2!=NULL)
  95.         {
  96. #if !defined(NO_CONSISTENCY_CHECKS)
  97.         /*
  98.             Do some constistency checks:
  99.             1. All MemChunks must be aligned to
  100.                MEMCHUNK_TOTAL.
  101.             2. The end (+1) of the current MemChunk
  102.                must be lower than the start of the next one.
  103.         */
  104.         if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  105.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  106.             &&p2->mc_Next!=NULL))
  107.             Alert(AN_MemCorrupt|AT_DeadEnd);
  108. #endif
  109.         /* Found a chunk that fits? */
  110.         if((UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p4&&p2<=p3)
  111.         {
  112.             /* Check if there's memory left at the end. */
  113.             if((UBYTE *)p2+p2->mc_Bytes!=(UBYTE *)p4)
  114.             {
  115.             /* Yes. Add it to the list */
  116.             p4->mc_Next=p2->mc_Next;
  117.             p4->mc_Bytes=(UBYTE *)p2+p2->mc_Bytes-(UBYTE *)p4;
  118.             p2->mc_Next=p4;
  119.             }
  120.  
  121.             /* Check if there's memory left at the start. */
  122.             if(p2!=p3)
  123.             /* Yes. Adjust the size */
  124.             p2->mc_Bytes=(UBYTE *)p3-(UBYTE *)p2;
  125.             else
  126.             /* No. Skip the old chunk */
  127.             p1->mc_Next=p2->mc_Next;
  128.  
  129.             /* Adjust free memory count */
  130.             mh->mh_Free-=byteSize;
  131.  
  132.             /* Return the memory */
  133.             Permit();
  134.             return p3;
  135.         }
  136.         /* goto next chunk */
  137.         p1=p2;
  138.         p2=p2->mc_Next;
  139.         }
  140.         /* The MemHeader didn't have the memory */
  141.         break;
  142.     }
  143.     /* Test next MemHeader */
  144.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  145.     }
  146.     /* There's nothing we could do */
  147.     Permit();
  148.     return NULL;
  149.     AROS_LIBFUNC_EXIT
  150. } /* AllocAbs */
  151.  
  152.