aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/futex_test.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2016-01-13 15:14:26 -0500
committerAustin Clements <austin@google.com>2016-01-14 03:47:49 +0000
commit8319c578906249ce0871a485acb2334a6cf54d6c (patch)
treeef8446fe2959760d37a8f35eced0bfbbc5e8416c /src/runtime/futex_test.go
parent8534429181ea99c86a5ccefee508f573ae6d4ba2 (diff)
downloadgo-8319c578906249ce0871a485acb2334a6cf54d6c.tar.gz
go-8319c578906249ce0871a485acb2334a6cf54d6c.zip
runtime: fix several issues in TestFutexsleep
TestFutexsleep is supposed to clean up before returning by waking up the goroutines it started and left blocked in futex sleeps. However, it currently fails at this in several ways: 1. Both the sleep and wakeup are done on the address of tt.mtx, but in both cases tt is a *local copy* of the futexsleepTest created by a loop, so the sleep and wakeup happen on completely different addresses. Fix this by making them both use the address of the global tt.mtx. 2. If the sleep happens after the wakeup (not likely, but not impossible), it won't wake up. Fix this by using the futex protocol properly: sleep if the mutex's value is 0, and set the mutex's value to non-zero before doing the wakeup. 3. If TestFutexsleep runs more than once, channels and mutex values left over from the first run will interfere with later runs. Fix this by clearing the mutex value and creating a new channel for each test and waiting for goroutines to finish before returning (lest they send their completion to the channel for the next run). As an added bonus, this test now actually tests that futex sleep/wakeup work. Previously this test would have been satisfied if futexsleep was an infinite loop and futexwakeup was a no-op. Change-Id: I1cbc6871cc9dcb8f4601b3621913bec2b79b0fc3 Reviewed-on: https://go-review.googlesource.com/18617 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Diffstat (limited to 'src/runtime/futex_test.go')
-rw-r--r--src/runtime/futex_test.go25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/runtime/futex_test.go b/src/runtime/futex_test.go
index b85249a548..8504396e1a 100644
--- a/src/runtime/futex_test.go
+++ b/src/runtime/futex_test.go
@@ -13,6 +13,8 @@ package runtime_test
import (
"runtime"
+ "sync"
+ "sync/atomic"
"testing"
"time"
)
@@ -21,12 +23,12 @@ type futexsleepTest struct {
mtx uint32
ns int64
msg string
- ch chan futexsleepTest
+ ch chan *futexsleepTest
}
var futexsleepTests = []futexsleepTest{
- beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038", ch: make(chan futexsleepTest, 1)},
- afterY2038: {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038", ch: make(chan futexsleepTest, 1)},
+ beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038"},
+ afterY2038: {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038"},
}
const (
@@ -42,12 +44,18 @@ func TestFutexsleep(t *testing.T) {
}
start := time.Now()
- for _, tt := range futexsleepTests {
- go func(tt futexsleepTest) {
+ var wg sync.WaitGroup
+ for i := range futexsleepTests {
+ tt := &futexsleepTests[i]
+ tt.mtx = 0
+ tt.ch = make(chan *futexsleepTest, 1)
+ wg.Add(1)
+ go func(tt *futexsleepTest) {
runtime.Entersyscall(0)
- runtime.Futexsleep(&tt.mtx, tt.mtx, tt.ns)
+ runtime.Futexsleep(&tt.mtx, 0, tt.ns)
runtime.Exitsyscall(0)
tt.ch <- tt
+ wg.Done()
}(tt)
}
loop:
@@ -71,7 +79,10 @@ loop:
break loop
}
}
- for _, tt := range futexsleepTests {
+ for i := range futexsleepTests {
+ tt := &futexsleepTests[i]
+ atomic.StoreUint32(&tt.mtx, 1)
runtime.Futexwakeup(&tt.mtx, 1)
}
+ wg.Wait()
}