diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index 72b51824..3ba77baa 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -5,24 +5,56 @@ #include "platform_api_vmcore.h" +#ifndef BH_ENABLE_TRACE_MMAP +#define BH_ENABLE_TRACE_MMAP 0 +#endif + +#if BH_ENABLE_TRACE_MMAP != 0 +static size_t total_size_mmapped = 0; +static size_t total_size_munmapped = 0; +#endif + +#define HUGE_PAGE_SIZE (2 * 1024 * 1024) + +static inline uintptr_t +round_up(uintptr_t v, uintptr_t b) +{ + uintptr_t m = b - 1; + return (v + m) & ~m; +} + +static inline uintptr_t +round_down(uintptr_t v, uintptr_t b) +{ + uintptr_t m = b - 1; + return v & ~m; +} + void * os_mmap(void *hint, size_t size, int prot, int flags) { int map_prot = PROT_NONE; int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; uint64 request_size, page_size; - uint8 *addr; + uint8 *addr = MAP_FAILED; uint32 i; page_size = (uint64)getpagesize(); request_size = (size + page_size - 1) & ~(page_size - 1); +#if !defined(__APPLE__) && !defined(__NuttX__) + /* huge page isn't supported on MacOS and NuttX */ + if (request_size >= HUGE_PAGE_SIZE) + /* apply one extra huge page */ + request_size += HUGE_PAGE_SIZE; +#endif + if ((size_t)request_size < size) /* integer overflow */ return NULL; if (request_size > 16 * (uint64)UINT32_MAX) - /* At most 16 G is allowed */ + /* at most 16 G is allowed */ return NULL; if (prot & MMAP_PROT_READ) @@ -80,25 +112,93 @@ os_mmap(void *hint, size_t size, int prot, int flags) os_munmap(addr, request_size); } else { - /* reset next hint address */ + /* success, reset next hint address */ hint_addr += request_size; - return addr; + break; } } hint_addr += BH_MB; } } -#endif +#endif /* end of BUILD_TARGET_RISCV64_LP64D || BUILD_TARGET_RISCV64_LP64 */ - /* try 5 times */ - for (i = 0; i < 5; i++) { - addr = mmap(hint, request_size, map_prot, map_flags, -1, 0); - if (addr != MAP_FAILED) - break; + /* memory has't been mapped or was mapped failed previously */ + if (addr == MAP_FAILED) { + /* try 5 times */ + for (i = 0; i < 5; i++) { + addr = mmap(hint, request_size, map_prot, map_flags, -1, 0); + if (addr != MAP_FAILED) + break; + } } - if (addr == MAP_FAILED) + if (addr == MAP_FAILED) { +#if BH_ENABLE_TRACE_MMAP != 0 + os_printf("mmap failed\n"); +#endif return NULL; + } + +#if BH_ENABLE_TRACE_MMAP != 0 + total_size_mmapped += request_size; + os_printf("mmap return: %p with size: %zu, total_size_mmapped: %zu, " + "total_size_munmapped: %zu\n", + addr, request_size, total_size_mmapped, total_size_munmapped); +#endif + +#if !defined(__APPLE__) && !defined(__NuttX__) + /* huge page isn't supported on MacOS and NuttX */ + if (request_size > HUGE_PAGE_SIZE) { + uintptr_t huge_start, huge_end; + size_t prefix_size = 0, suffix_size = HUGE_PAGE_SIZE; + + huge_start = round_up((uintptr_t)addr, HUGE_PAGE_SIZE); + + if (huge_start > (uintptr_t)addr) { + prefix_size += huge_start - (uintptr_t)addr; + suffix_size -= huge_start - (uintptr_t)addr; + } + + /* unmap one extra huge page */ + + if (prefix_size > 0) { + munmap(addr, prefix_size); +#if BH_ENABLE_TRACE_MMAP != 0 + total_size_munmapped += prefix_size; + os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, " + "total_size_munmapped: %zu\n", + addr, prefix_size, total_size_mmapped, + total_size_munmapped); +#endif + } + if (suffix_size > 0) { + munmap(addr + request_size - suffix_size, suffix_size); +#if BH_ENABLE_TRACE_MMAP != 0 + total_size_munmapped += suffix_size; + os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, " + "total_size_munmapped: %zu\n", + addr + request_size - suffix_size, suffix_size, + total_size_mmapped, total_size_munmapped); +#endif + } + + addr = (uint8 *)huge_start; + request_size -= HUGE_PAGE_SIZE; + + huge_end = round_down(huge_start + request_size, HUGE_PAGE_SIZE); + if (huge_end > huge_start) { + int ret = madvise((void *)huge_start, huge_end - huge_start, + MADV_HUGEPAGE); + if (ret) { +#if BH_ENABLE_TRACE_MMAP != 0 + os_printf( + "warning: madvise(%p, %lu) huge page failed, return %d\n", + (void *)huge_start, huge_end - huge_start, ret); +#endif + } + } + } +#endif /* end of __APPLE__ || __NuttX__ */ return addr; } @@ -113,7 +213,14 @@ os_munmap(void *addr, size_t size) if (munmap(addr, request_size)) { os_printf("os_munmap error addr:%p, size:0x%" PRIx64 ", errno:%d\n", addr, request_size, errno); + return; } +#if BH_ENABLE_TRACE_MMAP != 0 + total_size_munmapped += request_size; + os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, " + "total_size_munmapped: %zu\n", + addr, request_size, total_size_mmapped, total_size_munmapped); +#endif } }