uCBQN/src/opt/mm_buddyTemplate.c
2021-07-11 21:04:49 +03:00

91 lines
2.0 KiB
C

#define AllocInfo BN(AllocInfo)
#define al BN(al)
#define alCap BN(alCap)
#define alSize BN(alSize)
#define str(X) #X
#ifndef PROT
#define PROT PROT_READ|PROT_WRITE
#endif
#ifndef FLAGS
#define FLAGS MAP_NORESERVE|MAP_PRIVATE|MAP_ANON
#endif
EmptyValue* buckets[64];
typedef struct AllocInfo {
Value* p;
u64 sz;
} AllocInfo;
AllocInfo* al;
u64 alCap;
u64 alSize;
static void BN(guaranteeEmpty)(u8 bucket) {
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 >= ALSZ) {
u64 sz = BSZ(cb);
if (mm_heapAlloc+sz >= mm_heapMax) { printf("Heap size limit reached\n"); exit(1); }
mm_heapAlloc+= sz;
// gc_maybeGC();
c = mmap(NULL, sz, PROT, FLAGS, -1, 0);
#ifdef USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(c, sz);
#endif
if (alSize+1>=alCap) {
alCap = alCap? alCap*2 : 1024;
al = realloc(al, sizeof(AllocInfo)*alCap);
}
al[BN(alSize)++] = (AllocInfo){.p = (Value*)c, .sz = sz};
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) + (u8*)c);
b->type = t_empty;
b->mmInfo = MMI(cb);
b->next = buckets[cb];
buckets[cb] = b;
}
c->next = buckets[cb];
buckets[cb] = c;
}
NOINLINE void* BN(allocS)(i64 bucket, u8 type) {
BN(guaranteeEmpty)(bucket);
return BN(allocL)(bucket, type);
}
void BN(forHeap)(V2v f) {
for (u64 i = 0; i < alSize; i++) {
AllocInfo ci = al[i];
Value* s = ci.p;
Value* e = (Value*)(ci.sz + (u8*)ci.p);
while (s!=e) {
if (s->type!=t_empty) f(s);
s = (Value*)(BSZ(s->mmInfo&63) + (u8*)s);
}
}
}
#undef FLAGS
#undef PROT
#undef AllocInfo
#undef al
#undef alSize
#undef alCap
#undef MMI
#undef ALSZ