Source file
src/runtime/sema_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "fmt"
9 . "runtime"
10 "sync"
11 "sync/atomic"
12 "testing"
13 )
14
15
16
17
18
19 func TestSemaHandoff(t *testing.T) {
20 const iter = 10000
21 ok := 0
22 for i := 0; i < iter; i++ {
23 if testSemaHandoff() {
24 ok++
25 }
26 }
27
28
29
30
31
32
33
34
35 if ok < iter*2/3 {
36 t.Fatal("direct handoff < 2/3:", ok, iter)
37 }
38 }
39
40 func TestSemaHandoff1(t *testing.T) {
41 if GOMAXPROCS(-1) <= 1 {
42 t.Skip("GOMAXPROCS <= 1")
43 }
44 defer GOMAXPROCS(GOMAXPROCS(-1))
45 GOMAXPROCS(1)
46 TestSemaHandoff(t)
47 }
48
49 func TestSemaHandoff2(t *testing.T) {
50 if GOMAXPROCS(-1) <= 2 {
51 t.Skip("GOMAXPROCS <= 2")
52 }
53 defer GOMAXPROCS(GOMAXPROCS(-1))
54 GOMAXPROCS(2)
55 TestSemaHandoff(t)
56 }
57
58 func testSemaHandoff() bool {
59 var sema, res uint32
60 done := make(chan struct{})
61
62
63
64
65
66 var wg sync.WaitGroup
67 for i := 0; i < GOMAXPROCS(-1); i++ {
68 wg.Add(1)
69 go func() {
70 defer wg.Done()
71 for {
72 select {
73 case <-done:
74 return
75 default:
76 }
77 Gosched()
78 }
79 }()
80 }
81
82 wg.Add(1)
83 go func() {
84 defer wg.Done()
85 Semacquire(&sema)
86 atomic.CompareAndSwapUint32(&res, 0, 1)
87
88 Semrelease1(&sema, true, 0)
89 close(done)
90 }()
91 for SemNwait(&sema) == 0 {
92 Gosched()
93 }
94
95
96
97
98 Semrelease1(&sema, true, 0)
99 atomic.CompareAndSwapUint32(&res, 0, 2)
100
101 wg.Wait()
102
103 return res == 1
104 }
105
106 func BenchmarkSemTable(b *testing.B) {
107 for _, n := range []int{1000, 2000, 4000, 8000} {
108 b.Run(fmt.Sprintf("OneAddrCollision/n=%d", n), func(b *testing.B) {
109 tab := Escape(new(SemTable))
110 u := make([]uint32, SemTableSize+1)
111
112 b.ResetTimer()
113
114 for j := 0; j < b.N; j++ {
115
116
117
118
119
120
121
122
123
124
125
126
127 for i := 0; i < n; i++ {
128 if i < n/2 {
129 tab.Enqueue(&u[0])
130 } else {
131 tab.Enqueue(&u[SemTableSize])
132 }
133 }
134 for i := 0; i < n; i++ {
135 var ok bool
136 if i < n/2 {
137 ok = tab.Dequeue(&u[0])
138 } else {
139 ok = tab.Dequeue(&u[SemTableSize])
140 }
141 if !ok {
142 b.Fatal("failed to dequeue")
143 }
144 }
145 }
146 })
147 b.Run(fmt.Sprintf("ManyAddrCollision/n=%d", n), func(b *testing.B) {
148 tab := Escape(new(SemTable))
149 u := make([]uint32, n*SemTableSize)
150
151 b.ResetTimer()
152
153 for j := 0; j < b.N; j++ {
154
155
156
157
158
159 for i := 0; i < n; i++ {
160 tab.Enqueue(&u[i*SemTableSize])
161 }
162 for i := 0; i < n; i++ {
163 if !tab.Dequeue(&u[i*SemTableSize]) {
164 b.Fatal("failed to dequeue")
165 }
166 }
167 }
168 })
169 }
170 }
171
View as plain text