Lots more work on eng::malloc

This commit is contained in:
2022-02-28 21:57:54 -05:00
parent ff932dba10
commit 7cd8eb0a43
25 changed files with 314 additions and 253 deletions

View File

@@ -0,0 +1,122 @@
// We only use a custom allocator on linux (for now)
// The allocator we chose is 'dlmalloc' (doug lea's malloc).
// It's a good allocator for single-threaded programs.
// It needs to be configured by setting a bunch of defines.
//
#ifdef __linux__
// We need this to define dlmalloc, not malloc.
#define USE_DL_PREFIX 1
// We don't need mspaces.
#define ONLY_MSPACES 0
#define MSPACES 0
// We don't need mallinfo
#define NO_MALLINFO 1
// We don't need dlmalloc_inspect_all
#define MALLOC_INSPECT_ALL 0
// Disable locking. The entire engine is single-threaded.
#define USE_LOCKS 0
// This allocator can use sbrk to obtain RAM. We're going to
// emulate sbrk, in order to put it in a different memory region
// than the system malloc, which also uses sbrk.
#define HAVE_MORECORE 1
#define MORECORE emulated_sbrk
#define MORECORE_CANNOT_TRIM 1
// We won't let the memory allocator use mmap. This is because
// opening the replay log may be implemented in stdio using mmap.
// So using mmap might trigger different results under replay.
#define HAVE_MMAP 0
// Fix a warning in dlmalloc.
#define MAX_RELEASE_CHECK_RATE INT_MAX
// Don't generate random seeds, or time-based seeds.
#define USE_DEV_RANDOM 0
#define LACKS_TIME_H 1
// Don't export any dlmalloc functions.
#define DLMALLOC_EXPORT static inline
#include <sys/mman.h>
#include <cstdint>
#include <cassert>
#include <climits>
static char *emulated_sbrk_base;
static intptr_t emulated_sbrk_used;
static intptr_t emulated_sbrk_limit;
// We assume that the increments are already aligned to the system
// page size, because dlmalloc does that for us.
//
// Our emulated sbrk cannot trim the memory size. It can only grow.
//
static void *emulated_sbrk(intptr_t increment) {
if (emulated_sbrk_base == 0) {
emulated_sbrk_limit = intptr_t(64) * 1024 * 1024 * 1024;
void *map = mmap(nullptr, emulated_sbrk_limit, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(map != MAP_FAILED);
assert(map != nullptr);
emulated_sbrk_base = (char *)map;
emulated_sbrk_used = 0;
}
int64_t old_used = emulated_sbrk_used;
int64_t new_used = emulated_sbrk_used + increment;
if (new_used > emulated_sbrk_limit) {
return (void *)(-1);
}
assert(new_used >= old_used);
emulated_sbrk_used = new_used;
if (new_used > old_used) {
int status = mprotect(emulated_sbrk_base + old_used, new_used - old_used, PROT_READ | PROT_WRITE);
assert(status == 0);
}
return emulated_sbrk_base + old_used;
}
#include "dlmalloc/dlmalloc.c"
namespace eng {
static uint32_t hash;
void *malloc(size_t size) {
void *result = dlmalloc(size);
hash += uint32_t(uintptr_t(result)) + 0x83748374;
hash += hash << 10;
hash ^= hash >> 6;
hash += uint32_t(size) + 0x85893489;
hash += hash << 10;
hash ^= hash >> 6;
return result;
}
void *realloc(void *p, size_t size) {
void *result = dlrealloc(p, size);
hash += uint32_t(uintptr_t(p)) + 0x74741912;
hash += hash << 10;
hash ^= hash >> 6;
hash += uint32_t(uintptr_t(result)) + 0x68843823;
hash += hash << 10;
hash ^= hash >> 6;
hash += uint32_t(size) + 0x81444120;
hash += hash << 10;
hash ^= hash >> 6;
return result;
}
void free(void *p) {
hash += uint32_t(uintptr_t(p)) + 0x87823448;
dlfree(p);
}
int memhash() {
return hash;
}
} // namespace eng
#endif // ifdef __linux__