[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]