github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/runtime/go-cgo.c (about) 1 /* go-cgo.c -- SWIG support routines for libgo. 2 3 Copyright 2011 The Go Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style 5 license that can be found in the LICENSE file. */ 6 7 #include "runtime.h" 8 #include "go-alloc.h" 9 #include "interface.h" 10 #include "go-panic.h" 11 12 /* Prepare to call from code written in Go to code written in C or 13 C++. This takes the current goroutine out of the Go scheduler, as 14 though it were making a system call. Otherwise the program can 15 lock up if the C code goes to sleep on a mutex or for some other 16 reason. This idea is to call this function, then immediately call 17 the C/C++ function. After the C/C++ function returns, call 18 syscall_cgocalldone. The usual Go code would look like 19 20 syscall.Cgocall() 21 defer syscall.Cgocalldone() 22 cfunction() 23 24 */ 25 26 /* We let Go code call these via the syscall package. */ 27 void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall"); 28 void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone"); 29 void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack"); 30 void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone"); 31 32 void 33 syscall_cgocall () 34 { 35 M* m; 36 G* g; 37 38 if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0)) 39 runtime_newextram (); 40 41 m = runtime_m (); 42 ++m->ncgocall; 43 g = runtime_g (); 44 ++g->ncgo; 45 runtime_entersyscall (); 46 } 47 48 /* Prepare to return to Go code from C/C++ code. */ 49 50 void 51 syscall_cgocalldone () 52 { 53 G* g; 54 55 g = runtime_g (); 56 __go_assert (g != NULL); 57 --g->ncgo; 58 if (g->ncgo == 0) 59 { 60 /* We are going back to Go, and we are not in a recursive call. 61 Let the garbage collector clean up any unreferenced 62 memory. */ 63 g->cgomal = NULL; 64 } 65 66 /* If we are invoked because the C function called _cgo_panic, then 67 _cgo_panic will already have exited syscall mode. */ 68 if (g->status == Gsyscall) 69 runtime_exitsyscall (); 70 } 71 72 /* Call back from C/C++ code to Go code. */ 73 74 void 75 syscall_cgocallback () 76 { 77 M *mp; 78 79 mp = runtime_m (); 80 if (mp == NULL) 81 { 82 runtime_needm (); 83 mp = runtime_m (); 84 mp->dropextram = true; 85 } 86 87 runtime_exitsyscall (); 88 89 mp = runtime_m (); 90 if (mp->needextram) 91 { 92 mp->needextram = 0; 93 runtime_newextram (); 94 } 95 } 96 97 /* Prepare to return to C/C++ code from a callback to Go code. */ 98 99 void 100 syscall_cgocallbackdone () 101 { 102 M *mp; 103 104 runtime_entersyscall (); 105 mp = runtime_m (); 106 if (mp->dropextram && runtime_g ()->ncgo == 0) 107 { 108 mp->dropextram = false; 109 runtime_dropm (); 110 } 111 } 112 113 /* Allocate memory and save it in a list visible to the Go garbage 114 collector. */ 115 116 void * 117 alloc_saved (size_t n) 118 { 119 void *ret; 120 G *g; 121 CgoMal *c; 122 123 ret = __go_alloc (n); 124 125 g = runtime_g (); 126 c = (CgoMal *) __go_alloc (sizeof (CgoMal)); 127 c->next = g->cgomal; 128 c->alloc = ret; 129 g->cgomal = c; 130 131 return ret; 132 } 133 134 /* These are routines used by SWIG. The gc runtime library provides 135 the same routines under the same name, though in that case the code 136 is required to import runtime/cgo. */ 137 138 void * 139 _cgo_allocate (size_t n) 140 { 141 void *ret; 142 143 runtime_exitsyscall (); 144 ret = alloc_saved (n); 145 runtime_entersyscall (); 146 return ret; 147 } 148 149 extern const struct __go_type_descriptor string_type_descriptor 150 __asm__ (GOSYM_PREFIX "__go_tdn_string"); 151 152 void 153 _cgo_panic (const char *p) 154 { 155 intgo len; 156 unsigned char *data; 157 String *ps; 158 struct __go_empty_interface e; 159 160 runtime_exitsyscall (); 161 len = __builtin_strlen (p); 162 data = alloc_saved (len); 163 __builtin_memcpy (data, p, len); 164 ps = alloc_saved (sizeof *ps); 165 ps->str = data; 166 ps->len = len; 167 e.__type_descriptor = &string_type_descriptor; 168 e.__object = ps; 169 170 /* We don't call runtime_entersyscall here, because normally what 171 will happen is that we will walk up the stack to a Go deferred 172 function that calls recover. However, this will do the wrong 173 thing if this panic is recovered and the stack unwinding is 174 caught by a C++ exception handler. It might be possible to 175 handle this by calling runtime_entersyscall in the personality 176 function in go-unwind.c. FIXME. */ 177 178 __go_panic (e); 179 }