diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index cb46c2a5dc..c34c629b9c 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -225,9 +225,6 @@ func TestCgoCrashTraceback(t *testing.T) { } func TestCgoTracebackContext(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skipf("test does not work on %s/%s", runtime.GOOS, runtime.GOARCH) - } got := runTestProg(t, "testprogcgo", "TracebackContext") want := "OK\n" if got != want { diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt.go b/src/runtime/testdata/testprogcgo/tracebackctxt.go index 4b2e486304..51fa4ad25c 100644 --- a/src/runtime/testdata/testprogcgo/tracebackctxt.go +++ b/src/runtime/testdata/testprogcgo/tracebackctxt.go @@ -1,106 +1,22 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2016 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. // The __attribute__((weak)) used below doesn't seem to work on Windows. -// +build !windows - package main // Test the context argument to SetCgoTraceback. // Use fake context, traceback, and symbolizer functions. /* -#include -#include - -// Use weak declarations so that we can define functions here even -// though we use //export in the Go code. -extern void tcContext(void*) __attribute__((weak)); -extern void tcTraceback(void*) __attribute__((weak)); -extern void tcSymbolizer(void*) __attribute__((weak)); - -extern void G1(void); -extern void G2(void); - -static void C1() { - G1(); -} - -static void C2() { - G2(); -} - -struct cgoContextArg { - uintptr_t context; -}; - -struct cgoTracebackArg { - uintptr_t context; - uintptr_t* buf; - uintptr_t max; -}; - -struct cgoSymbolizerArg { - uintptr_t pc; - const char* file; - uintptr_t lineno; - const char* func; - uintptr_t entry; - uintptr_t more; - uintptr_t data; -}; - -// Global so that there is only one, weak so that //export works. -// Uses atomic adds and subtracts to catch the possibility of -// erroneous calls from multiple threads; that should be impossible in -// this test case, but we check just in case. -int contextCount __attribute__((weak)); - -static int getContextCount() { - return __sync_add_and_fetch(&contextCount, 0); -} - -void tcContext(void* parg) { - struct cgoContextArg* arg = (struct cgoContextArg*)(parg); - if (arg->context == 0) { - arg->context = __sync_add_and_fetch(&contextCount, 1); - } else { - if (arg->context != __sync_add_and_fetch(&contextCount, 0)) { - abort(); - } - __sync_sub_and_fetch(&contextCount, 1); - } -} - -void tcTraceback(void* parg) { - int base, i; - struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); - if (arg->context == 0) { - // This shouldn't happen in this program. - abort(); - } - // Return a variable number of PC values. - base = arg->context << 8; - for (i = 0; i < arg->context; i++) { - if (i < arg->max) { - arg->buf[i] = base + i; - } - } -} - -void tcSymbolizer(void *parg) { - struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg); - if (arg->pc == 0) { - return; - } - // Report two lines per PC returned by traceback, to test more handling. - arg->more = arg->file == NULL; - arg->file = "tracebackctxt.go"; - arg->func = "cFunction"; - arg->lineno = arg->pc + (arg->more << 16); -} +// Defined in tracebackctxt_c.c. +extern void C1(void); +extern void C2(void); +extern void tcContext(void*); +extern void tcTraceback(void*); +extern void tcSymbolizer(void*); +extern int getContextCount(void); */ import "C" diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c new file mode 100644 index 0000000000..bbac39658e --- /dev/null +++ b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c @@ -0,0 +1,90 @@ +// Copyright 2016 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. + +// The C definitions for tracebackctxt.go. That file uses //export so +// it can't put function definitions in the "C" import comment. + +#include +#include + +// Functions exported from Go. +extern void G1(void); +extern void G2(void); + +void C1() { + G1(); +} + +void C2() { + G2(); +} + +struct cgoContextArg { + uintptr_t context; +}; + +struct cgoTracebackArg { + uintptr_t context; + uintptr_t* buf; + uintptr_t max; +}; + +struct cgoSymbolizerArg { + uintptr_t pc; + const char* file; + uintptr_t lineno; + const char* func; + uintptr_t entry; + uintptr_t more; + uintptr_t data; +}; + +// Uses atomic adds and subtracts to catch the possibility of +// erroneous calls from multiple threads; that should be impossible in +// this test case, but we check just in case. +static int contextCount; + +int getContextCount() { + return __sync_add_and_fetch(&contextCount, 0); +} + +void tcContext(void* parg) { + struct cgoContextArg* arg = (struct cgoContextArg*)(parg); + if (arg->context == 0) { + arg->context = __sync_add_and_fetch(&contextCount, 1); + } else { + if (arg->context != __sync_add_and_fetch(&contextCount, 0)) { + abort(); + } + __sync_sub_and_fetch(&contextCount, 1); + } +} + +void tcTraceback(void* parg) { + int base, i; + struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); + if (arg->context == 0) { + // This shouldn't happen in this program. + abort(); + } + // Return a variable number of PC values. + base = arg->context << 8; + for (i = 0; i < arg->context; i++) { + if (i < arg->max) { + arg->buf[i] = base + i; + } + } +} + +void tcSymbolizer(void *parg) { + struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg); + if (arg->pc == 0) { + return; + } + // Report two lines per PC returned by traceback, to test more handling. + arg->more = arg->file == NULL; + arg->file = "tracebackctxt.go"; + arg->func = "cFunction"; + arg->lineno = arg->pc + (arg->more << 16); +}