Exemplo n.º 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();
}
Exemplo n.º 2
0
runtime·newm(void)
{
	M *m;

	m = runtime·malloc(sizeof(M));
	mcommoninit(m);

	if(runtime·iscgo) {
		CgoThreadStart ts;

		if(libcgo_thread_start == nil)
			runtime·throw("libcgo_thread_start missing");
		// pthread_create will make us a stack.
		m->g0 = runtime·malg(-1);
		ts.m = m;
		ts.g = m->g0;
		ts.fn = runtime·mstart;
		runtime·asmcgocall(libcgo_thread_start, &ts);
	} else {
		if(Windows)
			// windows will layout sched stack on os stack
			m->g0 = runtime·malg(-1);
		else
			m->g0 = runtime·malg(8192);
		runtime·newosproc(m, m->g0, m->g0->stackbase, runtime·mstart);
	}

	return m;
}
Exemplo n.º 3
0
// Update the C environment if cgo is loaded.
// Called from syscall.Setenv.
void
syscall·setenv_c(String k, String v)
{
	byte *arg[2];
	uintptr len;

	if(_cgo_setenv == nil)
		return;

	// Objects that are explicitly freed must be at least 16 bytes in size,
	// so that they are not allocated using tiny alloc.
	len = k.len + 1;
	if(len < TinySize)
		len = TinySize;
	arg[0] = runtime·malloc(len);
	runtime·memmove(arg[0], k.str, k.len);
	arg[0][k.len] = 0;

	len = v.len + 1;
	if(len < TinySize)
		len = TinySize;
	arg[1] = runtime·malloc(len);
	runtime·memmove(arg[1], v.str, v.len);
	arg[1][v.len] = 0;

	runtime·asmcgocall((void*)_cgo_setenv, arg);
	runtime·free(arg[0]);
	runtime·free(arg[1]);
}
Exemplo n.º 4
0
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
void
runtime·minit(void)
{
	runtime·asmcgocall(runtime·miniterrno, (void *)libc·___errno);
	// Initialize signal handling
	runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
	runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
Exemplo n.º 5
0
runtime·stdcall(void *fn, int32 count, ...)
{
	WinCall c;

	c.fn = fn;
	c.n = count;
	c.args = (uintptr*)&count + 1;
	runtime·asmcgocall(runtime·asmstdcall, &c);
	return (void*)c.r1;
}
Exemplo n.º 6
0
void
runtime·cgocall(void (*fn)(void*), void *arg)
{
	Defer d;

	if(!runtime·iscgo && !Windows)
		runtime·throw("cgocall unavailable");

	if(fn == 0)
		runtime·throw("cgocall nil");

	m->ncgocall++;

	/*
	 * Lock g to m to ensure we stay on the same stack if we do a
	 * cgo callback.
	 */
	d.nofree = false;
	if(m->lockedg == nil) {
		m->lockedg = g;
		g->lockedm = m;

		// Add entry to defer stack in case of panic.
		d.fn = (byte*)unlockm;
		d.siz = 0;
		d.link = g->defer;
		d.argp = (void*)-1;  // unused because unlockm never recovers
		d.nofree = true;
		g->defer = &d;
	}

	/*
	 * 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(d.nofree) {
		if(g->defer != &d || d.fn != (byte*)unlockm)
			runtime·throw("runtime: bad defer entry in cgocallback");
		g->defer = d.link;
		unlockm();
	}
}
Exemplo n.º 7
0
uintptr
runtime·sysvicall6(uintptr fn, int32 count, ...)
{
	runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
	m->libcall.fn = (void*)fn;
	m->libcall.n = (uintptr)count;
	for(;count; count--)
		m->scratch.v[count - 1] = *((uintptr*)&count + count);
	m->libcall.args = (uintptr*)&m->scratch.v[0];
	runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
	return m->libcall.r1;
}
Exemplo n.º 8
0
int32
runtime·semasleep(int64 ns)
{
	M *m;

	m = g->m;
	if(ns >= 0) {
		m->ts.tv_sec = ns / 1000000000LL;
		m->ts.tv_nsec = ns % 1000000000LL;

		m->libcall.fn = (uintptr)(void*)libc·sem_reltimedwait_np;
		m->libcall.n = 2;
		runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
		m->scratch.v[0] = m->waitsema;
		m->scratch.v[1] = (uintptr)&m->ts;
		m->libcall.args = (uintptr)(uintptr*)&m->scratch;
		runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
		if(*m->perrno != 0) {
			if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m->perrno == EINTR)
				return -1;
			runtime·throw("sem_reltimedwait_np");
		}
		return 0;
	}
	for(;;) {
		m->libcall.fn = (uintptr)(void*)libc·sem_wait;
		m->libcall.n = 1;
		runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
		m->scratch.v[0] = m->waitsema;
		m->libcall.args = (uintptr)(uintptr*)&m->scratch;
		runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
		if(m->libcall.r1 == 0)
			break;
		if(*m->perrno == EINTR) 
			continue;
		runtime·throw("sem_wait");
	}
	return 0;
}
Exemplo n.º 9
0
runtime·stdcall(void *fn, int32 count, ...)
{
	m->libcall.fn = fn;
	m->libcall.n = count;
	m->libcall.args = (uintptr*)&count + 1;
	if(m->profilehz != 0) {
		// leave pc/sp for cpu profiler
		m->libcallg = g;
		m->libcallpc = (uintptr)runtime·getcallerpc(&fn);
		// sp must be the last, because once async cpu profiler finds
		// all three values to be non-zero, it will use them
		m->libcallsp = (uintptr)runtime·getcallersp(&fn);
	}
	runtime·asmcgocall(runtime·asmstdcall, &m->libcall);
	m->libcallsp = 0;
	return (void*)m->libcall.r1;
}
Exemplo n.º 10
0
uintptr
runtime·semacreate(void)
{
	SemT* sem;

	// Call libc's malloc rather than runtime·malloc.  This will
	// allocate space on the C heap.  We can't call runtime·malloc
	// here because it could cause a deadlock.
	g->m->libcall.fn = (uintptr)(void*)libc·malloc;
	g->m->libcall.n = 1;
	runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
	g->m->scratch.v[0] = (uintptr)sizeof(*sem);
	g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch;
	runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
	sem = (void*)g->m->libcall.r1;
	if(runtime·sem_init(sem, 0, 0) != 0)
		runtime·throw("sem_init");
	return (uintptr)sem;
}
Exemplo n.º 11
0
Arquivo: proc.c Projeto: machinaut/go
// Kick off new ms as needed (up to mcpumax).
// There are already `other' other cpus that will
// start looking for goroutines shortly.
// Sched is locked.
static void
matchmg(void)
{
	G *g;

	if(m->mallocing || m->gcing)
		return;
	while(runtime·sched.mcpu < runtime·sched.mcpumax && (g = gget()) != nil){
		M *m;

		// Find the m that will run g.
		if((m = mget(g)) == nil){
			m = runtime·malloc(sizeof(M));
			// Add to runtime·allm so garbage collector doesn't free m
			// when it is just in a register or thread-local storage.
			m->alllink = runtime·allm;
			runtime·allm = m;
			m->id = runtime·sched.mcount++;

			if(runtime·iscgo) {
				CgoThreadStart ts;

				if(libcgo_thread_start == nil)
					runtime·throw("libcgo_thread_start missing");
				// pthread_create will make us a stack.
				m->g0 = runtime·malg(-1);
				ts.m = m;
				ts.g = m->g0;
				ts.fn = runtime·mstart;
				runtime·asmcgocall(libcgo_thread_start, &ts);
			} else {
				if(Windows)
					// windows will layout sched stack on os stack
					m->g0 = runtime·malg(-1);
				else
					m->g0 = runtime·malg(8192);
				runtime·newosproc(m, m->g0, m->g0->stackbase, runtime·mstart);
			}
		}
		mnextg(m, g);
	}
}
Exemplo n.º 12
0
// Update the C environment if cgo is loaded.
// Called from syscall.Setenv.
void
syscall·setenv_c(String k, String v)
{
	byte *arg[2];

	if(libcgo_setenv == nil)
		return;

	arg[0] = runtime·malloc(k.len + 1);
	runtime·memmove(arg[0], k.str, k.len);
	arg[0][k.len] = 0;

	arg[1] = runtime·malloc(v.len + 1);
	runtime·memmove(arg[1], v.str, v.len);
	arg[1][v.len] = 0;

	runtime·asmcgocall((void*)libcgo_setenv, arg);
	runtime·free(arg[0]);
	runtime·free(arg[1]);
}
Exemplo n.º 13
0
runtime·newm(void)
{
    M *mp;
    static Type *mtype;  // The Go type M

    if(mtype == nil) {
        Eface e;
        runtime·gc_m_ptr(&e);
        mtype = ((PtrType*)e.type)->elem;
    }

    mp = runtime·cnew(mtype);
    mcommoninit(mp);

    if(runtime·iscgo) {
        CgoThreadStart ts;

        if(libcgo_thread_start == nil)
            runtime·throw("libcgo_thread_start missing");
        // pthread_create will make us a stack.
        mp->g0 = runtime·malg(-1);
        ts.m = mp;
        ts.g = mp->g0;
        ts.fn = runtime·mstart;
        runtime·asmcgocall(libcgo_thread_start, &ts);
    } else {
        if(Windows)
            // windows will layout sched stack on os stack
            mp->g0 = runtime·malg(-1);
        else
            mp->g0 = runtime·malg(8192);
        runtime·newosproc(mp, mp->g0, (byte*)mp->g0->stackbase, runtime·mstart);
    }

    return mp;
}