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