2 Copyright � 2010-2011, The AROS Development Team. All rights reserved.
5 Desc: Common memory utility functions
11 #include <aros/debug.h>
12 #include <exec/execbase.h>
13 #include <exec/memory.h>
14 #include <exec/types.h>
15 #include <exec/memheaderext.h>
16 #include <proto/exec.h>
18 #include "kernel_base.h"
19 #include "kernel_debug.h"
23 static void destroy_Pool(struct MemHeaderExt
*mhe
)
25 tlsf_destroy(mhe
->mhe_UserData
);
28 static APTR
fetch_more_ram(void * data
, IPTR
*size
)
30 struct MemHeaderExt
*mhe
= (struct MemHeaderExt
*)data
;
32 D(nbug("[TLSF] fetch_more_ram(%p, %d)\n", mhe
, *size
));
34 APTR ptr
= AllocMem(*size
, mhe
->mhe_MemHeader
.mh_Attributes
);
38 static VOID
release_ram(void * data
, APTR ptr
, IPTR size
)
40 D(nbug("[TLSF] release_ram(%p, %d)\n", ptr
, size
));
45 static void * init_Pool(struct MemHeaderExt
*mhe
, IPTR puddleSize
, IPTR initialSize
)
47 return tlsf_init_autogrow(mhe
->mhe_UserData
, initialSize
, puddleSize
,
48 fetch_more_ram
, release_ram
, mhe
);
51 static APTR
alloc_mem(struct MemHeaderExt
*mhe
, IPTR size
, ULONG
*flags
)
56 struct ExecBase
*b
= SysBase
;
58 nbug("[TLSF] alloc_mem(%p, %d, %p(%d)), tlsf=%p, Task %p (%s)\n",
59 mhe
, size
, flags
, flags
? *flags
: -1, mhe
->mhe_UserData
,
60 b
? b
->ThisTask
: NULL
,
61 b
? (b
->ThisTask
? b
->ThisTask
->tc_Node
.ln_Name
: "unknown") : "no_exec")
64 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
65 ObtainSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
67 ptr
= tlsf_malloc(mhe
->mhe_UserData
, size
);
69 mhe
->mhe_MemHeader
.mh_Free
= tlsf_avail(mhe
->mhe_UserData
, MEMF_TOTAL
);
71 D(nbug("[TLSF] alloc returned %p\n", ptr
));
73 if (flags
&& (*flags
& MEMF_CLEAR
))
78 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
79 ReleaseSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
84 static void free_mem(struct MemHeaderExt
*mhe
, APTR ptr
, IPTR size
)
86 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
87 ObtainSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
89 D(nbug("[TLSF] free mem (%p, %p, %d), tlsf=%p\n",
90 mhe
, ptr
, size
, mhe
->mhe_UserData
));
93 tlsf_free(mhe
->mhe_UserData
, ptr
);
95 mhe
->mhe_MemHeader
.mh_Free
= tlsf_avail(mhe
->mhe_UserData
, MEMF_TOTAL
);
97 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
98 ReleaseSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
101 static void free_vec(struct MemHeaderExt
*mhe
, APTR ptr
)
103 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
104 ObtainSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
106 D(nbug("[TLSF] free vec (%p, %p), tlsf=%p\n",
107 mhe
, ptr
, mhe
->mhe_UserData
));
110 tlsf_free(mhe
->mhe_UserData
, ptr
);
112 mhe
->mhe_MemHeader
.mh_Free
= tlsf_avail(mhe
->mhe_UserData
, MEMF_TOTAL
);
114 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
115 ReleaseSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
118 static APTR
alloc_abs(struct MemHeaderExt
*mhe
, IPTR size
, APTR location
)
122 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
123 ObtainSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
125 D(nbug("[TLSF] alloc abs (%p, %p, %d), tlsf=%p\n",
126 mhe
, location
, size
, mhe
->mhe_UserData
));
128 if (location
&& size
)
129 ptr
= tlsf_allocabs(mhe
->mhe_UserData
, location
, size
);
131 mhe
->mhe_MemHeader
.mh_Free
= tlsf_avail(mhe
->mhe_UserData
, MEMF_TOTAL
);
133 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
134 ReleaseSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
139 static APTR
_realloc(struct MemHeaderExt
*mhe
, APTR location
, IPTR size
)
143 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
144 ObtainSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
146 D(nbug("[TLSF] realloc (%p, %p, %d), tlsf=%p\n",
147 mhe
, location
, size
, mhe
->mhe_UserData
));
149 ptr
= tlsf_realloc(mhe
->mhe_UserData
, location
, size
);
151 mhe
->mhe_MemHeader
.mh_Free
= tlsf_avail(mhe
->mhe_UserData
, MEMF_TOTAL
);
153 D(nbug("[TLSF] realloc returned %p\n", ptr
));
155 if (mhe
->mhe_MemHeader
.mh_Attributes
& MEMF_SEM_PROTECTED
)
156 ReleaseSemaphore((struct SignalSemaphore
*)mhe
->mhe_MemHeader
.mh_Node
.ln_Name
);
161 static IPTR
avail(struct MemHeaderExt
*mhe
, ULONG requirements
)
163 return tlsf_avail(mhe
->mhe_UserData
, requirements
);
166 static BOOL
inbounds(struct MemHeaderExt
*mhe
, APTR begin
, APTR end
)
168 return tlsf_in_bounds(mhe
->mhe_UserData
, begin
, end
);
172 * Create MemHeader structure for the specified RAM region.
173 * The header will be placed in the beginning of the region itself.
174 * The header will NOT be added to the memory list!
176 void krnCreateMemHeader(CONST_STRPTR name
, BYTE pri
, APTR start
, IPTR size
, ULONG flags
)
178 /* The MemHeader itself does not have to be aligned */
179 struct MemHeader
*mh
= start
;
181 /* If the end is less than (1 << 31), MEMF_31BIT is implied */
182 if (((IPTR
)start
+size
) < (1UL << 31))
185 flags
&= ~MEMF_31BIT
;
187 if (flags
& MEMF_MANAGED
)
189 struct MemHeaderExt
*mhe
= start
;
191 mhe
->mhe_DestroyPool
= destroy_Pool
;
192 mhe
->mhe_InitPool
= init_Pool
;
194 mhe
->mhe_Alloc
= alloc_mem
;
195 mhe
->mhe_AllocVec
= alloc_mem
;
196 mhe
->mhe_Free
= free_mem
;
197 mhe
->mhe_FreeVec
= free_vec
;
198 mhe
->mhe_AllocAbs
= alloc_abs
;
199 mhe
->mhe_ReAlloc
= _realloc
;
200 mhe
->mhe_Avail
= avail
;
201 mhe
->mhe_InBounds
= inbounds
;
203 mh
->mh_Node
.ln_Succ
= NULL
;
204 mh
->mh_Node
.ln_Pred
= NULL
;
205 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
206 mh
->mh_Node
.ln_Name
= (STRPTR
)name
;
207 mh
->mh_Node
.ln_Pri
= pri
;
208 mh
->mh_Attributes
= flags
;
209 /* The first MemChunk needs to be aligned. We do it by adding MEMHEADER_TOTAL. */
212 mhe
->mhe_UserData
= (APTR
)mh
+ ((sizeof(struct MemHeaderExt
) + 15) & ~15);
214 tlsf_init(mhe
->mhe_UserData
, size
- ((sizeof(struct MemHeaderExt
) + 15) & ~15));
217 * mh_Lower and mh_Upper are informational only. Since our MemHeader resides
218 * inside the region it describes, the region includes MemHeader.
220 mh
->mh_Lower
= start
;
221 mh
->mh_Upper
= start
+ size
;
226 mh
->mh_Node
.ln_Succ
= NULL
;
227 mh
->mh_Node
.ln_Pred
= NULL
;
228 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
229 mh
->mh_Node
.ln_Name
= (STRPTR
)name
;
230 mh
->mh_Node
.ln_Pri
= pri
;
231 mh
->mh_Attributes
= flags
;
233 /* The first MemChunk needs to be aligned. We do it by adding MEMHEADER_TOTAL. */
234 mh
->mh_First
= start
+ MEMHEADER_TOTAL
;
235 mh
->mh_First
->mc_Next
= NULL
;
236 mh
->mh_First
->mc_Bytes
= size
- MEMHEADER_TOTAL
;
239 * mh_Lower and mh_Upper are informational only. Since our MemHeader resides
240 * inside the region it describes, the region includes MemHeader.
242 mh
->mh_Lower
= start
;
243 mh
->mh_Upper
= start
+ size
;
244 mh
->mh_Free
= mh
->mh_First
->mc_Bytes
;
249 * Create informational MemHeader for ROM region.
250 * The header will be allocated from system's public memory lists.
251 * It will be not possible to allocate memory from the created MemHeader.
252 * The header will be added to the memory list.
253 * This routine uses exec.library/Allocate() for memory allocation, so it is safe
254 * to use before exec.library and kernel.resource memory management is initialized.
256 struct MemHeader
*krnCreateROMHeader(CONST_STRPTR name
, APTR start
, APTR end
)
258 struct MemHeader
*mh
= AllocMem(sizeof(struct MemHeader
), MEMF_ANY
);
262 mh
->mh_Node
.ln_Type
= NT_MEMORY
;
263 mh
->mh_Node
.ln_Name
= (STRPTR
)name
;
264 mh
->mh_Node
.ln_Pri
= -128;
265 mh
->mh_Attributes
= MEMF_KICK
;
267 mh
->mh_Lower
= start
;
268 mh
->mh_Upper
= end
+ 1; /* end is the last valid address of the region */
269 mh
->mh_Free
= 0; /* Never allocate from this chunk! */
270 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);