diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-17 22:10:58 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-17 22:10:58 +0000 |
commit | 956a9d3770ca7cfcec334147c98e26bc00d044e0 (patch) | |
tree | a190311458c423b71ed9f800fd5bd43faa7dccc3 /libgo/go/runtime | |
parent | 13be6c20301280dbd9172dc0fac31a6ed9c1e8e2 (diff) | |
download | gcc-956a9d3770ca7cfcec334147c98e26bc00d044e0.tar.gz |
libgo: update to Go 1.8.1 release
Reviewed-on: https://go-review.googlesource.com/40775
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@246957 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/runtime')
-rw-r--r-- | libgo/go/runtime/crash_unix_test.go | 73 | ||||
-rw-r--r-- | libgo/go/runtime/export_test.go | 13 | ||||
-rw-r--r-- | libgo/go/runtime/runtime1.go | 6 | ||||
-rw-r--r-- | libgo/go/runtime/sema.go | 1 |
4 files changed, 93 insertions, 0 deletions
diff --git a/libgo/go/runtime/crash_unix_test.go b/libgo/go/runtime/crash_unix_test.go index 97deed8b9d9..182c84b6392 100644 --- a/libgo/go/runtime/crash_unix_test.go +++ b/libgo/go/runtime/crash_unix_test.go @@ -9,6 +9,7 @@ package runtime_test import ( "bytes" "internal/testenv" + "io" "io/ioutil" "os" "os/exec" @@ -153,6 +154,78 @@ func loop(i int, c chan bool) { } ` +func TestPanicSystemstack(t *testing.T) { + // Test that GOTRACEBACK=crash prints both the system and user + // stack of other threads. + + // The GOTRACEBACK=crash handler takes 0.1 seconds even if + // it's not writing a core file and potentially much longer if + // it is. Skip in short mode. + if testing.Short() { + t.Skip("Skipping in short mode (GOTRACEBACK=crash is slow)") + } + + t.Parallel() + cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal") + cmd = testEnv(cmd) + cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") + pr, pw, err := os.Pipe() + if err != nil { + t.Fatal("creating pipe: ", err) + } + cmd.Stderr = pw + if err := cmd.Start(); err != nil { + t.Fatal("starting command: ", err) + } + defer cmd.Process.Wait() + defer cmd.Process.Kill() + if err := pw.Close(); err != nil { + t.Log("closing write pipe: ", err) + } + defer pr.Close() + + // Wait for "x\nx\n" to indicate readiness. + buf := make([]byte, 4) + _, err = io.ReadFull(pr, buf) + if err != nil || string(buf) != "x\nx\n" { + t.Fatal("subprocess failed; output:\n", string(buf)) + } + + // Send SIGQUIT. + if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil { + t.Fatal("signaling subprocess: ", err) + } + + // Get traceback. + tb, err := ioutil.ReadAll(pr) + if err != nil { + t.Fatal("reading traceback from pipe: ", err) + } + + // Traceback should have two testPanicSystemstackInternal's + // and two blockOnSystemStackInternal's. + if bytes.Count(tb, []byte("testPanicSystemstackInternal")) != 2 { + t.Fatal("traceback missing user stack:\n", string(tb)) + } else if bytes.Count(tb, []byte("blockOnSystemStackInternal")) != 2 { + t.Fatal("traceback missing system stack:\n", string(tb)) + } +} + +func init() { + if len(os.Args) >= 2 && os.Args[1] == "testPanicSystemstackInternal" { + // Get two threads running on the system stack with + // something recognizable in the stack trace. + runtime.GOMAXPROCS(2) + go testPanicSystemstackInternal() + testPanicSystemstackInternal() + } +} + +func testPanicSystemstackInternal() { + runtime.BlockOnSystemStack() + os.Exit(1) // Should be unreachable. +} + func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) exe, err := buildTestProg(t, "testprog") diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go index fcc1e6199a4..cc4b188b60c 100644 --- a/libgo/go/runtime/export_test.go +++ b/libgo/go/runtime/export_test.go @@ -243,3 +243,16 @@ func CountPagesInUse() (pagesInUse, counted uintptr) { return } */ + +// BlockOnSystemStack switches to the system stack, prints "x\n" to +// stderr, and blocks in a stack containing +// "runtime.blockOnSystemStackInternal". +func BlockOnSystemStack() { + systemstack(blockOnSystemStackInternal) +} + +func blockOnSystemStackInternal() { + print("x\n") + lock(&deadlock) + lock(&deadlock) +} diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go index a41cfc81181..99c0f11930f 100644 --- a/libgo/go/runtime/runtime1.go +++ b/libgo/go/runtime/runtime1.go @@ -280,6 +280,12 @@ func check() { throw("atomicor8") } + m = [4]byte{0xff, 0xff, 0xff, 0xff} + atomic.And8(&m[1], 0x1) + if m[0] != 0xff || m[1] != 0x1 || m[2] != 0xff || m[3] != 0xff { + throw("atomicand8") + } + *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0) if j == j { throw("float64nan") diff --git a/libgo/go/runtime/sema.go b/libgo/go/runtime/sema.go index 576a1fb7a20..37318ff9d55 100644 --- a/libgo/go/runtime/sema.go +++ b/libgo/go/runtime/sema.go @@ -171,6 +171,7 @@ func semrelease(addr *uint32) { for x := root.head; x != nil; x = x.next { if x.elem == unsafe.Pointer(addr) { x.acquiretime = t0 + break } } mutexevent(t0-s.acquiretime, 3) |