aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/runtime/export_test.go16
-rw-r--r--src/runtime/gc_test.go17
-rw-r--r--src/runtime/mheap.go2
3 files changed, 34 insertions, 1 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 5400c1d14e..438090842f 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -171,3 +171,19 @@ func SetTracebackEnv(level string) {
setTraceback(level)
traceback_env = traceback_cache
}
+
+func CountPagesInUse() (pagesInUse, counted uintptr) {
+ stopTheWorld("CountPagesInUse")
+
+ pagesInUse = uintptr(mheap_.pagesInUse)
+
+ for _, s := range h_allspans {
+ if s.state == mSpanInUse {
+ counted += s.npages
+ }
+ }
+
+ startTheWorld()
+
+ return
+}
diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go
index c8c96bb4ee..d53d3ee000 100644
--- a/src/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -473,3 +473,20 @@ func testIfaceEqual(x interface{}) {
a = true
}
}
+
+func TestPageAccounting(t *testing.T) {
+ // Grow the heap in small increments. This used to drop the
+ // pages-in-use count below zero because of a rounding
+ // mismatch (golang.org/issue/15022).
+ const blockSize = 64 << 10
+ blocks := make([]*[blockSize]byte, (64<<20)/blockSize)
+ for i := range blocks {
+ blocks[i] = new([blockSize]byte)
+ }
+
+ // Check that the running page count matches reality.
+ pagesInUse, counted := runtime.CountPagesInUse()
+ if pagesInUse != counted {
+ t.Fatalf("mheap_.pagesInUse is %d, but direct count is %d", pagesInUse, counted)
+ }
+}
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index e8189547f8..a153df0733 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -671,7 +671,7 @@ func (h *mheap) grow(npage uintptr) bool {
}
atomic.Store(&s.sweepgen, h.sweepgen)
s.state = _MSpanInUse
- h.pagesInUse += uint64(npage)
+ h.pagesInUse += uint64(s.npages)
h.freeSpanLocked(s, false, true, 0)
return true
}