2 buddy allocator
This commit is contained in:
parent
6f63fcd92a
commit
9e1eae8e58
4
src/h.h
4
src/h.h
@ -487,7 +487,7 @@ u64 talloc = 0;
|
||||
u32** actrs;
|
||||
#endif
|
||||
|
||||
void onAlloc(usz sz, u8 type) {
|
||||
static void onAlloc(usz sz, u8 type) {
|
||||
#ifdef ALLOC_STAT
|
||||
if (!actrs) {
|
||||
actrs = malloc(sizeof(u32*)*actrc);
|
||||
@ -501,7 +501,7 @@ void onAlloc(usz sz, u8 type) {
|
||||
talloc+= sz;
|
||||
#endif
|
||||
}
|
||||
void onFree(Value* x) {
|
||||
static void onFree(Value* x) {
|
||||
#ifdef ALLOC_STAT
|
||||
ctr_f[x->type]++;
|
||||
#endif
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#define FAKE_RUNTIME false
|
||||
|
||||
#include "h.h"
|
||||
#include "mm_buddy.c"
|
||||
#include "mm_2buddy.c"
|
||||
#include "harr.c"
|
||||
#include "fillarr.c"
|
||||
#include "i32arr.c"
|
||||
|
||||
56
src/mm_2buddy.c
Normal file
56
src/mm_2buddy.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "h.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0 // apparently needed for freebsd or something
|
||||
#endif
|
||||
|
||||
typedef struct EmptyValue EmptyValue;
|
||||
struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else can be garbage
|
||||
struct Value;
|
||||
EmptyValue* next;
|
||||
};
|
||||
|
||||
#define BSZ(x) (1ull<<(x))
|
||||
#define BSZI(x) (64-__builtin_clzl((x)-1ull))
|
||||
#define MMI(x) x
|
||||
#define buckets b1_buckets
|
||||
#define mm_free b1_free
|
||||
#define mm_makeEmpty b1_makeEmpty
|
||||
#define mm_allocL b1_allocL
|
||||
#include "mm_buddyTemplate.c"
|
||||
#undef buckets
|
||||
#undef mm_free
|
||||
#undef mm_makeEmpty
|
||||
#undef mm_allocL
|
||||
|
||||
#define BSZ(x) ((1ull<<(x))*3)
|
||||
#define BSZI(x) (64-__builtin_clzl((x/3)-1ull))
|
||||
#define MMI(x) ((x)|64)
|
||||
#define buckets b3_buckets
|
||||
#define mm_free b3_free
|
||||
#define mm_makeEmpty b3_makeEmpty
|
||||
#define mm_allocL b3_allocL
|
||||
#include "mm_buddyTemplate.c"
|
||||
#undef buckets
|
||||
#undef mm_free
|
||||
#undef mm_makeEmpty
|
||||
#undef mm_allocL
|
||||
|
||||
void* mm_allocN(usz sz, u8 type) {
|
||||
assert(sz>12);
|
||||
onAlloc(sz, type);
|
||||
u8 b1 = 64-__builtin_clzl(sz-1ull);
|
||||
if (sz*3 <= 1ull<<(b1+1)) return b3_allocL(b1-2, type);
|
||||
return b1_allocL(b1, type);
|
||||
}
|
||||
void mm_free(Value* x) {
|
||||
if (x->mmInfo&64) b3_free(x);
|
||||
else b1_free(x);
|
||||
}
|
||||
|
||||
u64 mm_round(usz sz) {
|
||||
u8 b1 = 64-__builtin_clzl(sz-1ull);
|
||||
if (sz*3 <= 1ull<<(b1+1)) return (1ull<<(b1-2)) * 3;
|
||||
return 1ull<<b1;
|
||||
}
|
||||
@ -10,68 +10,10 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca
|
||||
struct Value;
|
||||
EmptyValue* next;
|
||||
};
|
||||
|
||||
EmptyValue* buckets[64];
|
||||
|
||||
#define BSZI2(x) (64-__builtin_clzl((x)-1ull))
|
||||
#define BSZ(x) (1ull<<(x))
|
||||
#define BSZI(x) (64-__builtin_clzl((x)-1ull))
|
||||
|
||||
EmptyValue* makeEmpty(u8 bucket) { // result->next is garbage
|
||||
u8 cb = bucket;
|
||||
EmptyValue* c;
|
||||
while (true) {
|
||||
cb++;
|
||||
if (buckets[cb]) {
|
||||
c = buckets[cb];
|
||||
assert((c->mmInfo&63)==cb);
|
||||
buckets[cb] = c->next;
|
||||
break;
|
||||
}
|
||||
if (cb >= 20) {
|
||||
c = mmap(NULL, BSZ(cb), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
if (c==MAP_FAILED) {
|
||||
printf("failed to allocate memory\n");
|
||||
exit(1);
|
||||
}
|
||||
c->type = t_empty;
|
||||
c->mmInfo = cb;
|
||||
c->next = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->mmInfo = bucket;
|
||||
while (cb != bucket) {
|
||||
cb--;
|
||||
EmptyValue* b = (EmptyValue*) (BSZ(cb) + (char*)c);
|
||||
b->type = t_empty;
|
||||
b->mmInfo = cb;
|
||||
b->next = 0; assert(buckets[cb]==0);
|
||||
buckets[cb] = b;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void mm_free(Value* x) {
|
||||
onFree(x);
|
||||
EmptyValue* c = (EmptyValue*) x;
|
||||
c->type = t_empty;
|
||||
u8 b = c->mmInfo&63;
|
||||
c->next = buckets[b];
|
||||
buckets[b] = c;
|
||||
}
|
||||
|
||||
void* mm_allocN(usz sz, u8 type) {
|
||||
assert(sz>8);
|
||||
u8 bucket = BSZI(sz); // inverse of BSZ
|
||||
EmptyValue* x = buckets[bucket];
|
||||
if (x==NULL) x = makeEmpty(bucket);
|
||||
else buckets[bucket] = x->next;
|
||||
onAlloc(sz, type);
|
||||
x->flags = x->extra = x->type = 0;
|
||||
x->refc = 1;
|
||||
x->type = type;
|
||||
return x;
|
||||
}
|
||||
#define BSZI BSZI2
|
||||
#define MMI(x) x
|
||||
|
||||
u64 mm_round(usz sz) {
|
||||
return BSZ(BSZI(sz));
|
||||
@ -80,3 +22,11 @@ u64 mm_round(usz sz) {
|
||||
void mm_visit(B x) {
|
||||
|
||||
}
|
||||
|
||||
#include "mm_buddyTemplate.c"
|
||||
|
||||
void* mm_allocN(usz sz, u8 type) {
|
||||
assert(sz>8);
|
||||
onAlloc(sz, type);
|
||||
return mm_allocL(BSZI2(sz), type);
|
||||
}
|
||||
|
||||
60
src/mm_buddyTemplate.c
Normal file
60
src/mm_buddyTemplate.c
Normal file
@ -0,0 +1,60 @@
|
||||
EmptyValue* buckets[64];
|
||||
|
||||
static EmptyValue* mm_makeEmpty(u8 bucket) { // result->next is garbage
|
||||
u8 cb = bucket;
|
||||
EmptyValue* c;
|
||||
while (true) {
|
||||
cb++;
|
||||
if (buckets[cb]) {
|
||||
c = buckets[cb];
|
||||
assert((c->mmInfo&63)==cb);
|
||||
buckets[cb] = c->next;
|
||||
break;
|
||||
}
|
||||
if (cb >= 20) {
|
||||
u64 sz = BSZ(cb);
|
||||
c = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
if (c==MAP_FAILED) {
|
||||
printf("failed to allocate memory\n");
|
||||
exit(1);
|
||||
}
|
||||
c->type = t_empty;
|
||||
c->mmInfo = cb;
|
||||
c->next = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->mmInfo = MMI(bucket);
|
||||
while (cb != bucket) {
|
||||
cb--;
|
||||
EmptyValue* b = (EmptyValue*) (BSZ(cb) + (char*)c);
|
||||
b->type = t_empty;
|
||||
b->mmInfo = MMI(cb);
|
||||
b->next = 0; assert(buckets[cb]==0);
|
||||
buckets[cb] = b;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void mm_free(Value* x) {
|
||||
onFree(x);
|
||||
EmptyValue* c = (EmptyValue*) x;
|
||||
c->type = t_empty;
|
||||
u8 b = c->mmInfo&63;
|
||||
c->next = buckets[b];
|
||||
buckets[b] = c;
|
||||
}
|
||||
|
||||
void* mm_allocL(u8 bucket, u8 type) {
|
||||
EmptyValue* x = buckets[bucket];
|
||||
if (x==NULL) x = mm_makeEmpty(bucket);
|
||||
else buckets[bucket] = x->next;
|
||||
x->flags = x->extra = x->type = 0;
|
||||
x->refc = 1;
|
||||
x->type = type;
|
||||
return x;
|
||||
}
|
||||
|
||||
#undef BSZ
|
||||
#undef BSZI
|
||||
#undef MMI
|
||||
Loading…
Reference in New Issue
Block a user