1 // Copyright 2016 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 // The C definitions for tracebackctxt.go. That file uses //export so
6 // it can't put function definitions in the "C" import comment.
7
8 #include <stdlib.h>
9 #include <stdint.h>
10
11 // Functions exported from Go.
12 extern void G1(void);
13 extern void G2(void);
14 extern void TracebackContextPreemptionGoFunction(int);
15 extern void TracebackContextProfileGoFunction(void);
16
17 void C1() {
18 G1();
19 }
20
21 void C2() {
22 G2();
23 }
24
25 struct cgoContextArg {
26 uintptr_t context;
27 };
28
29 struct cgoTracebackArg {
30 uintptr_t context;
31 uintptr_t sigContext;
32 uintptr_t* buf;
33 uintptr_t max;
34 };
35
36 struct cgoSymbolizerArg {
37 uintptr_t pc;
38 const char* file;
39 uintptr_t lineno;
40 const char* func;
41 uintptr_t entry;
42 uintptr_t more;
43 uintptr_t data;
44 };
45
46 // Uses atomic adds and subtracts to catch the possibility of
47 // erroneous calls from multiple threads; that should be impossible in
48 // this test case, but we check just in case.
49 static int contextCount;
50
51 int getContextCount() {
52 return __sync_add_and_fetch(&contextCount, 0);
53 }
54
55 void tcContext(void* parg) {
56 struct cgoContextArg* arg = (struct cgoContextArg*)(parg);
57 if (arg->context == 0) {
58 arg->context = __sync_add_and_fetch(&contextCount, 1);
59 } else {
60 if (arg->context != __sync_add_and_fetch(&contextCount, 0)) {
61 abort();
62 }
63 __sync_sub_and_fetch(&contextCount, 1);
64 }
65 }
66
67 void tcContextSimple(void* parg) {
68 struct cgoContextArg* arg = (struct cgoContextArg*)(parg);
69 if (arg->context == 0) {
70 arg->context = 1;
71 }
72 }
73
74 void tcTraceback(void* parg) {
75 int base, i;
76 struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
77 if (arg->context == 0 && arg->sigContext == 0) {
78 // This shouldn't happen in this program.
79 abort();
80 }
81 // Return a variable number of PC values.
82 base = arg->context << 8;
83 for (i = 0; i < arg->context; i++) {
84 if (i < arg->max) {
85 arg->buf[i] = base + i;
86 }
87 }
88 }
89
90 void tcSymbolizer(void *parg) {
91 struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg);
92 if (arg->pc == 0) {
93 return;
94 }
95 // Report two lines per PC returned by traceback, to test more handling.
96 arg->more = arg->file == NULL;
97 arg->file = "tracebackctxt.go";
98 arg->func = "cFunction";
99 arg->lineno = arg->pc + (arg->more << 16);
100 }
101
102 void TracebackContextPreemptionCallGo(int i) {
103 TracebackContextPreemptionGoFunction(i);
104 }
105
106 void TracebackContextProfileCallGo(void) {
107 TracebackContextProfileGoFunction();
108 }
109
View as plain text