2 Copyright © 2010-2017, 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_intern.h>
19 #include <kernel_debug.h>
20 #include <kernel_mm.h>
24 void *mm_AllocPages(void *addr
, uintptr_t length
, uint32_t flags
, struct KernelBase
*KernelBase
)
28 ULONG physFlags
= flags
& MEMF_PHYSICAL_MASK
;
31 * Loop over MemHeader structures.
32 * We only add MemHeaders and never remove them, so i hope Forbid()/Permit()
33 * is not really necessary here.
35 ForeachNode(&SysBase
->MemList
, mh
)
38 * Check for the right requirements and enough free memory.
39 * The requirements are OK if there's no bit in the
40 * 'physFlags' that isn't set in the 'mh->mh_Attributes'.
42 if ((physFlags
& ~mh
->mh_Attributes
) || mh
->mh_Free
< length
)
48 * If we have starting address, only one MemHeader can be
49 * appropriate for us. We look for it and attempt to allocate
50 * the given region from it.
52 if (addr
>= mh
->mh_Lower
|| addr
+ length
<= mh
->mh_Upper
)
54 res
= mm_AllocAbs(mh
, addr
, length
);
61 * Otherwise try to allocate pages from every MemHeader.
62 * Note that we still may fail if the memory is fragmented too much.
64 res
= mm_Allocate(mh
, length
, flags
);
73 void mm_FreePages(void *addr
, uintptr_t length
, struct KernelBase
*KernelBase
)
77 ForeachNode(&SysBase
->MemList
, mh
)
79 D(bug("[KrnFreePages] Checking MemHeader 0x%p... ", mh
));
81 /* Test if the memory belongs to this MemHeader. */
82 if (mh
->mh_Lower
<= addr
&& mh
->mh_Upper
> addr
)
84 D(bug("[KrnFreePages] Match!\n"));
86 /* Test if it really fits into this MemHeader. */
87 if ((addr
+ length
) > mh
->mh_Upper
)
88 /* Something is completely wrong. */
89 Alert(AN_MemCorrupt
|AT_DeadEnd
);
91 mm_Free(mh
, addr
, length
);
95 D(bug("[KrnFreePages] No match!\n"));
99 /* Allocate a space usable by exec.library/Allocate() inside kernel's MemHeader. */
100 struct MemHeader
*mm_AllocExecHeader(struct MemHeader
*mh
, STRPTR name
, IPTR maxsize
)
102 struct MemHeader
*bootmh
= mm_Allocate(mh
, maxsize
, MEMF_ANY
);
106 bootmh
->mh_Node
.ln_Succ
= NULL
;
107 bootmh
->mh_Node
.ln_Pred
= NULL
;
108 bootmh
->mh_Node
.ln_Name
= name
;
109 bootmh
->mh_Node
.ln_Type
= mh
->mh_Node
.ln_Type
;
110 bootmh
->mh_Node
.ln_Pri
= mh
->mh_Node
.ln_Pri
;
111 bootmh
->mh_Attributes
= mh
->mh_Attributes
;
112 bootmh
->mh_First
= (APTR
)((IPTR
)bootmh
+ MEMHEADER_TOTAL
);
113 bootmh
->mh_First
->mc_Next
= NULL
;
114 bootmh
->mh_First
->mc_Bytes
= maxsize
- MEMHEADER_TOTAL
;
117 * mh_Lower and mh_Upper are informational only. Since our MemHeader resides
118 * inside the region it describes, the region includes MemHeader.
120 bootmh
->mh_Lower
= (APTR
)((IPTR
)bootmh
);
121 bootmh
->mh_Upper
= (APTR
)((IPTR
)bootmh
+ maxsize
);
122 bootmh
->mh_Free
= bootmh
->mh_First
->mc_Bytes
;