github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/runtime/futex_test.go (about) 1 // Copyright 2013 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 // Futex is only available on DragonFly BSD, FreeBSD and Linux. 6 // The race detector emits calls to split stack functions so it breaks 7 // the test. 8 9 // +build dragonfly freebsd linux 10 // +build !race 11 12 package runtime_test 13 14 import ( 15 "runtime" 16 "sync" 17 "sync/atomic" 18 "testing" 19 "time" 20 ) 21 22 type futexsleepTest struct { 23 mtx uint32 24 ns int64 25 msg string 26 ch chan *futexsleepTest 27 } 28 29 var futexsleepTests = []futexsleepTest{ 30 beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038"}, 31 afterY2038: {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038"}, 32 } 33 34 const ( 35 beforeY2038 = iota 36 afterY2038 37 ) 38 39 func TestFutexsleep(t *testing.T) { 40 if runtime.GOMAXPROCS(0) > 1 { 41 // futexsleep doesn't handle EINTR or other signals, 42 // so spurious wakeups may happen. 43 t.Skip("skipping; GOMAXPROCS>1") 44 } 45 46 start := time.Now() 47 var wg sync.WaitGroup 48 for i := range futexsleepTests { 49 tt := &futexsleepTests[i] 50 tt.mtx = 0 51 tt.ch = make(chan *futexsleepTest, 1) 52 wg.Add(1) 53 go func(tt *futexsleepTest) { 54 runtime.Entersyscall(0) 55 runtime.Futexsleep(&tt.mtx, 0, tt.ns) 56 runtime.Exitsyscall(0) 57 tt.ch <- tt 58 wg.Done() 59 }(tt) 60 } 61 loop: 62 for { 63 select { 64 case tt := <-futexsleepTests[beforeY2038].ch: 65 t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start)) 66 break loop 67 case tt := <-futexsleepTests[afterY2038].ch: 68 // Looks like FreeBSD 10 kernel has changed 69 // the semantics of timedwait on userspace 70 // mutex to make broken stuff look broken. 71 switch { 72 case runtime.GOOS == "freebsd" && runtime.GOARCH == "386": 73 t.Log("freebsd/386 may not work correctly after the year 2038, see golang.org/issue/7194") 74 default: 75 t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start)) 76 break loop 77 } 78 case <-time.After(time.Second): 79 break loop 80 } 81 } 82 for i := range futexsleepTests { 83 tt := &futexsleepTests[i] 84 atomic.StoreUint32(&tt.mtx, 1) 85 runtime.Futexwakeup(&tt.mtx, 1) 86 } 87 wg.Wait() 88 }