github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/misc/cgo/test/issue7978.go (about) 1 // Copyright 2014 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 // Issue 7978. Stack tracing didn't work during cgo code after calling a Go 6 // callback. Make sure GC works and the stack trace is correct. 7 8 package cgotest 9 10 /* 11 #include <stdint.h> 12 13 void issue7978cb(void); 14 15 #if defined(__APPLE__) && defined(__arm__) 16 // on Darwin/ARM, libSystem doesn't provide implementation of the __sync_fetch_and_add 17 // primitive, and although gcc supports it, it doesn't inline its definition. 18 // Clang could inline its definition, so we require clang on Darwin/ARM. 19 #if defined(__clang__) 20 #define HAS_SYNC_FETCH_AND_ADD 1 21 #else 22 #define HAS_SYNC_FETCH_AND_ADD 0 23 #endif 24 #else 25 #define HAS_SYNC_FETCH_AND_ADD 1 26 #endif 27 28 // use ugly atomic variable sync since that doesn't require calling back into 29 // Go code or OS dependencies 30 static void issue7978c(uint32_t *sync) { 31 #if HAS_SYNC_FETCH_AND_ADD 32 while(__sync_fetch_and_add(sync, 0) != 0) 33 ; 34 __sync_fetch_and_add(sync, 1); 35 while(__sync_fetch_and_add(sync, 0) != 2) 36 ; 37 issue7978cb(); 38 __sync_fetch_and_add(sync, 1); 39 while(__sync_fetch_and_add(sync, 0) != 6) 40 ; 41 #endif 42 } 43 */ 44 import "C" 45 46 import ( 47 "os" 48 "runtime" 49 "strings" 50 "sync/atomic" 51 "testing" 52 ) 53 54 var issue7978sync uint32 55 56 func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) { 57 runtime.GC() 58 buf := make([]byte, 65536) 59 trace := string(buf[:runtime.Stack(buf, true)]) 60 for _, goroutine := range strings.Split(trace, "\n\n") { 61 if strings.Contains(goroutine, "test.issue7978go") { 62 trace := strings.Split(goroutine, "\n") 63 // look for the expected function in the stack 64 for i := 0; i < depth; i++ { 65 if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) { 66 t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine) 67 return 68 } 69 if strings.Contains(trace[1+2*i], wantFunc) { 70 return 71 } 72 } 73 t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine) 74 return 75 } 76 } 77 t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace) 78 } 79 80 func issue7978wait(store uint32, wait uint32) { 81 if store != 0 { 82 atomic.StoreUint32(&issue7978sync, store) 83 } 84 for atomic.LoadUint32(&issue7978sync) != wait { 85 runtime.Gosched() 86 } 87 } 88 89 //export issue7978cb 90 func issue7978cb() { 91 // Force a stack growth from the callback to put extra 92 // pressure on the runtime. See issue #17785. 93 growStack(64) 94 issue7978wait(3, 4) 95 } 96 97 func growStack(n int) int { 98 var buf [128]int 99 if n == 0 { 100 return 0 101 } 102 return buf[growStack(n-1)] 103 } 104 105 func issue7978go() { 106 C.issue7978c((*C.uint32_t)(&issue7978sync)) 107 issue7978wait(7, 8) 108 } 109 110 func test7978(t *testing.T) { 111 if runtime.Compiler == "gccgo" { 112 t.Skip("gccgo can not do stack traces of C code") 113 } 114 if C.HAS_SYNC_FETCH_AND_ADD == 0 { 115 t.Skip("clang required for __sync_fetch_and_add support on darwin/arm") 116 } 117 if runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { 118 t.Skip("GOTRACEBACK is not passed on to the exec wrapper") 119 } 120 if os.Getenv("GOTRACEBACK") != "2" { 121 t.Fatalf("GOTRACEBACK must be 2") 122 } 123 issue7978sync = 0 124 go issue7978go() 125 // test in c code, before callback 126 issue7978wait(0, 1) 127 issue7978check(t, "_Cfunc_issue7978c(", "", 1) 128 // test in go code, during callback 129 issue7978wait(2, 3) 130 issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) 131 // test in c code, after callback 132 issue7978wait(4, 5) 133 issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1) 134 // test in go code, after return from cgo 135 issue7978wait(6, 7) 136 issue7978check(t, "test.issue7978go(", "", 3) 137 atomic.StoreUint32(&issue7978sync, 8) 138 }