summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/cgo/test/callback.go45
-rw-r--r--misc/cgo/test/callback_c.c16
-rw-r--r--misc/cgo/test/cgo_test.go98
3 files changed, 111 insertions, 48 deletions
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index a7f1a3ecd..44167e6e9 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -10,6 +10,9 @@ void callGoFoo(void);
void callGoStackCheck(void);
void callPanic(void);
void callCgoAllocate(void);
+int callGoReturnVal(void);
+int returnAfterGrow(void);
+int returnAfterGrowFromGo(void);
*/
import "C"
@@ -212,6 +215,48 @@ func testAllocateFromC(t *testing.T) {
C.callCgoAllocate() // crashes or exits on failure
}
+// Test that C code can return a value if it calls a Go function that
+// causes a stack copy.
+func testReturnAfterGrow(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrow())
+ }()
+ if got, want := <-c, 123456; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+// Test that we can return a value from Go->C->Go if the Go code
+// causes a stack copy.
+func testReturnAfterGrowFromGo(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrowFromGo())
+ }()
+ if got, want := <-c, 129*128/2; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+//export goReturnVal
+func goReturnVal() (r C.int) {
+ // Force a stack copy.
+ var f func(int) int
+ f = func(i int) int {
+ var buf [256]byte
+ use(buf[:])
+ if i == 0 {
+ return 0
+ }
+ return i + f(i-1)
+ }
+ r = C.int(f(128))
+ return
+}
+
func testCallbackStack(t *testing.T) {
// Make cgo call and callback with different amount of stack stack available.
// We do not do any explicit checks, just ensure that it does not crash.
diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c
index dcd4ddd4e..5bb642534 100644
--- a/misc/cgo/test/callback_c.c
+++ b/misc/cgo/test/callback_c.c
@@ -64,3 +64,19 @@ callGoStackCheck(void)
extern void goStackCheck(void);
goStackCheck();
}
+
+int
+returnAfterGrow(void)
+{
+ extern int goReturnVal(void);
+ goReturnVal();
+ return 123456;
+}
+
+int
+returnAfterGrowFromGo(void)
+{
+ extern int goReturnVal(void);
+ return goReturnVal();
+}
+
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 1d1abf729..fcfad8304 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -10,53 +10,55 @@ import "testing"
// so that they can use cgo (import "C").
// These wrappers are here for gotest to find.
-func TestAlign(t *testing.T) { testAlign(t) }
-func TestConst(t *testing.T) { testConst(t) }
-func TestEnum(t *testing.T) { testEnum(t) }
-func TestAtol(t *testing.T) { testAtol(t) }
-func TestErrno(t *testing.T) { testErrno(t) }
-func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
-func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
-func TestCallback(t *testing.T) { testCallback(t) }
-func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
-func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
-func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
-func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
-func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
-func TestAllocateFromC(t *testing.T) { testAllocateFromC(t) }
-func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
-func TestBlocking(t *testing.T) { testBlocking(t) }
-func Test1328(t *testing.T) { test1328(t) }
-func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
-func TestSetEnv(t *testing.T) { testSetEnv(t) }
-func TestHelpers(t *testing.T) { testHelpers(t) }
-func TestLibgcc(t *testing.T) { testLibgcc(t) }
-func Test1635(t *testing.T) { test1635(t) }
-func TestPrintf(t *testing.T) { testPrintf(t) }
-func Test4029(t *testing.T) { test4029(t) }
-func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
-func Test3729(t *testing.T) { test3729(t) }
-func Test3775(t *testing.T) { test3775(t) }
-func TestCthread(t *testing.T) { testCthread(t) }
-func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
-func Test5227(t *testing.T) { test5227(t) }
-func TestCflags(t *testing.T) { testCflags(t) }
-func Test5337(t *testing.T) { test5337(t) }
-func Test5548(t *testing.T) { test5548(t) }
-func Test5603(t *testing.T) { test5603(t) }
-func Test6833(t *testing.T) { test6833(t) }
-func Test3250(t *testing.T) { test3250(t) }
-func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
-func TestFpVar(t *testing.T) { testFpVar(t) }
-func Test4339(t *testing.T) { test4339(t) }
-func Test6390(t *testing.T) { test6390(t) }
-func Test5986(t *testing.T) { test5986(t) }
-func Test7665(t *testing.T) { test7665(t) }
-func TestNaming(t *testing.T) { testNaming(t) }
-func Test7560(t *testing.T) { test7560(t) }
-func Test5242(t *testing.T) { test5242(t) }
-func Test8092(t *testing.T) { test8092(t) }
-func Test7978(t *testing.T) { test7978(t) }
-func Test8694(t *testing.T) { test8694(t) }
+func TestAlign(t *testing.T) { testAlign(t) }
+func TestConst(t *testing.T) { testConst(t) }
+func TestEnum(t *testing.T) { testEnum(t) }
+func TestAtol(t *testing.T) { testAtol(t) }
+func TestErrno(t *testing.T) { testErrno(t) }
+func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
+func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
+func TestCallback(t *testing.T) { testCallback(t) }
+func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
+func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
+func TestAllocateFromC(t *testing.T) { testAllocateFromC(t) }
+func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T) { testBlocking(t) }
+func Test1328(t *testing.T) { test1328(t) }
+func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
+func TestSetEnv(t *testing.T) { testSetEnv(t) }
+func TestHelpers(t *testing.T) { testHelpers(t) }
+func TestLibgcc(t *testing.T) { testLibgcc(t) }
+func Test1635(t *testing.T) { test1635(t) }
+func TestPrintf(t *testing.T) { testPrintf(t) }
+func Test4029(t *testing.T) { test4029(t) }
+func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
+func Test3729(t *testing.T) { test3729(t) }
+func Test3775(t *testing.T) { test3775(t) }
+func TestCthread(t *testing.T) { testCthread(t) }
+func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
+func Test5227(t *testing.T) { test5227(t) }
+func TestCflags(t *testing.T) { testCflags(t) }
+func Test5337(t *testing.T) { test5337(t) }
+func Test5548(t *testing.T) { test5548(t) }
+func Test5603(t *testing.T) { test5603(t) }
+func Test6833(t *testing.T) { test6833(t) }
+func Test3250(t *testing.T) { test3250(t) }
+func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
+func TestFpVar(t *testing.T) { testFpVar(t) }
+func Test4339(t *testing.T) { test4339(t) }
+func Test6390(t *testing.T) { test6390(t) }
+func Test5986(t *testing.T) { test5986(t) }
+func Test7665(t *testing.T) { test7665(t) }
+func TestNaming(t *testing.T) { testNaming(t) }
+func Test7560(t *testing.T) { test7560(t) }
+func Test5242(t *testing.T) { test5242(t) }
+func Test8092(t *testing.T) { test8092(t) }
+func Test7978(t *testing.T) { test7978(t) }
+func Test8694(t *testing.T) { test8694(t) }
+func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) }
+func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }