2018-03-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / rwmutex_test.go
blob872b3b098e866b2db4a390b992ea3f6e4224594b
1 // Copyright 2017 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.
5 // GOMAXPROCS=10 go test
7 // This is a copy of sync/rwmutex_test.go rewritten to test the
8 // runtime rwmutex.
10 package runtime_test
12 import (
13 "fmt"
14 . "runtime"
15 "runtime/debug"
16 "sync/atomic"
17 "testing"
20 func parallelReader(m *RWMutex, clocked chan bool, cunlock *uint32, cdone chan bool) {
21 m.RLock()
22 clocked <- true
23 for atomic.LoadUint32(cunlock) == 0 {
25 m.RUnlock()
26 cdone <- true
29 func doTestParallelReaders(numReaders int) {
30 GOMAXPROCS(numReaders + 1)
31 var m RWMutex
32 clocked := make(chan bool, numReaders)
33 var cunlock uint32
34 cdone := make(chan bool)
35 for i := 0; i < numReaders; i++ {
36 go parallelReader(&m, clocked, &cunlock, cdone)
38 // Wait for all parallel RLock()s to succeed.
39 for i := 0; i < numReaders; i++ {
40 <-clocked
42 atomic.StoreUint32(&cunlock, 1)
43 // Wait for the goroutines to finish.
44 for i := 0; i < numReaders; i++ {
45 <-cdone
49 func TestParallelRWMutexReaders(t *testing.T) {
50 defer GOMAXPROCS(GOMAXPROCS(-1))
51 // If runtime triggers a forced GC during this test then it will deadlock,
52 // since the goroutines can't be stopped/preempted.
53 // Disable GC for this test (see issue #10958).
54 defer debug.SetGCPercent(debug.SetGCPercent(-1))
55 doTestParallelReaders(1)
56 doTestParallelReaders(3)
57 doTestParallelReaders(4)
60 func reader(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
61 for i := 0; i < num_iterations; i++ {
62 rwm.RLock()
63 n := atomic.AddInt32(activity, 1)
64 if n < 1 || n >= 10000 {
65 panic(fmt.Sprintf("wlock(%d)\n", n))
67 for i := 0; i < 100; i++ {
69 atomic.AddInt32(activity, -1)
70 rwm.RUnlock()
72 cdone <- true
75 func writer(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
76 for i := 0; i < num_iterations; i++ {
77 rwm.Lock()
78 n := atomic.AddInt32(activity, 10000)
79 if n != 10000 {
80 panic(fmt.Sprintf("wlock(%d)\n", n))
82 for i := 0; i < 100; i++ {
84 atomic.AddInt32(activity, -10000)
85 rwm.Unlock()
87 cdone <- true
90 func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
91 GOMAXPROCS(gomaxprocs)
92 // Number of active readers + 10000 * number of active writers.
93 var activity int32
94 var rwm RWMutex
95 cdone := make(chan bool)
96 go writer(&rwm, num_iterations, &activity, cdone)
97 var i int
98 for i = 0; i < numReaders/2; i++ {
99 go reader(&rwm, num_iterations, &activity, cdone)
101 go writer(&rwm, num_iterations, &activity, cdone)
102 for ; i < numReaders; i++ {
103 go reader(&rwm, num_iterations, &activity, cdone)
105 // Wait for the 2 writers and all readers to finish.
106 for i := 0; i < 2+numReaders; i++ {
107 <-cdone
111 func TestRWMutex(t *testing.T) {
112 defer GOMAXPROCS(GOMAXPROCS(-1))
113 n := 1000
114 if testing.Short() {
115 n = 5
117 HammerRWMutex(1, 1, n)
118 HammerRWMutex(1, 3, n)
119 HammerRWMutex(1, 10, n)
120 HammerRWMutex(4, 1, n)
121 HammerRWMutex(4, 3, n)
122 HammerRWMutex(4, 10, n)
123 HammerRWMutex(10, 1, n)
124 HammerRWMutex(10, 3, n)
125 HammerRWMutex(10, 10, n)
126 HammerRWMutex(10, 5, n)
129 func BenchmarkRWMutexUncontended(b *testing.B) {
130 type PaddedRWMutex struct {
131 RWMutex
132 pad [32]uint32
134 b.RunParallel(func(pb *testing.PB) {
135 var rwm PaddedRWMutex
136 for pb.Next() {
137 rwm.RLock()
138 rwm.RLock()
139 rwm.RUnlock()
140 rwm.RUnlock()
141 rwm.Lock()
142 rwm.Unlock()
147 func benchmarkRWMutex(b *testing.B, localWork, writeRatio int) {
148 var rwm RWMutex
149 b.RunParallel(func(pb *testing.PB) {
150 foo := 0
151 for pb.Next() {
152 foo++
153 if foo%writeRatio == 0 {
154 rwm.Lock()
155 rwm.Unlock()
156 } else {
157 rwm.RLock()
158 for i := 0; i != localWork; i += 1 {
159 foo *= 2
160 foo /= 2
162 rwm.RUnlock()
165 _ = foo
169 func BenchmarkRWMutexWrite100(b *testing.B) {
170 benchmarkRWMutex(b, 0, 100)
173 func BenchmarkRWMutexWrite10(b *testing.B) {
174 benchmarkRWMutex(b, 0, 10)
177 func BenchmarkRWMutexWorkWrite100(b *testing.B) {
178 benchmarkRWMutex(b, 100, 100)
181 func BenchmarkRWMutexWorkWrite10(b *testing.B) {
182 benchmarkRWMutex(b, 100, 10)