diff options
author | Michael Anthony Knyszek <mknyszek@google.com> | 2022-07-13 15:35:44 +0000 |
---|---|---|
committer | Michael Anthony Knyszek <mknyszek@google.com> | 2022-07-13 15:35:44 +0000 |
commit | 7d5078e3bf2d865526e8ec2d211f61b2fac2936f (patch) | |
tree | 8f434be7d8e2ec1e3e5783f57deacdec41d454d9 /src/runtime | |
parent | 4658e6e324a85b0076f66acdab77799ffa9ac7bb (diff) | |
parent | 1ed3c127daceaffb9aadc806ba60f0b51b47421b (diff) | |
download | go-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.go | 4 | ||||
-rw-r--r-- | src/runtime/mcache.go | 16 | ||||
-rw-r--r-- | src/runtime/metrics.go | 45 | ||||
-rw-r--r-- | src/runtime/mgcsweep.go | 6 | ||||
-rw-r--r-- | src/runtime/mstats.go | 42 | ||||
-rw-r--r-- | src/runtime/syscall_windows.go | 28 |
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) } |