...
Run Format

Source file src/runtime/futex_test.go

Documentation: runtime

  // Copyright 2013 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // Futex is only available on DragonFly BSD, FreeBSD and Linux.
  // The race detector emits calls to split stack functions so it breaks
  // the test.
  
  // +build dragonfly freebsd linux
  // +build !race
  
  package runtime_test
  
  import (
  	"runtime"
  	"sync"
  	"sync/atomic"
  	"testing"
  	"time"
  )
  
  type futexsleepTest struct {
  	mtx uint32
  	ns  int64
  	msg string
  	ch  chan *futexsleepTest
  }
  
  var futexsleepTests = []futexsleepTest{
  	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 (
  	beforeY2038 = iota
  	afterY2038
  )
  
  func TestFutexsleep(t *testing.T) {
  	if runtime.GOMAXPROCS(0) > 1 {
  		// futexsleep doesn't handle EINTR or other signals,
  		// so spurious wakeups may happen.
  		t.Skip("skipping; GOMAXPROCS>1")
  	}
  
  	start := time.Now()
  	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, 0, tt.ns)
  			runtime.Exitsyscall(0)
  			tt.ch <- tt
  			wg.Done()
  		}(tt)
  	}
  loop:
  	for {
  		select {
  		case tt := <-futexsleepTests[beforeY2038].ch:
  			t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start))
  			break loop
  		case tt := <-futexsleepTests[afterY2038].ch:
  			// Looks like FreeBSD 10 kernel has changed
  			// the semantics of timedwait on userspace
  			// mutex to make broken stuff look broken.
  			switch {
  			case runtime.GOOS == "freebsd" && runtime.GOARCH == "386":
  				t.Log("freebsd/386 may not work correctly after the year 2038, see golang.org/issue/7194")
  			default:
  				t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start))
  				break loop
  			}
  		case <-time.After(time.Second):
  			break loop
  		}
  	}
  	for i := range futexsleepTests {
  		tt := &futexsleepTests[i]
  		atomic.StoreUint32(&tt.mtx, 1)
  		runtime.Futexwakeup(&tt.mtx, 1)
  	}
  	wg.Wait()
  }
  

View as plain text