mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-31 22:48:21 +00:00
memory management: add more protection against corruption
This commit is contained in:
+19
-3
@@ -7,16 +7,31 @@
|
|||||||
// ptr: data capacity (allocsizes size)
|
// ptr: data capacity (allocsizes size)
|
||||||
// ptr + sizeof(size_t): current size
|
// ptr + sizeof(size_t): current size
|
||||||
// ptr + sizeof(size_t) * 2: data
|
// ptr + sizeof(size_t) * 2: data
|
||||||
|
// ptr + datasize: poison value
|
||||||
|
|
||||||
|
#define USE_POISON 0
|
||||||
|
#define POISON_VALUE 0xdeadbeefbadc0ffel
|
||||||
#define CACHE_COUNT 12
|
#define CACHE_COUNT 12
|
||||||
|
|
||||||
|
#define CAPACITY_SIZE(cache) cache->size - sizeof(size_t) * 2 - USE_POISON * sizeof(size_t)
|
||||||
|
|
||||||
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};
|
||||||
static scache_t *caches[CACHE_COUNT];
|
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) * 2;
|
*ptr = CAPACITY_SIZE(cache);
|
||||||
memset(ptr + 2, 0, *ptr);
|
memset(ptr + 2, 0, *ptr);
|
||||||
|
#if USE_POISON == 1
|
||||||
|
*((size_t *)((uintptr_t)obj + cache->size - sizeof(size_t))) = POISON_VALUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dtor(scache_t *cache, void *obj) {
|
||||||
|
#if USE_POISON == 1
|
||||||
|
__assert(*(size_t *)((uintptr_t)obj + cache->size - sizeof(size_t)) == POISON_VALUE);
|
||||||
|
#endif
|
||||||
|
initarea(cache, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static scache_t *getcachefromsize(size_t size) {
|
static scache_t *getcachefromsize(size_t size) {
|
||||||
@@ -34,9 +49,10 @@ 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;
|
||||||
|
__assert(*ret == CAPACITY_SIZE(cache));
|
||||||
|
*(ret + 1) = size;
|
||||||
return ret + 2;
|
return ret + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +97,7 @@ void *realloc(void *ptr, size_t size) {
|
|||||||
|
|
||||||
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) * 2, 0, initarea, initarea);
|
caches[i] = slab_newcache(allocsizes[i] + sizeof(size_t) * 2 + sizeof(size_t) * USE_POISON, 0, initarea, dtor);
|
||||||
__assert(caches[i]);
|
__assert(caches[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-1
@@ -42,6 +42,16 @@ static inline void bmset(void *addr, uint64_t v) {
|
|||||||
bitmap[entry] = entryval;
|
bitmap[entry] = entryval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool bmget(void *addr) {
|
||||||
|
uintmax_t page = (uintptr_t)addr / PAGE_SIZE;
|
||||||
|
uintmax_t entry = page / 64;
|
||||||
|
uintmax_t offset = page % 64;
|
||||||
|
|
||||||
|
uint64_t entryval = bitmap[entry];
|
||||||
|
entryval &= ((uint64_t)1 << offset);
|
||||||
|
return entryval;
|
||||||
|
}
|
||||||
|
|
||||||
static uintmax_t getfreearea(bmsection_t *section, size_t size) {
|
static uintmax_t getfreearea(bmsection_t *section, size_t size) {
|
||||||
uintmax_t result = 0;
|
uintmax_t result = 0;
|
||||||
uintmax_t found = 0;
|
uintmax_t found = 0;
|
||||||
@@ -112,8 +122,10 @@ void pmm_free(void *addr, size_t size) {
|
|||||||
if ((uintptr_t)addr / PAGE_SIZE < bmsections[i].searchstart)
|
if ((uintptr_t)addr / PAGE_SIZE < bmsections[i].searchstart)
|
||||||
bmsections[i].searchstart = (uintptr_t)addr / PAGE_SIZE;
|
bmsections[i].searchstart = (uintptr_t)addr / PAGE_SIZE;
|
||||||
|
|
||||||
for (uintmax_t j = 0; j < size; ++j)
|
for (uintmax_t j = 0; j < size; ++j) {
|
||||||
|
__assert(bmget((void *)((page + j) * PAGE_SIZE)) == false);
|
||||||
bmset((void *)((page + j) * PAGE_SIZE), 1);
|
bmset((void *)((page + j) * PAGE_SIZE), 1);
|
||||||
|
}
|
||||||
|
|
||||||
spinlock_release(&bmsections[i].lock);
|
spinlock_release(&bmsections[i].lock);
|
||||||
__atomic_sub_fetch(&used, 1, __ATOMIC_SEQ_CST);
|
__atomic_sub_fetch(&used, 1, __ATOMIC_SEQ_CST);
|
||||||
|
|||||||
@@ -87,10 +87,10 @@ static void *takeobject(scache_t *cache, slab_t *slab) {
|
|||||||
if (cache->size < SLAB_INDIRECT_CUTOFF) {
|
if (cache->size < SLAB_INDIRECT_CUTOFF) {
|
||||||
void *addr = (void *)objend;
|
void *addr = (void *)objend;
|
||||||
void *base = (void *)ROUND_DOWN((uintptr_t)slab, PAGE_SIZE);
|
void *base = (void *)ROUND_DOWN((uintptr_t)slab, PAGE_SIZE);
|
||||||
__assert(addr > base && addr < (void *)slab);
|
__assert(addr >= base && addr < (void *)slab);
|
||||||
} else {
|
} else {
|
||||||
void *addr = slab->base + ((uintptr_t)objend - ROUND_DOWN((uintptr_t)slab, PAGE_SIZE)) / sizeof(void **) * cache->truesize;
|
void *addr = slab->base + ((uintptr_t)objend - ROUND_DOWN((uintptr_t)slab, PAGE_SIZE)) / sizeof(void **) * cache->truesize;
|
||||||
__assert(addr > slab->base && (uintptr_t)addr < (uintptr_t)slab->base + cache->slabobjcount * cache->truesize);
|
__assert(addr >= slab->base && (uintptr_t)addr < (uintptr_t)slab->base + cache->slabobjcount * cache->truesize);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user