aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mem_linux.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2015-02-23 13:58:05 -0800
committerKeith Randall <khr@golang.org>2015-02-25 21:16:18 +0000
commit7e1b61c71840386a494a0a9f99cb7237112c1116 (patch)
tree31ddf6ddb37801ab1c6465a369355c711e433dc1 /src/runtime/mem_linux.go
parent6d1ebeb5271a06cd55f55a84e95709e2f4805bcc (diff)
downloadgo-7e1b61c71840386a494a0a9f99cb7237112c1116.tar.gz
go-7e1b61c71840386a494a0a9f99cb7237112c1116.zip
runtime: mark pages we return to kernel as NOHUGEPAGE
We return memory to the kernel with madvise(..., DONTNEED). Also mark returned memory with NOHUGEPAGE to keep the kernel from merging this memory into a huge page, effectively reallocating it. Only known to be a problem on linux/{386,amd64,amd64p32} at the moment. It may come up on other os/arch combinations in the future. Fixes #8832 Change-Id: Ifffc6627a0296926e3f189a8a9b6e4bdb54c79eb Reviewed-on: https://go-review.googlesource.com/5660 Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Diffstat (limited to 'src/runtime/mem_linux.go')
-rw-r--r--src/runtime/mem_linux.go19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index 920fbcf6d6..74de11caea 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -67,10 +67,29 @@ func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
}
func sysUnused(v unsafe.Pointer, n uintptr) {
+ if hugePageSize != 0 && (uintptr(v)%hugePageSize != 0 || n%hugePageSize != 0) {
+ // See issue 8832
+ // Linux kernel bug: https://bugzilla.kernel.org/show_bug.cgi?id=93111
+ // Mark the region as NOHUGEPAGE so the kernel's khugepaged
+ // doesn't undo our DONTNEED request. khugepaged likes to migrate
+ // regions which are only partially mapped to huge pages, including
+ // regions with some DONTNEED marks. That needlessly allocates physical
+ // memory for our DONTNEED regions.
+ madvise(v, n, _MADV_NOHUGEPAGE)
+ }
madvise(v, n, _MADV_DONTNEED)
}
func sysUsed(v unsafe.Pointer, n uintptr) {
+ if hugePageSize != 0 {
+ // Undo the NOHUGEPAGE marks from sysUnused. There is no alignment check
+ // around this call as spans may have been merged in the interim.
+ // Note that this might enable huge pages for regions which were
+ // previously disabled. Unfortunately there is no easy way to detect
+ // what the previous state was, and in any case we probably want huge
+ // pages to back our heap if the kernel can arrange that.
+ madvise(v, n, _MADV_HUGEPAGE)
+ }
}
func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {