xref: /haiku/src/tests/system/boot/heap/heapTest.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 /*
2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS License.
4 */
5 
6 
7 #include <boot/platform.h>
8 #include <boot/heap.h>
9 
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdarg.h>
14 
15 
16 extern "C" void *heap_malloc(size_t size);
17 extern "C" void heap_free(void *buffer);
18 extern void dump_chunks(void);
19 extern uint32 heap_available(void);
20 
21 
22 const int32	kHeapSize = 32 * 1024;
23 
24 int32 gVerbosity = 1;
25 
26 
27 void
28 platform_release_heap(struct stage2_args *args, void *base)
29 {
30 	free(base);
31 }
32 
33 
34 status_t
35 platform_init_heap(struct stage2_args *args, void **_base, void **_top)
36 {
37 	void *base = malloc(kHeapSize);
38 	if (base == NULL)
39 		return B_NO_MEMORY;
40 
41 	*_base = base;
42 	*_top = (void *)((uint8 *)base + kHeapSize);
43 
44 	return B_OK;
45 }
46 
47 
48 void
49 panic(const char *format, ...)
50 {
51 	va_list args;
52 
53 	va_start(args, format);
54 	vfprintf(stderr, format, args);
55 	va_end(args);
56 
57 	exit(-1);
58 }
59 
60 
61 //	#pragma mark -
62 
63 
64 static void
65 dump_allocated_chunk(int32 index, void *buffer)
66 {
67 	if (buffer == NULL || gVerbosity < 3)
68 		return;
69 
70 	size_t *size = (size_t *)((uint8 *)buffer - sizeof(uint32));
71 	printf("\t%ld. allocation at %p, chunk at %p, size = %ld\n", index, buffer, size, *size);
72 
73 	if (gVerbosity > 3)
74 		dump_chunks();
75 }
76 
77 
78 static void *
79 test_malloc(size_t bytes)
80 {
81 	return heap_malloc(bytes);
82 }
83 
84 
85 static void
86 test_free(void *buffer)
87 {
88 	if (gVerbosity > 4) {
89 		printf("\tfreeing buffer at %p\n", buffer);
90 		dump_allocated_chunk(-1, buffer);
91 	}
92 
93 	heap_free(buffer);
94 
95 	if (gVerbosity > 4) {
96 		puts("\t- after:");
97 		dump_chunks();
98 	}
99 }
100 
101 
102 static int32
103 random_allocations(void *array[], size_t maxSize)
104 {
105 	printf("* random allocations (up to %ld bytes)\n", maxSize);
106 
107 	size_t total = 0;
108 	int32 count = 0;
109 
110 	for (int32 i = 0; i < 100; i++) {
111 		size_t size = size_t(rand() * 1. * maxSize / RAND_MAX);
112 		array[i] = test_malloc(size);
113 		if (array[i] == NULL) {
114 			if ((size > heap_available() || size == 0) && gVerbosity < 2)
115 				continue;
116 
117 			printf(	"%ld. allocating %ld bytes failed (%ld bytes total allocated, "
118 					"%ld free (%ld))\n",
119 					i, size, total, heap_available(), kHeapSize - total);
120 		} else {
121 			dump_allocated_chunk(i, array[i]);
122 
123 			total += size;
124 			count++;
125 		}
126 	}
127 
128 	printf("\t%ld bytes allocated\n", total);
129 	if (gVerbosity > 3)
130 		dump_chunks();
131 
132 	return count;
133 }
134 
135 
136 int
137 main(int argc, char **argv)
138 {
139 	if (argc > 1)
140 		gVerbosity = atoi(argv[1]);
141 
142 	stage2_args args;
143 	memset(&args, 0, sizeof(args));
144 	args.heap_size = kHeapSize;
145 
146 	if (heap_init(&args) < B_OK) {
147 		fprintf(stderr, "Could not initialize heap.\n");
148 		return -1;
149 	}
150 
151 	printf("heap size == %ld\n", kHeapSize);
152 	if (gVerbosity > 2)
153 		dump_chunks();
154 
155 	puts("* simple allocation of 100 * 128 bytes");
156 	void *array[100];
157 	for (int32 i = 0; i < 100; i++) {
158 		array[i] = test_malloc(128);
159 		dump_allocated_chunk(i, array[i]);
160 	}
161 
162 	if (gVerbosity > 2)
163 		dump_chunks();
164 
165 	puts("* testing different deleting order");
166 	if (gVerbosity > 2)
167 		puts("- free 30 from the end (descending):");
168 
169 	for (int32 i = 100; i-- > 70; ) {
170 		test_free(array[i]);
171 		array[i] = NULL;
172 	}
173 
174 	if (gVerbosity > 2) {
175 		dump_chunks();
176 		puts("- free 40 from the middle (ascending):");
177 	}
178 
179 	for (int32 i = 30; i < 70; i++) {
180 		test_free(array[i]);
181 		array[i] = NULL;
182 	}
183 
184 	if (gVerbosity > 2) {
185 		dump_chunks();
186 		puts("- free 30 from the start (ascending):");
187 	}
188 
189 	for (int32 i = 0; i < 30; i++) {
190 		test_free(array[i]);
191 		array[i] = NULL;
192 	}
193 
194 	if (gVerbosity > 2)
195 		dump_chunks();
196 
197 	puts("* allocate until it fails");
198 	int32 i = 0;
199 	for (i = 0; i < 100; i++) {
200 		array[i] = test_malloc(kHeapSize / 64);
201 		if (array[i] == NULL) {
202 			printf("\tallocation %ld failed - could allocate %ld bytes (64th should fail).\n", i + 1, (kHeapSize / 64) * (i + 1));
203 
204 			if (gVerbosity > 2)
205 				dump_chunks();
206 
207 			while (i-- > 0) {
208 				test_free(array[i]);
209 				array[i] = NULL;
210 			}
211 
212 			break;
213 		} else
214 			dump_allocated_chunk(i, array[i]);
215 	}
216 	if (i == 100)
217 		fprintf(stderr, "could allocate more memory than in heap\n");
218 
219 	random_allocations(array, 768);
220 
221 	puts("* free memory again");
222 	for (i = 0; i < 100; i++) {
223 		test_free(array[i]);
224 		array[i] = NULL;
225 	}
226 
227 	for (size_t amount = 32; amount < 1024; amount *= 2) {
228 		int32 count = random_allocations(array, amount);
229 
230 		puts("* random freeing");
231 		while (count) {
232 			i = int32(rand() * 100. / RAND_MAX);
233 			if (array[i] == NULL)
234 				continue;
235 
236 			test_free(array[i]);
237 			array[i] = NULL;
238 			count--;
239 
240 			if (gVerbosity > 2) {
241 				puts("- freed one");
242 				dump_chunks();
243 			}
244 		}
245 	}
246 
247 	heap_release(&args);
248 	return 0;
249 }
250 
251