Example #1
0
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();
}
Example #2
0
// 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;
}