ruby-changes:66058
From: Nobuyoshi <ko1@a...>
Date: Thu, 6 May 2021 00:02:59 +0900 (JST)
Subject: [ruby-changes:66058] 3d5b6ddff8 (master): Fix compilation on M1 Mac
https://git.ruby-lang.org/ruby.git/commit/?id=3d5b6ddff8 From 3d5b6ddff8def49e59fb9a9ddd28a653498ae861 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Wed, 5 May 2021 23:54:36 +0900 Subject: Fix compilation on M1 Mac As PAGE_SIZE may not be a preprocessor constant, dispatch at runtime in that case. --- configure.ac | 18 +++++++++ gc.c | 118 +++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/configure.ac b/configure.ac index d2ea9ea..1eb4be4 100644 --- a/configure.ac +++ b/configure.ac @@ -2726,6 +2726,24 @@ main(int argc, char *argv[]) https://github.com/ruby/ruby/blob/trunk/configure.ac#L2726 rb_cv_fork_with_pthread=yes)]) test x$rb_cv_fork_with_pthread = xyes || AC_DEFINE(CANNOT_FORK_WITH_PTHREAD) ]) + +AS_IF([test "x$ac_cv_func_mmap" = xyes], [ + malloc_headers=`sed -n '/MALLOC_HEADERS_BEGIN/,/MALLOC_HEADERS_END/p' ${srcdir}/gc.c` + AC_CACHE_CHECK([PAGE_SIZE is defined], rb_cv_page_size, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${malloc_headers} + typedef char conftest_page[PAGE_SIZE]; + ]], [[]])], + [rb_cv_page_size=const], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${malloc_headers}]], [[ + int page_size = (int)PAGE_SIZE; + (void)page_size; + ]])], + [rb_cv_page_size=variable], [rb_cv_page_size=no])])]) + AS_CASE([$rb_cv_page_size], + [const], [AC_DEFINE(USE_MMAP_ALIGNED_ALLOC, [(PAGE_SIZE <= HEAP_PAGE_SIZE)])], + [no], [AC_DEFINE(USE_MMAP_ALIGNED_ALLOC, 1)], + ) +], [AC_DEFINE(USE_MMAP_ALIGNED_ALLOC, 0)]) } : "runtime section" && { diff --git a/gc.c b/gc.c index 9fdcbb4..ee9fa49 100644 --- a/gc.c +++ b/gc.c @@ -32,6 +32,7 @@ https://github.com/ruby/ruby/blob/trunk/gc.c#L32 #include <stdarg.h> #include <stdio.h> +/* MALLOC_HEADERS_BEGIN */ #ifndef HAVE_MALLOC_USABLE_SIZE # ifdef _WIN32 # define HAVE_MALLOC_USABLE_SIZE @@ -53,6 +54,7 @@ https://github.com/ruby/ruby/blob/trunk/gc.c#L54 # include <malloc/malloc.h> # endif #endif +/* MALLOC_HEADERS_END */ #ifdef HAVE_SYS_TIME_H # include <sys/time.h> @@ -830,10 +832,19 @@ enum { https://github.com/ruby/ruby/blob/trunk/gc.c#L832 }; #define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG) #define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN -#if defined(HAVE_MMAP) && (!defined(PAGE_SIZE) || PAGE_SIZE <= HEAP_PAGE_SIZE) +#ifdef USE_MMAP_ALIGNED_ALLOC +# define Init_use_mmap_aligned_alloc() (void)0 +#elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE) # define USE_MMAP_ALIGNED_ALLOC 1 +# define Init_use_mmap_aligned_alloc() (void)0 #else -# define USE_MMAP_ALIGNED_ALLOC 0 +# define USE_MMAP_ALIGNED_ALLOC (use_mmap_aligned_alloc != false) +static bool use_mmap_aligned_alloc; +static inline void +Init_use_mmap_aligned_alloc(void) +{ + use_mmap_aligned_alloc = (PAGE_SIZE <= HEAP_PAGE_SIZE); +} #endif struct heap_page { @@ -3197,6 +3208,7 @@ Init_heap(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L3208 { rb_objspace_t *objspace = &rb_objspace; + Init_use_mmap_aligned_alloc(); #if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) /* If Ruby's heap pages are not a multiple of the system page size, we * cannot use mprotect for the read barrier, so we must disable automatic @@ -10086,8 +10098,10 @@ gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v) https://github.com/ruby/ruby/blob/trunk/gc.c#L10098 /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for * the read barrier, so we must disable automatic compaction. */ -#if !defined(__MINGW32__) && !defined(_WIN32) && !USE_MMAP_ALIGNED_ALLOC - rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform"); +#if !defined(__MINGW32__) && !defined(_WIN32) + if (!USE_MMAP_ALIGNED_ALLOC) { + rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform"); + } #endif ruby_enable_autocompact = RTEST(v); @@ -10486,49 +10500,54 @@ rb_aligned_malloc(size_t alignment, size_t size) https://github.com/ruby/ruby/blob/trunk/gc.c#L10500 #elif defined _WIN32 void *_aligned_malloc(size_t, size_t); res = _aligned_malloc(size, alignment); -#elif USE_MMAP_ALIGNED_ALLOC - GC_ASSERT(alignment % sysconf(_SC_PAGE_SIZE) == 0); +#else + if (USE_MMAP_ALIGNED_ALLOC) { + 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; - } + char *ptr = mmap(NULL, alignment + size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ptr == MAP_FAILED) { + return NULL; + } - char *aligned = ptr + alignment; - aligned -= ((VALUE)aligned & (alignment - 1)); - GC_ASSERT(aligned > ptr); - GC_ASSERT(aligned <= ptr + alignment); + 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 failed for start"); + 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 failed 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"); + 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; -#elif defined(HAVE_POSIX_MEMALIGN) - if (posix_memalign(&res, alignment, size) != 0) { - return NULL; + res = (void *)aligned; + } + else { +# if defined(HAVE_POSIX_MEMALIGN) + if (posix_memalign(&res, alignment, size) != 0) { + return NULL; + } +# elif defined(HAVE_MEMALIGN) + res = memalign(alignment, size); +# else + char* aligned; + res = malloc(alignment + size + sizeof(void*)); + aligned = (char*)res + alignment + sizeof(void*); + aligned -= ((VALUE)aligned & (alignment - 1)); + ((void**)aligned)[-1] = res; + res = (void*)aligned; +# endif } -#elif defined(HAVE_MEMALIGN) - res = memalign(alignment, size); -#else - char* aligned; - res = malloc(alignment + size + sizeof(void*)); - aligned = (char*)res + alignment + sizeof(void*); - aligned -= ((VALUE)aligned & (alignment - 1)); - ((void**)aligned)[-1] = res; - res = (void*)aligned; #endif /* alignment must be a power of 2 */ @@ -10544,15 +10563,20 @@ rb_aligned_free(void *ptr, size_t size) https://github.com/ruby/ruby/blob/trunk/gc.c#L10563 __mingw_aligned_free(ptr); #elif defined _WIN32 _aligned_free(ptr); -#elif USE_MMAP_ALIGNED_ALLOC - GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0); - if (munmap(ptr, size)) { - rb_bug("rb_aligned_free: munmap failed"); - } -#elif defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) - free(ptr); #else - free(((void**)ptr)[-1]); + if (USE_MMAP_ALIGNED_ALLOC) { + GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0); + if (munmap(ptr, size)) { + rb_bug("rb_aligned_free: munmap failed"); + } + } + else { +# if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) + free(ptr); +# else + free(((void**)ptr)[-1]); +# endif + } #endif } -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/