ruby-changes:65343
From: Peter <ko1@a...>
Date: Fri, 26 Feb 2021 04:02:10 +0900 (JST)
Subject: [ruby-changes:65343] 1e13548953 (master): Use mmap for allocating heap pages
https://git.ruby-lang.org/ruby.git/commit/?id=1e13548953 From 1e13548953659bd12c28625d45998322449f3be8 Mon Sep 17 00:00:00 2001 From: Peter Zhu <peter@p...> Date: Tue, 23 Feb 2021 16:28:56 -0500 Subject: Use mmap for allocating heap pages --- configure.ac | 3 +-- gc.c | 50 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 41f2879..911ebdf 100644 --- a/configure.ac +++ b/configure.ac @@ -1931,7 +1931,6 @@ AC_CHECK_FUNCS(lutimes) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1931 AC_CHECK_FUNCS(malloc_usable_size) AC_CHECK_FUNCS(malloc_size) AC_CHECK_FUNCS(mblen) -AC_CHECK_FUNCS(memalign) AC_CHECK_FUNCS(memset_s) AC_CHECK_FUNCS(writev) AC_CHECK_FUNCS(memrchr) @@ -1939,11 +1938,11 @@ AC_CHECK_FUNCS(memmem) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1938 AC_CHECK_FUNCS(mkfifo) AC_CHECK_FUNCS(mknod) AC_CHECK_FUNCS(mktime) +AC_CHECK_FUNCS(mmap) AC_CHECK_FUNCS(openat) AC_CHECK_FUNCS(pipe2) AC_CHECK_FUNCS(poll) AC_CHECK_FUNCS(posix_fadvise) -AC_CHECK_FUNCS(posix_memalign) AC_CHECK_FUNCS(ppoll) AC_CHECK_FUNCS(pread) AC_CHECK_FUNCS(pwrite) diff --git a/gc.c b/gc.c index 8aad4b9..2a0fa80 100644 --- a/gc.c +++ b/gc.c @@ -1765,14 +1765,14 @@ heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pag https://github.com/ruby/ruby/blob/trunk/gc.c#L1765 heap->total_slots -= page->total_slots; } -static void rb_aligned_free(void *ptr); +static void rb_aligned_free(void *ptr, size_t size); static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page) { heap_allocated_pages--; objspace->profile.total_freed_pages++; - rb_aligned_free(GET_PAGE_BODY(page->start)); + rb_aligned_free(GET_PAGE_BODY(page->start), HEAP_PAGE_SIZE); free(page); } @@ -1824,7 +1824,7 @@ heap_page_allocate(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L1824 /* assign heap_page entry */ page = calloc1(sizeof(struct heap_page)); if (page == 0) { - rb_aligned_free(page_body); + rb_aligned_free(page_body, HEAP_PAGE_SIZE); rb_memerror(); } @@ -10382,15 +10382,36 @@ rb_aligned_malloc(size_t alignment, size_t size) https://github.com/ruby/ruby/blob/trunk/gc.c#L10382 #elif defined _WIN32 void *_aligned_malloc(size_t, size_t); res = _aligned_malloc(size, alignment); -#elif defined(HAVE_POSIX_MEMALIGN) - if (posix_memalign(&res, alignment, size) == 0) { - return res; - } - else { +#elif defined(HAVE_MMAP) + GC_ASSERT(alignment % sysconf(_SC_PAGE_SIZE) == 0); + + char *ptr = mmap(NULL, alignment + size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ptr == MAP_FAILED) { return NULL; } -#elif defined(HAVE_MEMALIGN) - res = memalign(alignment, size); + + char *aligned = ptr + alignment; + aligned -= ((VALUE)aligned & (alignment - 1)); + GC_ASSERT(aligned > ptr); + GC_ASSERT(aligned <= ptr + alignment); + + size_t start_out_of_range_size = aligned - ptr; + GC_ASSERT(start_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); + if (start_out_of_range_size > 0) { + if (munmap(ptr, start_out_of_range_size)) { + rb_bug("rb_aligned_malloc: munmap faile for start"); + } + } + + size_t end_out_of_range_size = alignment - start_out_of_range_size; + GC_ASSERT(end_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); + if (end_out_of_range_size > 0) { + if (munmap(aligned + size, end_out_of_range_size)) { + rb_bug("rb_aligned_malloc: munmap failed for end"); + } + } + + res = (void *)aligned; #else char* aligned; res = malloc(alignment + size + sizeof(void*)); @@ -10407,14 +10428,17 @@ rb_aligned_malloc(size_t alignment, size_t size) https://github.com/ruby/ruby/blob/trunk/gc.c#L10428 } static void -rb_aligned_free(void *ptr) +rb_aligned_free(void *ptr, size_t size) { #if defined __MINGW32__ __mingw_aligned_free(ptr); #elif defined _WIN32 _aligned_free(ptr); -#elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN) - free(ptr); +#elif defined HAVE_MMAP + GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0); + if (munmap(ptr, size)) { + rb_bug("rb_aligned_free: munmap failed"); + } #else free(((void**)ptr)[-1]); #endif -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/