Michael Knyszek submitted this change.
4 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
runtime: add harddecommit GODEBUG flag
This change adds a new debug flag that makes the runtime map pages
PROT_NONE in sysUnused on Linux, in addition to the usual madvise calls.
This behavior mimics the behavior of decommit on Windows, and is helpful
in debugging the scavenger. sysUsed is also updated to re-map the pages
as PROT_READ|PROT_WRITE, mimicing Windows' explicit commit behavior.
Change-Id: Iaac5fcd0e6920bd1d0e753dd4e7f0c0b128fe842
Reviewed-on: https://go-review.googlesource.com/c/go/+/356612
Trust: Michael Knyszek <mkny...@google.com>
Reviewed-by: Michael Pratt <mpr...@google.com>
---
M src/runtime/extern.go
M src/runtime/mem_linux.go
M src/runtime/runtime1.go
3 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/src/runtime/extern.go b/src/runtime/extern.go
index b2003ba..f1f6ea5 100644
--- a/src/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -78,6 +78,11 @@
If the line ends with "(forced)", this GC was forced by a
runtime.GC() call.
+ harddecommit: setting harddecommit=1 causes memory that is returned to the OS to
+ also have protections removed on it. This is the only mode of operation on Windows,
+ but is helpful in debugging scavenger-related issues on other platforms. Currently,
+ only supported on Linux.
+
inittrace: setting inittrace=1 causes the runtime to emit a single line to standard
error for each package with init work, summarizing the execution time and memory
allocation. No information is printed for inits executed as part of plugin loading
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index 3436851..f8f9c53 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -114,9 +114,29 @@
atomic.Store(&adviseUnused, _MADV_DONTNEED)
madvise(v, n, _MADV_DONTNEED)
}
+
+ if debug.harddecommit > 0 {
+ p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+ if p != v || err != 0 {
+ throw("runtime: cannot disable permissions in address space")
+ }
+ }
}
func sysUsed(v unsafe.Pointer, n uintptr) {
+ if debug.harddecommit > 0 {
+ p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+ if err == _ENOMEM {
+ throw("runtime: out of memory")
+ }
+ if p != v || err != 0 {
+ throw("runtime: cannot remap pages in address space")
+ }
+ return
+
+ // Don't do the sysHugePage optimization in hard decommit mode.
+ // We're breaking up pages everywhere, there's no point.
+ }
// Partially undo the NOHUGEPAGE marks from sysUnused
// for whole huge pages between v and v+n. This may
// leave huge pages off at the end points v and v+n
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index b6c3cbf..65e1e0e 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -315,6 +315,7 @@
schedtrace int32
tracebackancestors int32
asyncpreemptoff int32
+ harddecommit int32
// debug.malloc is used as a combined debug check
// in the malloc function and should be set
@@ -344,6 +345,7 @@
{"tracebackancestors", &debug.tracebackancestors},
{"asyncpreemptoff", &debug.asyncpreemptoff},
{"inittrace", &debug.inittrace},
+ {"harddecommit", &debug.harddecommit},
}
func parsedebugvars() {
To view, visit change 356612. To unsubscribe, or for help writing mail filters, visit settings.