Beispiel #1
0
void
runtime·stoptheworld(void)
{
	uint32 v;

	schedlock();
	runtime·gcwaiting = 1;

	setmcpumax(1);

	// while mcpu > 1
	for(;;) {
		v = runtime·sched.atomic;
		if(atomic_mcpu(v) <= 1)
			break;

		// It would be unsafe for multiple threads to be using
		// the stopped note at once, but there is only
		// ever one thread doing garbage collection.
		runtime·noteclear(&runtime·sched.stopped);
		if(atomic_waitstop(v))
			runtime·throw("invalid waitstop");

		// atomic { waitstop = 1 }, predicated on mcpu <= 1 check above
		// still being true.
		if(!runtime·cas(&runtime·sched.atomic, v, v+(1<<waitstopShift)))
			continue;

		schedunlock();
		runtime·notesleep(&runtime·sched.stopped);
		schedlock();
	}
	runtime·singleproc = runtime·gomaxprocs == 1;
	schedunlock();
}
Beispiel #2
0
void
runtime·starttheworld(bool extra)
{
	M *m;

	schedlock();
	runtime·gcwaiting = 0;
	setmcpumax(runtime·gomaxprocs);
	matchmg();
	if(extra && canaddmcpu()) {
		// Start a new m that will (we hope) be idle
		// and so available to help when the next
		// garbage collection happens.
		// canaddmcpu above did mcpu++
		// (necessary, because m will be doing various
		// initialization work so is definitely running),
		// but m is not running a specific goroutine,
		// so set the helpgc flag as a signal to m's
		// first schedule(nil) to mcpu-- and grunning--.
		m = runtime·newm();
		m->helpgc = 1;
		runtime·sched.grunning++;
	}
	schedunlock();
}
Beispiel #3
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 = __go_go(runtime_MHeap_Scavenger, nil);
	main_init();
	runtime_sched.init = false;
	if(!runtime_sched.lockmain)
		runtime_UnlockOSThread();

	// For gccgo we have to wait until after main is initialized
	// to enable GC, because initializing main registers the GC
	// roots.
	mstats.enablegc = 1;

	// 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();
	runtime_exit(0);
	for(;;)
		*(int32*)0 = 0;
}
Beispiel #4
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);
	main·init();
	runtime·sched.init = false;
	if(!runtime·sched.lockmain)
		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();
	runtime·exit(0);
	for(;;)
		*(int32*)runtime·main = 0;
}
Beispiel #5
0
// The bootstrap sequence is:
//
//	call osinit
//	call schedinit
//	make & queue new G
//	call runtime_mstart
//
// The new G calls runtime_main.
void
runtime_schedinit(void)
{
	int32 n;
	const byte *p;

	m = &runtime_m0;
	g = &runtime_g0;
	m->g0 = g;
	m->curg = g;
	g->m = m;

	initcontext();
	inittlssize();

	m->nomemprof++;
	runtime_mallocinit();
	mcommoninit(m);

	runtime_goargs();
	runtime_goenvs();

	// For debugging:
	// Allocate internal symbol table representation now,
	// so that we don't need to call malloc when we crash.
	// runtime_findfunc(0);

	runtime_gomaxprocs = 1;
	p = runtime_getenv("GOMAXPROCS");
	if(p != nil && (n = runtime_atoi(p)) != 0) {
		if(n > maxgomaxprocs)
			n = maxgomaxprocs;
		runtime_gomaxprocs = n;
	}
	// wait for the main goroutine to start before taking
	// GOMAXPROCS into account.
	setmcpumax(1);
	runtime_singleproc = runtime_gomaxprocs == 1;

	canaddmcpu();	// mcpu++ to account for bootstrap m
	m->helpgc = 1;	// flag to tell schedule() to mcpu--
	runtime_sched.grunning++;

	// Can not enable GC until all roots are registered.
	// mstats.enablegc = 1;
	m->nomemprof--;
}
Beispiel #6
0
// The bootstrap sequence is:
//
//	call osinit
//	call schedinit
//	make & queue new G
//	call runtime·mstart
//
// The new G calls runtime·main.
void
runtime·schedinit(void)
{
    int32 n;
    byte *p;

    m->nomemprof++;
    runtime·mprofinit();
    runtime·mallocinit();
    mcommoninit(m);

    runtime·goargs();
    runtime·goenvs();

    // For debugging:
    // Allocate internal symbol table representation now,
    // so that we don't need to call malloc when we crash.
    // runtime·findfunc(0);

    runtime·gomaxprocs = 1;
    p = runtime·getenv("GOMAXPROCS");
    if(p != nil && (n = runtime·atoi(p)) != 0) {
        if(n > maxgomaxprocs)
            n = maxgomaxprocs;
        runtime·gomaxprocs = n;
    }
    // wait for the main goroutine to start before taking
    // GOMAXPROCS into account.
    setmcpumax(1);
    runtime·singleproc = runtime·gomaxprocs == 1;

    canaddmcpu();	// mcpu++ to account for bootstrap m
    m->helpgc = 1;	// flag to tell schedule() to mcpu--
    runtime·sched.grunning++;

    mstats.enablegc = 1;
    m->nomemprof--;

    if(raceenabled)
        runtime·raceinit();
}
Beispiel #7
0
// Implementation of runtime.GOMAXPROCS.
// delete when scheduler is stronger
int32
runtime·gomaxprocsfunc(int32 n)
{
	int32 ret;
	uint32 v;

	schedlock();
	ret = runtime·gomaxprocs;
	if(n <= 0)
		n = ret;
	if(n > maxgomaxprocs)
		n = maxgomaxprocs;
	runtime·gomaxprocs = n;
	if(runtime·gomaxprocs > 1)
		runtime·singleproc = false;
 	if(runtime·gcwaiting != 0) {
 		if(atomic_mcpumax(runtime·sched.atomic) != 1)
 			runtime·throw("invalid mcpumax during gc");
		schedunlock();
		return ret;
	}

	setmcpumax(n);

	// If there are now fewer allowed procs
	// than procs running, stop.
	v = runtime·atomicload(&runtime·sched.atomic);
	if(atomic_mcpu(v) > n) {
		schedunlock();
		runtime·gosched();
		return ret;
	}
	// handle more procs
	matchmg();
	schedunlock();
	return ret;
}
Beispiel #8
0
void
runtime·starttheworld(void)
{
    M *mp;
    int32 max;

    // Figure out how many CPUs GC could possibly use.
    max = runtime·gomaxprocs;
    if(max > runtime·ncpu)
        max = runtime·ncpu;
    if(max > MaxGcproc)
        max = MaxGcproc;

    schedlock();
    runtime·gcwaiting = 0;
    setmcpumax(runtime·gomaxprocs);
    matchmg();
    if(runtime·gcprocs() < max && canaddmcpu()) {
        // If GC could have used another helper proc, start one now,
        // in the hope that it will be available next time.
        // It would have been even better to start it before the collection,
        // but doing so requires allocating memory, so it's tricky to
        // coordinate.  This lazy approach works out in practice:
        // we don't mind if the first couple gc rounds don't have quite
        // the maximum number of procs.
        // canaddmcpu above did mcpu++
        // (necessary, because m will be doing various
        // initialization work so is definitely running),
        // but m is not running a specific goroutine,
        // so set the helpgc flag as a signal to m's
        // first schedule(nil) to mcpu-- and grunning--.
        mp = runtime·newm();
        mp->helpgc = 1;
        runtime·sched.grunning++;
    }
    schedunlock();
}
Beispiel #9
0
Datei: proc.c Projekt: rlcook0/go
// The bootstrap sequence is:
//
//	call osinit
//	call schedinit
//	make & queue new G
//	call runtime·mstart
//
// The new G calls runtime·main.
void
runtime·schedinit(void)
{
	int32 n;
	byte *p;

	m->nomemprof++;
	runtime·mallocinit();
	mcommoninit(m);

	runtime·goargs();
	runtime·goenvs();

	// For debugging:
	// Allocate internal symbol table representation now,
	// so that we don't need to call malloc when we crash.
	// runtime·findfunc(0);

	runtime·gomaxprocs = 1;
	p = runtime·getenv("GOMAXPROCS");
	if(p != nil && (n = runtime·atoi(p)) != 0) {
		if(n > maxgomaxprocs)
			n = maxgomaxprocs;
		runtime·gomaxprocs = n;
	}
	setmcpumax(runtime·gomaxprocs);
	runtime·singleproc = runtime·gomaxprocs == 1;

	canaddmcpu();	// mcpu++ to account for bootstrap m
	m->helpgc = 1;	// flag to tell schedule() to mcpu--
	runtime·sched.grunning++;

	mstats.enablegc = 1;
	m->nomemprof--;

	scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·schedinit);
}