You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.3 KiB
136 lines
3.3 KiB
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <string.h>
|
|
|
|
#include "alloc_api.h"
|
|
|
|
void *get_new_region(uintptr_t size) {
|
|
void *m = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
if (m == MAP_FAILED) {
|
|
return NULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
void error(char *msg) {
|
|
printf("=== ALLOCATOR ERROR ===\n%s\n====== END ERROR ======\n", msg);
|
|
}
|
|
|
|
struct AllocationRecord {
|
|
uintptr_t size;
|
|
void *allocation;
|
|
void *reference;
|
|
int id;
|
|
struct AllocationRecord *next;
|
|
struct AllocationRecord *prev;
|
|
};
|
|
|
|
void insert_record(struct AllocationRecord *dummy, void *allocation, uintptr_t size) {
|
|
struct AllocationRecord *record = malloc(sizeof(struct AllocationRecord));
|
|
record->size = size;
|
|
record->allocation = allocation;
|
|
record->reference = malloc(size);
|
|
record->next = dummy;
|
|
record->prev = dummy->prev;
|
|
record->id = dummy->id;
|
|
dummy->prev->next = record;
|
|
dummy->prev = record;
|
|
dummy->size += 1;
|
|
dummy->id += 1;
|
|
memcpy(record->reference, allocation, size);
|
|
}
|
|
|
|
void delete_record(struct AllocationRecord *dummy, struct AllocationRecord *delete) {
|
|
free(delete->reference);
|
|
delete->prev->next = delete->next;
|
|
delete->next->prev = delete->prev;
|
|
free(delete);
|
|
dummy->size -= 1;
|
|
}
|
|
|
|
struct AllocationRecord *get_record(struct AllocationRecord *dummy, int which) {
|
|
struct AllocationRecord *head = dummy->next;
|
|
while (which--) {
|
|
head = head->next;
|
|
}
|
|
return head;
|
|
}
|
|
|
|
int validate_record(struct AllocationRecord *record) {
|
|
if (memcmp(record->allocation, record->reference, record->size) != 0) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void new_region(struct AllocationRecord *dummy, struct Arena *arena) {
|
|
uintptr_t size = 1 + (rand() % 8192);
|
|
uintptr_t align = 1 << (rand() % 4);
|
|
printf("alloc'ing a region of size %lu with alignment %lu, id %i\n", size, align, dummy->id);
|
|
void *region = alloc(arena, size, align);
|
|
if (region == NULL) {
|
|
printf("memory allocator broke, we have 1L though\n");
|
|
return;
|
|
}
|
|
for (int ii = 0; ii < size; ii++) {
|
|
((char*) region)[ii] = (char) rand();
|
|
}
|
|
insert_record(dummy, region, size);
|
|
}
|
|
|
|
void delete_region(struct AllocationRecord *dummy, struct Arena *arena) {
|
|
if (dummy->size == 0) {
|
|
return;
|
|
}
|
|
uintptr_t which = rand() % dummy->size;
|
|
struct AllocationRecord *zap = get_record(dummy, which);
|
|
printf("dealloc'ing a region of size %lu, id %i\n", zap->size, zap->id);
|
|
unalloc(arena, zap->allocation);
|
|
delete_record(dummy, zap);
|
|
}
|
|
|
|
int act(struct AllocationRecord *dummy, struct Arena *arena) {
|
|
if (rand() & 1) {
|
|
new_region(dummy, arena);
|
|
} else {
|
|
delete_region(dummy, arena);
|
|
}
|
|
int die = 0;
|
|
struct AllocationRecord *head = dummy->next;
|
|
while (head != dummy) {
|
|
if (!validate_record(head)) {
|
|
printf("validation failed at id %i\n", head->id);
|
|
die = 1;
|
|
}
|
|
head = head->next;
|
|
}
|
|
return die;
|
|
}
|
|
|
|
int main() {
|
|
srand(1);
|
|
struct Arena arena = {
|
|
NULL,
|
|
NULL,
|
|
get_new_region,
|
|
error,
|
|
};
|
|
void *reg = alloc(&arena, 20, 4);
|
|
unalloc(&arena, reg);
|
|
struct AllocationRecord dummy = {
|
|
.size = 0,
|
|
.allocation = NULL,
|
|
.reference = NULL,
|
|
.id = 0,
|
|
};
|
|
dummy.next = &dummy;
|
|
dummy.prev = &dummy;
|
|
for (int ii = 0; ii < 100; ii++) {
|
|
act(&dummy, &arena);
|
|
}
|
|
return 0;
|
|
}
|