@@ -6,6 +6,107 @@ package runtime
6
6
7
7
import "unsafe"
8
8
9
+ /*
10
+ Stack layout parameters.
11
+ Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
12
+
13
+ The per-goroutine g->stackguard is set to point StackGuard bytes
14
+ above the bottom of the stack. Each function compares its stack
15
+ pointer against g->stackguard to check for overflow. To cut one
16
+ instruction from the check sequence for functions with tiny frames,
17
+ the stack is allowed to protrude StackSmall bytes below the stack
18
+ guard. Functions with large frames don't bother with the check and
19
+ always call morestack. The sequences are (for amd64, others are
20
+ similar):
21
+
22
+ guard = g->stackguard
23
+ frame = function's stack frame size
24
+ argsize = size of function arguments (call + return)
25
+
26
+ stack frame size <= StackSmall:
27
+ CMPQ guard, SP
28
+ JHI 3(PC)
29
+ MOVQ m->morearg, $(argsize << 32)
30
+ CALL morestack(SB)
31
+
32
+ stack frame size > StackSmall but < StackBig
33
+ LEAQ (frame-StackSmall)(SP), R0
34
+ CMPQ guard, R0
35
+ JHI 3(PC)
36
+ MOVQ m->morearg, $(argsize << 32)
37
+ CALL morestack(SB)
38
+
39
+ stack frame size >= StackBig:
40
+ MOVQ m->morearg, $((argsize << 32) | frame)
41
+ CALL morestack(SB)
42
+
43
+ The bottom StackGuard - StackSmall bytes are important: there has
44
+ to be enough room to execute functions that refuse to check for
45
+ stack overflow, either because they need to be adjacent to the
46
+ actual caller's frame (deferproc) or because they handle the imminent
47
+ stack overflow (morestack).
48
+
49
+ For example, deferproc might call malloc, which does one of the
50
+ above checks (without allocating a full frame), which might trigger
51
+ a call to morestack. This sequence needs to fit in the bottom
52
+ section of the stack. On amd64, morestack's frame is 40 bytes, and
53
+ deferproc's frame is 56 bytes. That fits well within the
54
+ StackGuard - StackSmall bytes at the bottom.
55
+ The linkers explore all possible call traces involving non-splitting
56
+ functions to make sure that this limit cannot be violated.
57
+ */
58
+
59
+ const (
60
+ // StackSystem is a number of additional bytes to add
61
+ // to each stack below the usual guard area for OS-specific
62
+ // purposes like signal handling. Used on Windows, Plan 9,
63
+ // and Darwin/ARM because they do not use a separate stack.
64
+ _StackSystem = goos_windows * 512 * ptrSize + goos_plan9 * 512 + goos_darwin * goarch_arm * 1024
65
+
66
+ // The minimum size of stack used by Go code
67
+ _StackMin = 2048
68
+
69
+ // The minimum stack size to allocate.
70
+ // The hackery here rounds FixedStack0 up to a power of 2.
71
+ _FixedStack0 = _StackMin + _StackSystem
72
+ _FixedStack1 = _FixedStack0 - 1
73
+ _FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1 )
74
+ _FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2 )
75
+ _FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4 )
76
+ _FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8 )
77
+ _FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16 )
78
+ _FixedStack = _FixedStack6 + 1
79
+
80
+ // Functions that need frames bigger than this use an extra
81
+ // instruction to do the stack split check, to avoid overflow
82
+ // in case SP - framesize wraps below zero.
83
+ // This value can be no bigger than the size of the unmapped
84
+ // space at zero.
85
+ _StackBig = 4096
86
+
87
+ // The stack guard is a pointer this many bytes above the
88
+ // bottom of the stack.
89
+ _StackGuard = 640 * stackGuardMultiplier + _StackSystem
90
+
91
+ // After a stack split check the SP is allowed to be this
92
+ // many bytes below the stack guard. This saves an instruction
93
+ // in the checking sequence for tiny frames.
94
+ _StackSmall = 128
95
+
96
+ // The maximum number of bytes that a chain of NOSPLIT
97
+ // functions can use.
98
+ _StackLimit = _StackGuard - _StackSystem - _StackSmall
99
+ )
100
+
101
+ // Goroutine preemption request.
102
+ // Stored into g->stackguard0 to cause split stack check failure.
103
+ // Must be greater than any real sp.
104
+ // 0xfffffade in hex.
105
+ const (
106
+ _StackPreempt = uintptrMask & - 1314
107
+ _StackFork = uintptrMask & - 1234
108
+ )
109
+
9
110
const (
10
111
// stackDebug == 0: no logging
11
112
// == 1: logging of per-stack operations
0 commit comments