Beispiel #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();
}
Beispiel #2
0
void
runtime·cgocallbackg(FuncVal *fn, void *arg, uintptr argsize)
{
	Defer d;

	if(m->racecall) {
		reflect·call(fn, arg, argsize);
		return;
	}

	if(g != m->curg)
		runtime·throw("runtime: bad g in cgocallback");

	runtime·exitsyscall();	// coming out of cgo call

	if(m->needextram) {
		m->needextram = 0;
		runtime·newextram();
	}

	// Add entry to defer stack in case of panic.
	d.fn = &unwindmf;
	d.siz = 0;
	d.link = g->defer;
	d.argp = (void*)-1;  // unused because unwindm never recovers
	d.special = true;
	d.free = false;
	g->defer = &d;

	if(raceenabled)
		runtime·raceacquire(&cgosync);

	// Invoke callback.
	reflect·call(fn, arg, argsize);

	if(raceenabled)
		runtime·racereleasemerge(&cgosync);

	// Pop defer.
	// Do not unwind m->g0->sched.sp.
	// Our caller, cgocallback, will do that.
	if(g->defer != &d || d.fn != &unwindmf)
		runtime·throw("runtime: bad defer entry in cgocallback");
	g->defer = d.link;

	runtime·entersyscall();	// going back to cgo call
}
Beispiel #3
0
void
runtime·cgocallbackg1(void)
{
	CallbackArgs *cb;
	Defer d;

	if(m->needextram) {
		m->needextram = 0;
		runtime·newextram();
	}

	// Add entry to defer stack in case of panic.
	d.fn = &unwindmf;
	d.siz = 0;
	d.link = g->defer;
	d.argp = (void*)-1;  // unused because unwindm never recovers
	d.special = true;
	d.free = false;
	g->defer = &d;

	if(raceenabled && !m->racecall)
		runtime·raceacquire(&cgosync);

	// Invoke callback.
	cb = CBARGS;
	runtime·newstackcall(cb->fn, cb->arg, cb->argsize);

	if(raceenabled && !m->racecall)
		runtime·racereleasemerge(&cgosync);

	// Pop defer.
	// Do not unwind m->g0->sched.sp.
	// Our caller, cgocallback, will do that.
	if(g->defer != &d || d.fn != &unwindmf)
		runtime·throw("runtime: bad defer entry in cgocallback");
	g->defer = d.link;
}