github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/sync/mutex_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // GOMAXPROCS=10 go test 6 7 package sync_test 8 9 import ( 10 "runtime" 11 . "sync" 12 "testing" 13 ) 14 15 func HammerSemaphore(s *uint32, loops int, cdone chan bool) { 16 for i := 0; i < loops; i++ { 17 Runtime_Semacquire(s) 18 Runtime_Semrelease(s) 19 } 20 cdone <- true 21 } 22 23 func TestSemaphore(t *testing.T) { 24 s := new(uint32) 25 *s = 1 26 c := make(chan bool) 27 for i := 0; i < 10; i++ { 28 go HammerSemaphore(s, 1000, c) 29 } 30 for i := 0; i < 10; i++ { 31 <-c 32 } 33 } 34 35 func BenchmarkUncontendedSemaphore(b *testing.B) { 36 s := new(uint32) 37 *s = 1 38 HammerSemaphore(s, b.N, make(chan bool, 2)) 39 } 40 41 func BenchmarkContendedSemaphore(b *testing.B) { 42 b.StopTimer() 43 s := new(uint32) 44 *s = 1 45 c := make(chan bool) 46 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) 47 b.StartTimer() 48 49 go HammerSemaphore(s, b.N/2, c) 50 go HammerSemaphore(s, b.N/2, c) 51 <-c 52 <-c 53 } 54 55 func HammerMutex(m *Mutex, loops int, cdone chan bool) { 56 for i := 0; i < loops; i++ { 57 m.Lock() 58 m.Unlock() 59 } 60 cdone <- true 61 } 62 63 func TestMutex(t *testing.T) { 64 m := new(Mutex) 65 c := make(chan bool) 66 for i := 0; i < 10; i++ { 67 go HammerMutex(m, 1000, c) 68 } 69 for i := 0; i < 10; i++ { 70 <-c 71 } 72 } 73 74 func TestMutexPanic(t *testing.T) { 75 defer func() { 76 if recover() == nil { 77 t.Fatalf("unlock of unlocked mutex did not panic") 78 } 79 }() 80 81 var mu Mutex 82 mu.Lock() 83 mu.Unlock() 84 mu.Unlock() 85 } 86 87 func BenchmarkMutexUncontended(b *testing.B) { 88 type PaddedMutex struct { 89 Mutex 90 pad [128]uint8 91 } 92 b.RunParallel(func(pb *testing.PB) { 93 var mu PaddedMutex 94 for pb.Next() { 95 mu.Lock() 96 mu.Unlock() 97 } 98 }) 99 } 100 101 func benchmarkMutex(b *testing.B, slack, work bool) { 102 var mu Mutex 103 if slack { 104 b.SetParallelism(10) 105 } 106 b.RunParallel(func(pb *testing.PB) { 107 foo := 0 108 for pb.Next() { 109 mu.Lock() 110 mu.Unlock() 111 if work { 112 for i := 0; i < 100; i++ { 113 foo *= 2 114 foo /= 2 115 } 116 } 117 } 118 _ = foo 119 }) 120 } 121 122 func BenchmarkMutex(b *testing.B) { 123 benchmarkMutex(b, false, false) 124 } 125 126 func BenchmarkMutexSlack(b *testing.B) { 127 benchmarkMutex(b, true, false) 128 } 129 130 func BenchmarkMutexWork(b *testing.B) { 131 benchmarkMutex(b, false, true) 132 } 133 134 func BenchmarkMutexWorkSlack(b *testing.B) { 135 benchmarkMutex(b, true, true) 136 }