github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/runtime/cgo/gcc_libinit.c (about) 1 // Copyright 2015 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 // +build cgo 6 // +build darwin dragonfly freebsd linux netbsd solaris 7 8 #include <pthread.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> // strerror 12 #include "libcgo.h" 13 14 static pthread_cond_t runtime_init_cond = PTHREAD_COND_INITIALIZER; 15 static pthread_mutex_t runtime_init_mu = PTHREAD_MUTEX_INITIALIZER; 16 static int runtime_init_done; 17 18 // The context function, used when tracing back C calls into Go. 19 static void (*cgo_context_function)(struct context_arg*); 20 21 void 22 x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { 23 pthread_t p; 24 int err = pthread_create(&p, NULL, func, arg); 25 if (err != 0) { 26 fprintf(stderr, "pthread_create failed: %s", strerror(err)); 27 abort(); 28 } 29 } 30 31 uintptr_t 32 _cgo_wait_runtime_init_done() { 33 void (*pfn)(struct context_arg*); 34 35 pthread_mutex_lock(&runtime_init_mu); 36 while (runtime_init_done == 0) { 37 pthread_cond_wait(&runtime_init_cond, &runtime_init_mu); 38 } 39 40 // TODO(iant): For the case of a new C thread calling into Go, such 41 // as when using -buildmode=c-archive, we know that Go runtime 42 // initialization is complete but we do not know that all Go init 43 // functions have been run. We should not fetch cgo_context_function 44 // until they have been, because that is where a call to 45 // SetCgoTraceback is likely to occur. We are going to wait for Go 46 // initialization to be complete anyhow, later, by waiting for 47 // main_init_done to be closed in cgocallbackg1. We should wait here 48 // instead. See also issue #15943. 49 pfn = cgo_context_function; 50 51 pthread_mutex_unlock(&runtime_init_mu); 52 if (pfn != nil) { 53 struct context_arg arg; 54 55 arg.Context = 0; 56 (*pfn)(&arg); 57 return arg.Context; 58 } 59 return 0; 60 } 61 62 void 63 x_cgo_notify_runtime_init_done(void* dummy) { 64 pthread_mutex_lock(&runtime_init_mu); 65 runtime_init_done = 1; 66 pthread_cond_broadcast(&runtime_init_cond); 67 pthread_mutex_unlock(&runtime_init_mu); 68 } 69 70 // Sets the context function to call to record the traceback context 71 // when calling a Go function from C code. Called from runtime.SetCgoTraceback. 72 void x_cgo_set_context_function(void (*context)(struct context_arg*)) { 73 pthread_mutex_lock(&runtime_init_mu); 74 cgo_context_function = context; 75 pthread_mutex_unlock(&runtime_init_mu); 76 } 77 78 // Gets the context function. 79 void (*(_cgo_get_context_function(void)))(struct context_arg*) { 80 void (*ret)(struct context_arg*); 81 82 pthread_mutex_lock(&runtime_init_mu); 83 ret = cgo_context_function; 84 pthread_mutex_unlock(&runtime_init_mu); 85 return ret; 86 }