Implement -freuse-stack= option
[official-gcc.git] / libgo / go / sync / rwmutex_test.go
blob39d5d6540de7853680e6f813983508436ea1fab6
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.
5 // GOMAXPROCS=10 go test
7 package sync_test
9 import (
10 "fmt"
11 "runtime"
12 . "sync"
13 "sync/atomic"
14 "testing"
17 func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
18 m.RLock()
19 clocked <- true
20 <-cunlock
21 m.RUnlock()
22 cdone <- true
25 func doTestParallelReaders(numReaders, gomaxprocs int) {
26 runtime.GOMAXPROCS(gomaxprocs)
27 var m RWMutex
28 clocked := make(chan bool)
29 cunlock := make(chan bool)
30 cdone := make(chan bool)
31 for i := 0; i < numReaders; i++ {
32 go parallelReader(&m, clocked, cunlock, cdone)
34 // Wait for all parallel RLock()s to succeed.
35 for i := 0; i < numReaders; i++ {
36 <-clocked
38 for i := 0; i < numReaders; i++ {
39 cunlock <- true
41 // Wait for the goroutines to finish.
42 for i := 0; i < numReaders; i++ {
43 <-cdone
47 func TestParallelReaders(t *testing.T) {
48 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
49 doTestParallelReaders(1, 4)
50 doTestParallelReaders(3, 4)
51 doTestParallelReaders(4, 2)
54 func reader(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
55 for i := 0; i < num_iterations; i++ {
56 rwm.RLock()
57 n := atomic.AddInt32(activity, 1)
58 if n < 1 || n >= 10000 {
59 panic(fmt.Sprintf("wlock(%d)\n", n))
61 for i := 0; i < 100; i++ {
63 atomic.AddInt32(activity, -1)
64 rwm.RUnlock()
66 cdone <- true
69 func writer(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
70 for i := 0; i < num_iterations; i++ {
71 rwm.Lock()
72 n := atomic.AddInt32(activity, 10000)
73 if n != 10000 {
74 panic(fmt.Sprintf("wlock(%d)\n", n))
76 for i := 0; i < 100; i++ {
78 atomic.AddInt32(activity, -10000)
79 rwm.Unlock()
81 cdone <- true
84 func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
85 runtime.GOMAXPROCS(gomaxprocs)
86 // Number of active readers + 10000 * number of active writers.
87 var activity int32
88 var rwm RWMutex
89 cdone := make(chan bool)
90 go writer(&rwm, num_iterations, &activity, cdone)
91 var i int
92 for i = 0; i < numReaders/2; i++ {
93 go reader(&rwm, num_iterations, &activity, cdone)
95 go writer(&rwm, num_iterations, &activity, cdone)
96 for ; i < numReaders; i++ {
97 go reader(&rwm, num_iterations, &activity, cdone)
99 // Wait for the 2 writers and all readers to finish.
100 for i := 0; i < 2+numReaders; i++ {
101 <-cdone
105 func TestRWMutex(t *testing.T) {
106 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
107 n := 1000
108 if testing.Short() {
109 n = 5
111 HammerRWMutex(1, 1, n)
112 HammerRWMutex(1, 3, n)
113 HammerRWMutex(1, 10, n)
114 HammerRWMutex(4, 1, n)
115 HammerRWMutex(4, 3, n)
116 HammerRWMutex(4, 10, n)
117 HammerRWMutex(10, 1, n)
118 HammerRWMutex(10, 3, n)
119 HammerRWMutex(10, 10, n)
120 HammerRWMutex(10, 5, n)
123 func TestRLocker(t *testing.T) {
124 var wl RWMutex
125 var rl Locker
126 wlocked := make(chan bool, 1)
127 rlocked := make(chan bool, 1)
128 rl = wl.RLocker()
129 n := 10
130 go func() {
131 for i := 0; i < n; i++ {
132 rl.Lock()
133 rl.Lock()
134 rlocked <- true
135 wl.Lock()
136 wlocked <- true
139 for i := 0; i < n; i++ {
140 <-rlocked
141 rl.Unlock()
142 select {
143 case <-wlocked:
144 t.Fatal("RLocker() didn't read-lock it")
145 default:
147 rl.Unlock()
148 <-wlocked
149 select {
150 case <-rlocked:
151 t.Fatal("RLocker() didn't respect the write lock")
152 default:
154 wl.Unlock()
158 func BenchmarkRWMutexUncontended(b *testing.B) {
159 type PaddedRWMutex struct {
160 RWMutex
161 pad [32]uint32
163 const CallsPerSched = 1000
164 procs := runtime.GOMAXPROCS(-1)
165 N := int32(b.N / CallsPerSched)
166 c := make(chan bool, procs)
167 for p := 0; p < procs; p++ {
168 go func() {
169 var rwm PaddedRWMutex
170 for atomic.AddInt32(&N, -1) >= 0 {
171 runtime.Gosched()
172 for g := 0; g < CallsPerSched; g++ {
173 rwm.RLock()
174 rwm.RLock()
175 rwm.RUnlock()
176 rwm.RUnlock()
177 rwm.Lock()
178 rwm.Unlock()
181 c <- true
184 for p := 0; p < procs; p++ {
189 func benchmarkRWMutex(b *testing.B, localWork, writeRatio int) {
190 const CallsPerSched = 1000
191 procs := runtime.GOMAXPROCS(-1)
192 N := int32(b.N / CallsPerSched)
193 c := make(chan bool, procs)
194 var rwm RWMutex
195 for p := 0; p < procs; p++ {
196 go func() {
197 foo := 0
198 for atomic.AddInt32(&N, -1) >= 0 {
199 runtime.Gosched()
200 for g := 0; g < CallsPerSched; g++ {
201 foo++
202 if foo%writeRatio == 0 {
203 rwm.Lock()
204 rwm.Unlock()
205 } else {
206 rwm.RLock()
207 for i := 0; i != localWork; i += 1 {
208 foo *= 2
209 foo /= 2
211 rwm.RUnlock()
215 c <- foo == 42
218 for p := 0; p < procs; p++ {
223 func BenchmarkRWMutexWrite100(b *testing.B) {
224 benchmarkRWMutex(b, 0, 100)
227 func BenchmarkRWMutexWrite10(b *testing.B) {
228 benchmarkRWMutex(b, 0, 10)
231 func BenchmarkRWMutexWorkWrite100(b *testing.B) {
232 benchmarkRWMutex(b, 100, 100)
235 func BenchmarkRWMutexWorkWrite10(b *testing.B) {
236 benchmarkRWMutex(b, 100, 10)