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