parent
187cc164cb
commit
b881b62e5b
|
@ -1,4 +1,5 @@
|
||||||
*-prototyping
|
*-prototyping
|
||||||
**/compiled
|
**/compiled
|
||||||
_build
|
_build
|
||||||
.dir-locals.el
|
.dir-locals.el
|
||||||
|
ax*
|
|
@ -0,0 +1,23 @@
|
||||||
|
cc = clang
|
||||||
|
|
||||||
|
cflags = -g -O0 -pthread \
|
||||||
|
-Wall \
|
||||||
|
-Wshadow \
|
||||||
|
-Wno-pragma-once-outside-header \
|
||||||
|
-Wpointer-arith \
|
||||||
|
-Wstrict-prototypes \
|
||||||
|
-Wmissing-prototypes \
|
||||||
|
-Wfloat-equal \
|
||||||
|
-Werror=implicit-function-declaration
|
||||||
|
|
||||||
|
srcs = $(wildcard src/**/*.c test/*.c)
|
||||||
|
hdrs = $(wildcard **/*.h)
|
||||||
|
|
||||||
|
test_bin = axtest
|
||||||
|
|
||||||
|
all: ${test_bin}
|
||||||
|
|
||||||
|
${test_bin}: ${srcs} ${hdrs}
|
||||||
|
${cc} ${cflags} ${srcs} -o ${test_bin}
|
||||||
|
|
||||||
|
.PHONY: all
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define ASSERT(_cond, ...) do { \
|
||||||
|
if (!(_cond)) { \
|
||||||
|
fprintf(stderr, "ASSERT FAILED:\n" __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ASSERT_NON_NULL(_ptr, _who) \
|
||||||
|
ASSERT((_ptr) != NULL, "`" _who "' should not be null")
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include "../util.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static inline void* underlying_alloc(size_t sz)
|
||||||
|
{
|
||||||
|
void* p = malloc(sz);
|
||||||
|
// printf("[region] allocate %zu ==> %p\n", sz, p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void underlying_free(void* p)
|
||||||
|
{
|
||||||
|
// printf("[regoin] free %p\n", p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rgn_block {
|
||||||
|
struct rgn_block* next;
|
||||||
|
char* eob;
|
||||||
|
char data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
void rgn_init(struct rgn* rgn, size_t pgsize)
|
||||||
|
{
|
||||||
|
rgn->pgsize = pgsize;
|
||||||
|
rgn->here = rgn->eob = NULL;
|
||||||
|
rgn->unused_blocks = NULL;
|
||||||
|
rgn->used_blocks = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unused_blocks(struct rgn_block* b0)
|
||||||
|
{
|
||||||
|
struct rgn_block* b1;
|
||||||
|
for (; b0 != NULL; b0 = b1) {
|
||||||
|
b1 = b0->next;
|
||||||
|
underlying_free(b0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgn_cleanup(struct rgn* rgn)
|
||||||
|
{
|
||||||
|
unused_blocks(rgn->unused_blocks);
|
||||||
|
unused_blocks(rgn->used_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgn_clear(struct rgn* rgn)
|
||||||
|
{
|
||||||
|
struct rgn_block* uub = rgn->unused_blocks;
|
||||||
|
struct rgn_block* b0 = rgn->used_blocks;
|
||||||
|
struct rgn_block* b1;
|
||||||
|
for (; b0 != NULL; b0 = b1) {
|
||||||
|
b1 = b0->next;
|
||||||
|
b0->next = uub;
|
||||||
|
uub = b0;
|
||||||
|
}
|
||||||
|
rgn->unused_blocks = uub;
|
||||||
|
rgn->used_blocks = NULL;
|
||||||
|
rgn->here = rgn->eob = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void use_block(struct rgn* rgn, struct rgn_block* b)
|
||||||
|
{
|
||||||
|
b->next = rgn->used_blocks;
|
||||||
|
rgn->used_blocks = b;
|
||||||
|
rgn->here = b->data;
|
||||||
|
rgn->eob = b->eob;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void new_block(struct rgn* rgn)
|
||||||
|
{
|
||||||
|
struct rgn_block* b0 = rgn->unused_blocks;
|
||||||
|
if (b0 != NULL) {
|
||||||
|
rgn->unused_blocks = b0->next;
|
||||||
|
} else {
|
||||||
|
b0 = underlying_alloc(rgn->pgsize);
|
||||||
|
b0->eob = ((char*) b0) + rgn->pgsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
use_block(rgn, b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz)
|
||||||
|
{
|
||||||
|
// TODO: relax this
|
||||||
|
ASSERT(siz < rgn->pgsize, "allocation too big!");
|
||||||
|
|
||||||
|
char* there = rgn->here + siz;
|
||||||
|
if (there > rgn->eob) {
|
||||||
|
new_block(rgn);
|
||||||
|
there = rgn->here + siz;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* here = rgn->here;
|
||||||
|
rgn->here = there;
|
||||||
|
return here;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void rgn_print_stats(struct rgn* rgn, FILE* out)
|
||||||
|
{
|
||||||
|
fprintf(out, "[region stats] ======================\n");
|
||||||
|
fprintf(out, "[region stats] page size: %zu\n", rgn->pgsize);
|
||||||
|
fprintf(out, "[region stats] space left in block: %zu\n",
|
||||||
|
(rgn->eob - rgn->here));
|
||||||
|
|
||||||
|
size_t nub = 0;
|
||||||
|
size_t nuub = 0;
|
||||||
|
for (struct rgn_block* b = rgn->used_blocks;
|
||||||
|
b != NULL;
|
||||||
|
b = b->next) {
|
||||||
|
nub++;
|
||||||
|
}
|
||||||
|
for (struct rgn_block* b = rgn->unused_blocks;
|
||||||
|
b != NULL;
|
||||||
|
b = b->next) {
|
||||||
|
nuub++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(out, "[region stats] # used blocks: %zu\n", nub);
|
||||||
|
fprintf(out, "[region stats] # unused blocks: %zu\n", nuub);
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct rgn_block;
|
||||||
|
|
||||||
|
struct rgn {
|
||||||
|
size_t pgsize;
|
||||||
|
char* here;
|
||||||
|
char* eob;
|
||||||
|
struct rgn_block* unused_blocks;
|
||||||
|
struct rgn_block* used_blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SMALL 1024
|
||||||
|
#define MEDIUM (16*1024)
|
||||||
|
#define LARGE (1024*1024)
|
||||||
|
|
||||||
|
void rgn_init(struct rgn* rgn, size_t pgsize);
|
||||||
|
void rgn_cleanup(struct rgn* rgn);
|
||||||
|
void rgn_clear(struct rgn* rgn);
|
||||||
|
|
||||||
|
// void rgn_print_stats(struct rgn* rgn, FILE* out);
|
||||||
|
|
||||||
|
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz);
|
||||||
|
|
||||||
|
static inline void* ralloc(struct rgn* rgn, size_t siz)
|
||||||
|
{
|
||||||
|
if ((siz & 7) != 0) {
|
||||||
|
siz = (siz | 7) + 1;
|
||||||
|
}
|
||||||
|
return ralloc_assume_aligned(rgn, siz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void* rmemdup(struct rgn* rgn, const void* ptr, size_t siz)
|
||||||
|
{
|
||||||
|
void* new = ralloc(rgn, siz);
|
||||||
|
memcpy(new, ptr, siz);
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char* rstrdup(struct rgn* rgn, const char* str)
|
||||||
|
{
|
||||||
|
return rmemdup(rgn, str, strlen(str) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ralloc_typed(_rgn, T, _n) \
|
||||||
|
((T*) ralloc(_rgn, sizeof(T) * (_n)))
|
||||||
|
|
||||||
|
#define rmemdup_typed(_rgn, T, _p, _n) \
|
||||||
|
((T*) rmemdup(_rgn, _p, sizeof(T) * (_n)))
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "../src/region.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct rgn rgn[1];
|
||||||
|
rgn_init(rgn, SMALL);
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
char test[100];
|
||||||
|
memset(test, 'A', 99);
|
||||||
|
test[99] = '\0';
|
||||||
|
printf("%d; %p\n", j, rstrdup(rgn, test));
|
||||||
|
}
|
||||||
|
rgn_clear(rgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
rgn_cleanup(rgn);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue