Rewrite memory manager

Actually Portable Executable now supports Android. Cosmo's old mmap code
required a 47 bit address space. The new implementation is very agnostic
and supports both smaller address spaces (e.g. embedded) and even modern
56-bit PML5T paging for x86 which finally came true on Zen4 Threadripper

Cosmopolitan no longer requires UNIX systems to observe the Windows 64kb
granularity; i.e. sysconf(_SC_PAGE_SIZE) will now report the host native
page size. This fixes a longstanding POSIX conformance issue, concerning
file mappings that overlap the end of file. Other aspects of conformance
have been improved too, such as the subtleties of address assignment and
and the various subtleties surrounding MAP_FIXED and MAP_FIXED_NOREPLACE

On Windows, mappings larger than 100 megabytes won't be broken down into
thousands of independent 64kb mappings. Support for MAP_STACK is removed
by this change; please use NewCosmoStack() instead.

Stack overflow avoidance is now being implemented using the POSIX thread
APIs. Please use GetStackBottom() and GetStackAddr(), instead of the old
error-prone GetStackAddr() and HaveStackMemory() APIs which are removed.
This commit is contained in:
Justine Tunney 2024-06-20 20:46:42 -07:00
parent 7f6d0b8709
commit 6ffed14b9c
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
150 changed files with 1893 additions and 5634 deletions

View file

@ -31,9 +31,20 @@
#error "threaded dlmalloc needs footers and mspaces"
#endif
union Heap {
struct malloc_state mstate;
struct {
size_t top_foot[2];
struct malloc_state m;
};
_Alignas(16) char mspace[DEFAULT_GRANULARITY];
};
static void init_heap(union Heap *heap, int locked);
static struct magicu magiu;
static unsigned g_heapslen;
static mstate g_heaps[128];
static union Heap g_heaps[128];
void dlfree(void *p) {
return mspace_free(0, p);
@ -54,7 +65,7 @@ int dlmallopt(int param_number, int value) {
int dlmalloc_trim(size_t pad) {
int got_some = 0;
for (unsigned i = 0; i < g_heapslen; ++i)
got_some |= mspace_trim(g_heaps[i], pad);
got_some |= mspace_trim(&g_heaps[i].m, pad);
return got_some;
}
@ -68,7 +79,7 @@ void dlmalloc_inspect_all(void handler(void *start, void *end,
size_t used_bytes, void *callback_arg),
void *arg) {
for (unsigned i = 0; i < g_heapslen; ++i)
mspace_inspect_all(g_heaps[i], handler, arg);
mspace_inspect_all(&g_heaps[i].m, handler, arg);
}
forceinline mstate get_arena(void) {
@ -82,11 +93,11 @@ forceinline mstate get_arena(void) {
asm("mrs\t%0,tpidr_el0" : "=r"(tpidr_el0));
cpu = tpidr_el0 & 255;
#endif
return g_heaps[__magicu_div(cpu, magiu) % g_heapslen];
return &g_heaps[__magicu_div(cpu, magiu) % g_heapslen].m;
}
static void *dlmalloc_single(size_t n) {
return mspace_malloc(g_heaps[0], n);
return mspace_malloc(&g_heaps[0].m, n);
}
static void *dlmalloc_threaded(size_t n) {
@ -94,7 +105,7 @@ static void *dlmalloc_threaded(size_t n) {
}
static void *dlcalloc_single(size_t n, size_t z) {
return mspace_calloc(g_heaps[0], n, z);
return mspace_calloc(&g_heaps[0].m, n, z);
}
static void *dlcalloc_threaded(size_t n, size_t z) {
@ -102,7 +113,7 @@ static void *dlcalloc_threaded(size_t n, size_t z) {
}
static void *dlrealloc_single(void *p, size_t n) {
return mspace_realloc(g_heaps[0], p, n);
return mspace_realloc(&g_heaps[0].m, p, n);
}
static void *dlrealloc_threaded(void *p, size_t n) {
@ -113,7 +124,7 @@ static void *dlrealloc_threaded(void *p, size_t n) {
}
static void *dlmemalign_single(size_t a, size_t n) {
return mspace_memalign(g_heaps[0], a, n);
return mspace_memalign(&g_heaps[0].m, a, n);
}
static void *dlmemalign_threaded(size_t a, size_t n) {
@ -121,7 +132,7 @@ static void *dlmemalign_threaded(size_t a, size_t n) {
}
static struct mallinfo dlmallinfo_single(void) {
return mspace_mallinfo(g_heaps[0]);
return mspace_mallinfo(&g_heaps[0].m);
}
static struct mallinfo dlmallinfo_threaded(void) {
@ -144,8 +155,7 @@ static void use_single_heap(bool uses_locks) {
dlrealloc = dlrealloc_single;
dlmemalign = dlmemalign_single;
dlmallinfo = dlmallinfo_single;
if (!(g_heaps[0] = create_mspace(0, uses_locks)))
__builtin_trap();
init_heap(&g_heaps[0], uses_locks);
}
static void threaded_dlmalloc(void) {
@ -180,10 +190,9 @@ static void threaded_dlmalloc(void) {
// we need this too due to linux's cpu count affinity hack
g_heapslen = heaps;
// create the arenas
// create the heaps
for (size_t i = 0; i < g_heapslen; ++i)
if (!(g_heaps[i] = create_mspace(0, true)))
__builtin_trap();
init_heap(&g_heaps[i], true);
// install function pointers
dlmalloc = dlmalloc_threaded;
@ -192,5 +201,5 @@ static void threaded_dlmalloc(void) {
dlmemalign = dlmemalign_threaded;
dlmallinfo = dlmallinfo_threaded;
STRACE("created %d dlmalloc arenas for %d cpus", heaps, cpus);
STRACE("created %d dlmalloc heaps for %d cpus", heaps, cpus);
}