diff options
-rw-r--r-- | src/runtime/export_test.go | 16 | ||||
-rw-r--r-- | src/runtime/gc_test.go | 17 | ||||
-rw-r--r-- | src/runtime/mheap.go | 2 |
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 } |