gcc-4.6.2: Update with patch for gengtype.c
[AROS.git] / rom / kernel / kernel_mm.c
blob749502499b0514ca599ce7f61e4f36b731b83f01
1 /*
2 Copyright © 2010-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Page-based memory allocator, low-level routines.
6 Lang: english
7 */
9 #include <aros/config.h>
10 #include <exec/alerts.h>
11 #include <exec/execbase.h>
12 #include <proto/arossupport.h>
13 #include <proto/exec.h>
15 #include <inttypes.h>
17 #include <kernel_base.h>
18 #include <kernel_debug.h>
19 #include <kernel_mm.h>
21 #define D(x)
23 void *mm_AllocPages(void *addr, uintptr_t length, uint32_t flags, struct KernelBase *KernelBase)
25 APTR res = NULL;
26 struct MemHeader *mh;
27 ULONG physFlags = flags & MEMF_PHYSICAL_MASK;
30 * Loop over MemHeader structures.
31 * We only add MemHeaders and never remove them, so i hope Forbid()/Permit()
32 * is not really necessary here.
34 ForeachNode(&SysBase->MemList, mh)
37 * Check for the right requirements and enough free memory.
38 * The requirements are OK if there's no bit in the
39 * 'physFlags' that isn't set in the 'mh->mh_Attributes'.
41 if ((physFlags & ~mh->mh_Attributes) || mh->mh_Free < length)
42 continue;
44 if (addr)
47 * If we have starting address, only one MemHeader can be
48 * appropriate for us. We look for it and attempt to allocate
49 * the given region from it.
51 if (addr >= mh->mh_Lower || addr + length <= mh->mh_Upper)
53 res = mm_AllocAbs(mh, addr, length);
54 break;
57 else
60 * Otherwise try to allocate pages from every MemHeader.
61 * Note that we still may fail if the memory is fragmented too much.
63 res = mm_Allocate(mh, length, flags);
64 if (res)
65 break;
69 return res;
72 void mm_FreePages(void *addr, uintptr_t length, struct KernelBase *KernelBase)
74 struct MemHeader *mh;
76 ForeachNode(&SysBase->MemList, mh)
78 D(bug("[KrnFreePages] Checking MemHeader 0x%p... ", mh));
80 /* Test if the memory belongs to this MemHeader. */
81 if (mh->mh_Lower <= addr && mh->mh_Upper > addr)
83 D(bug("[KrnFreePages] Match!\n"));
85 /* Test if it really fits into this MemHeader. */
86 if ((addr + length) > mh->mh_Upper)
87 /* Something is completely wrong. */
88 Alert(AN_MemCorrupt|AT_DeadEnd);
90 mm_Free(mh, addr, length);
91 break;
94 D(bug("[KrnFreePages] No match!\n"));
98 /* Allocate a space usable by exec.library/Allocate() inside kernel's MemHeader. */
99 struct MemHeader *mm_AllocExecHeader(struct MemHeader *mh, STRPTR name, IPTR maxsize)
101 struct MemHeader *bootmh = mm_Allocate(mh, maxsize, MEMF_ANY);
103 if (bootmh)
105 bootmh->mh_Node.ln_Succ = NULL;
106 bootmh->mh_Node.ln_Pred = NULL;
107 bootmh->mh_Node.ln_Name = name;
108 bootmh->mh_Node.ln_Type = mh->mh_Node.ln_Type;
109 bootmh->mh_Node.ln_Pri = mh->mh_Node.ln_Pri;
110 bootmh->mh_Attributes = mh->mh_Attributes;
111 bootmh->mh_First = (APTR)((IPTR)bootmh + MEMHEADER_TOTAL);
112 bootmh->mh_First->mc_Next = NULL;
113 bootmh->mh_First->mc_Bytes = maxsize - MEMHEADER_TOTAL;
116 * mh_Lower and mh_Upper are informational only. Since our MemHeader resides
117 * inside the region it describes, the region includes MemHeader.
119 bootmh->mh_Lower = (APTR)((IPTR)bootmh);
120 bootmh->mh_Upper = (APTR)((IPTR)bootmh + maxsize);
121 bootmh->mh_Free = bootmh->mh_First->mc_Bytes;
124 return bootmh;