diff --git a/configure.ac b/configure.ac index 911ebdfdd5..1dcf48b2b1 100644 --- a/configure.ac +++ b/configure.ac @@ -1931,6 +1931,7 @@ AC_CHECK_FUNCS(lutimes) 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) @@ -1943,6 +1944,7 @@ 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 30ded93535..b9f49db600 100644 --- a/gc.c +++ b/gc.c @@ -823,6 +823,13 @@ enum { HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT), HEAP_PAGE_BITMAP_PLANES = 4 /* RGENGC: mark, unprotected, uncollectible, marking */ }; +#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG) +#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN +#if defined(HAVE_MMAP) && (PAGE_SIZE <= HEAP_PAGE_SIZE) +# define USE_MMAP_ALIGNED_ALLOC 1 +#else +# define USE_MMAP_ALIGNED_ALLOC 0 +#endif struct heap_page { short total_slots; @@ -9989,7 +9996,7 @@ gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v) /* 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) && !defined(HAVE_MMAP) +#if !defined(__MINGW32__) && !defined(_WIN32) && !USE_MMAP_ALIGNED_ALLOC rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform"); #endif @@ -10389,7 +10396,7 @@ rb_aligned_malloc(size_t alignment, size_t size) #elif defined _WIN32 void *_aligned_malloc(size_t, size_t); res = _aligned_malloc(size, alignment); -#elif defined(HAVE_MMAP) +#elif 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); @@ -10419,6 +10426,12 @@ rb_aligned_malloc(size_t alignment, size_t size) } res = (void *)aligned; +#elif 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*)); @@ -10441,11 +10454,13 @@ rb_aligned_free(void *ptr, size_t size) __mingw_aligned_free(ptr); #elif defined _WIN32 _aligned_free(ptr); -#elif defined HAVE_MMAP +#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]); #endif