mirror of
https://github.com/golang/go
synced 2024-11-13 16:30:25 -07:00
runtime: put tracebackctxt C functions in .c file
Since tracebackctxt.go uses //export functions, the C functions can't be externally visible in the C comment. The code was using attributes to work around that, but that failed on Windows. Change-Id: If4449fd8209a8998b4f6855ea89e5db1471b2981 Reviewed-on: https://go-review.googlesource.com/22786 Reviewed-by: Minux Ma <minux@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
57be1607d9
commit
34f97d28d2
@ -225,9 +225,6 @@ func TestCgoCrashTraceback(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCgoTracebackContext(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")
|
got := runTestProg(t, "testprogcgo", "TracebackContext")
|
||||||
want := "OK\n"
|
want := "OK\n"
|
||||||
if got != want {
|
if got != want {
|
||||||
|
100
src/runtime/testdata/testprogcgo/tracebackctxt.go
vendored
100
src/runtime/testdata/testprogcgo/tracebackctxt.go
vendored
@ -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
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// The __attribute__((weak)) used below doesn't seem to work on Windows.
|
// The __attribute__((weak)) used below doesn't seem to work on Windows.
|
||||||
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
// Test the context argument to SetCgoTraceback.
|
// Test the context argument to SetCgoTraceback.
|
||||||
// Use fake context, traceback, and symbolizer functions.
|
// Use fake context, traceback, and symbolizer functions.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <stdlib.h>
|
// Defined in tracebackctxt_c.c.
|
||||||
#include <stdint.h>
|
extern void C1(void);
|
||||||
|
extern void C2(void);
|
||||||
// Use weak declarations so that we can define functions here even
|
extern void tcContext(void*);
|
||||||
// though we use //export in the Go code.
|
extern void tcTraceback(void*);
|
||||||
extern void tcContext(void*) __attribute__((weak));
|
extern void tcSymbolizer(void*);
|
||||||
extern void tcTraceback(void*) __attribute__((weak));
|
extern int getContextCount(void);
|
||||||
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);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
90
src/runtime/testdata/testprogcgo/tracebackctxt_c.c
vendored
Normal file
90
src/runtime/testdata/testprogcgo/tracebackctxt_c.c
vendored
Normal file
@ -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 <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user