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