aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2022-07-13 15:35:44 +0000
committerMichael Anthony Knyszek <mknyszek@google.com>2022-07-13 15:35:44 +0000
commit7d5078e3bf2d865526e8ec2d211f61b2fac2936f (patch)
tree8f434be7d8e2ec1e3e5783f57deacdec41d454d9 /src/runtime
parent4658e6e324a85b0076f66acdab77799ffa9ac7bb (diff)
parent1ed3c127daceaffb9aadc806ba60f0b51b47421b (diff)
downloadgo-7d5078e3bf2d865526e8ec2d211f61b2fac2936f.tar.gz
go-7d5078e3bf2d865526e8ec2d211f61b2fac2936f.zip
[dev.boringcrypto.go1.17] all: merge go1.17.12 into dev.boringcrypto.go1.17
Change-Id: I652dbbb5721fa0c7be09be34b9ac1a987c331f6d
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/export_test.go4
-rw-r--r--src/runtime/mcache.go16
-rw-r--r--src/runtime/metrics.go45
-rw-r--r--src/runtime/mgcsweep.go6
-rw-r--r--src/runtime/mstats.go42
-rw-r--r--src/runtime/syscall_windows.go28
6 files changed, 89 insertions, 52 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 03ccfe10a8..3cee4dec57 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -321,9 +321,9 @@ func ReadMetricsSlow(memStats *MemStats, samplesp unsafe.Pointer, len, cap int)
// Initialize the metrics beforehand because this could
// allocate and skew the stats.
- semacquire(&metricsSema)
+ metricsLock()
initMetrics()
- semrelease(&metricsSema)
+ metricsUnlock()
systemstack(func() {
// Read memstats first. It's going to flush
diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go
index a9e959109a..99303358be 100644
--- a/src/runtime/mcache.go
+++ b/src/runtime/mcache.go
@@ -175,11 +175,11 @@ func (c *mcache) refill(spc spanClass) {
// Assume all objects from this span will be allocated in the
// mcache. If it gets uncached, we'll adjust this.
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.smallAllocCount[spc.sizeclass()], uintptr(s.nelems)-uintptr(s.allocCount))
+ atomic.Xadd64(&stats.smallAllocCount[spc.sizeclass()], int64(s.nelems)-int64(s.allocCount))
// Flush tinyAllocs.
if spc == tinySpanClass {
- atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs)
+ atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
c.tinyAllocs = 0
}
memstats.heapStats.release()
@@ -229,8 +229,8 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, b
throw("out of memory")
}
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.largeAlloc, npages*pageSize)
- atomic.Xadduintptr(&stats.largeAllocCount, 1)
+ atomic.Xadd64(&stats.largeAlloc, int64(npages*pageSize))
+ atomic.Xadd64(&stats.largeAllocCount, 1)
memstats.heapStats.release()
// Update gcController.heapLive and revise pacing if needed.
@@ -261,9 +261,9 @@ func (c *mcache) releaseAll() {
s := c.alloc[i]
if s != &emptymspan {
// Adjust nsmallalloc in case the span wasn't fully allocated.
- n := uintptr(s.nelems) - uintptr(s.allocCount)
+ n := int64(s.nelems) - int64(s.allocCount)
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.smallAllocCount[spanClass(i).sizeclass()], -n)
+ atomic.Xadd64(&stats.smallAllocCount[spanClass(i).sizeclass()], -n)
memstats.heapStats.release()
if s.sweepgen != sg+1 {
// refill conservatively counted unallocated slots in gcController.heapLive.
@@ -273,7 +273,7 @@ func (c *mcache) releaseAll() {
// gcController.heapLive was totally recomputed since
// caching this span, so we don't do this for
// stale spans.
- atomic.Xadd64(&gcController.heapLive, -int64(n)*int64(s.elemsize))
+ atomic.Xadd64(&gcController.heapLive, -n*int64(s.elemsize))
}
// Release the span to the mcentral.
mheap_.central[i].mcentral.uncacheSpan(s)
@@ -286,7 +286,7 @@ func (c *mcache) releaseAll() {
// Flush tinyAllocs.
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs)
+ atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
c.tinyAllocs = 0
memstats.heapStats.release()
diff --git a/src/runtime/metrics.go b/src/runtime/metrics.go
index ba0a920a5d..922dd2f814 100644
--- a/src/runtime/metrics.go
+++ b/src/runtime/metrics.go
@@ -12,9 +12,12 @@ import (
)
var (
- // metrics is a map of runtime/metrics keys to
- // data used by the runtime to sample each metric's
- // value.
+ // metrics is a map of runtime/metrics keys to data used by the runtime
+ // to sample each metric's value. metricsInit indicates it has been
+ // initialized.
+ //
+ // These fields are protected by metricsSema which should be
+ // locked/unlocked with metricsLock() / metricsUnlock().
metricsSema uint32 = 1
metricsInit bool
metrics map[string]metricData
@@ -34,6 +37,23 @@ type metricData struct {
compute func(in *statAggregate, out *metricValue)
}
+func metricsLock() {
+ // Acquire the metricsSema but with handoff. Operations are typically
+ // expensive enough that queueing up goroutines and handing off between
+ // them will be noticeably better-behaved.
+ semacquire1(&metricsSema, true, 0, 0)
+ if raceenabled {
+ raceacquire(unsafe.Pointer(&metricsSema))
+ }
+}
+
+func metricsUnlock() {
+ if raceenabled {
+ racerelease(unsafe.Pointer(&metricsSema))
+ }
+ semrelease(&metricsSema)
+}
+
// initMetrics initializes the metrics map if it hasn't been yet.
//
// metricsSema must be held.
@@ -388,13 +408,13 @@ func (a *heapStatsAggregate) compute() {
memstats.heapStats.read(&a.heapStatsDelta)
// Calculate derived stats.
- a.totalAllocs = uint64(a.largeAllocCount)
- a.totalFrees = uint64(a.largeFreeCount)
- a.totalAllocated = uint64(a.largeAlloc)
- a.totalFreed = uint64(a.largeFree)
+ a.totalAllocs = a.largeAllocCount
+ a.totalFrees = a.largeFreeCount
+ a.totalAllocated = a.largeAlloc
+ a.totalFreed = a.largeFree
for i := range a.smallAllocCount {
- na := uint64(a.smallAllocCount[i])
- nf := uint64(a.smallFreeCount[i])
+ na := a.smallAllocCount[i]
+ nf := a.smallFreeCount[i]
a.totalAllocs += na
a.totalFrees += nf
a.totalAllocated += na * uint64(class_to_size[i])
@@ -546,10 +566,7 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
sl := slice{samplesp, len, cap}
samples := *(*[]metricSample)(unsafe.Pointer(&sl))
- // Acquire the metricsSema but with handoff. This operation
- // is expensive enough that queueing up goroutines and handing
- // off between them will be noticeably better-behaved.
- semacquire1(&metricsSema, true, 0, 0)
+ metricsLock()
// Ensure the map is initialized.
initMetrics()
@@ -573,5 +590,5 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
data.compute(&agg, &sample.value)
}
- semrelease(&metricsSema)
+ metricsUnlock()
}
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go
index 8fe3a65340..468df4d097 100644
--- a/src/runtime/mgcsweep.go
+++ b/src/runtime/mgcsweep.go
@@ -581,7 +581,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool {
// free slots zeroed.
s.needzero = 1
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.smallFreeCount[spc.sizeclass()], uintptr(nfreed))
+ atomic.Xadd64(&stats.smallFreeCount[spc.sizeclass()], int64(nfreed))
memstats.heapStats.release()
}
if !preserve {
@@ -628,8 +628,8 @@ func (sl *sweepLocked) sweep(preserve bool) bool {
mheap_.freeSpan(s)
}
stats := memstats.heapStats.acquire()
- atomic.Xadduintptr(&stats.largeFreeCount, 1)
- atomic.Xadduintptr(&stats.largeFree, size)
+ atomic.Xadd64(&stats.largeFreeCount, 1)
+ atomic.Xadd64(&stats.largeFree, int64(size))
memstats.heapStats.release()
return true
}
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index eeb2a7b4bc..94c507b45f 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -8,7 +8,6 @@ package runtime
import (
"runtime/internal/atomic"
- "runtime/internal/sys"
"unsafe"
)
@@ -565,29 +564,29 @@ func updatememstats() {
memstats.heapStats.unsafeRead(&consStats)
// Collect large allocation stats.
- totalAlloc := uint64(consStats.largeAlloc)
- memstats.nmalloc += uint64(consStats.largeAllocCount)
- totalFree := uint64(consStats.largeFree)
- memstats.nfree += uint64(consStats.largeFreeCount)
+ totalAlloc := consStats.largeAlloc
+ memstats.nmalloc += consStats.largeAllocCount
+ totalFree := consStats.largeFree
+ memstats.nfree += consStats.largeFreeCount
// Collect per-sizeclass stats.
for i := 0; i < _NumSizeClasses; i++ {
// Malloc stats.
- a := uint64(consStats.smallAllocCount[i])
+ a := consStats.smallAllocCount[i]
totalAlloc += a * uint64(class_to_size[i])
memstats.nmalloc += a
memstats.by_size[i].nmalloc = a
// Free stats.
- f := uint64(consStats.smallFreeCount[i])
+ f := consStats.smallFreeCount[i]
totalFree += f * uint64(class_to_size[i])
memstats.nfree += f
memstats.by_size[i].nfree = f
}
// Account for tiny allocations.
- memstats.nfree += uint64(consStats.tinyAllocCount)
- memstats.nmalloc += uint64(consStats.tinyAllocCount)
+ memstats.nfree += consStats.tinyAllocCount
+ memstats.nmalloc += consStats.tinyAllocCount
// Calculate derived stats.
memstats.total_alloc = totalAlloc
@@ -703,17 +702,20 @@ type heapStatsDelta struct {
inPtrScalarBits int64 // byte delta of memory reserved for unrolled GC prog bits
// Allocator stats.
- tinyAllocCount uintptr // number of tiny allocations
- largeAlloc uintptr // bytes allocated for large objects
- largeAllocCount uintptr // number of large object allocations
- smallAllocCount [_NumSizeClasses]uintptr // number of allocs for small objects
- largeFree uintptr // bytes freed for large objects (>maxSmallSize)
- largeFreeCount uintptr // number of frees for large objects (>maxSmallSize)
- smallFreeCount [_NumSizeClasses]uintptr // number of frees for small objects (<=maxSmallSize)
-
- // Add a uint32 to ensure this struct is a multiple of 8 bytes in size.
- // Only necessary on 32-bit platforms.
- _ [(sys.PtrSize / 4) % 2]uint32
+ //
+ // These are all uint64 because they're cumulative, and could quickly wrap
+ // around otherwise.
+ tinyAllocCount uint64 // number of tiny allocations
+ largeAlloc uint64 // bytes allocated for large objects
+ largeAllocCount uint64 // number of large object allocations
+ smallAllocCount [_NumSizeClasses]uint64 // number of allocs for small objects
+ largeFree uint64 // bytes freed for large objects (>maxSmallSize)
+ largeFreeCount uint64 // number of frees for large objects (>maxSmallSize)
+ smallFreeCount [_NumSizeClasses]uint64 // number of frees for small objects (<=maxSmallSize)
+
+ // NOTE: This struct must be a multiple of 8 bytes in size because it
+ // is stored in an array. If it's not, atomic accesses to the above
+ // fields may be unaligned and fail on 32-bit platforms.
}
// merge adds in the deltas from b into a.
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 94a61c8823..30ef72bce9 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -12,12 +12,30 @@ import (
// cbs stores all registered Go callbacks.
var cbs struct {
- lock mutex
+ lock mutex // use cbsLock / cbsUnlock for race instrumentation.
ctxt [cb_max]winCallback
index map[winCallbackKey]int
n int
}
+func cbsLock() {
+ lock(&cbs.lock)
+ // compileCallback is used by goenvs prior to completion of schedinit.
+ // raceacquire involves a racecallback to get the proc, which is not
+ // safe prior to scheduler initialization. Thus avoid instrumentation
+ // until then.
+ if raceenabled && mainStarted {
+ raceacquire(unsafe.Pointer(&cbs.lock))
+ }
+}
+
+func cbsUnlock() {
+ if raceenabled && mainStarted {
+ racerelease(unsafe.Pointer(&cbs.lock))
+ }
+ unlock(&cbs.lock)
+}
+
// winCallback records information about a registered Go callback.
type winCallback struct {
fn *funcval // Go function
@@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
key := winCallbackKey{(*funcval)(fn.data), cdecl}
- lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack.
+ cbsLock()
// Check if this callback is already registered.
if n, ok := cbs.index[key]; ok {
- unlock(&cbs.lock)
+ cbsUnlock()
return callbackasmAddr(n)
}
@@ -316,7 +334,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
}
n := cbs.n
if n >= len(cbs.ctxt) {
- unlock(&cbs.lock)
+ cbsUnlock()
throw("too many callback functions")
}
c := winCallback{key.fn, retPop, abiMap}
@@ -324,7 +342,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
cbs.index[key] = n
cbs.n++
- unlock(&cbs.lock)
+ cbsUnlock()
return callbackasmAddr(n)
}