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
20 func parallelReader(m
*RWMutex
, clocked
chan bool, cunlock
*uint32, cdone
chan bool) {
23 for atomic
.LoadUint32(cunlock
) == 0 {
29 func doTestParallelReaders(numReaders
int) {
30 GOMAXPROCS(numReaders
+ 1)
32 clocked
:= make(chan bool, numReaders
)
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
++ {
42 atomic
.StoreUint32(&cunlock
, 1)
43 // Wait for the goroutines to finish.
44 for i
:= 0; i
< numReaders
; i
++ {
49 func TestParallelRWMutexReaders(t
*testing
.T
) {
51 t
.Skip("wasm has no threads yet")
53 defer GOMAXPROCS(GOMAXPROCS(-1))
54 // If runtime triggers a forced GC during this test then it will deadlock,
55 // since the goroutines can't be stopped/preempted.
56 // Disable GC for this test (see issue #10958).
57 defer debug
.SetGCPercent(debug
.SetGCPercent(-1))
58 doTestParallelReaders(1)
59 doTestParallelReaders(3)
60 doTestParallelReaders(4)
63 func reader(rwm
*RWMutex
, num_iterations
int, activity
*int32, cdone
chan bool) {
64 for i
:= 0; i
< num_iterations
; i
++ {
66 n
:= atomic
.AddInt32(activity
, 1)
67 if n
< 1 || n
>= 10000 {
68 panic(fmt
.Sprintf("wlock(%d)\n", n
))
70 for i
:= 0; i
< 100; i
++ {
72 atomic
.AddInt32(activity
, -1)
78 func writer(rwm
*RWMutex
, num_iterations
int, activity
*int32, cdone
chan bool) {
79 for i
:= 0; i
< num_iterations
; i
++ {
81 n
:= atomic
.AddInt32(activity
, 10000)
83 panic(fmt
.Sprintf("wlock(%d)\n", n
))
85 for i
:= 0; i
< 100; i
++ {
87 atomic
.AddInt32(activity
, -10000)
93 func HammerRWMutex(gomaxprocs
, numReaders
, num_iterations
int) {
94 GOMAXPROCS(gomaxprocs
)
95 // Number of active readers + 10000 * number of active writers.
98 cdone
:= make(chan bool)
99 go writer(&rwm
, num_iterations
, &activity
, cdone
)
101 for i
= 0; i
< numReaders
/2; i
++ {
102 go reader(&rwm
, num_iterations
, &activity
, cdone
)
104 go writer(&rwm
, num_iterations
, &activity
, cdone
)
105 for ; i
< numReaders
; i
++ {
106 go reader(&rwm
, num_iterations
, &activity
, cdone
)
108 // Wait for the 2 writers and all readers to finish.
109 for i
:= 0; i
< 2+numReaders
; i
++ {
114 func TestRWMutex(t
*testing
.T
) {
115 defer GOMAXPROCS(GOMAXPROCS(-1))
120 HammerRWMutex(1, 1, n
)
121 HammerRWMutex(1, 3, n
)
122 HammerRWMutex(1, 10, n
)
123 HammerRWMutex(4, 1, n
)
124 HammerRWMutex(4, 3, n
)
125 HammerRWMutex(4, 10, n
)
126 HammerRWMutex(10, 1, n
)
127 HammerRWMutex(10, 3, n
)
128 HammerRWMutex(10, 10, n
)
129 HammerRWMutex(10, 5, n
)
132 func BenchmarkRWMutexUncontended(b
*testing
.B
) {
133 type PaddedRWMutex
struct {
137 b
.RunParallel(func(pb
*testing
.PB
) {
138 var rwm PaddedRWMutex
150 func benchmarkRWMutex(b
*testing
.B
, localWork
, writeRatio
int) {
152 b
.RunParallel(func(pb
*testing
.PB
) {
156 if foo%writeRatio
== 0 {
161 for i
:= 0; i
!= localWork
; i
+= 1 {
172 func BenchmarkRWMutexWrite100(b
*testing
.B
) {
173 benchmarkRWMutex(b
, 0, 100)
176 func BenchmarkRWMutexWrite10(b
*testing
.B
) {
177 benchmarkRWMutex(b
, 0, 10)
180 func BenchmarkRWMutexWorkWrite100(b
*testing
.B
) {
181 benchmarkRWMutex(b
, 100, 100)
184 func BenchmarkRWMutexWorkWrite10(b
*testing
.B
) {
185 benchmarkRWMutex(b
, 100, 10)