From: Xiangdong Ji Date: Wed, 5 Aug 2020 06:02:58 +0000 (+0000) Subject: cmd/dist: fix build failure of misc/cgo/test on arm64 X-Git-Tag: archive/raspbian/1.15.6-1+rpi1^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=8142d8010ea9fc25241f5c8509634ef84cd97580;p=golang-1.15.git cmd/dist: fix build failure of misc/cgo/test on arm64 Test7978 of misc/cgo/test fails in 'dist test' on arm64 if the C compiler is of GCC-9.4 or above and its 'outline atomics' feature is enabled, since the internal linking hasn't yet supported "__attribute__((constructor))" and also mis-handles hidden visibility. Two changes are made for 'misc/cgo/test' to fix the issue: 1. passing "-tags=internal" for the internal linking PIE case. 2. skipping Test7978 on arm64 for the internal linking cases. This CL fixes 'dist test' failure only, user is expected to pass the option '-mno-outline-atomics' via CGO_CFLAGS if running into the same problem when building cgo program using internal linking. Updates #39466 Change-Id: I2011bb051cae7c43eb0f1c78c7f4fbdb94bf78a6 Gbp-Pq: Name 0004-cmd-dist-fix-build-failure-of-misc-cgo-test-on-arm64.patch --- diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go new file mode 100644 index 00000000..18d418fd --- /dev/null +++ b/misc/cgo/test/issue7978.go @@ -0,0 +1,117 @@ +// Copyright 2020 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. + +// +build !arm64 !internal + +package cgotest + +import ( + "runtime" + "runtime/debug" + "strings" + "sync/atomic" + "testing" +) + +/* +#include + +void issue7978cb(void); + +// use ugly atomic variable sync since that doesn't require calling back into +// Go code or OS dependencies +static void issue7978c(uint32_t *sync) { + while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0) + ; + __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST); + while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2) + ; + issue7978cb(); + __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST); + while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6) + ; +} + +*/ +import "C" + +// issue 7978 + +var issue7978sync uint32 + +func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) { + runtime.GC() + buf := make([]byte, 65536) + trace := string(buf[:runtime.Stack(buf, true)]) + for _, goroutine := range strings.Split(trace, "\n\n") { + if strings.Contains(goroutine, "test.issue7978go") { + trace := strings.Split(goroutine, "\n") + // look for the expected function in the stack + for i := 0; i < depth; i++ { + if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) { + t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine) + return + } + if strings.Contains(trace[1+2*i], wantFunc) { + return + } + } + t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine) + return + } + } + t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace) +} + +func issue7978wait(store uint32, wait uint32) { + if store != 0 { + atomic.StoreUint32(&issue7978sync, store) + } + for atomic.LoadUint32(&issue7978sync) != wait { + runtime.Gosched() + } +} + +//export issue7978cb +func issue7978cb() { + // Force a stack growth from the callback to put extra + // pressure on the runtime. See issue #17785. + growStack(64) + issue7978wait(3, 4) +} + +func growStack(n int) int { + var buf [128]int + if n == 0 { + return 0 + } + return buf[growStack(n-1)] +} + +func issue7978go() { + C.issue7978c((*C.uint32_t)(&issue7978sync)) + issue7978wait(7, 8) +} + +func test7978(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gccgo can not do stack traces of C code") + } + debug.SetTraceback("2") + issue7978sync = 0 + go issue7978go() + // test in c code, before callback + issue7978wait(0, 1) + issue7978check(t, "_Cfunc_issue7978c(", "", 1) + // test in go code, during callback + issue7978wait(2, 3) + issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) + // test in c code, after callback + issue7978wait(4, 5) + issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1) + // test in go code, after return from cgo + issue7978wait(6, 7) + issue7978check(t, "test.issue7978go(", "", 3) + atomic.StoreUint32(&issue7978sync, 8) +} diff --git a/misc/cgo/test/issue7978b.go b/misc/cgo/test/issue7978b.go new file mode 100644 index 00000000..3ab11ee8 --- /dev/null +++ b/misc/cgo/test/issue7978b.go @@ -0,0 +1,24 @@ +// Copyright 2020 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. + +// GCC-9.4 and above on arm64 introduced the "outline atomics" that the +// current internal linking doesn't support. +// See issue #39466. + +// +build arm64,internal + +package cgotest + +import ( + "runtime" + "testing" +) + +func test7978(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gccgo can not do stack traces of C code") + } + + t.Skip("skip on arm64+internal") +} diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go index 7fbc5c64..08c3287c 100644 --- a/misc/cgo/test/testx.go +++ b/misc/cgo/test/testx.go @@ -12,10 +12,7 @@ package cgotest import ( "runtime" - "runtime/debug" - "strings" "sync" - "sync/atomic" "testing" "time" "unsafe" @@ -75,28 +72,6 @@ extern int CheckIssue6907C(_GoString_); extern void f7665(void); -// issue 7978 -// Stack tracing didn't work during cgo code after calling a Go -// callback. Make sure GC works and the stack trace is correct. - -#include - -void issue7978cb(void); - -// use ugly atomic variable sync since that doesn't require calling back into -// Go code or OS dependencies -static void issue7978c(uint32_t *sync) { - while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0) - ; - __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST); - while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2) - ; - issue7978cb(); - __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST); - while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6) - ; -} - // issue 8331 part 2 - part 1 in test.go // A typedef of an unnamed struct is the same struct when // #include'd twice. No runtime test; just make sure it compiles. @@ -440,86 +415,6 @@ func test7665(t *testing.T) { } } -// issue 7978 - -var issue7978sync uint32 - -func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) { - runtime.GC() - buf := make([]byte, 65536) - trace := string(buf[:runtime.Stack(buf, true)]) - for _, goroutine := range strings.Split(trace, "\n\n") { - if strings.Contains(goroutine, "test.issue7978go") { - trace := strings.Split(goroutine, "\n") - // look for the expected function in the stack - for i := 0; i < depth; i++ { - if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) { - t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine) - return - } - if strings.Contains(trace[1+2*i], wantFunc) { - return - } - } - t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine) - return - } - } - t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace) -} - -func issue7978wait(store uint32, wait uint32) { - if store != 0 { - atomic.StoreUint32(&issue7978sync, store) - } - for atomic.LoadUint32(&issue7978sync) != wait { - runtime.Gosched() - } -} - -//export issue7978cb -func issue7978cb() { - // Force a stack growth from the callback to put extra - // pressure on the runtime. See issue #17785. - growStack(64) - issue7978wait(3, 4) -} - -func growStack(n int) int { - var buf [128]int - if n == 0 { - return 0 - } - return buf[growStack(n-1)] -} - -func issue7978go() { - C.issue7978c((*C.uint32_t)(&issue7978sync)) - issue7978wait(7, 8) -} - -func test7978(t *testing.T) { - if runtime.Compiler == "gccgo" { - t.Skip("gccgo can not do stack traces of C code") - } - debug.SetTraceback("2") - issue7978sync = 0 - go issue7978go() - // test in c code, before callback - issue7978wait(0, 1) - issue7978check(t, "_Cfunc_issue7978c(", "", 1) - // test in go code, during callback - issue7978wait(2, 3) - issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) - // test in c code, after callback - issue7978wait(4, 5) - issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1) - // test in go code, after return from cgo - issue7978wait(6, 7) - issue7978check(t, "test.issue7978go(", "", 3) - atomic.StoreUint32(&issue7978sync, 8) -} - // issue 8331 part 2 var issue8331Var C.issue8331 diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 2dc94592..ef0c743a 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1145,7 +1145,7 @@ func (t *tester) cgoTest(dt *distTest) error { if t.supportedBuildmode("pie") { t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") if t.internalLink() && t.internalLinkPIE() { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal") } t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie") t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")