OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / sync / mutex_test.go
index f5c20ca..4775884 100644 (file)
@@ -9,6 +9,7 @@ package sync_test
 import (
        "runtime"
        . "sync"
+       "sync/atomic"
        "testing"
 )
 
@@ -43,7 +44,7 @@ func BenchmarkContendedSemaphore(b *testing.B) {
        s := new(uint32)
        *s = 1
        c := make(chan bool)
-       runtime.GOMAXPROCS(2)
+       defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
        b.StartTimer()
 
        go HammerSemaphore(s, b.N/2, c)
@@ -52,7 +53,6 @@ func BenchmarkContendedSemaphore(b *testing.B) {
        <-c
 }
 
-
 func HammerMutex(m *Mutex, loops int, cdone chan bool) {
        for i := 0; i < loops; i++ {
                m.Lock()
@@ -72,24 +72,6 @@ func TestMutex(t *testing.T) {
        }
 }
 
-func BenchmarkUncontendedMutex(b *testing.B) {
-       m := new(Mutex)
-       HammerMutex(m, b.N, make(chan bool, 2))
-}
-
-func BenchmarkContendedMutex(b *testing.B) {
-       b.StopTimer()
-       m := new(Mutex)
-       c := make(chan bool)
-       runtime.GOMAXPROCS(2)
-       b.StartTimer()
-
-       go HammerMutex(m, b.N/2, c)
-       go HammerMutex(m, b.N/2, c)
-       <-c
-       <-c
-}
-
 func TestMutexPanic(t *testing.T) {
        defer func() {
                if recover() == nil {
@@ -102,3 +84,83 @@ func TestMutexPanic(t *testing.T) {
        mu.Unlock()
        mu.Unlock()
 }
+
+func BenchmarkMutexUncontended(b *testing.B) {
+       type PaddedMutex struct {
+               Mutex
+               pad [128]uint8
+       }
+       const CallsPerSched = 1000
+       procs := runtime.GOMAXPROCS(-1)
+       N := int32(b.N / CallsPerSched)
+       c := make(chan bool, procs)
+       for p := 0; p < procs; p++ {
+               go func() {
+                       var mu PaddedMutex
+                       for atomic.AddInt32(&N, -1) >= 0 {
+                               runtime.Gosched()
+                               for g := 0; g < CallsPerSched; g++ {
+                                       mu.Lock()
+                                       mu.Unlock()
+                               }
+                       }
+                       c <- true
+               }()
+       }
+       for p := 0; p < procs; p++ {
+               <-c
+       }
+}
+
+func benchmarkMutex(b *testing.B, slack, work bool) {
+       const (
+               CallsPerSched  = 1000
+               LocalWork      = 100
+               GoroutineSlack = 10
+       )
+       procs := runtime.GOMAXPROCS(-1)
+       if slack {
+               procs *= GoroutineSlack
+       }
+       N := int32(b.N / CallsPerSched)
+       c := make(chan bool, procs)
+       var mu Mutex
+       for p := 0; p < procs; p++ {
+               go func() {
+                       foo := 0
+                       for atomic.AddInt32(&N, -1) >= 0 {
+                               runtime.Gosched()
+                               for g := 0; g < CallsPerSched; g++ {
+                                       mu.Lock()
+                                       mu.Unlock()
+                                       if work {
+                                               for i := 0; i < LocalWork; i++ {
+                                                       foo *= 2
+                                                       foo /= 2
+                                               }
+                                       }
+                               }
+                       }
+                       c <- foo == 42
+               }()
+       }
+       for p := 0; p < procs; p++ {
+               <-c
+       }
+}
+
+func BenchmarkMutex(b *testing.B) {
+       benchmarkMutex(b, false, false)
+}
+
+func BenchmarkMutexSlack(b *testing.B) {
+       benchmarkMutex(b, true, false)
+}
+
+func BenchmarkMutexWork(b *testing.B) {
+       benchmarkMutex(b, false, true)
+}
+
+func BenchmarkMutexWorkSlack(b *testing.B) {
+       benchmarkMutex(b, true, true)
+}