// 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; }
void runtime·newproc(int32 siz, byte* fn, ...) { byte *argp; if(thechar == '5') argp = (byte*)(&fn+2); // skip caller's saved LR else argp = (byte*)(&fn+1); runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz)); }
static void addtimer ( Timer *t ) { int32 n; Timer **nt; #line 110 "/home/14/ren/source/golang/go/src/pkg/runtime/time.goc" if ( t->when < 0 ) t->when = ( 1LL<<63 ) -1; #line 113 "/home/14/ren/source/golang/go/src/pkg/runtime/time.goc" if ( timers.len >= timers.cap ) { #line 115 "/home/14/ren/source/golang/go/src/pkg/runtime/time.goc" n = 16; if ( n <= timers.cap ) n = timers.cap*3 / 2; nt = runtime·malloc ( n*sizeof nt[0] ) ; runtime·memmove ( nt , timers.t , timers.len*sizeof nt[0] ) ; runtime·free ( timers.t ) ; timers.t = nt; timers.cap = n; } t->i = timers.len++; timers.t[t->i] = t; siftup ( t->i ) ; if ( t->i == 0 ) { #line 129 "/home/14/ren/source/golang/go/src/pkg/runtime/time.goc" if ( timers.sleeping ) { timers.sleeping = false; runtime·notewakeup ( &timers.waitnote ) ; } if ( timers.rescheduling ) { timers.rescheduling = false; runtime·ready ( timers.timerproc ) ; } } if ( timers.timerproc == nil ) { timers.timerproc = runtime·newproc1 ( &timerprocv , nil , 0 , 0 , addtimer ) ; timers.timerproc->issystem = true; } if ( debug ) dumptimers ( "addtimer" ) ; }
// 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); }
void gc(int32 force) { int64 t0, t1; byte *p; Finalizer *fp; // The gc is turned off (via enablegc) until // the bootstrap has completed. // Also, malloc gets called in the guts // of a number of libraries that might be // holding locks. To avoid priority inversion // problems, don't bother trying to run gc // while holding a lock. The next mallocgc // without a lock will do the gc instead. if(!mstats.enablegc || m->locks > 0 || panicking) return; if(gcpercent == -2) { // first time through p = getenv("GOGC"); if(p == nil || p[0] == '\0') gcpercent = 100; else if(strcmp(p, (byte*)"off") == 0) gcpercent = -1; else gcpercent = atoi(p); } if(gcpercent < 0) return; semacquire(&gcsema); t0 = nanotime(); m->gcing = 1; stoptheworld(); if(mheap.Lock.key != 0) throw("mheap locked during gc"); if(force || mstats.heap_alloc >= mstats.next_gc) { mark(); sweep(); stealcache(); mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100; } m->gcing = 0; m->locks++; // disable gc during the mallocs in newproc fp = finq; if(fp != nil) { // kick off or wake up goroutine to run queued finalizers if(fing == nil) fing = newproc1((byte*)runfinq, nil, 0, 0); else if(fingwait) { fingwait = 0; ready(fing); } } m->locks--; t1 = nanotime(); mstats.numgc++; mstats.pause_ns += t1 - t0; if(mstats.debuggc) printf("pause %D\n", t1-t0); semrelease(&gcsema); starttheworld(); // give the queued finalizers, if any, a chance to run if(fp != nil) gosched(); }