github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/cgocall.c (about) 1 // Copyright 2009 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 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "stack.h" 8 #include "cgocall.h" 9 #include "race.h" 10 #include "../../cmd/ld/textflag.h" 11 12 // Cgo call and callback support. 13 // 14 // To call into the C function f from Go, the cgo-generated code calls 15 // runtime.cgocall(_cgo_Cfunc_f, frame), where _cgo_Cfunc_f is a 16 // gcc-compiled function written by cgo. 17 // 18 // runtime.cgocall (below) locks g to m, calls entersyscall 19 // so as not to block other goroutines or the garbage collector, 20 // and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame). 21 // 22 // runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack 23 // (assumed to be an operating system-allocated stack, so safe to run 24 // gcc-compiled code on) and calls _cgo_Cfunc_f(frame). 25 // 26 // _cgo_Cfunc_f invokes the actual C function f with arguments 27 // taken from the frame structure, records the results in the frame, 28 // and returns to runtime.asmcgocall. 29 // 30 // After it regains control, runtime.asmcgocall switches back to the 31 // original g (m->curg)'s stack and returns to runtime.cgocall. 32 // 33 // After it regains control, runtime.cgocall calls exitsyscall, which blocks 34 // until this m can run Go code without violating the $GOMAXPROCS limit, 35 // and then unlocks g from m. 36 // 37 // The above description skipped over the possibility of the gcc-compiled 38 // function f calling back into Go. If that happens, we continue down 39 // the rabbit hole during the execution of f. 40 // 41 // To make it possible for gcc-compiled C code to call a Go function p.GoF, 42 // cgo writes a gcc-compiled function named GoF (not p.GoF, since gcc doesn't 43 // know about packages). The gcc-compiled C function f calls GoF. 44 // 45 // GoF calls crosscall2(_cgoexp_GoF, frame, framesize). Crosscall2 46 // (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument 47 // adapter from the gcc function call ABI to the 6c function call ABI. 48 // It is called from gcc to call 6c functions. In this case it calls 49 // _cgoexp_GoF(frame, framesize), still running on m->g0's stack 50 // and outside the $GOMAXPROCS limit. Thus, this code cannot yet 51 // call arbitrary Go code directly and must be careful not to allocate 52 // memory or use up m->g0's stack. 53 // 54 // _cgoexp_GoF calls runtime.cgocallback(p.GoF, frame, framesize). 55 // (The reason for having _cgoexp_GoF instead of writing a crosscall3 56 // to make this call directly is that _cgoexp_GoF, because it is compiled 57 // with 6c instead of gcc, can refer to dotted names like 58 // runtime.cgocallback and p.GoF.) 59 // 60 // runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's 61 // stack to the original g (m->curg)'s stack, on which it calls 62 // runtime.cgocallbackg(p.GoF, frame, framesize). 63 // As part of the stack switch, runtime.cgocallback saves the current 64 // SP as m->g0->sched.sp, so that any use of m->g0's stack during the 65 // execution of the callback will be done below the existing stack frames. 66 // Before overwriting m->g0->sched.sp, it pushes the old value on the 67 // m->g0 stack, so that it can be restored later. 68 // 69 // runtime.cgocallbackg (below) is now running on a real goroutine 70 // stack (not an m->g0 stack). First it calls runtime.exitsyscall, which will 71 // block until the $GOMAXPROCS limit allows running this goroutine. 72 // Once exitsyscall has returned, it is safe to do things like call the memory 73 // allocator or invoke the Go callback function p.GoF. runtime.cgocallbackg 74 // first defers a function to unwind m->g0.sched.sp, so that if p.GoF 75 // panics, m->g0.sched.sp will be restored to its old value: the m->g0 stack 76 // and the m->curg stack will be unwound in lock step. 77 // Then it calls p.GoF. Finally it pops but does not execute the deferred 78 // function, calls runtime.entersyscall, and returns to runtime.cgocallback. 79 // 80 // After it regains control, runtime.cgocallback switches back to 81 // m->g0's stack (the pointer is still in m->g0.sched.sp), restores the old 82 // m->g0.sched.sp value from the stack, and returns to _cgoexp_GoF. 83 // 84 // _cgoexp_GoF immediately returns to crosscall2, which restores the 85 // callee-save registers for gcc and returns to GoF, which returns to f. 86 87 void *_cgo_init; /* filled in by dynamic linker when Cgo is available */ 88 static int64 cgosync; /* represents possible synchronization in C code */ 89 90 static void unwindm(void); 91 92 // Call from Go to C. 93 94 static void endcgo(void); 95 static FuncVal endcgoV = { endcgo }; 96 97 void 98 runtime·cgocall(void (*fn)(void*), void *arg) 99 { 100 Defer d; 101 102 if(m->racecall) { 103 runtime·asmcgocall(fn, arg); 104 return; 105 } 106 107 if(!runtime·iscgo && !Windows) 108 runtime·throw("cgocall unavailable"); 109 110 if(fn == 0) 111 runtime·throw("cgocall nil"); 112 113 if(raceenabled) 114 runtime·racereleasemerge(&cgosync); 115 116 // Create an extra M for callbacks on threads not created by Go on first cgo call. 117 if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0)) 118 runtime·newextram(); 119 120 m->ncgocall++; 121 122 /* 123 * Lock g to m to ensure we stay on the same stack if we do a 124 * cgo callback. Add entry to defer stack in case of panic. 125 */ 126 runtime·lockOSThread(); 127 d.fn = &endcgoV; 128 d.siz = 0; 129 d.link = g->defer; 130 d.argp = (void*)-1; // unused because unlockm never recovers 131 d.special = true; 132 d.free = false; 133 g->defer = &d; 134 135 m->ncgo++; 136 137 /* 138 * Announce we are entering a system call 139 * so that the scheduler knows to create another 140 * M to run goroutines while we are in the 141 * foreign code. 142 * 143 * The call to asmcgocall is guaranteed not to 144 * split the stack and does not allocate memory, 145 * so it is safe to call while "in a system call", outside 146 * the $GOMAXPROCS accounting. 147 */ 148 runtime·entersyscall(); 149 runtime·asmcgocall(fn, arg); 150 runtime·exitsyscall(); 151 152 if(g->defer != &d || d.fn != &endcgoV) 153 runtime·throw("runtime: bad defer entry in cgocallback"); 154 g->defer = d.link; 155 endcgo(); 156 } 157 158 static void 159 endcgo(void) 160 { 161 runtime·unlockOSThread(); 162 m->ncgo--; 163 if(m->ncgo == 0) { 164 // We are going back to Go and are not in a recursive 165 // call. Let the GC collect any memory allocated via 166 // _cgo_allocate that is no longer referenced. 167 m->cgomal = nil; 168 } 169 170 if(raceenabled) 171 runtime·raceacquire(&cgosync); 172 } 173 174 void 175 runtime·NumCgoCall(int64 ret) 176 { 177 M *mp; 178 179 ret = 0; 180 for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink) 181 ret += mp->ncgocall; 182 FLUSH(&ret); 183 } 184 185 // Helper functions for cgo code. 186 187 void (*_cgo_malloc)(void*); 188 void (*_cgo_free)(void*); 189 190 void* 191 runtime·cmalloc(uintptr n) 192 { 193 struct { 194 uint64 n; 195 void *ret; 196 } a; 197 198 a.n = n; 199 a.ret = nil; 200 runtime·cgocall(_cgo_malloc, &a); 201 if(a.ret == nil) 202 runtime·throw("runtime: C malloc failed"); 203 return a.ret; 204 } 205 206 void 207 runtime·cfree(void *p) 208 { 209 runtime·cgocall(_cgo_free, p); 210 } 211 212 // Call from C back to Go. 213 214 static FuncVal unwindmf = {unwindm}; 215 216 typedef struct CallbackArgs CallbackArgs; 217 struct CallbackArgs 218 { 219 FuncVal *fn; 220 void *arg; 221 uintptr argsize; 222 }; 223 224 // Location of callback arguments depends on stack frame layout 225 // and size of stack frame of cgocallback_gofunc. 226 227 // On arm, stack frame is two words and there's a saved LR between 228 // SP and the stack frame and between the stack frame and the arguments. 229 #ifdef GOARCH_arm 230 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) 231 #endif 232 233 // On amd64, stack frame is one word, plus caller PC. 234 #ifdef GOARCH_amd64 235 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*)) 236 #endif 237 238 // On 386, stack frame is three words, plus caller PC. 239 #ifdef GOARCH_386 240 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) 241 #endif 242 243 void runtime·cgocallbackg1(void); 244 245 #pragma textflag NOSPLIT 246 void 247 runtime·cgocallbackg(void) 248 { 249 if(g != m->curg) { 250 runtime·prints("runtime: bad g in cgocallback"); 251 runtime·exit(2); 252 } 253 254 if(m->racecall) { 255 // We were not in syscall, so no need to call runtime·exitsyscall. 256 // However we must set m->locks for the following reason. 257 // Race detector runtime makes __tsan_symbolize cgo callback 258 // holding internal mutexes. The mutexes are not cooperative with Go scheduler. 259 // So if we deschedule a goroutine that holds race detector internal mutex 260 // (e.g. preempt it), another goroutine will deadlock trying to acquire the same mutex. 261 m->locks++; 262 runtime·cgocallbackg1(); 263 m->locks--; 264 } else { 265 runtime·exitsyscall(); // coming out of cgo call 266 runtime·cgocallbackg1(); 267 runtime·entersyscall(); // going back to cgo call 268 } 269 } 270 271 void 272 runtime·cgocallbackg1(void) 273 { 274 CallbackArgs *cb; 275 Defer d; 276 277 if(m->needextram) { 278 m->needextram = 0; 279 runtime·newextram(); 280 } 281 282 // Add entry to defer stack in case of panic. 283 d.fn = &unwindmf; 284 d.siz = 0; 285 d.link = g->defer; 286 d.argp = (void*)-1; // unused because unwindm never recovers 287 d.special = true; 288 d.free = false; 289 g->defer = &d; 290 291 if(raceenabled && !m->racecall) 292 runtime·raceacquire(&cgosync); 293 294 // Invoke callback. 295 cb = CBARGS; 296 runtime·newstackcall(cb->fn, cb->arg, cb->argsize); 297 298 if(raceenabled && !m->racecall) 299 runtime·racereleasemerge(&cgosync); 300 301 // Pop defer. 302 // Do not unwind m->g0->sched.sp. 303 // Our caller, cgocallback, will do that. 304 if(g->defer != &d || d.fn != &unwindmf) 305 runtime·throw("runtime: bad defer entry in cgocallback"); 306 g->defer = d.link; 307 } 308 309 static void 310 unwindm(void) 311 { 312 // Restore sp saved by cgocallback during 313 // unwind of g's stack (see comment at top of file). 314 switch(thechar){ 315 default: 316 runtime·throw("runtime: unwindm not implemented"); 317 case '8': 318 case '6': 319 m->g0->sched.sp = *(uintptr*)m->g0->sched.sp; 320 break; 321 case '5': 322 m->g0->sched.sp = *(uintptr*)((byte*)m->g0->sched.sp + 4); 323 break; 324 } 325 } 326 327 void 328 runtime·badcgocallback(void) // called from assembly 329 { 330 runtime·throw("runtime: misaligned stack in cgocallback"); 331 } 332 333 void 334 runtime·cgounimpl(void) // called from (incomplete) assembly 335 { 336 runtime·throw("runtime: cgo not implemented"); 337 } 338 339 // For cgo-using programs with external linking, 340 // export "main" (defined in assembly) so that libc can handle basic 341 // C runtime startup and call the Go program as if it were 342 // the C main function. 343 #pragma cgo_export_static main