2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Free memory allocated by Allocate().
8 #include <exec/execbase.h>
9 #include <exec/alerts.h>
10 #include <aros/libcall.h>
12 #include <exec/memory.h>
13 #include <proto/exec.h>
15 /*****************************************************************************
19 AROS_LH3(void, Deallocate
,
22 AROS_LHA(struct MemHeader
*, freeList
, A0
),
23 AROS_LHA(APTR
, memoryBlock
, A1
),
24 AROS_LHA(ULONG
, byteSize
, D0
),
27 struct ExecBase
*, SysBase
, 32, Exec
)
30 Free block of memory associated with a given MemHandler structure.
33 freeList - Pointer to the MemHeader structure
34 memoryBlock - Pointer to the memory to be freed
35 byteSize - Size of the block
40 The start and end borders of the block are aligned to
41 a multiple of sizeof(struct MemChunk) and to include the block.
52 ******************************************************************************/
56 struct MemChunk
*p1
, *p2
, *p3
;
59 /* If there is no memory free nothing */
63 /* Align size to the requirements */
64 byteSize
+=(IPTR
)memoryBlock
&(MEMCHUNK_TOTAL
-1);
65 byteSize
=(byteSize
+MEMCHUNK_TOTAL
-1)&~(MEMCHUNK_TOTAL
-1);
67 /* Align the block as well */
68 memoryBlock
=(APTR
)((IPTR
)memoryBlock
&~(MEMCHUNK_TOTAL
-1));
71 The free memory list is only single linked, i.e. to insert
72 elements into the list I need the node as well as it's
73 predessor. For the first element I can use freeList->mh_First
74 instead of a real predessor.
76 p1
=(struct MemChunk
*)&freeList
->mh_First
;
77 p2
=freeList
->mh_First
;
79 /* Start and end(+1) of the block */
80 p3
=(struct MemChunk
*)memoryBlock
;
81 p4
=(UBYTE
*)p3
+byteSize
;
83 /* No chunk in list? Just insert the current one and return. */
86 p3
->mc_Bytes
=byteSize
;
89 freeList
->mh_Free
+=byteSize
;
93 /* Follow the list to find a place where to insert our memory. */
96 #if !defined(NO_CONSISTENCY_CHECKS)
98 Do some constistency checks:
99 1. All MemChunks must be aligned to MEMCHUNK_TOTAL.
100 2. The end (+1) of the current MemChunk
101 must be lower than the start of the next one.
103 if( ((IPTR
)p2
|p2
->mc_Bytes
)&(MEMCHUNK_TOTAL
-1)
104 ||( (UBYTE
*)p2
+p2
->mc_Bytes
>=(UBYTE
*)p2
->mc_Next
105 &&p2
->mc_Next
!=NULL
))
106 Alert(AN_MemCorrupt
|AT_DeadEnd
);
108 /* Found a block with a higher address? */
111 #if !defined(NO_CONSISTENCY_CHECKS)
113 If the memory to be freed overlaps with the current
114 block something must be wrong.
122 /* End the loop with p2 non-zero */
125 /* goto next block */
129 /* If the loop ends with p2 zero add it at the end. */
132 /* If there was a previous block merge with it. */
133 if(p1
!=(struct MemChunk
*)&freeList
->mh_First
)
135 #if !defined(NO_CONSISTENCY_CHECKS)
136 /* Check if they overlap. */
137 if((UBYTE
*)p1
+p1
->mc_Bytes
>(UBYTE
*)p3
)
143 /* Merge if possible */
144 if((UBYTE
*)p1
+p1
->mc_Bytes
==(UBYTE
*)p3
)
147 /* Not possible to merge */
151 There was no previous block. Just insert the memory at
152 the start of the list.
156 /* Try to merge with next block (if there is one ;-) ). */
157 if(p4
==(UBYTE
*)p2
&&p2
!=NULL
)
160 Overlap checking already done. Doing it here after
161 the list potentially changed would be a bad idea.
166 /* relink the list and return. */
168 p3
->mc_Bytes
=p4
-(UBYTE
*)p3
;
169 freeList
->mh_Free
+=byteSize
;