Copyright clean-up (part 1):
[AROS.git] / test / kernel / allocator.c
blob24368b9b2fc151d67829598166d15ae89a3678bb
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 * WARNING!!!
8 * This test relies on some particular internal functioning of kernel memory allocator!
9 * You'll have to change the code if you change something in kernel!
11 * Note also that this test requires working exec trap handling.
15 * We will not perform access tests because when we exit from trap handler,
16 * execution continues from the same location (re-triggering the trap again).
17 * Fixing this requires adjusting PC register in the context, which is not
18 * portable accross various CPUs and additionally will not currently work
19 * on all ports. We don't want to overcomplicate things so much.
21 #define NO_ACCESS_TESTS
23 #include <aros/kernel.h>
24 #include <exec/execbase.h>
25 #include <proto/exec.h>
26 #include <proto/kernel.h>
28 #include <stdio.h>
30 /* Include private kernel.resource stuff, for DumpState() */
31 struct KernelBase;
32 #include "../../rom/kernel/mm_linear.h"
34 #define PAGES_NUM 14
36 volatile static ULONG trap;
38 static void TrapHandler(ULONG code, void *ctx)
40 trap = code;
43 static void TestRead(UBYTE *location)
45 #ifdef NO_ACCESS_TESTS
46 printf("Access tests disabled\n");
47 #else
49 volatile UBYTE val;
51 /* Reset trap indication */
52 trap = -1;
54 printf("Test read from 0x%p... ", location);
55 val = *location;
58 * We can't printf() from trap handler. Instead we just
59 * remember trap code and check it later here.
61 if (trap == -1)
62 printf("Success, value is 0x%02X\n", val);
63 else
64 printf("Hit trap 0x%08X\n", trap);
66 #endif
70 * Print status of all pages in the specified MemHeader.
71 * '#' means allocated page, '.' means free page
73 static void DumpState(struct MemHeader *mh)
75 struct BlockHeader *head = (struct BlockHeader *)mh->mh_First;
76 IPTR p;
78 printf("Page map (%u total):\n", (unsigned)head->size);
80 for (p = 0; p < head->size; p++)
81 printf(P_STATUS(head->map[p]) ? "#" : ".");
83 printf("\n");
86 int main(void)
88 #if defined(KrnStatMemory)
90 APTR KernelBase;
91 struct Task *me;
92 ULONG page;
93 struct MemHeader *TestArea;
94 ULONG TestLength;
95 struct MemChunk *mc;
96 APTR region1, region2, region3, region4;
98 KernelBase = OpenResource("kernel.resource");
99 if (!KernelBase)
101 printf("Failed to open kernel.resource!\n");
102 return 1;
105 if (!KrnStatMemory(0, KMS_PageSize, &page, TAG_DONE))
107 printf("MMU support is not implemented for this system!\n"
108 "kernel.resource memory allocator will not work!\n");
109 return 1;
111 printf("System page size: %u (0x%08X)\n", (unsigned)page, (unsigned)page);
113 TestLength = PAGES_NUM * page;
114 TestArea = AllocMem(TestLength, MEMF_ANY);
115 printf("Allocated test region (%u bytes) at 0x%p\n", (unsigned)TestLength, TestArea);
116 if (!TestArea)
118 printf("Failed to allocate test region!\n");
119 return 1;
122 /* Install trap handler */
123 me = FindTask(NULL);
124 me->tc_TrapCode = TrapHandler;
126 /* Compose a MemHeader */
127 TestArea->mh_Node.ln_Succ = NULL;
128 TestArea->mh_Node.ln_Type = NT_MEMORY;
129 TestArea->mh_Node.ln_Name = "Kernel allocator test area";
130 TestArea->mh_Node.ln_Pri = 127; /* This MemHeader must be the first in the list, otherwise KrnFreePages() will find a wrong one */
131 TestArea->mh_Attributes = MEMF_FAST;
132 TestArea->mh_Lower = TestArea;
133 TestArea->mh_Upper = TestArea->mh_Lower + TestLength - 1;
134 TestArea->mh_First = TestArea->mh_Lower + MEMHEADER_TOTAL;
135 TestArea->mh_Free = TestLength - MEMHEADER_TOTAL;
137 mc = TestArea->mh_First;
138 mc->mc_Next = NULL;
139 mc->mc_Bytes = TestArea->mh_Free;
141 /* Give up the area to kernel allocator */
142 KrnInitMemory(TestArea);
143 if (mc->mc_Next || mc->mc_Bytes)
145 printf("KrnInitMemory() failed:\n"
146 " mc_Next is 0x%p\n"
147 " mc_Bytes is %lu\n",
148 mc->mc_Next, mc->mc_Bytes);
149 goto exit;
152 printf("Testing initial no-access protection...\n");
153 TestRead((UBYTE *)TestArea + page);
156 * Insert the area into system list.
157 * We do it manually because in future AddMemList() will call KrnInitMemory() itself.
159 Forbid();
160 Enqueue(&SysBase->MemList, &TestArea->mh_Node);
161 Permit();
163 printf("Allocating region1 (two read-write pages)...\n");
164 region1 = KrnAllocPages(NULL, 2 * page, MEMF_FAST);
165 printf("region1 at 0x%p\n", region1);
166 DumpState(TestArea);
168 printf("Freeing region1...\n");
169 KrnFreePages(region1, 2 * page);
170 printf("Done!\n");
171 DumpState(TestArea);
173 printf("Allocating region1 (3 read-only pages)...\n");
174 region1 = KrnAllocPages(NULL, 3 * page, MEMF_FAST);
175 printf("region1 at 0x%p\n", region1);
176 DumpState(TestArea);
178 printf("Allocating region2 (4 write-only ;-) pages)...\n");
179 region2 = KrnAllocPages(NULL, 4 * page, MEMF_FAST);
180 printf("region2 at 0x%p\n", region2);
181 DumpState(TestArea);
183 printf("Attempting to allocate page with wrong flags...\n");
184 region3 = KrnAllocPages(NULL, page, MEMF_CHIP|MEMF_FAST);
185 printf("Region at 0x%p\n", region3);
186 if (region3)
188 printf("WARNING!!! This should have been NULL!\n");
189 KrnFreePages(region3, page);
192 printf("Freeing region1...\n");
193 KrnFreePages(region1, 3 * page);
194 printf("Done!\n");
195 DumpState(TestArea);
197 printf("Freeing region2...\n");
198 KrnFreePages(region2, 4 * page);
199 printf("Done!\n");
200 DumpState(TestArea);
202 printf("Allocating region1 (one read-write page)...\n");
203 region1 = KrnAllocPages(NULL, page, MEMF_FAST);
204 printf("region1 at 0x%p\n", region1);
205 DumpState(TestArea);
207 printf("Freeing region1...\n");
208 KrnFreePages(region1, page);
209 printf("Done!\n");
210 DumpState(TestArea);
212 printf("Now we'll try to fragment the memory\n");
214 printf("Allocating region1 (2 pages)...\n");
215 region1 = KrnAllocPages(NULL, 2 * page, MEMF_FAST);
216 printf("region1 at 0x%p\n", region1);
217 DumpState(TestArea);
219 printf("Allocating region2 (3 pages)...\n");
220 region2 = KrnAllocPages(NULL, 3 * page, MEMF_FAST);
221 printf("region2 at 0x%p\n", region2);
222 DumpState(TestArea);
224 printf("Allocating region 3 (1 page)...\n");
225 region3 = KrnAllocPages(NULL, page, MEMF_FAST);
226 printf("Region at 0x%p\n", region3);
227 DumpState(TestArea);
229 printf("Allocating region 4 (2 pages)...\n");
230 region4 = KrnAllocPages(NULL, 2 * page, MEMF_FAST);
231 printf("region4 at 0x%p\n", region1);
232 DumpState(TestArea);
234 printf("Freeing region1...\n");
235 KrnFreePages(region1, 2 * page);
236 printf("Done!\n");
237 DumpState(TestArea);
239 printf("Freeing region3...\n");
240 KrnFreePages(region3, page);
241 printf("Done!\n");
242 DumpState(TestArea);
244 printf("Allocating region 3 (1 page) again...\n");
245 region3 = KrnAllocPages(NULL, page, MEMF_FAST);
246 printf("Region at 0x%p\n", region3);
247 DumpState(TestArea);
249 printf("Freeing region2...\n");
250 KrnFreePages(region2, 3 * page);
251 printf("Done!\n");
252 DumpState(TestArea);
254 printf("Freeing region3...\n");
255 KrnFreePages(region3, page);
256 printf("Done!\n");
257 DumpState(TestArea);
259 printf("Freeing region4...\n");
260 KrnFreePages(region4, 2 * page);
261 printf("Done!\n");
262 DumpState(TestArea);
264 exit:
265 if (TestArea->mh_Node.ln_Succ)
267 Forbid();
268 Remove(&TestArea->mh_Node);
269 Permit();
271 FreeMem(TestArea, TestLength);
273 #else
274 printf("The test can't be built for this kernel.resource implementation\n");
275 #endif
277 return 0;