2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Allocate memory at address
8 #include <exec/alerts.h>
9 #include <exec/execbase.h>
11 #include <exec/memory.h>
12 #include <exec/memheaderext.h>
13 #include <proto/exec.h>
15 /*****************************************************************************
19 AROS_LH2(APTR
, AllocAbs
,
22 AROS_LHA(ULONG
, byteSize
, D0
),
23 AROS_LHA(APTR
, location
, D1
),
26 struct ExecBase
*, SysBase
, 34, Exec
)
29 Allocate some memory from the system memory pool at a given address.
32 byteSize - Number of bytes you want to get
33 location - Where you want to get the memory
36 A pointer to some memory including the requested bytes or NULL if
37 the memory couldn't be allocated
50 ******************************************************************************/
57 /* Zero bytes requested? May return everything ;-). */
61 /* Protect the memory list from access by other tasks. */
64 /* Loop over MemHeader structures */
65 ForeachNode(&SysBase
->MemList
, mh
)
67 if (mh
->mh_Lower
<= location
&& mh
->mh_Upper
> location
)
71 /* If no header was found which matched the requirements, just give up. */
72 if (!mh
->mh_Node
.ln_Succ
)
78 /* If the header is managed, let the mager handle the request. */
79 if (mh
->mh_Attributes
& MEMF_MANAGED
)
81 struct MemHeaderExt
*mhe
= (struct MemHeaderExt
*)mh
;
83 if (mhe
->mhe_AllocAbs
)
84 ret
= mhe
->mhe_AllocAbs(mhe
, byteSize
, location
);
88 struct MemChunk
*p1
, *p2
, *p3
, *p4
;
90 /* Align size to the requirements */
91 byteSize
+= (IPTR
)location
&(MEMCHUNK_TOTAL
- 1);
92 byteSize
= (byteSize
+ MEMCHUNK_TOTAL
-1) & ~(MEMCHUNK_TOTAL
-1);
94 /* Align the location as well */
95 location
=(APTR
)((IPTR
)location
& ~(MEMCHUNK_TOTAL
-1));
97 /* Start and end(+1) of the block */
98 p3
=(struct MemChunk
*)location
;
99 p4
=(struct MemChunk
*)((UBYTE
*)p3
+byteSize
);
102 The free memory list is only single linked, i.e. to remove
103 elements from the list I need the node's predessor. For the
104 first element I can use freeList->mh_First instead of a real
107 p1
= (struct MemChunk
*)&mh
->mh_First
;
110 /* Follow the list to find a chunk with our memory. */
113 #if !defined(NO_CONSISTENCY_CHECKS)
115 Do some constistency checks:
116 1. All MemChunks must be aligned to
118 2. The end (+1) of the current MemChunk
119 must be lower than the start of the next one.
121 if( ((IPTR
)p2
|p2
->mc_Bytes
)&(MEMCHUNK_TOTAL
-1)
122 ||( (UBYTE
*)p2
+p2
->mc_Bytes
>=(UBYTE
*)p2
->mc_Next
123 &&p2
->mc_Next
!=NULL
))
124 Alert(AN_MemCorrupt
|AT_DeadEnd
);
127 /* Found a chunk that fits? */
128 if((UBYTE
*)p2
+p2
->mc_Bytes
>=(UBYTE
*)p4
&&p2
<=p3
)
130 /* Check if there's memory left at the end. */
131 if((UBYTE
*)p2
+p2
->mc_Bytes
!=(UBYTE
*)p4
)
133 /* Yes. Add it to the list */
134 p4
->mc_Next
= p2
->mc_Next
;
135 p4
->mc_Bytes
= (UBYTE
*)p2
+p2
->mc_Bytes
-(UBYTE
*)p4
;
139 /* Check if there's memory left at the start. */
141 /* Yes. Adjust the size */
142 p2
->mc_Bytes
=(UBYTE
*)p3
-(UBYTE
*)p2
;
144 /* No. Skip the old chunk */
145 p1
->mc_Next
=p2
->mc_Next
;
147 /* Adjust free memory count */
148 mh
->mh_Free
-=byteSize
;
150 /* Return the memory */
154 /* goto next chunk */