From 28e388589b48063047dbe7738bc1dfd4ed8e36bd Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Fri, 26 Aug 2022 10:26:05 +0800 Subject: [PATCH] runtime: convert workType.cycles to internal atomic types Note that this changes a non-atomic operation to atomic operation in gcStart(). For #53821 Change-Id: I754d254f6f190855144ff62151b6bae673b47867 Reviewed-on: https://go-review.googlesource.com/c/go/+/425776 Reviewed-by: Michael Pratt Reviewed-by: Michael Knyszek Auto-Submit: Michael Pratt TryBot-Result: Gopher Robot Run-TryBot: Michael Knyszek --- src/runtime/mgc.go | 16 ++++++++-------- src/runtime/mgcpacer.go | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 3361d48abd..8021a56b9a 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -393,7 +393,7 @@ type workType struct { // cycle is sweep termination, mark, mark termination, and // sweep. This differs from memstats.numgc, which is // incremented at mark termination. - cycles uint32 + cycles atomic.Uint32 // Timing/utilization stats for this cycle. stwprocs, maxprocs int32 @@ -436,7 +436,7 @@ func GC() { // Wait until the current sweep termination, mark, and mark // termination complete. - n := atomic.Load(&work.cycles) + n := work.cycles.Load() gcWaitOnMark(n) // We're now in sweep N or later. Trigger GC cycle N+1, which @@ -451,7 +451,7 @@ func GC() { // complete the cycle and because runtime.GC() is often used // as part of tests and benchmarks to get the system into a // relatively stable and isolated state. - for atomic.Load(&work.cycles) == n+1 && sweepone() != ^uintptr(0) { + for work.cycles.Load() == n+1 && sweepone() != ^uintptr(0) { sweep.nbgsweep++ Gosched() } @@ -467,7 +467,7 @@ func GC() { // First, wait for sweeping to finish. (We know there are no // more spans on the sweep queue, but we may be concurrently // sweeping spans, so we have to wait.) - for atomic.Load(&work.cycles) == n+1 && !isSweepDone() { + for work.cycles.Load() == n+1 && !isSweepDone() { Gosched() } @@ -475,7 +475,7 @@ func GC() { // stable heap profile. Only do this if we haven't already hit // another mark termination. mp := acquirem() - cycle := atomic.Load(&work.cycles) + cycle := work.cycles.Load() if cycle == n+1 || (gcphase == _GCmark && cycle == n+2) { mProf_PostSweep() } @@ -488,7 +488,7 @@ func gcWaitOnMark(n uint32) { for { // Disable phase transitions. lock(&work.sweepWaiters.lock) - nMarks := atomic.Load(&work.cycles) + nMarks := work.cycles.Load() if gcphase != _GCmark { // We've already completed this cycle's mark. nMarks++ @@ -565,7 +565,7 @@ func (t gcTrigger) test() bool { return lastgc != 0 && t.now-lastgc > forcegcperiod case gcTriggerCycle: // t.n > work.cycles, but accounting for wraparound. - return int32(t.n-work.cycles) > 0 + return int32(t.n-work.cycles.Load()) > 0 } return true } @@ -672,7 +672,7 @@ func gcStart(trigger gcTrigger) { // reclaimed until the next GC cycle. clearpools() - work.cycles++ + work.cycles.Add(1) // Assists and workers can start the moment we start // the world. diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 633d181a9d..2e73ac2923 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -1314,7 +1314,7 @@ func setGCPercent(in int32) (out int32) { // If we just disabled GC, wait for any concurrent GC mark to // finish so we always return with no GC running. if in < 0 { - gcWaitOnMark(atomic.Load(&work.cycles)) + gcWaitOnMark(work.cycles.Load()) } return out -- 2.50.0