2014-04-11 Marc Glisse <marc.glisse@inria.fr>
[official-gcc.git] / libgo / go / sync / mutex_test.go
blobbf78c6f609ca67c7e0ce42822521900dc089ac61
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
7 package sync_test
9 import (
10 "runtime"
11 . "sync"
12 "sync/atomic"
13 "testing"
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)
21 cdone <- true
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)
31 for i := 0; i < 10; i++ {
32 <-c
36 func BenchmarkUncontendedSemaphore(b *testing.B) {
37 s := new(uint32)
38 *s = 1
39 HammerSemaphore(s, b.N, make(chan bool, 2))
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()
50 go HammerSemaphore(s, b.N/2, c)
51 go HammerSemaphore(s, b.N/2, c)
52 <-c
53 <-c
56 func HammerMutex(m *Mutex, loops int, cdone chan bool) {
57 for i := 0; i < loops; i++ {
58 m.Lock()
59 m.Unlock()
61 cdone <- true
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)
70 for i := 0; i < 10; i++ {
71 <-c
75 func TestMutexPanic(t *testing.T) {
76 defer func() {
77 if recover() == nil {
78 t.Fatalf("unlock of unlocked mutex did not panic")
80 }()
82 var mu Mutex
83 mu.Lock()
84 mu.Unlock()
85 mu.Unlock()
88 func BenchmarkMutexUncontended(b *testing.B) {
89 type PaddedMutex struct {
90 Mutex
91 pad [128]uint8
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()
107 c <- true
110 for p := 0; p < procs; p++ {
115 func benchmarkMutex(b *testing.B, slack, work bool) {
116 const (
117 CallsPerSched = 1000
118 LocalWork = 100
119 GoroutineSlack = 10
121 procs := runtime.GOMAXPROCS(-1)
122 if slack {
123 procs *= GoroutineSlack
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
144 c <- foo == 42
147 for p := 0; p < procs; p++ {
152 func BenchmarkMutex(b *testing.B) {
153 benchmarkMutex(b, false, false)
156 func BenchmarkMutexSlack(b *testing.B) {
157 benchmarkMutex(b, true, false)
160 func BenchmarkMutexWork(b *testing.B) {
161 benchmarkMutex(b, false, true)
164 func BenchmarkMutexWorkSlack(b *testing.B) {
165 benchmarkMutex(b, true, true)