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
17 // There is a modified copy of this file in runtime/rwmutex_test.go.
18 // If you make any changes here, see if you should make them there.
20 func parallelReader(m
*RWMutex
, clocked
, cunlock
, cdone
chan bool) {
28 func doTestParallelReaders(numReaders
, gomaxprocs
int) {
29 runtime
.GOMAXPROCS(gomaxprocs
)
31 clocked
:= make(chan bool)
32 cunlock
:= make(chan bool)
33 cdone
:= make(chan bool)
34 for i
:= 0; i
< numReaders
; i
++ {
35 go parallelReader(&m
, clocked
, cunlock
, cdone
)
37 // Wait for all parallel RLock()s to succeed.
38 for i
:= 0; i
< numReaders
; i
++ {
41 for i
:= 0; i
< numReaders
; i
++ {
44 // Wait for the goroutines to finish.
45 for i
:= 0; i
< numReaders
; i
++ {
50 func TestParallelReaders(t
*testing
.T
) {
51 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(-1))
52 doTestParallelReaders(1, 4)
53 doTestParallelReaders(3, 4)
54 doTestParallelReaders(4, 2)
57 func reader(rwm
*RWMutex
, num_iterations
int, activity
*int32, cdone
chan bool) {
58 for i
:= 0; i
< num_iterations
; i
++ {
60 n
:= atomic
.AddInt32(activity
, 1)
61 if n
< 1 || n
>= 10000 {
63 panic(fmt
.Sprintf("wlock(%d)\n", n
))
65 for i
:= 0; i
< 100; i
++ {
67 atomic
.AddInt32(activity
, -1)
73 func writer(rwm
*RWMutex
, num_iterations
int, activity
*int32, cdone
chan bool) {
74 for i
:= 0; i
< num_iterations
; i
++ {
76 n
:= atomic
.AddInt32(activity
, 10000)
79 panic(fmt
.Sprintf("wlock(%d)\n", n
))
81 for i
:= 0; i
< 100; i
++ {
83 atomic
.AddInt32(activity
, -10000)
89 func HammerRWMutex(gomaxprocs
, numReaders
, num_iterations
int) {
90 runtime
.GOMAXPROCS(gomaxprocs
)
91 // Number of active readers + 10000 * number of active writers.
94 cdone
:= make(chan bool)
95 go writer(&rwm
, num_iterations
, &activity
, cdone
)
97 for i
= 0; i
< numReaders
/2; i
++ {
98 go reader(&rwm
, num_iterations
, &activity
, cdone
)
100 go writer(&rwm
, num_iterations
, &activity
, cdone
)
101 for ; i
< numReaders
; i
++ {
102 go reader(&rwm
, num_iterations
, &activity
, cdone
)
104 // Wait for the 2 writers and all readers to finish.
105 for i
:= 0; i
< 2+numReaders
; i
++ {
110 func TestRWMutex(t
*testing
.T
) {
115 t
.Fatalf("TryLock succeeded with mutex locked")
118 t
.Fatalf("TryRLock succeeded with mutex locked")
123 t
.Fatalf("TryLock failed with mutex unlocked")
128 t
.Fatalf("TryRLock failed with mutex unlocked")
131 t
.Fatalf("TryRLock failed with mutex rlocked")
134 t
.Fatalf("TryLock succeeded with mutex rlocked")
139 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(-1))
144 HammerRWMutex(1, 1, n
)
145 HammerRWMutex(1, 3, n
)
146 HammerRWMutex(1, 10, n
)
147 HammerRWMutex(4, 1, n
)
148 HammerRWMutex(4, 3, n
)
149 HammerRWMutex(4, 10, n
)
150 HammerRWMutex(10, 1, n
)
151 HammerRWMutex(10, 3, n
)
152 HammerRWMutex(10, 10, n
)
153 HammerRWMutex(10, 5, n
)
156 func TestRLocker(t
*testing
.T
) {
159 wlocked
:= make(chan bool, 1)
160 rlocked
:= make(chan bool, 1)
164 for i
:= 0; i
< n
; i
++ {
172 for i
:= 0; i
< n
; i
++ {
177 t
.Fatal("RLocker() didn't read-lock it")
184 t
.Fatal("RLocker() didn't respect the write lock")
191 func BenchmarkRWMutexUncontended(b
*testing
.B
) {
192 type PaddedRWMutex
struct {
196 b
.RunParallel(func(pb
*testing
.PB
) {
197 var rwm PaddedRWMutex
209 func benchmarkRWMutex(b
*testing
.B
, localWork
, writeRatio
int) {
211 b
.RunParallel(func(pb
*testing
.PB
) {
215 if foo%writeRatio
== 0 {
220 for i
:= 0; i
!= localWork
; i
+= 1 {
231 func BenchmarkRWMutexWrite100(b
*testing
.B
) {
232 benchmarkRWMutex(b
, 0, 100)
235 func BenchmarkRWMutexWrite10(b
*testing
.B
) {
236 benchmarkRWMutex(b
, 0, 10)
239 func BenchmarkRWMutexWorkWrite100(b
*testing
.B
) {
240 benchmarkRWMutex(b
, 100, 100)
243 func BenchmarkRWMutexWorkWrite10(b
*testing
.B
) {
244 benchmarkRWMutex(b
, 100, 10)