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