@@ -1245,40 +1245,21 @@ func pprof_threadCreateInternal(p []profilerecord.StackRecord) (n int, ok bool)
12451245 })
12461246}
12471247
1248- //go:linkname pprof_goroutineProfileWithLabels
1249- func pprof_goroutineProfileWithLabels (p []profilerecord.StackRecord , labels []unsafe. Pointer ) (n int , ok bool ) {
1250- return goroutineProfileWithLabels ( p , labels )
1248+ //go:linkname pprof_goroutineProfile
1249+ func pprof_goroutineProfile (p []profilerecord.GoroutineRecord ) (n int , ok bool ) {
1250+ return goroutineProfileInternal ( p )
12511251}
12521252
1253- // labels may be nil. If labels is non-nil, it must have the same length as p.
1254- func goroutineProfileWithLabels (p []profilerecord.StackRecord , labels []unsafe.Pointer ) (n int , ok bool ) {
1255- if labels != nil && len (labels ) != len (p ) {
1256- labels = nil
1257- }
1258-
1259- return goroutineProfileWithLabelsConcurrent (p , labels )
1260- }
1261-
1262- //go:linkname pprof_goroutineLeakProfileWithLabels
1263- func pprof_goroutineLeakProfileWithLabels (p []profilerecord.StackRecord , labels []unsafe.Pointer ) (n int , ok bool ) {
1264- return goroutineLeakProfileWithLabelsConcurrent (p , labels )
1265- }
1266-
1267- // labels may be nil. If labels is non-nil, it must have the same length as p.
1268- func goroutineLeakProfileWithLabels (p []profilerecord.StackRecord , labels []unsafe.Pointer ) (n int , ok bool ) {
1269- if labels != nil && len (labels ) != len (p ) {
1270- labels = nil
1271- }
1272-
1273- return goroutineLeakProfileWithLabelsConcurrent (p , labels )
1253+ //go:linkname pprof_goroutineLeakProfile
1254+ func pprof_goroutineLeakProfile (p []profilerecord.GoroutineRecord ) (n int , ok bool ) {
1255+ return goroutineLeakProfileInternal (p )
12741256}
12751257
12761258var goroutineProfile = struct {
12771259 sema uint32
12781260 active bool
12791261 offset atomic.Int64
1280- records []profilerecord.StackRecord
1281- labels []unsafe.Pointer
1262+ records []profilerecord.GoroutineRecord
12821263}{
12831264 sema : 1 ,
12841265}
@@ -1316,18 +1297,18 @@ func (p *goroutineProfileStateHolder) CompareAndSwap(old, new goroutineProfileSt
13161297 return (* atomic .Uint32 )(p ).CompareAndSwap (uint32 (old ), uint32 (new ))
13171298}
13181299
1319- func goroutineLeakProfileWithLabelsConcurrent (p []profilerecord.StackRecord , labels []unsafe. Pointer ) (n int , ok bool ) {
1300+ func goroutineLeakProfileInternal (p []profilerecord.GoroutineRecord ) (n int , ok bool ) {
13201301 if len (p ) == 0 {
13211302 // An empty slice is obviously too small. Return a rough
13221303 // allocation estimate.
13231304 return work .goroutineLeak .count , false
13241305 }
13251306
1326- // Use the same semaphore as goroutineProfileWithLabelsConcurrent ,
1307+ // Use the same semaphore as goroutineProfileInternal ,
13271308 // because ultimately we still use goroutine profiles.
13281309 semacquire (& goroutineProfile .sema )
13291310
1330- // Unlike in goroutineProfileWithLabelsConcurrent , we don't need to
1311+ // Unlike in goroutineProfileInternal , we don't need to
13311312 // save the current goroutine stack, because it is obviously not leaked.
13321313
13331314 pcbuf := makeProfStack () // see saveg() for explanation
@@ -1358,7 +1339,7 @@ func goroutineLeakProfileWithLabelsConcurrent(p []profilerecord.StackRecord, lab
13581339 return n , true
13591340}
13601341
1361- func goroutineProfileWithLabelsConcurrent (p []profilerecord.StackRecord , labels []unsafe. Pointer ) (n int , ok bool ) {
1342+ func goroutineProfileInternal (p []profilerecord.GoroutineRecord ) (n int , ok bool ) {
13621343 if len (p ) == 0 {
13631344 // An empty slice is obviously too small. Return a rough
13641345 // allocation estimate without bothering to STW. As long as
@@ -1401,9 +1382,8 @@ func goroutineProfileWithLabelsConcurrent(p []profilerecord.StackRecord, labels
14011382 systemstack (func () {
14021383 saveg (pc , sp , ourg , & p [0 ], pcbuf )
14031384 })
1404- if labels != nil {
1405- labels [0 ] = ourg .labels
1406- }
1385+
1386+ p [0 ].Labels = ourg .labels
14071387 ourg .goroutineProfiled .Store (goroutineProfileSatisfied )
14081388 goroutineProfile .offset .Store (1 )
14091389
@@ -1414,7 +1394,6 @@ func goroutineProfileWithLabelsConcurrent(p []profilerecord.StackRecord, labels
14141394 // field set to goroutineProfileSatisfied.
14151395 goroutineProfile .active = true
14161396 goroutineProfile .records = p
1417- goroutineProfile .labels = labels
14181397 startTheWorld (stw )
14191398
14201399 // Visit each goroutine that existed as of the startTheWorld call above.
@@ -1436,7 +1415,6 @@ func goroutineProfileWithLabelsConcurrent(p []profilerecord.StackRecord, labels
14361415 endOffset := goroutineProfile .offset .Swap (0 )
14371416 goroutineProfile .active = false
14381417 goroutineProfile .records = nil
1439- goroutineProfile .labels = nil
14401418 startTheWorld (stw )
14411419
14421420 // Restore the invariant that every goroutine struct in allgs has its
@@ -1528,7 +1506,7 @@ func doRecordGoroutineProfile(gp1 *g, pcbuf []uintptr) {
15281506 // System goroutines should not appear in the profile.
15291507 // Check this here and not in tryRecordGoroutineProfile because isSystemGoroutine
15301508 // may change on a goroutine while it is executing, so while the scheduler might
1531- // see a system goroutine, goroutineProfileWithLabelsConcurrent might not, and
1509+ // see a system goroutine, goroutineProfileInternal might not, and
15321510 // this inconsistency could cause invariants to be violated, such as trying to
15331511 // record the stack of a running goroutine below. In short, we still want system
15341512 // goroutines to participate in the same state machine on gp1.goroutineProfiled as
@@ -1556,7 +1534,7 @@ func doRecordGoroutineProfile(gp1 *g, pcbuf []uintptr) {
15561534 if offset >= len (goroutineProfile .records ) {
15571535 // Should be impossible, but better to return a truncated profile than
15581536 // to crash the entire process at this point. Instead, deal with it in
1559- // goroutineProfileWithLabelsConcurrent where we have more context.
1537+ // goroutineProfileInternal where we have more context.
15601538 return
15611539 }
15621540
@@ -1570,88 +1548,7 @@ func doRecordGoroutineProfile(gp1 *g, pcbuf []uintptr) {
15701548 // to avoid schedule delays.
15711549 systemstack (func () { saveg (^ uintptr (0 ), ^ uintptr (0 ), gp1 , & goroutineProfile .records [offset ], pcbuf ) })
15721550
1573- if goroutineProfile .labels != nil {
1574- goroutineProfile .labels [offset ] = gp1 .labels
1575- }
1576- }
1577-
1578- func goroutineProfileWithLabelsSync (p []profilerecord.StackRecord , labels []unsafe.Pointer ) (n int , ok bool ) {
1579- gp := getg ()
1580-
1581- isOK := func (gp1 * g ) bool {
1582- // Checking isSystemGoroutine here makes GoroutineProfile
1583- // consistent with both NumGoroutine and Stack.
1584- if gp1 == gp {
1585- return false
1586- }
1587- if status := readgstatus (gp1 ); status == _Gdead || status == _Gdeadextra {
1588- return false
1589- }
1590- if isSystemGoroutine (gp1 , false ) {
1591- return false
1592- }
1593- return true
1594- }
1595-
1596- pcbuf := makeProfStack () // see saveg() for explanation
1597- stw := stopTheWorld (stwGoroutineProfile )
1598-
1599- // World is stopped, no locking required.
1600- n = 1
1601- forEachGRace (func (gp1 * g ) {
1602- if isOK (gp1 ) {
1603- n ++
1604- }
1605- })
1606-
1607- if n <= len (p ) {
1608- ok = true
1609- r , lbl := p , labels
1610-
1611- // Save current goroutine.
1612- sp := sys .GetCallerSP ()
1613- pc := sys .GetCallerPC ()
1614- systemstack (func () {
1615- saveg (pc , sp , gp , & r [0 ], pcbuf )
1616- })
1617- r = r [1 :]
1618-
1619- // If we have a place to put our goroutine labelmap, insert it there.
1620- if labels != nil {
1621- lbl [0 ] = gp .labels
1622- lbl = lbl [1 :]
1623- }
1624-
1625- // Save other goroutines.
1626- forEachGRace (func (gp1 * g ) {
1627- if ! isOK (gp1 ) {
1628- return
1629- }
1630-
1631- if len (r ) == 0 {
1632- // Should be impossible, but better to return a
1633- // truncated profile than to crash the entire process.
1634- return
1635- }
1636- // saveg calls gentraceback, which may call cgo traceback functions.
1637- // The world is stopped, so it cannot use cgocall (which will be
1638- // blocked at exitsyscall). Do it on the system stack so it won't
1639- // call into the schedular (see traceback.go:cgoContextPCs).
1640- systemstack (func () { saveg (^ uintptr (0 ), ^ uintptr (0 ), gp1 , & r [0 ], pcbuf ) })
1641- if labels != nil {
1642- lbl [0 ] = gp1 .labels
1643- lbl = lbl [1 :]
1644- }
1645- r = r [1 :]
1646- })
1647- }
1648-
1649- if raceenabled {
1650- raceacquire (unsafe .Pointer (& labelSync ))
1651- }
1652-
1653- startTheWorld (stw )
1654- return n , ok
1551+ goroutineProfile .records [offset ].Labels = gp1 .labels
16551552}
16561553
16571554// GoroutineProfile returns n, the number of records in the active goroutine stack profile.
@@ -1661,7 +1558,7 @@ func goroutineProfileWithLabelsSync(p []profilerecord.StackRecord, labels []unsa
16611558// Most clients should use the [runtime/pprof] package instead
16621559// of calling GoroutineProfile directly.
16631560func GoroutineProfile (p []StackRecord ) (n int , ok bool ) {
1664- records := make ([]profilerecord.StackRecord , len (p ))
1561+ records := make ([]profilerecord.GoroutineRecord , len (p ))
16651562 n , ok = goroutineProfileInternal (records )
16661563 if ! ok {
16671564 return
@@ -1673,11 +1570,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
16731570 return
16741571}
16751572
1676- func goroutineProfileInternal (p []profilerecord.StackRecord ) (n int , ok bool ) {
1677- return goroutineProfileWithLabels (p , nil )
1678- }
1679-
1680- func saveg (pc , sp uintptr , gp * g , r * profilerecord.StackRecord , pcbuf []uintptr ) {
1573+ func saveg (pc , sp uintptr , gp * g , r * profilerecord.GoroutineRecord , pcbuf []uintptr ) {
16811574 // To reduce memory usage, we want to allocate a r.Stack that is just big
16821575 // enough to hold gp's stack trace. Naively we might achieve this by
16831576 // recording our stack trace into mp.profStack, and then allocating a
0 commit comments