| // Copyright 2009 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. | |
| #include <stdint.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #undef nil | |
| #define nil ((void*)0) | |
| #define nelem(x) (sizeof(x)/sizeof((x)[0])) | |
| typedef uint32_t uint32; | |
| typedef uint64_t uint64; | |
| typedef uintptr_t uintptr; | |
| /* | |
| * The beginning of the per-goroutine structure, | |
| * as defined in ../pkg/runtime/runtime.h. | |
| * Just enough to edit these two fields. | |
| */ | |
| typedef struct G G; | |
| struct G | |
| { | |
| uintptr stacklo; | |
| uintptr stackhi; | |
| }; | |
| /* | |
| * Arguments to the _cgo_thread_start call. | |
| * Also known to ../pkg/runtime/runtime.h. | |
| */ | |
| typedef struct ThreadStart ThreadStart; | |
| struct ThreadStart | |
| { | |
| G *g; | |
| uintptr *tls; | |
| void (*fn)(void); | |
| }; | |
| /* | |
| * Called by 5c/6c/8c world. | |
| * Makes a local copy of the ThreadStart and | |
| * calls _cgo_sys_thread_start(ts). | |
| */ | |
| extern void (*_cgo_thread_start)(ThreadStart *ts); | |
| /* | |
| * Creates a new operating system thread without updating any Go state | |
| * (OS dependent). | |
| */ | |
| extern void (*_cgo_sys_thread_create)(void* (*func)(void*)); | |
| /* | |
| * Indicates whether a dummy pthread per-thread variable is allocated. | |
| */ | |
| extern uintptr_t *_cgo_pthread_key_created; | |
| /* | |
| * Creates the new operating system thread (OS, arch dependent). | |
| */ | |
| void _cgo_sys_thread_start(ThreadStart *ts); | |
| /* | |
| * Waits for the Go runtime to be initialized (OS dependent). | |
| * If runtime.SetCgoTraceback is used to set a context function, | |
| * calls the context function and returns the context value. | |
| */ | |
| uintptr_t _cgo_wait_runtime_init_done(void); | |
| /* | |
| * Get the low and high boundaries of the stack. | |
| */ | |
| void x_cgo_getstackbound(uintptr bounds[2]); | |
| /* | |
| * Calls into the Go tool chain, where all registers are caller save. | |
| * Called from C, it saves all callee-save registers and calls | |
| * setg_gcc to set g before calling fn. | |
| */ | |
| void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); | |
| /* | |
| * Prints error then calls abort. For linux and android. | |
| */ | |
| void fatalf(const char* format, ...) __attribute__ ((noreturn)); | |
| /* | |
| * The cgo traceback callback. See runtime.SetCgoTraceback. | |
| */ | |
| struct cgoTracebackArg { | |
| uintptr_t Context; | |
| uintptr_t SigContext; | |
| uintptr_t* Buf; | |
| uintptr_t Max; | |
| }; | |
| extern void (*(_cgo_get_traceback_function(void)))(struct cgoTracebackArg*); | |
| /* | |
| * The cgo context callback. See runtime.SetCgoTraceback. | |
| */ | |
| struct cgoContextArg { | |
| uintptr_t Context; | |
| }; | |
| extern void (*(_cgo_get_context_function(void)))(struct cgoContextArg*); | |
| /* | |
| * The argument for the cgo symbolizer callback. See runtime.SetCgoTraceback. | |
| */ | |
| struct cgoSymbolizerArg { | |
| uintptr_t PC; | |
| const char* File; | |
| uintptr_t Lineno; | |
| const char* Func; | |
| uintptr_t Entry; | |
| uintptr_t More; | |
| uintptr_t Data; | |
| }; | |
| extern void (*(_cgo_get_symbolizer_function(void)))(struct cgoSymbolizerArg*); | |
| /* | |
| * The argument for x_cgo_set_traceback_functions. See runtime.SetCgoTraceback. | |
| */ | |
| struct cgoSetTracebackFunctionsArg { | |
| void (*Traceback)(struct cgoTracebackArg*); | |
| void (*Context)(struct cgoContextArg*); | |
| void (*Symbolizer)(struct cgoSymbolizerArg*); | |
| }; | |
| /* | |
| * TSAN support. This is only useful when building with | |
| * CGO_CFLAGS="-fsanitize=thread" CGO_LDFLAGS="-fsanitize=thread" go install | |
| */ | |
| #undef CGO_TSAN | |
| #if defined(__has_feature) | |
| # if __has_feature(thread_sanitizer) | |
| # define CGO_TSAN | |
| # endif | |
| #elif defined(__SANITIZE_THREAD__) | |
| # define CGO_TSAN | |
| #endif | |
| #ifdef CGO_TSAN | |
| // _cgo_tsan_acquire tells C/C++ TSAN that we are acquiring a dummy lock. We | |
| // call this when calling from Go to C. This is necessary because TSAN cannot | |
| // see the synchronization in Go. Note that C/C++ code built with TSAN is not | |
| // the same as the Go race detector. | |
| // | |
| // cmd/cgo generates calls to _cgo_tsan_acquire and _cgo_tsan_release. For | |
| // other cgo calls, manual calls are required. | |
| // | |
| // These must match the definitions in yesTsanProlog in cmd/cgo/out.go. | |
| // In general we should call _cgo_tsan_acquire when we enter C code, | |
| // and call _cgo_tsan_release when we return to Go code. | |
| // | |
| // This is only necessary when calling code that might be instrumented | |
| // by TSAN, which mostly means system library calls that TSAN intercepts. | |
| // | |
| // See the comment in cmd/cgo/out.go for more details. | |
| long long _cgo_sync __attribute__ ((common)); | |
| extern void __tsan_acquire(void*); | |
| extern void __tsan_release(void*); | |
| __attribute__ ((unused)) | |
| static void _cgo_tsan_acquire() { | |
| __tsan_acquire(&_cgo_sync); | |
| } | |
| __attribute__ ((unused)) | |
| static void _cgo_tsan_release() { | |
| __tsan_release(&_cgo_sync); | |
| } | |
| #else // !defined(CGO_TSAN) | |
| #define _cgo_tsan_acquire() | |
| #define _cgo_tsan_release() | |
| #endif // !defined(CGO_TSAN) |