G* __go_go(void (*fn)(void*), void* arg) { byte *sp; size_t spsize; G * volatile newg; // volatile to avoid longjmp warning schedlock(); if((newg = gfget()) != nil){ #ifdef USING_SPLIT_STACK int dont_block_signals = 0; sp = __splitstack_resetcontext(&newg->stack_context[0], &spsize); __splitstack_block_signals_context(&newg->stack_context[0], &dont_block_signals, nil); #else sp = newg->gcinitial_sp; spsize = newg->gcstack_size; if(spsize == 0) runtime_throw("bad spsize in __go_go"); newg->gcnext_sp = sp; #endif } else { newg = runtime_malg(StackMin, &sp, &spsize); if(runtime_lastg == nil) runtime_allg = newg; else runtime_lastg->alllink = newg; runtime_lastg = newg; } newg->status = Gwaiting; newg->waitreason = "new goroutine"; newg->entry = (byte*)fn; newg->param = arg; newg->gopc = (uintptr)__builtin_return_address(0); runtime_sched.gcount++; runtime_sched.goidgen++; newg->goid = runtime_sched.goidgen; if(sp == nil) runtime_throw("nil g->stack0"); getcontext(&newg->context); newg->context.uc_stack.ss_sp = sp; #ifdef MAKECONTEXT_STACK_TOP newg->context.uc_stack.ss_sp += spsize; #endif newg->context.uc_stack.ss_size = spsize; makecontext(&newg->context, kickoff, 0); newprocreadylocked(newg); schedunlock(); return newg; //printf(" goid=%d\n", newg->goid); }
runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc) { byte *sp; G *newg; int32 siz; //printf("newproc1 %p %p narg=%d nret=%d\n", fn, argp, narg, nret); siz = narg + nret; siz = (siz+7) & ~7; // We could instead create a secondary stack frame // and make it look like goexit was on the original but // the call to the actual goroutine function was split. // Not worth it: this is almost always an error. if(siz > StackMin - 1024) runtime·throw("runtime.newproc: function arguments too large for new goroutine"); schedlock(); if((newg = gfget()) != nil){ if(newg->stackguard - StackGuard != newg->stack0) runtime·throw("invalid stack in newg"); } else { newg = runtime·malg(StackMin); if(runtime·lastg == nil) runtime·allg = newg; else runtime·lastg->alllink = newg; runtime·lastg = newg; } newg->status = Gwaiting; newg->waitreason = "new goroutine"; sp = newg->stackbase; sp -= siz; runtime·memmove(sp, argp, narg); if(thechar == '5') { // caller's LR sp -= sizeof(void*); *(void**)sp = nil; } newg->sched.sp = sp; newg->sched.pc = (byte*)runtime·goexit; newg->sched.g = newg; newg->entry = fn; newg->gopc = (uintptr)callerpc; runtime·sched.gcount++; runtime·sched.goidgen++; newg->goid = runtime·sched.goidgen; newprocreadylocked(newg); schedunlock(); return newg; //printf(" goid=%d\n", newg->goid); }
runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc) { byte *sp; G *newg; int32 siz; //printf("newproc1 %p %p narg=%d nret=%d\n", fn, argp, narg, nret); siz = narg + nret; siz = (siz+7) & ~7; if(siz > 1024) runtime·throw("runtime.newproc: too many args"); schedlock(); if((newg = gfget()) != nil){ newg->status = Gwaiting; if(newg->stackguard - StackGuard != newg->stack0) runtime·throw("invalid stack in newg"); } else { newg = runtime·malg(StackMin); newg->status = Gwaiting; newg->alllink = runtime·allg; runtime·allg = newg; } sp = newg->stackbase; sp -= siz; runtime·mcpy(sp, argp, narg); if(thechar == '5') { // caller's LR sp -= sizeof(void*); *(void**)sp = nil; } newg->sched.sp = sp; newg->sched.pc = (byte*)runtime·goexit; newg->sched.g = newg; newg->entry = fn; newg->gopc = (uintptr)callerpc; runtime·sched.gcount++; runtime·goidgen++; newg->goid = runtime·goidgen; newprocreadylocked(newg); schedunlock(); return newg; //printf(" goid=%d\n", newg->goid); }