From 279038f15981bceccd67a18c8c36c44751a68d92 Mon Sep 17 00:00:00 2001 From: Douglas Katzman Date: Tue, 14 Feb 2017 09:56:01 -0500 Subject: [PATCH] Halve the number of syscalls in zero_pages_with_mmap on Linux --- src/runtime/coreparse.c | 11 +++++++++++ src/runtime/gencgc.c | 29 ++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/runtime/coreparse.c b/src/runtime/coreparse.c index d58032432..ee29cd9c9 100644 --- a/src/runtime/coreparse.c +++ b/src/runtime/coreparse.c @@ -277,6 +277,10 @@ os_vm_address_t inflate_core_bytes(int fd, os_vm_offset_t offset, int merge_core_pages = -1; +#ifdef LISP_FEATURE_LINUX +os_vm_address_t anon_dynamic_space_start; +#endif + static void process_directory(int fd, lispobj *ptr, int count, os_vm_offset_t file_offset) { @@ -369,6 +373,13 @@ process_directory(int fd, lispobj *ptr, int count, os_vm_offset_t file_offset) * space 0. (We checked above that for GENCGC, * addr==DYNAMIC_SPACE_START.) */ current_dynamic_space = (lispobj *)addr; +#ifdef LISP_FEATURE_LINUX + anon_dynamic_space_start = addr + len; + // This assertion is here because of the test in zero_pages_with_mmap() + // which trusts that if addr > anon_dynamic_space_start + // then addr did not come from any file mapping. + gc_assert((lispobj)anon_dynamic_space_start > STATIC_SPACE_END); +#endif break; case STATIC_CORE_SPACE_ID: if (addr != (os_vm_address_t)STATIC_SPACE_START) { diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 06d6cbb68..2fd93c985 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -635,11 +635,30 @@ void zero_pages_with_mmap(page_index_t start, page_index_t end) { gc_assert(length >= gencgc_release_granularity); gc_assert((length % gencgc_release_granularity) == 0); - os_invalidate(addr, length); - new_addr = os_validate(addr, length); - if (new_addr == NULL || new_addr != addr) { - lose("remap_free_pages: page moved, 0x%08x ==> 0x%08x", - start, new_addr); +#ifdef LISP_FEATURE_LINUX + extern os_vm_address_t anon_dynamic_space_start; + // We use MADV_DONTNEED only on Linux due to differing semantics from BSD. + // Linux treats it as a demand that the memory be 0-filled, or refreshed + // from a file that backs the range. BSD takes it as a hint that you don't + // care if the memory has to brought in from swap when next accessed, + // i.e. it's not a request to make a user-visible alteration to memory. + // So in theory this can bring a page in from the core file, if we happen + // to hit a page that resides in the portion of memory mapped by coreparse. + // In practice this should not happen because objects from a core file can't + // become garbage. Except in save-lisp-and-die they can, and we must be + // cautious not to resurrect bytes that originally came from the file. + if ((os_vm_address_t)addr >= anon_dynamic_space_start) { + if (madvise(addr, length, MADV_DONTNEED) != 0) + lose("madvise failed\n"); + } else +#endif + { + os_invalidate(addr, length); + new_addr = os_validate(addr, length); + if (new_addr == NULL || new_addr != addr) { + lose("remap_free_pages: page moved, 0x%08x ==> 0x%08x", + start, new_addr); + } } for (i = start; i <= end; i++) { -- 2.11.4.GIT