]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use uintptr instead of int32 for counting to next heap profile sample
authorKeith Randall <khr@google.com>
Mon, 29 Jul 2019 19:51:19 +0000 (12:51 -0700)
committerKeith Randall <khr@golang.org>
Mon, 29 Jul 2019 21:07:49 +0000 (21:07 +0000)
Overflow of the comparison caused very large (>=1<<32) allocations to
sometimes not get sampled at all. Use uintptr so the comparison will
never overflow.

Fixes #33342

Tested on the example in 33342. I don't want to check a test in that
needs that much memory, however.

Change-Id: I51fe77a9117affed8094da93c0bc5f445ac2d3d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/188017
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
src/runtime/malloc.go
src/runtime/mcache.go

index 8ad7035d94c917f222947f710cab0f065c0f3f7d..5a21e80e18dbdb72e870f944310739fc3478e98f 100644 (file)
@@ -1075,8 +1075,8 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
        }
 
        if rate := MemProfileRate; rate > 0 {
-               if rate != 1 && int32(size) < c.next_sample {
-                       c.next_sample -= int32(size)
+               if rate != 1 && size < c.next_sample {
+                       c.next_sample -= size
                } else {
                        mp := acquirem()
                        profilealloc(mp, x, size)
@@ -1170,7 +1170,7 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) {
 // processes, the distance between two samples follows the exponential
 // distribution (exp(MemProfileRate)), so the best return value is a random
 // number taken from an exponential distribution whose mean is MemProfileRate.
-func nextSample() int32 {
+func nextSample() uintptr {
        if GOOS == "plan9" {
                // Plan 9 doesn't support floating point in note handler.
                if g := getg(); g == g.m.gsignal {
@@ -1178,7 +1178,7 @@ func nextSample() int32 {
                }
        }
 
-       return fastexprand(MemProfileRate)
+       return uintptr(fastexprand(MemProfileRate))
 }
 
 // fastexprand returns a random number from an exponential distribution with
@@ -1213,14 +1213,14 @@ func fastexprand(mean int) int32 {
 
 // nextSampleNoFP is similar to nextSample, but uses older,
 // simpler code to avoid floating point.
-func nextSampleNoFP() int32 {
+func nextSampleNoFP() uintptr {
        // Set first allocation sample size.
        rate := MemProfileRate
        if rate > 0x3fffffff { // make 2*rate not overflow
                rate = 0x3fffffff
        }
        if rate != 0 {
-               return int32(fastrand() % uint32(2*rate))
+               return uintptr(fastrand() % uint32(2*rate))
        }
        return 0
 }
index 0cb21f719049b52e51d00b3e0ca7aa8b66d07c88..d4fa9a012db6ef53a6e048f8830bd358ede66d5a 100644 (file)
@@ -19,7 +19,7 @@ import (
 type mcache struct {
        // The following members are accessed on every malloc,
        // so they are grouped here for better caching.
-       next_sample int32   // trigger heap sample after allocating this many bytes
+       next_sample uintptr // trigger heap sample after allocating this many bytes
        local_scan  uintptr // bytes of scannable heap allocated
 
        // Allocator cache for tiny objects w/o pointers.