aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/pprof
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-02-18 13:10:34 -0800
committerIan Lance Taylor <iant@golang.org>2022-02-18 13:12:08 -0800
commit20a33efdf32bf0aedcb0c9813ddc7572bb1ab8c7 (patch)
tree94aec72c2092a11fa49f0b45da8e036f13416209 /libgo/go/runtime/pprof
parent1931cbad498e625b1e24452dcfffe02539b12224 (diff)
downloadgcc-20a33efdf32bf0aedcb0c9813ddc7572bb1ab8c7.zip
gcc-20a33efdf32bf0aedcb0c9813ddc7572bb1ab8c7.tar.gz
gcc-20a33efdf32bf0aedcb0c9813ddc7572bb1ab8c7.tar.bz2
libgo: update to Go1.18rc1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/386594
Diffstat (limited to 'libgo/go/runtime/pprof')
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go67
1 files changed, 49 insertions, 18 deletions
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index def49c1..983d4d4 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -798,7 +798,7 @@ func TestBlockProfile(t *testing.T) {
t.Skip("lots of details are different for gccgo; FIXME")
type TestCase struct {
name string
- f func()
+ f func(*testing.T)
stk []string
re string
}
@@ -907,7 +907,7 @@ func TestBlockProfile(t *testing.T) {
runtime.SetBlockProfileRate(1)
defer runtime.SetBlockProfileRate(0)
for _, test := range tests {
- test.f()
+ test.f(t)
}
t.Run("debug=1", func(t *testing.T) {
@@ -983,42 +983,73 @@ func containsStack(got [][]string, want []string) bool {
return false
}
-const blockDelay = 10 * time.Millisecond
+// awaitBlockedGoroutine spins on runtime.Gosched until a runtime stack dump
+// shows a goroutine in the given state with a stack frame in
+// runtime/pprof.<fName>.
+func awaitBlockedGoroutine(t *testing.T, state, fName string) {
+ re := fmt.Sprintf(`(?m)^goroutine \d+ \[%s\]:\n(?:.+\n\t.+\n)*runtime/pprof\.%s`, regexp.QuoteMeta(state), fName)
+ r := regexp.MustCompile(re)
-func blockChanRecv() {
+ if deadline, ok := t.Deadline(); ok {
+ if d := time.Until(deadline); d > 1*time.Second {
+ timer := time.AfterFunc(d-1*time.Second, func() {
+ debug.SetTraceback("all")
+ panic(fmt.Sprintf("timed out waiting for %#q", re))
+ })
+ defer timer.Stop()
+ }
+ }
+
+ buf := make([]byte, 64<<10)
+ for {
+ runtime.Gosched()
+ n := runtime.Stack(buf, true)
+ if n == len(buf) {
+ // Buffer wasn't large enough for a full goroutine dump.
+ // Resize it and try again.
+ buf = make([]byte, 2*len(buf))
+ continue
+ }
+ if r.Match(buf[:n]) {
+ return
+ }
+ }
+}
+
+func blockChanRecv(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan receive", "blockChanRecv")
c <- true
}()
<-c
}
-func blockChanSend() {
+func blockChanSend(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan send", "blockChanSend")
<-c
}()
c <- true
}
-func blockChanClose() {
+func blockChanClose(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan receive", "blockChanClose")
close(c)
}()
<-c
}
-func blockSelectRecvAsync() {
+func blockSelectRecvAsync(t *testing.T) {
const numTries = 3
c := make(chan bool, 1)
c2 := make(chan bool, 1)
go func() {
for i := 0; i < numTries; i++ {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "select", "blockSelectRecvAsync")
c <- true
}
}()
@@ -1030,11 +1061,11 @@ func blockSelectRecvAsync() {
}
}
-func blockSelectSendSync() {
+func blockSelectSendSync(t *testing.T) {
c := make(chan bool)
c2 := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "select", "blockSelectSendSync")
<-c
}()
select {
@@ -1043,11 +1074,11 @@ func blockSelectSendSync() {
}
}
-func blockMutex() {
+func blockMutex(t *testing.T) {
var mu sync.Mutex
mu.Lock()
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "semacquire", "blockMutex")
mu.Unlock()
}()
// Note: Unlock releases mu before recording the mutex event,
@@ -1057,12 +1088,12 @@ func blockMutex() {
mu.Lock()
}
-func blockCond() {
+func blockCond(t *testing.T) {
var mu sync.Mutex
c := sync.NewCond(&mu)
mu.Lock()
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "sync.Cond.Wait", "blockCond")
mu.Lock()
c.Signal()
mu.Unlock()
@@ -1148,7 +1179,7 @@ func TestMutexProfile(t *testing.T) {
t.Fatalf("need MutexProfileRate 0, got %d", old)
}
- blockMutex()
+ blockMutex(t)
t.Run("debug=1", func(t *testing.T) {
var w bytes.Buffer