OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package cgotest | 5 package cgotest |
6 | 6 |
7 /* | 7 /* |
8 void callback(void *f); | 8 void callback(void *f); |
9 void callGoFoo(void); | 9 void callGoFoo(void); |
10 */ | 10 */ |
11 import "C" | 11 import "C" |
12 | 12 |
13 import ( | 13 import ( |
14 "./backdoor" | 14 "./backdoor" |
| 15 "path" |
15 "runtime" | 16 "runtime" |
| 17 "strings" |
16 "testing" | 18 "testing" |
17 "unsafe" | 19 "unsafe" |
18 ) | 20 ) |
19 | 21 |
20 // nestedCall calls into C, back into Go, and finally to f. | 22 // nestedCall calls into C, back into Go, and finally to f. |
21 func nestedCall(f func()) { | 23 func nestedCall(f func()) { |
22 // NOTE: Depends on representation of f. | 24 // NOTE: Depends on representation of f. |
23 // callback(x) calls goCallback(x) | 25 // callback(x) calls goCallback(x) |
24 C.callback(*(*unsafe.Pointer)(unsafe.Pointer(&f))) | 26 C.callback(*(*unsafe.Pointer)(unsafe.Pointer(&f))) |
25 } | 27 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 }() | 131 }() |
130 nestedCall(func() { | 132 nestedCall(func() { |
131 for i := 0; i < 10; i++ { | 133 for i := 0; i < 10; i++ { |
132 c <- i | 134 c <- i |
133 if j := <-c; j != i { | 135 if j := <-c; j != i { |
134 t.Errorf("out of sync %d != %d", j, i) | 136 t.Errorf("out of sync %d != %d", j, i) |
135 } | 137 } |
136 } | 138 } |
137 }) | 139 }) |
138 } | 140 } |
| 141 |
| 142 // Test that the stack can be unwound through a call out and call back |
| 143 // into Go. |
| 144 func testCallbackCallers(t *testing.T) { |
| 145 pc := make([]uintptr, 100) |
| 146 n := 0 |
| 147 name := []string{ |
| 148 "test.goCallback", |
| 149 "runtime.cgocallbackg", |
| 150 "runtime.cgocallback_gofunc", |
| 151 "return", |
| 152 "runtime.cgocall", |
| 153 "test._Cfunc_callback", |
| 154 "test.nestedCall", |
| 155 "test.testCallbackCallers", |
| 156 "test.TestCallbackCallers", |
| 157 "testing.tRunner", |
| 158 "runtime.goexit", |
| 159 } |
| 160 nestedCall(func() { |
| 161 n = runtime.Callers(2, pc) |
| 162 }) |
| 163 // The ARM cannot unwind all the way down to runtime.goexit. |
| 164 // See issue 5124. |
| 165 if n != len(name) && runtime.GOARCH != "arm" { |
| 166 t.Errorf("expected %d frames, got %d", len(name), n) |
| 167 } |
| 168 for i := 0; i < n; i++ { |
| 169 f := runtime.FuncForPC(pc[i]) |
| 170 if f == nil { |
| 171 t.Fatalf("expected non-nil Func for pc %p", pc[i]) |
| 172 } |
| 173 fname := f.Name() |
| 174 // Remove the prepended pathname from automatically |
| 175 // generated cgo function names. |
| 176 if strings.HasPrefix(fname, "_") { |
| 177 fname = path.Base(f.Name()[1:]) |
| 178 } |
| 179 if fname != name[i] { |
| 180 t.Errorf("expected function name %s, got %s", name[i], f
name) |
| 181 } |
| 182 // The ARM cannot unwind frames past runtime.cgocall. |
| 183 // See issue 5124. |
| 184 if runtime.GOARCH == "arm" && i == 4 { |
| 185 break |
| 186 } |
| 187 } |
| 188 } |
OLD | NEW |