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