From 7cbcd2e2b70d9a8547030b5a8640c85b2b7b50ab Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Thu, 9 Mar 2017 18:20:02 -0800 Subject: [PATCH] Fix pages_purge_forced() to discard pages on non-Linux systems. madvise(..., MADV_DONTNEED) only causes demand-zeroing on Linux, so fall back to overlaying a new mapping. --- configure.ac | 2 ++ include/jemalloc/internal/jemalloc_internal_defs.h.in | 11 ++++++++--- include/jemalloc/internal/pages_types.h | 4 +++- src/pages.c | 9 ++++++++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 96b105f3..db42a505 100644 --- a/configure.ac +++ b/configure.ac @@ -547,6 +547,7 @@ case "${host}" in dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) abi="elf" + AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS]) AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) @@ -558,6 +559,7 @@ case "${host}" in dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) abi="elf" + AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS]) AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in index 500f4274..28eb0b34 100644 --- a/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -265,12 +265,17 @@ * * madvise(..., MADV_FREE) : This marks pages as being unused, such that they * will be discarded rather than swapped out. - * madvise(..., MADV_DONTNEED) : This immediately discards pages, such that - * new pages will be demand-zeroed if the - * address region is later touched. + * madvise(..., MADV_DONTNEED) : If JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS is + * defined, this immediately discards pages, + * such that new pages will be demand-zeroed if + * the address region is later touched; + * otherwise this behaves similarly to + * MADV_FREE, though typically with higher + * system overhead. */ #undef JEMALLOC_PURGE_MADVISE_FREE #undef JEMALLOC_PURGE_MADVISE_DONTNEED +#undef JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS /* * Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE diff --git a/include/jemalloc/internal/pages_types.h b/include/jemalloc/internal/pages_types.h index 9e6e7c5c..e44ee2a4 100644 --- a/include/jemalloc/internal/pages_types.h +++ b/include/jemalloc/internal/pages_types.h @@ -37,7 +37,9 @@ * next step after purging on Windows anyway, there's no point in adding such * complexity. */ -#if !defined(_WIN32) && defined(JEMALLOC_PURGE_MADVISE_DONTNEED) +#if !defined(_WIN32) && ((defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS)) || \ + defined(JEMALLOC_MAPS_COALESCE)) # define PAGES_CAN_PURGE_FORCED #endif diff --git a/src/pages.c b/src/pages.c index 444a97c2..e80c3652 100644 --- a/src/pages.c +++ b/src/pages.c @@ -170,6 +170,9 @@ pages_purge_lazy(void *addr, size_t size) { VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); #elif defined(JEMALLOC_PURGE_MADVISE_FREE) madvise(addr, size, MADV_FREE); +#elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + !defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS) + madvise(addr, size, MADV_DONTNEED); #else not_reached(); #endif @@ -182,8 +185,12 @@ pages_purge_forced(void *addr, size_t size) { return true; } -#if defined(JEMALLOC_PURGE_MADVISE_DONTNEED) +#if defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS) return (madvise(addr, size, MADV_DONTNEED) != 0); +#elif defined(JEMALLOC_MAPS_COALESCE) + /* Try to overlay a new demand-zeroed mapping. */ + return pages_commit(addr, size); #else not_reached(); #endif