diff options
author | Danny Lin <danny@kdrag0n.dev> | 2021-10-11 20:49:26 -0700 |
---|---|---|
committer | alk3pInjection <5e147612@kscope.ink> | 2022-05-08 12:40:50 +0800 |
commit | e36e52fb6ec54bc47e17e849ca5a3a301eaa6d05 (patch) | |
tree | 854d309be91bcdd38fe46ea8ad0f906bef39d017 /src/pages.c | |
parent | 6d4d27fd2651ed114386b89c2d251b816a849460 (diff) | |
parent | ea6b3e973b477b8061e0076bb257dbd7f3faa756 (diff) |
Merge tag '5.2.1' into HEAD
Release
Change-Id: I269b861cb81499b78f13dc2e88827f13ef5a207d
Diffstat (limited to 'src/pages.c')
-rw-r--r-- | src/pages.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/src/pages.c b/src/pages.c index 132aeeb7..2125d17f 100644 --- a/src/pages.c +++ b/src/pages.c @@ -194,6 +194,35 @@ pages_map(void *addr, size_t size, size_t alignment, bool *commit) { assert(alignment >= PAGE); assert(ALIGNMENT_ADDR2BASE(addr, alignment) == addr); +#if defined(__FreeBSD__) && defined(MAP_EXCL) + /* + * FreeBSD has mechanisms both to mmap at specific address without + * touching existing mappings, and to mmap with specific alignment. + */ + { + if (os_overcommits) { + *commit = true; + } + + int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT; + int flags = mmap_flags; + + if (addr != NULL) { + flags |= MAP_FIXED | MAP_EXCL; + } else { + unsigned alignment_bits = ffs_zu(alignment); + assert(alignment_bits > 1); + flags |= MAP_ALIGNED(alignment_bits - 1); + } + + void *ret = mmap(addr, size, prot, flags, -1, 0); + if (ret == MAP_FAILED) { + ret = NULL; + } + + return ret; + } +#endif /* * Ideally, there would be a way to specify alignment to mmap() (like * NetBSD has), but in the absence of such a feature, we have to work @@ -275,7 +304,7 @@ pages_decommit(void *addr, size_t size) { bool pages_purge_lazy(void *addr, size_t size) { - assert(PAGE_ADDR2BASE(addr) == addr); + assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr); assert(PAGE_CEILING(size) == size); if (!pages_can_purge_lazy) { @@ -405,6 +434,10 @@ os_page_detect(void) { GetSystemInfo(&si); return si.dwPageSize; #elif defined(__FreeBSD__) + /* + * This returns the value obtained from + * the auxv vector, avoiding a syscall. + */ return getpagesize(); #else long result = sysconf(_SC_PAGESIZE); @@ -558,6 +591,10 @@ init_thp_state(void) { close(fd); #endif + if (nread < 0) { + goto label_error; + } + if (strncmp(buf, sys_state_madvise, (size_t)nread) == 0) { init_system_thp_mode = thp_mode_default; } else if (strncmp(buf, sys_state_always, (size_t)nread) == 0) { @@ -609,6 +646,11 @@ pages_boot(void) { init_thp_state(); +#ifdef __FreeBSD__ + /* + * FreeBSD doesn't need the check; madvise(2) is known to work. + */ +#else /* Detect lazy purge runtime support. */ if (pages_can_purge_lazy) { bool committed = false; @@ -622,6 +664,7 @@ pages_boot(void) { } os_pages_unmap(madv_free_page, PAGE); } +#endif return false; } |