diff --git a/src/tests/kernel/boot/heap/heapTest.cpp b/src/tests/kernel/boot/heap/heapTest.cpp new file mode 100644 index 0000000000..2987add802 --- /dev/null +++ b/src/tests/kernel/boot/heap/heapTest.cpp @@ -0,0 +1,249 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include + +#include +#include +#include +#include + + +extern "C" void *heap_malloc(size_t size); +extern "C" void heap_free(void *buffer); +extern void dump_chunks(void); +extern int32 heap_available(void); + + +const int32 kHeapSize = 32 * 1024; + +int32 gVerbosity = 1; + + +void +platform_release_heap(void *base) +{ + free(base); +} + + +status_t +platform_init_heap(struct stage2_args *args, void **_base, void **_top) +{ + void *base = malloc(kHeapSize); + if (base == NULL) + return B_NO_MEMORY; + + *_base = base; + *_top = (void *)((uint8 *)base + kHeapSize); + + return B_OK; +} + + +void +panic(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + exit(-1); +} + + +// #pragma mark - + + +static void +dump_allocated_chunk(int32 index, void *buffer) +{ + if (buffer == NULL || gVerbosity < 3) + return; + + size_t *size = (size_t *)((uint8 *)buffer - sizeof(uint32)); + printf("\t%ld. allocation at %p, chunk at %p, size = %ld\n", index, buffer, size, *size); + + if (gVerbosity > 3) + dump_chunks(); +} + + +static void * +test_malloc(size_t bytes) +{ + return heap_malloc(bytes); +} + + +static void +test_free(void *buffer) +{ + if (gVerbosity > 4) { + printf("\tfreeing buffer at %p\n", buffer); + dump_allocated_chunk(-1, buffer); + } + + heap_free(buffer); + + if (gVerbosity > 4) { + puts("\t- after:"); + dump_chunks(); + } +} + + +static int32 +random_allocations(void *array[], size_t maxSize) +{ + printf("* random allocations (up to %ld bytes)\n", maxSize); + + size_t total = 0; + int32 count = 0; + + for (int32 i = 0; i < 100; i++) { + size_t size = size_t(rand() * 1. * maxSize / RAND_MAX); + array[i] = test_malloc(size); + if (array[i] == NULL) { + if ((size > heap_available() || size == 0) && gVerbosity < 2) + continue; + + printf( "%ld. allocating %ld bytes failed (%ld bytes total allocated, " + "%ld free (%ld))\n", + i, size, total, heap_available(), kHeapSize - total); + } else { + dump_allocated_chunk(i, array[i]); + + total += size; + count++; + } + } + + printf("\t%ld bytes allocated\n", total); + if (gVerbosity > 3) + dump_chunks(); + + return count; +} + + +int +main(int argc, char **argv) +{ + if (argc > 1) + gVerbosity = atoi(argv[1]); + + stage2_args args; + memset(&args, 0, sizeof(args)); + + if (heap_init(&args) < B_OK) { + fprintf(stderr, "Could not initialize heap.\n"); + return -1; + } + + printf("heap size == %ld\n", kHeapSize); + if (gVerbosity > 2) + dump_chunks(); + + puts("* simple allocation of 100 * 128 bytes"); + void *array[100]; + for (int32 i = 0; i < 100; i++) { + array[i] = test_malloc(128); + dump_allocated_chunk(i, array[i]); + } + + if (gVerbosity > 2) + dump_chunks(); + + puts("* testing different deleting order"); + if (gVerbosity > 2) + puts("- free 30 from the end (descending):"); + + for (int32 i = 100; i-- > 70; ) { + test_free(array[i]); + array[i] = NULL; + } + + if (gVerbosity > 2) { + dump_chunks(); + puts("- free 40 from the middle (ascending):"); + } + + for (int32 i = 30; i < 70; i++) { + test_free(array[i]); + array[i] = NULL; + } + + if (gVerbosity > 2) { + dump_chunks(); + puts("- free 30 from the start (ascending):"); + } + + for (int32 i = 0; i < 30; i++) { + test_free(array[i]); + array[i] = NULL; + } + + if (gVerbosity > 2) + dump_chunks(); + + puts("* allocate until it fails"); + int32 i = 0; + for (i = 0; i < 100; i++) { + array[i] = test_malloc(kHeapSize / 64); + if (array[i] == NULL) { + printf("\tallocation %ld failed - could allocate %ld bytes (64th should fail).\n", i + 1, (kHeapSize / 64) * (i + 1)); + + if (gVerbosity > 2) + dump_chunks(); + + while (i-- > 0) { + test_free(array[i]); + array[i] = NULL; + } + + break; + } else + dump_allocated_chunk(i, array[i]); + } + if (i == 100) + fprintf(stderr, "could allocate more memory than in heap\n"); + + random_allocations(array, 768); + + puts("* free memory again"); + for (i = 0; i < 100; i++) { + test_free(array[i]); + array[i] = NULL; + } + + for (size_t amount = 32; amount < 1024; amount *= 2) { + int32 count = random_allocations(array, amount); + + puts("* random freeing"); + while (count) { + i = int32(rand() * 100. / RAND_MAX); + if (array[i] == NULL) + continue; + + test_free(array[i]); + array[i] = NULL; + count--; + + if (gVerbosity > 2) { + puts("- freed one"); + dump_chunks(); + } + } + } + + heap_release(); + return 0; +} +