home *** CD-ROM | disk | FTP | other *** search
- /*
- (C) 1995-96 AROS - The Amiga Replacement OS
- $Id: allocate.c,v 1.9 1997/01/01 03:46:05 ldp Exp $
- $Log: allocate.c,v $
- Revision 1.9 1997/01/01 03:46:05 ldp
- Committed Amiga native (support) code
-
- Changed clib to proto
-
- Revision 1.8 1996/12/10 13:51:36 aros
- Moved all #include's in the first column so makedepend can see it.
-
- Revision 1.7 1996/10/24 15:50:43 aros
- Use the official AROS macros over the __AROS versions.
-
- Revision 1.6 1996/10/19 17:07:24 aros
- Include <aros/machine.h> instead of machine.h
-
- Revision 1.5 1996/09/13 17:51:21 digulla
- Use IPTR
-
- Revision 1.4 1996/08/13 13:55:57 digulla
- Replaced AROS_LA by AROS_LHA
- Replaced some AROS_LH*I by AROS_LH*
- Sorted and added includes
-
- Revision 1.3 1996/08/01 17:41:04 digulla
- Added standard header for all files
-
- Desc:
- Lang:
- */
- #include "exec_intern.h"
- #include "memory.h"
- #include <aros/machine.h>
- #include <exec/alerts.h>
- #include <aros/libcall.h>
- #include <exec/memory.h>
- #include <proto/exec.h>
-
- /*****************************************************************************
-
- NAME */
-
- AROS_LH2(APTR, Allocate,
-
- /* SYNOPSIS */
- AROS_LHA(struct MemHeader *, freeList, A0),
- AROS_LHA(ULONG, byteSize, D0),
-
- /* LOCATION */
- struct ExecBase *, SysBase, 31, Exec)
-
- /* FUNCTION
- Allocate memory out of a private region handled by the MemHeader
- structure.
-
- INPUTS
- freeList - Pointer to the MemHeader structure which holds the memory
- byteSize - Number of bytes you want to get
-
- RESULT
- A pointer to the number of bytes you wanted or NULL if the memory
- couldn't be allocated
-
- NOTES
- The memory is aligned to sizeof(struct MemChunk). All requests
- are rounded up to a multiple of that size.
-
- EXAMPLE
- #define POOLSIZE 4096
- \* Get a MemHeader structure and some private memory *\
- mh=(struct MemHeader *)
- AllocMem(sizeof(struct MemHeader)+POOLSIZE,MEMF_ANY);
- if(mh!=NULL)
- {
- \* Build a private pool *\
- mh->mh_First=(struct MemChunk *)(mh+1);
- mh->mh_First->mc_Next=NULL;
- mh->mh_First->mc_Bytes=POOLSIZE;
- mh->mh_Free=POOLSIZE;
- {
- \* Use the pool *\
- UBYTE *mem1,*mem2;
- mem1=Allocate(mh,1000);
- mem2=Allocate(mh,2000);
- \* Do something with memory... *\
- }
- \* Free everything at once *\
- FreeMem(mh,sizeof(struct MemHeader)+POOLSIZE);
- }
-
- BUGS
-
- SEE ALSO
- Deallocate()
-
- INTERNALS
-
- HISTORY
- 17-09-95 created by m. fleischer
- 16-10-95 increased portability
-
- ******************************************************************************/
- {
- AROS_LIBFUNC_INIT
- struct MemChunk *p1, *p2;
-
- /* Zero bytes requested? May return everything ;-). */
- if(!byteSize)
- return NULL;
-
- /* First round byteSize to a multiple of MEMCHUNK_TOTAL. */
- byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
-
- /* Is there enough free memory in the list? */
- if(freeList->mh_Free<byteSize)
- return NULL;
-
- /*
- The free memory list is only single linked, i.e. to remove
- elements from the list I need the node as well as it's
- predessor. For the first element I can use freeList->mh_First
- instead of a real predessor.
- */
- p1=(struct MemChunk *)&freeList->mh_First;
- p2=p1->mc_Next;
-
- /* Is the list enpty? */
- if(p2==NULL)
- return NULL;
-
- /* Follow the list */
- for(;;)
- {
- #if !defined(NO_CONSISTENCY_CHECKS)
- /* Consistency check: Check alignment restrictions */
- if( ((IPTR)p2|(ULONG)p2->mc_Bytes) & (MEMCHUNK_TOTAL-1) )
- {
- Alert(AN_MemCorrupt);
- return NULL;
- }
- #endif
- /* Check if current block is large enough */
- if(p2->mc_Bytes>=byteSize)
- {
- /* It is. Remove it from the list and return it. */
- if(p2->mc_Bytes==byteSize)
- /* Fits exactly. Just relink the list. */
- p1->mc_Next=p2->mc_Next;
- else
- {
- /* Split the current chunk and return the first bytes. */
- p1->mc_Next=(struct MemChunk *)((UBYTE *)p2+byteSize);
- p1=p1->mc_Next;
- p1->mc_Next=p2->mc_Next;
- p1->mc_Bytes=p2->mc_Bytes-byteSize;
- }
- /* Adjust free memory count and return */
- freeList->mh_Free-=byteSize;
- return p2;
- }
-
- /* Go to next block */
- p1=p2;
- p2=p1->mc_Next;
-
- /* Check if this was the end */
- if(p2==NULL)
- return NULL;
- #if !defined(NO_CONSISTENCY_CHECKS)
- /*
- Consistency check:
- If the end of the last block+1 is bigger or equal to
- the start of the current block something must be wrong.
- */
- if((UBYTE *)p2<=(UBYTE *)p1+p1->mc_Bytes)
- {
- Alert(AN_MemCorrupt);
- return NULL;
- }
- #endif
- }
- AROS_LIBFUNC_EXIT
- } /* Allocate */
-