mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
alloc: realloc
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
void alloc_init();
|
void alloc_init();
|
||||||
void *alloc(size_t s);
|
void *alloc(size_t s);
|
||||||
|
void *realloc(void *addr, size_t s);
|
||||||
void free(void *addr);
|
void free(void *addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+42
-5
@@ -3,6 +3,11 @@
|
|||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
// each allocation has the following structure:
|
||||||
|
// ptr: data capacity (allocsizes size)
|
||||||
|
// ptr + sizeof(size_t): current size
|
||||||
|
// ptr + sizeof(size_t) * 2: data
|
||||||
|
|
||||||
#define CACHE_COUNT 12
|
#define CACHE_COUNT 12
|
||||||
|
|
||||||
static size_t allocsizes[CACHE_COUNT] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
|
static size_t allocsizes[CACHE_COUNT] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
|
||||||
@@ -10,8 +15,8 @@ static scache_t *caches[CACHE_COUNT];
|
|||||||
|
|
||||||
static void initarea(scache_t *cache, void *obj) {
|
static void initarea(scache_t *cache, void *obj) {
|
||||||
size_t *ptr = obj;
|
size_t *ptr = obj;
|
||||||
*ptr = cache->size - sizeof(size_t);
|
*ptr = cache->size - sizeof(size_t) * 2;
|
||||||
memset(ptr + 1, 0, *ptr);
|
memset(ptr + 2, 0, *ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static scache_t *getcachefromsize(size_t size) {
|
static scache_t *getcachefromsize(size_t size) {
|
||||||
@@ -30,22 +35,54 @@ static scache_t *getcachefromsize(size_t size) {
|
|||||||
void *alloc(size_t size) {
|
void *alloc(size_t size) {
|
||||||
scache_t *cache = getcachefromsize(size);
|
scache_t *cache = getcachefromsize(size);
|
||||||
size_t *ret = slab_allocate(cache);
|
size_t *ret = slab_allocate(cache);
|
||||||
|
*(ret + 1) = size;
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return ret + 1;
|
return ret + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void *ptr) {
|
void free(void *ptr) {
|
||||||
size_t *start = ptr;
|
size_t *start = ptr;
|
||||||
start -= 1;
|
start -= 2;
|
||||||
size_t size = *start;
|
size_t size = *start;
|
||||||
scache_t *cache = getcachefromsize(size);
|
scache_t *cache = getcachefromsize(size);
|
||||||
slab_free(cache, start);
|
slab_free(cache, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *realloc(void *ptr, size_t size) {
|
||||||
|
size_t *start = ptr;
|
||||||
|
start -= 2;
|
||||||
|
size_t currentsize = *(start + 1);
|
||||||
|
if (size <= currentsize) {
|
||||||
|
*(start + 1) = size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grow
|
||||||
|
scache_t *oldcache = getcachefromsize(*start);
|
||||||
|
scache_t *newcache = getcachefromsize(size);
|
||||||
|
|
||||||
|
// same allocation
|
||||||
|
if (oldcache == newcache) {
|
||||||
|
size_t diff = size - currentsize;
|
||||||
|
memset((void *)((uintptr_t)ptr + currentsize), 0, diff);
|
||||||
|
*(start + 1) = size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// different allocation
|
||||||
|
size_t *new = slab_allocate(newcache);
|
||||||
|
if (new == NULL)
|
||||||
|
return NULL;
|
||||||
|
*(new + 1) = size;
|
||||||
|
memcpy((new + 2), ptr, currentsize);
|
||||||
|
slab_free(oldcache, start);
|
||||||
|
return new + 2;
|
||||||
|
}
|
||||||
|
|
||||||
void alloc_init() {
|
void alloc_init() {
|
||||||
for (int i = 0; i < CACHE_COUNT; ++i) {
|
for (int i = 0; i < CACHE_COUNT; ++i) {
|
||||||
caches[i] = slab_newcache(allocsizes[i] + sizeof(size_t), 0, initarea, initarea);
|
caches[i] = slab_newcache(allocsizes[i] + sizeof(size_t) * 2, 0, initarea, initarea);
|
||||||
__assert(caches[i]);
|
__assert(caches[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user