OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / sync / mutex_test.go
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.
4
5 // GOMAXPROCS=10 gotest
6
7 package sync_test
8
9 import (
10         "runtime"
11         . "sync"
12         "sync/atomic"
13         "testing"
14 )
15
16 func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
17         for i := 0; i < loops; i++ {
18                 runtime.Semacquire(s)
19                 runtime.Semrelease(s)
20         }
21         cdone <- true
22 }
23
24 func TestSemaphore(t *testing.T) {
25         s := new(uint32)
26         *s = 1
27         c := make(chan bool)
28         for i := 0; i < 10; i++ {
29                 go HammerSemaphore(s, 1000, c)
30         }
31         for i := 0; i < 10; i++ {
32                 <-c
33         }
34 }
35
36 func BenchmarkUncontendedSemaphore(b *testing.B) {
37         s := new(uint32)
38         *s = 1
39         HammerSemaphore(s, b.N, make(chan bool, 2))
40 }
41
42 func BenchmarkContendedSemaphore(b *testing.B) {
43         b.StopTimer()
44         s := new(uint32)
45         *s = 1
46         c := make(chan bool)
47         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
48         b.StartTimer()
49
50         go HammerSemaphore(s, b.N/2, c)
51         go HammerSemaphore(s, b.N/2, c)
52         <-c
53         <-c
54 }
55
56 func HammerMutex(m *Mutex, loops int, cdone chan bool) {
57         for i := 0; i < loops; i++ {
58                 m.Lock()
59                 m.Unlock()
60         }
61         cdone <- true
62 }
63
64 func TestMutex(t *testing.T) {
65         m := new(Mutex)
66         c := make(chan bool)
67         for i := 0; i < 10; i++ {
68                 go HammerMutex(m, 1000, c)
69         }
70         for i := 0; i < 10; i++ {
71                 <-c
72         }
73 }
74
75 func TestMutexPanic(t *testing.T) {
76         defer func() {
77                 if recover() == nil {
78                         t.Fatalf("unlock of unlocked mutex did not panic")
79                 }
80         }()
81
82         var mu Mutex
83         mu.Lock()
84         mu.Unlock()
85         mu.Unlock()
86 }
87
88 func BenchmarkMutexUncontended(b *testing.B) {
89         type PaddedMutex struct {
90                 Mutex
91                 pad [128]uint8
92         }
93         const CallsPerSched = 1000
94         procs := runtime.GOMAXPROCS(-1)
95         N := int32(b.N / CallsPerSched)
96         c := make(chan bool, procs)
97         for p := 0; p < procs; p++ {
98                 go func() {
99                         var mu PaddedMutex
100                         for atomic.AddInt32(&N, -1) >= 0 {
101                                 runtime.Gosched()
102                                 for g := 0; g < CallsPerSched; g++ {
103                                         mu.Lock()
104                                         mu.Unlock()
105                                 }
106                         }
107                         c <- true
108                 }()
109         }
110         for p := 0; p < procs; p++ {
111                 <-c
112         }
113 }
114
115 func benchmarkMutex(b *testing.B, slack, work bool) {
116         const (
117                 CallsPerSched  = 1000
118                 LocalWork      = 100
119                 GoroutineSlack = 10
120         )
121         procs := runtime.GOMAXPROCS(-1)
122         if slack {
123                 procs *= GoroutineSlack
124         }
125         N := int32(b.N / CallsPerSched)
126         c := make(chan bool, procs)
127         var mu Mutex
128         for p := 0; p < procs; p++ {
129                 go func() {
130                         foo := 0
131                         for atomic.AddInt32(&N, -1) >= 0 {
132                                 runtime.Gosched()
133                                 for g := 0; g < CallsPerSched; g++ {
134                                         mu.Lock()
135                                         mu.Unlock()
136                                         if work {
137                                                 for i := 0; i < LocalWork; i++ {
138                                                         foo *= 2
139                                                         foo /= 2
140                                                 }
141                                         }
142                                 }
143                         }
144                         c <- foo == 42
145                 }()
146         }
147         for p := 0; p < procs; p++ {
148                 <-c
149         }
150 }
151
152 func BenchmarkMutex(b *testing.B) {
153         benchmarkMutex(b, false, false)
154 }
155
156 func BenchmarkMutexSlack(b *testing.B) {
157         benchmarkMutex(b, true, false)
158 }
159
160 func BenchmarkMutexWork(b *testing.B) {
161         benchmarkMutex(b, false, true)
162 }
163
164 func BenchmarkMutexWorkSlack(b *testing.B) {
165         benchmarkMutex(b, true, true)
166 }