1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-28 14:00:31 +02:00

Use PROT_NONE to reserve memory, then remap within that memory

Should play better with the kernel's overcommit heuristics.
This commit is contained in:
Andy Wingo 2024-11-23 09:13:57 +01:00
parent 922c13a183
commit 6a6f5b09e3
2 changed files with 52 additions and 6 deletions

View file

@ -128,17 +128,18 @@ size_t gc_platform_page_size(void) {
return getpagesize(); return getpagesize();
} }
void* gc_platform_acquire_memory(size_t size, size_t alignment) { struct gc_reservation gc_platform_reserve_memory(size_t size,
size_t alignment) {
GC_ASSERT_EQ(size, align_down(size, getpagesize())); GC_ASSERT_EQ(size, align_down(size, getpagesize()));
GC_ASSERT_EQ(alignment & (alignment - 1), 0); GC_ASSERT_EQ(alignment & (alignment - 1), 0);
GC_ASSERT_EQ(alignment, align_down(alignment, getpagesize())); GC_ASSERT_EQ(alignment, align_down(alignment, getpagesize()));
size_t extent = size + alignment; size_t extent = size + alignment;
char *mem = mmap(NULL, extent, PROT_READ|PROT_WRITE, void *mem = mmap(NULL, extent, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) { if (mem == MAP_FAILED) {
perror("mmap failed"); perror("failed to reserve address space");
return NULL; GC_CRASH();
} }
uintptr_t base = (uintptr_t) mem; uintptr_t base = (uintptr_t) mem;
@ -151,7 +152,37 @@ void* gc_platform_acquire_memory(size_t size, size_t alignment) {
if (end - aligned_end) if (end - aligned_end)
munmap((void*)aligned_end, end - aligned_end); munmap((void*)aligned_end, end - aligned_end);
return (void*) aligned_base; return (struct gc_reservation){aligned_base, size};
}
void*
gc_platform_acquire_memory_from_reservation(struct gc_reservation reservation,
size_t offset, size_t size) {
GC_ASSERT_EQ(size, align_down(size, getpagesize()));
GC_ASSERT(size <= reservation.size);
GC_ASSERT(offset <= reservation.size - size);
void *mem = mmap((void*)(reservation.base + offset), size,
PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) {
perror("mmap failed");
return NULL;
}
return mem;
}
void
gc_platform_release_reservation(struct gc_reservation reservation) {
if (munmap((void*)reservation.base, reservation.size) != 0)
perror("failed to unmap memory");
}
void*
gc_platform_acquire_memory(size_t size, size_t alignment) {
struct gc_reservation reservation =
gc_platform_reserve_memory(size, alignment);
return gc_platform_acquire_memory_from_reservation(reservation, 0, size);
} }
void gc_platform_release_memory(void *ptr, size_t size) { void gc_platform_release_memory(void *ptr, size_t size) {

View file

@ -24,6 +24,21 @@ GC_INTERNAL int gc_platform_processor_count(void);
GC_INTERNAL uint64_t gc_platform_monotonic_nanoseconds(void); GC_INTERNAL uint64_t gc_platform_monotonic_nanoseconds(void);
GC_INTERNAL size_t gc_platform_page_size(void); GC_INTERNAL size_t gc_platform_page_size(void);
struct gc_reservation {
uintptr_t base;
size_t size;
};
GC_INTERNAL
struct gc_reservation gc_platform_reserve_memory(size_t size, size_t alignment);
GC_INTERNAL
void*
gc_platform_acquire_memory_from_reservation(struct gc_reservation reservation,
size_t offset, size_t size);
GC_INTERNAL
void gc_platform_release_reservation(struct gc_reservation reservation);
GC_INTERNAL void* gc_platform_acquire_memory(size_t size, size_t alignment); GC_INTERNAL void* gc_platform_acquire_memory(size_t size, size_t alignment);
GC_INTERNAL void gc_platform_release_memory(void *base, size_t size); GC_INTERNAL void gc_platform_release_memory(void *base, size_t size);