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