| // Copyright 2011 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package runtime | |
| /* | |
| Stack layout parameters. | |
| Included both by runtime (compiled via 6c) and linkers (compiled via gcc). | |
| The per-goroutine g->stackguard is set to point StackGuard bytes | |
| above the bottom of the stack. Each function compares its stack | |
| pointer against g->stackguard to check for overflow. To cut one | |
| instruction from the check sequence for functions with tiny frames, | |
| the stack is allowed to protrude StackSmall bytes below the stack | |
| guard. Functions with large frames don't bother with the check and | |
| always call morestack. The sequences are (for amd64, others are | |
| similar): | |
| guard = g->stackguard | |
| frame = function's stack frame size | |
| argsize = size of function arguments (call + return) | |
| stack frame size <= StackSmall: | |
| CMPQ guard, SP | |
| JHI 3(PC) | |
| MOVQ m->morearg, $(argsize << 32) | |
| CALL morestack(SB) | |
| stack frame size > StackSmall but < StackBig | |
| LEAQ (frame-StackSmall)(SP), R0 | |
| CMPQ guard, R0 | |
| JHI 3(PC) | |
| MOVQ m->morearg, $(argsize << 32) | |
| CALL morestack(SB) | |
| stack frame size >= StackBig: | |
| MOVQ m->morearg, $((argsize << 32) | frame) | |
| CALL morestack(SB) | |
| The bottom StackGuard - StackSmall bytes are important: there has | |
| to be enough room to execute functions that refuse to check for | |
| stack overflow, either because they need to be adjacent to the | |
| actual caller's frame (deferproc) or because they handle the imminent | |
| stack overflow (morestack). | |
| For example, deferproc might call malloc, which does one of the | |
| above checks (without allocating a full frame), which might trigger | |
| a call to morestack. This sequence needs to fit in the bottom | |
| section of the stack. On amd64, morestack's frame is 40 bytes, and | |
| deferproc's frame is 56 bytes. That fits well within the | |
| StackGuard - StackSmall bytes at the bottom. | |
| The linkers explore all possible call traces involving non-splitting | |
| functions to make sure that this limit cannot be violated. | |
| */ | |
| const ( | |
| // StackSystem is a number of additional bytes to add | |
| // to each stack below the usual guard area for OS-specific | |
| // purposes like signal handling. Used on Windows, Plan 9, | |
| // and Darwin/ARM because they do not use a separate stack. | |
| _StackSystem = goos_windows*512*ptrSize + goos_plan9*512 + goos_darwin*goarch_arm*1024 | |
| // The minimum size of stack used by Go code | |
| _StackMin = 2048 | |
| // The minimum stack size to allocate. | |
| // The hackery here rounds FixedStack0 up to a power of 2. | |
| _FixedStack0 = _StackMin + _StackSystem | |
| _FixedStack1 = _FixedStack0 - 1 | |
| _FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1) | |
| _FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2) | |
| _FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4) | |
| _FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8) | |
| _FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16) | |
| _FixedStack = _FixedStack6 + 1 | |
| // Functions that need frames bigger than this use an extra | |
| // instruction to do the stack split check, to avoid overflow | |
| // in case SP - framesize wraps below zero. | |
| // This value can be no bigger than the size of the unmapped | |
| // space at zero. | |
| _StackBig = 4096 | |
| // The stack guard is a pointer this many bytes above the | |
| // bottom of the stack. | |
| _StackGuard = 640*stackGuardMultiplier + _StackSystem | |
| // After a stack split check the SP is allowed to be this | |
| // many bytes below the stack guard. This saves an instruction | |
| // in the checking sequence for tiny frames. | |
| _StackSmall = 128 | |
| // The maximum number of bytes that a chain of NOSPLIT | |
| // functions can use. | |
| _StackLimit = _StackGuard - _StackSystem - _StackSmall | |
| ) | |
| // Goroutine preemption request. | |
| // Stored into g->stackguard0 to cause split stack check failure. | |
| // Must be greater than any real sp. | |
| // 0xfffffade in hex. | |
| const ( | |
| _StackPreempt = uintptrMask & -1314 | |
| _StackFork = uintptrMask & -1234 | |
| ) |