420 lines
12 KiB
C
420 lines
12 KiB
C
#include <stdio.h>
|
|
#include "malunal/allocators/arena.h"
|
|
|
|
const malunal_size_t page_bytes = 4096;
|
|
const malunal_size_t init_bytes = sizeof(malunal_int32_t) * 4;
|
|
const malunal_size_t final_bytes = sizeof(malunal_int32_t) * 8;
|
|
|
|
static
|
|
allocator_acquire_res_t
|
|
test_arena_acquires(allocator_mptr_t arena) {
|
|
allocator_acquire_res_t result =
|
|
allocator_acquire((allocator_acquire_req_t) {
|
|
.allocator = arena,
|
|
.size = init_bytes
|
|
});
|
|
|
|
if (result.threw)
|
|
return result;
|
|
|
|
// Upstream checks.
|
|
if (arena->upstream->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->reserved);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->upstream->allocated != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->allocated);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->upstream->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->acquires);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->upstream->releases != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->releases != 0, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->releases);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
// Arena checks.
|
|
if (arena->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->reserved);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->allocated != init_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, init_bytes, arena->allocated);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->acquires);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
if (arena->releases != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->releases != 0, actual == %d";
|
|
fprintf(stderr, format, arena->releases);
|
|
return (allocator_acquire_res_t) {
|
|
.threw = 1,
|
|
.exception = ALLOCATOR_EXCEPTION_FAILURE
|
|
};
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int
|
|
test_arena_reacquire(
|
|
allocator_mptr_t arena,
|
|
malunal_mptr_t address
|
|
) {
|
|
malunal_int32_t index;
|
|
malunal_int32_t* vector;
|
|
|
|
vector = address;
|
|
for (index = 0; index < 4; index++)
|
|
vector[index] = index + 1;
|
|
|
|
allocator_acquire_res_t result =
|
|
allocator_reacquire((allocator_reacquire_req_t) {
|
|
.allocator = arena,
|
|
.prev = result.address,
|
|
.oldsz = init_bytes,
|
|
.newsz = final_bytes
|
|
});
|
|
|
|
if (result.threw)
|
|
return result.exception;
|
|
|
|
// Upstream checks.
|
|
if (arena->upstream->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->allocated != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->releases != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->releases != 0, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->releases);
|
|
return 1;
|
|
}
|
|
|
|
// Arena checks.
|
|
if (arena->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->reserved);
|
|
return 1;
|
|
}
|
|
|
|
malunal_int32_t all_bytes = init_bytes + final_bytes;
|
|
if (arena->allocated != all_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, all_bytes, arena->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->acquires != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->acquires != 2, actual == %d";
|
|
fprintf(stderr, format, arena->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->releases != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->releases != 1, actual == %d";
|
|
fprintf(stderr, format, arena->releases);
|
|
return 1;
|
|
}
|
|
|
|
return ALLOCATOR_EXCEPTION_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
test_arena_release(
|
|
allocator_mptr_t arena,
|
|
malunal_mptr_t address
|
|
) {
|
|
malunal_int32_t index;
|
|
malunal_int32_t* vector;
|
|
|
|
vector = address;
|
|
for (index = 0; index < 4; index++)
|
|
if (vector[index] != index + 1)
|
|
return 1;
|
|
|
|
allocator_exception_t relexc =
|
|
allocator_release((allocator_release_req_t) {
|
|
.allocator = arena,
|
|
.address = address,
|
|
.size = final_bytes
|
|
});
|
|
|
|
if (relexc != ALLOCATOR_EXCEPTION_SUCCESS)
|
|
return relexc;
|
|
|
|
// Upstream checks.
|
|
if (arena->upstream->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->allocated != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->releases != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->releases != 0, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->releases);
|
|
return 1;
|
|
}
|
|
|
|
// Arena checks.
|
|
if (arena->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->reserved);
|
|
return 1;
|
|
}
|
|
|
|
malunal_int32_t all_bytes = init_bytes + final_bytes;
|
|
if (arena->allocated != all_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, all_bytes, arena->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->acquires != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->acquires != 2, actual == %d";
|
|
fprintf(stderr, format, arena->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->releases != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->releases != 2, actual == %d";
|
|
fprintf(stderr, format, arena->releases);
|
|
return 1;
|
|
}
|
|
|
|
return ALLOCATOR_EXCEPTION_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
test_arena_reset(allocator_mptr_t arena) {
|
|
arena_reset(arena);
|
|
|
|
// Upstream checks.
|
|
if (arena->upstream->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->allocated != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->upstream->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->releases != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->releases != 0, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->releases);
|
|
return 1;
|
|
}
|
|
|
|
// Arena checks.
|
|
if (arena->reserved != page_bytes) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, page_bytes, arena->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->allocated != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->allocated != 0, actual == %d";
|
|
fprintf(stderr, format, arena->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->acquires != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->acquires != 2, actual == %d";
|
|
fprintf(stderr, format, arena->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->releases != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->releases != 2, actual == %d";
|
|
fprintf(stderr, format, arena->releases);
|
|
return 1;
|
|
}
|
|
|
|
return ALLOCATOR_EXCEPTION_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
test_arena_free(allocator_mptr_t arena) {
|
|
arena_free(arena);
|
|
|
|
// Upstream checks.
|
|
if (arena->upstream->reserved != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->reserved != 0, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->allocated != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->allocated != %d, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->acquires != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->acquires != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->upstream->releases != 1) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->upstream->releases != 1, actual == %d";
|
|
fprintf(stderr, format, arena->upstream->releases);
|
|
return 1;
|
|
}
|
|
|
|
// Arena checks.
|
|
if (arena->reserved != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->reserved != %d, actual == %d";
|
|
fprintf(stderr, format, arena->reserved);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->allocated != 0) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->allocated != 0, actual == %d";
|
|
fprintf(stderr, format, arena->allocated);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->acquires != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->acquires != 2, actual == %d";
|
|
fprintf(stderr, format, arena->acquires);
|
|
return 1;
|
|
}
|
|
|
|
if (arena->releases != 2) {
|
|
const malunal_cstr_t format =
|
|
"[arena_allocator]: arena->releases != 2, actual == %d";
|
|
fprintf(stderr, format, arena->releases);
|
|
return 1;
|
|
}
|
|
|
|
return ALLOCATOR_EXCEPTION_SUCCESS;
|
|
}
|
|
|
|
int test_arena_allocator() {
|
|
allocator_t upstream = platform_allocator();
|
|
allocator_t arena = arena_allocator(&upstream, page_bytes);
|
|
|
|
allocator_acquire_res_t result =
|
|
test_arena_acquires(&arena);
|
|
|
|
return !(
|
|
!result.threw &&
|
|
test_arena_reacquire(result.address, &arena) &&
|
|
test_arena_release(result.address, &arena) &&
|
|
test_arena_reset(&arena) &&
|
|
test_arena_free(&arena)
|
|
);
|
|
}
|