Source file
src/runtime/sema_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 . "runtime"
9 "sync"
10 "sync/atomic"
11 "testing"
12 )
13
14
15
16
17
18 func TestSemaHandoff(t *testing.T) {
19 const iter = 10000
20 ok := 0
21 for i := 0; i < iter; i++ {
22 if testSemaHandoff() {
23 ok++
24 }
25 }
26
27
28
29
30
31
32
33
34 if ok < iter*2/3 {
35 t.Fatal("direct handoff < 2/3:", ok, iter)
36 }
37 }
38
39 func TestSemaHandoff1(t *testing.T) {
40 if GOMAXPROCS(-1) <= 1 {
41 t.Skip("GOMAXPROCS <= 1")
42 }
43 defer GOMAXPROCS(GOMAXPROCS(-1))
44 GOMAXPROCS(1)
45 TestSemaHandoff(t)
46 }
47
48 func TestSemaHandoff2(t *testing.T) {
49 if GOMAXPROCS(-1) <= 2 {
50 t.Skip("GOMAXPROCS <= 2")
51 }
52 defer GOMAXPROCS(GOMAXPROCS(-1))
53 GOMAXPROCS(2)
54 TestSemaHandoff(t)
55 }
56
57 func testSemaHandoff() bool {
58 var sema, res uint32
59 done := make(chan struct{})
60
61
62
63
64
65 var wg sync.WaitGroup
66 for i := 0; i < GOMAXPROCS(-1); i++ {
67 wg.Add(1)
68 go func() {
69 defer wg.Done()
70 for {
71 select {
72 case <-done:
73 return
74 default:
75 }
76 Gosched()
77 }
78 }()
79 }
80
81 wg.Add(1)
82 go func() {
83 defer wg.Done()
84 Semacquire(&sema)
85 atomic.CompareAndSwapUint32(&res, 0, 1)
86
87 Semrelease1(&sema, true, 0)
88 close(done)
89 }()
90 for SemNwait(&sema) == 0 {
91 Gosched()
92 }
93
94
95
96
97 Semrelease1(&sema, true, 0)
98 atomic.CompareAndSwapUint32(&res, 0, 2)
99
100 wg.Wait()
101
102 return res == 1
103 }
104
View as plain text