| // 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 sigContext; |
| 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); |
| } |