runtime·stackalloc(uint32 n) { uint32 pos; void *v; // Stackalloc must be called on scheduler stack, so that we // never try to grow the stack during the code that stackalloc runs. // Doing so would cause a deadlock (issue 1547). if(g != m->g0) runtime·throw("stackalloc not on scheduler stack"); // Stack allocator uses malloc/free most of the time, // but if we're in the middle of malloc and need stack, // we have to do something else to avoid deadlock. // In that case, we fall back on a fixed-size free-list // allocator, assuming that inside malloc all the stack // frames are small, so that all the stack allocations // will be a single size, the minimum (right now, 5k). if(n == FixedStack || m->mallocing || m->gcing) { if(n != FixedStack) { runtime·printf("stackalloc: in malloc, size=%d want %d\n", FixedStack, n); runtime·throw("stackalloc"); } if(m->stackcachecnt == 0) stackcacherefill(); pos = m->stackcachepos; pos = (pos - 1) % StackCacheSize; v = m->stackcache[pos]; m->stackcachepos = pos; m->stackcachecnt--; m->stackinuse++; return v; } return runtime·mallocgc(n, FlagNoProfiling|FlagNoGC, 0, 0); }
runtime·stackalloc(G *gp, uint32 n) { uint32 pos; void *v; bool malloced; Stktop *top; // Stackalloc must be called on scheduler stack, so that we // never try to grow the stack during the code that stackalloc runs. // Doing so would cause a deadlock (issue 1547). if(g != m->g0) runtime·throw("stackalloc not on scheduler stack"); if((n & (n-1)) != 0) runtime·throw("stack size not a power of 2"); if(StackDebug >= 1) runtime·printf("stackalloc %d\n", n); gp->stacksize += n; if(runtime·debug.efence || StackFromSystem) { v = runtime·SysAlloc(ROUND(n, PageSize), &mstats.stacks_sys); if(v == nil) runtime·throw("out of memory (stackalloc)"); return v; } // Minimum-sized stacks are allocated with a fixed-size free-list allocator, // but if we need a stack of a bigger size, we fall back on malloc // (assuming that inside malloc all the stack frames are small, // so that we do not deadlock). malloced = true; if(n == FixedStack || m->mallocing) { if(n != FixedStack) { runtime·printf("stackalloc: in malloc, size=%d want %d\n", FixedStack, n); runtime·throw("stackalloc"); } if(m->stackcachecnt == 0) stackcacherefill(); pos = m->stackcachepos; pos = (pos - 1) % StackCacheSize; v = m->stackcache[pos]; m->stackcachepos = pos; m->stackcachecnt--; m->stackinuse++; malloced = false; } else v = runtime·mallocgc(n, 0, FlagNoProfiling|FlagNoGC|FlagNoZero|FlagNoInvokeGC); top = (Stktop*)((byte*)v+n-sizeof(Stktop)); runtime·memclr((byte*)top, sizeof(*top)); top->malloced = malloced; return v; }