diff options
Diffstat (limited to 'libgo/go/time/sleep_test.go')
-rw-r--r-- | libgo/go/time/sleep_test.go | 124 |
1 files changed, 106 insertions, 18 deletions
diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go index 762549d3a4d..cb09a84469e 100644 --- a/libgo/go/time/sleep_test.go +++ b/libgo/go/time/sleep_test.go @@ -9,6 +9,7 @@ import ( "fmt" "runtime" "sort" + "sync" "sync/atomic" "testing" . "time" @@ -68,33 +69,94 @@ func TestAfterStress(t *testing.T) { atomic.StoreUint32(&stop, 1) } +func benchmark(b *testing.B, bench func(n int)) { + garbage := make([]*Timer, 1<<17) + for i := 0; i < len(garbage); i++ { + garbage[i] = AfterFunc(Hour, nil) + } + + const batch = 1000 + P := runtime.GOMAXPROCS(-1) + N := int32(b.N / batch) + + b.ResetTimer() + + var wg sync.WaitGroup + wg.Add(P) + + for p := 0; p < P; p++ { + go func() { + for atomic.AddInt32(&N, -1) >= 0 { + bench(batch) + } + wg.Done() + }() + } + + wg.Wait() + + b.StopTimer() + for i := 0; i < len(garbage); i++ { + garbage[i].Stop() + } +} + func BenchmarkAfterFunc(b *testing.B) { - i := b.N - c := make(chan bool) - var f func() - f = func() { - i-- - if i >= 0 { - AfterFunc(0, f) - } else { - c <- true + benchmark(b, func(n int) { + c := make(chan bool) + var f func() + f = func() { + n-- + if n >= 0 { + AfterFunc(0, f) + } else { + c <- true + } } - } - AfterFunc(0, f) - <-c + AfterFunc(0, f) + <-c + }) } func BenchmarkAfter(b *testing.B) { - for i := 0; i < b.N; i++ { - <-After(1) - } + benchmark(b, func(n int) { + for i := 0; i < n; i++ { + <-After(1) + } + }) } func BenchmarkStop(b *testing.B) { - for i := 0; i < b.N; i++ { - NewTimer(1 * Second).Stop() - } + benchmark(b, func(n int) { + for i := 0; i < n; i++ { + NewTimer(1 * Second).Stop() + } + }) +} + +func BenchmarkSimultaneousAfterFunc(b *testing.B) { + benchmark(b, func(n int) { + var wg sync.WaitGroup + wg.Add(n) + for i := 0; i < n; i++ { + AfterFunc(0, wg.Done) + } + wg.Wait() + }) +} + +func BenchmarkStartStop(b *testing.B) { + benchmark(b, func(n int) { + timers := make([]*Timer, n) + for i := 0; i < n; i++ { + timers[i] = AfterFunc(Hour, nil) + } + + for i := 0; i < n; i++ { + timers[i].Stop() + } + }) } func TestAfter(t *testing.T) { @@ -315,3 +377,29 @@ func TestOverflowSleep(t *testing.T) { t.Fatalf("negative timeout didn't fire") } } + +// Test that a panic while deleting a timer does not leave +// the timers mutex held, deadlocking a ticker.Stop in a defer. +func TestIssue5745(t *testing.T) { + ticker := NewTicker(Hour) + defer func() { + // would deadlock here before the fix due to + // lock taken before the segfault. + ticker.Stop() + + if r := recover(); r == nil { + t.Error("Expected panic, but none happened.") + } + }() + + // cause a panic due to a segfault + var timer *Timer + timer.Stop() + t.Error("Should be unreachable.") +} + +func TestOverflowRuntimeTimer(t *testing.T) { + if err := CheckRuntimeTimerOverflow(); err != nil { + t.Fatalf(err.Error()) + } +} |