krnCreateMemHeader understands that it has to initialize MEMF_MANAGED
[AROS.git] / rom / kernel / kernel_memory.c
blobf8c9b5331440fbb765db88b7e98afd6947a317fc
1 /*
2 Copyright � 2010-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Common memory utility functions
6 Lang: english
7 */
9 #define DEBUG 0
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"
21 #include "tlsf.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);
35 return ptr;
38 static VOID release_ram(void * data, APTR ptr, IPTR size)
40 D(nbug("[TLSF] release_ram(%p, %d)\n", ptr, size));
42 FreeMem(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)
53 void *ptr;
55 D({
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")
62 });
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))
75 bzero(ptr, size);
78 if (mhe->mhe_MemHeader.mh_Attributes & MEMF_SEM_PROTECTED)
79 ReleaseSemaphore((struct SignalSemaphore *)mhe->mhe_MemHeader.mh_Node.ln_Name);
81 return ptr;
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));
92 if (ptr && size)
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));
109 if (ptr)
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)
120 void *ptr = NULL;
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);
136 return ptr;
139 static APTR _realloc(struct MemHeaderExt *mhe, APTR location, IPTR size)
141 void *ptr;
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);
158 return ptr;
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))
183 flags |= MEMF_31BIT;
184 else
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. */
210 mh->mh_First = NULL;
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;
222 mh->mh_Free = size;
224 else
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);
260 if (mh)
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;
266 mh->mh_First = NULL;
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);
273 return mh;