2 Copyright © 2010-2011, The AROS Development Team. All rights reserved.
5 Desc: Page-based memory allocator, low-level routines.
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>
17 #include <kernel_base.h>
18 #include <kernel_debug.h>
19 #include <kernel_mm.h>
23 void *mm_AllocPages(void *addr
, uintptr_t length
, uint32_t flags
, struct KernelBase
*KernelBase
)
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
)
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
);
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
);
72 void mm_FreePages(void *addr
, uintptr_t length
, struct KernelBase
*KernelBase
)
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
);
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
);
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
;