void runtime·cgocall(void (*fn)(void*), void *arg) { Defer d; if(m->racecall) { runtime·asmcgocall(fn, arg); return; } if(!runtime·iscgo && !Windows) runtime·throw("cgocall unavailable"); if(fn == 0) runtime·throw("cgocall nil"); if(raceenabled) runtime·racereleasemerge(&cgosync); // Create an extra M for callbacks on threads not created by Go on first cgo call. if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0)) runtime·newextram(); m->ncgocall++; /* * Lock g to m to ensure we stay on the same stack if we do a * cgo callback. Add entry to defer stack in case of panic. */ runtime·lockOSThread(); d.fn = &endcgoV; d.siz = 0; d.link = g->defer; d.argp = (void*)-1; // unused because unlockm never recovers d.special = true; d.free = false; g->defer = &d; m->ncgo++; /* * Announce we are entering a system call * so that the scheduler knows to create another * M to run goroutines while we are in the * foreign code. * * The call to asmcgocall is guaranteed not to * split the stack and does not allocate memory, * so it is safe to call while "in a system call", outside * the $GOMAXPROCS accounting. */ runtime·entersyscall(); runtime·asmcgocall(fn, arg); runtime·exitsyscall(); if(g->defer != &d || d.fn != &endcgoV) runtime·throw("runtime: bad defer entry in cgocallback"); g->defer = d.link; endcgo(); }
// The main goroutine. void runtime·main(void) { // Lock the main goroutine onto this, the main OS thread, // during initialization. Most programs won't care, but a few // do require certain calls to be made by the main thread. // Those can arrange for main.main to run in the main thread // by calling runtime.LockOSThread during initialization // to preserve the lock. runtime·lockOSThread(); // From now on, newgoroutines may use non-main threads. setmcpumax(runtime·gomaxprocs); runtime·sched.init = true; scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·main); scvg->issystem = true; main·init(); runtime·sched.init = false; runtime·unlockOSThread(); // The deadlock detection has false negatives. // Let scvg start up, to eliminate the false negative // for the trivial program func main() { select{} }. runtime·gosched(); main·main(); if(raceenabled) runtime·racefini(); runtime·exit(0); for(;;) *(int32*)runtime·main = 0; }