Skip to content

Commit 3f28a8c

Browse files
committed
Removed FindGoLeaks API, addressed nits, and cleaned comments.
1 parent 7da26f4 commit 3f28a8c

File tree

2 files changed

+18
-38
lines changed

2 files changed

+18
-38
lines changed

src/runtime/mgc.go

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -569,24 +569,6 @@ func GC() {
569569
releasem(mp)
570570
}
571571

572-
// FindGoleaks instructs the Go garbage collector to attempt
573-
// goroutine leak detection during the next GC cycle.
574-
//
575-
// Only operates if goroutineleakfindergc is enabled in GOEXPERIMENT.
576-
// Otherwise, it just runs runtime.GC().
577-
func FindGoLeaks() {
578-
if !goexperiment.GoroutineLeakFinderGC {
579-
GC()
580-
return
581-
}
582-
583-
work.goroutineLeakFinder.pending.Store(true)
584-
585-
for work.goroutineLeakFinder.pending.Load() {
586-
GC()
587-
}
588-
}
589-
590572
// gcWaitOnMark blocks until GC finishes the Nth mark phase. If GC has
591573
// already completed this mark phase, it returns immediately.
592574
func gcWaitOnMark(n uint32) {
@@ -1095,13 +1077,11 @@ top:
10951077
gcMarkTermination(stw)
10961078
}
10971079

1098-
// checkIfMaybeRunnable checks whether a goroutine may still be semantically runnable.
1080+
// isMaybeRunnable checks whether a goroutine may still be semantically runnable.
10991081
// For goroutines which are semantically runnable, this will eventually return true
11001082
// as the GC marking phase progresses. It returns false for leaked goroutines, or for
11011083
// goroutines which are not yet computed as possibly runnable by the GC.
1102-
func (gp *g) checkIfMaybeRunnable() bool {
1103-
// Unmask the goroutine address to ensure we are not
1104-
// dereferencing a masked address.
1084+
func (gp *g) isMaybeRunnable() bool {
11051085
switch gp.waitreason {
11061086
case waitReasonSelectNoCases,
11071087
waitReasonChanSendNilChan,
@@ -1128,7 +1108,6 @@ func (gp *g) checkIfMaybeRunnable() bool {
11281108
// If waiting on mutexes, wait groups, or condition variables,
11291109
// check if the synchronization primitive attached to the sudog is marked.
11301110
if gp.waiting != nil {
1131-
// Unmask the sema address and check if it's marked.
11321111
return isMarkedOrNotInHeap(gp.waiting.elem.get())
11331112
}
11341113
}
@@ -1148,12 +1127,12 @@ func findMaybeRunnableGoroutines() (moreWork bool) {
11481127
var vIndex, ivIndex int = work.nMaybeRunnableStackRoots, work.nStackRoots
11491128
// Reorder goroutine list
11501129
for vIndex < ivIndex {
1151-
if work.stackRoots[vIndex].checkIfMaybeRunnable() {
1130+
if work.stackRoots[vIndex].isMaybeRunnable() {
11521131
vIndex = vIndex + 1
11531132
continue
11541133
}
11551134
for ivIndex = ivIndex - 1; ivIndex != vIndex; ivIndex = ivIndex - 1 {
1156-
if gp := work.stackRoots[ivIndex]; gp.checkIfMaybeRunnable() {
1135+
if gp := work.stackRoots[ivIndex]; gp.isMaybeRunnable() {
11571136
work.stackRoots[ivIndex] = work.stackRoots[vIndex]
11581137
work.stackRoots[vIndex] = gp
11591138
vIndex = vIndex + 1
@@ -1186,8 +1165,6 @@ func gcUntrackSyncObjects() {
11861165

11871166
// gcRestoreSyncObjects restores the elem and c fields of all sudogs to their original values.
11881167
// Should be invoked after the goroutine leak detection phase.
1189-
//
1190-
//go:nosplit
11911168
func gcRestoreSyncObjects() {
11921169
assertWorldStopped()
11931170

src/runtime/mgcmark.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,12 @@ func (gp *g) internalBlocked() bool {
6363
return reason < waitReasonChanReceiveNilChan || waitReasonSyncWaitGroupWait < reason
6464
}
6565

66+
// allGsSnapshotSortedForGC takes a snapshot of allgs and returns a sorted
67+
// array of Gs. The array is sorted by the G's status, with running Gs
68+
// first, followed by blocked Gs. The returned index indicates the cutoff
69+
// between runnable and blocked Gs.
70+
//
6671
// The world must be stopped or allglock must be held.
67-
// go through the snapshot of allgs, putting them into an arrays,
68-
// separated by index, where [0:blockedIndex] contains only running Gs
69-
// allGs[blockedIndex:] contain only blocking Gs
70-
// To avoid GC from marking and scanning the blocked Gs by scanning
71-
// the returned array (which is heap allocated), we mask the highest
72-
// bit of the pointers to Gs with gcBitMask.
7372
func allGsSnapshotSortedForGC() ([]*g, int) {
7473
assertWorldStoppedOrLockHeld(&allglock)
7574

@@ -1195,7 +1194,11 @@ func gcDrainMarkWorkerFractional(gcw *gcWork) {
11951194
gcDrain(gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
11961195
}
11971196

1198-
func gcUpdateMarkrootNext() (uint32, bool) {
1197+
// gcNextMarkRoot safely increments work.markrootNext and returns the
1198+
// index of the next root job. The returned boolean is true if the root job
1199+
// is valid, and false if there are no more root jobs to be claimed,
1200+
// i.e. work.markrootNext >= work.markrootJobs.
1201+
func gcNextMarkRoot() (uint32, bool) {
11991202
var success bool
12001203
next, jobs := work.markrootNext.Load(), work.markrootJobs.Load()
12011204

@@ -1281,8 +1284,8 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
12811284
// Stop if we're preemptible, if someone wants to STW, or if
12821285
// someone is calling forEachP.
12831286
for !(gp.preempt && (preemptible || sched.gcwaiting.Load() || pp.runSafePointFn != 0)) {
1284-
job, success := gcUpdateMarkrootNext()
1285-
if !success {
1287+
job, ok := gcNextMarkRoot()
1288+
if !ok {
12861289
break
12871290
}
12881291
markroot(gcw, job, flushBgCredit)
@@ -1429,8 +1432,8 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 {
14291432
if b = gcw.tryGetObj(); b == 0 {
14301433
// Try to do a root job.
14311434
if work.markrootNext.Load() < work.markrootJobs.Load() {
1432-
job, success := gcUpdateMarkrootNext()
1433-
if success {
1435+
job, ok := gcNextMarkRoot()
1436+
if ok {
14341437
workFlushed += markroot(gcw, job, false)
14351438
continue
14361439
}

0 commit comments

Comments
 (0)