1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Garbage collector: stack barriers
7 // Stack barriers enable the garbage collector to determine how much
8 // of a gorountine stack has changed between when a stack is scanned
9 // during the concurrent scan phase and when it is re-scanned during
10 // the stop-the-world mark termination phase. Mark termination only
11 // needs to re-scan the changed part, so for deep stacks this can
12 // significantly reduce GC pause time compared to the alternative of
13 // re-scanning whole stacks. The deeper the stacks, the more stack
16 // When stacks are scanned during the concurrent scan phase, the stack
17 // scan installs stack barriers by selecting stack frames and
18 // overwriting the saved return PCs (or link registers) of these
19 // frames with the PC of a "stack barrier trampoline". Later, when a
20 // selected frame returns, it "returns" to this trampoline instead of
21 // returning to its actual caller. The trampoline records that the
22 // stack has unwound past this frame and jumps to the original return
23 // PC recorded when the stack barrier was installed. Mark termination
24 // re-scans only as far as the first frame that hasn't hit a stack
25 // barrier and then removes and un-hit stack barriers.
27 // This scheme is very lightweight. No special code is required in the
28 // mutator to record stack unwinding and the trampoline is only a few
29 // assembly instructions.
34 // The primary cost of stack barriers is book-keeping: the runtime has
35 // to record the locations of all stack barriers and the original
36 // return PCs in order to return to the correct caller when a stack
37 // barrier is hit and so it can remove un-hit stack barriers. In order
38 // to minimize this cost, the Go runtime places stack barriers in
39 // exponentially-spaced frames, starting 1K past the current frame.
40 // The book-keeping structure hence grows logarithmically with the
41 // size of the stack and mark termination re-scans at most twice as
42 // much stack as necessary.
44 // The runtime reserves space for this book-keeping structure at the
45 // top of the stack allocation itself (just above the outermost
46 // frame). This is necessary because the regular memory allocator can
47 // itself grow the stack, and hence can't be used when allocating
48 // stack-related structures.
50 // For debugging, the runtime also supports installing stack barriers
51 // at every frame. However, this requires significantly more
52 // book-keeping space.
57 // The runtime and the compiler cooperate to ensure that all objects
58 // reachable from the stack as of mark termination are marked.
59 // Anything unchanged since the concurrent scan phase will be marked
60 // because it is marked by the concurrent scan. After the concurrent
61 // scan, there are three possible classes of stack modifications that
64 // 1) Mutator writes below the lowest un-hit stack barrier. This
65 // includes all writes performed by an executing function to its own
66 // stack frame. This part of the stack will be re-scanned by mark
67 // termination, which will mark any objects made reachable from
68 // modifications to this part of the stack.
70 // 2) Mutator writes above the lowest un-hit stack barrier. It's
71 // possible for a mutator to modify the stack above the lowest un-hit
72 // stack barrier if a higher frame has passed down a pointer to a
73 // stack variable in its frame. This is called an "up-pointer". The
74 // compiler ensures that writes through up-pointers have an
75 // accompanying write barrier (it simply doesn't distinguish between
76 // writes through up-pointers and writes through heap pointers). This
77 // write barrier marks any object made reachable from modifications to
78 // this part of the stack.
80 // 3) Runtime writes to the stack. Various runtime operations such as
81 // sends to unbuffered channels can write to arbitrary parts of the
82 // stack, including above the lowest un-hit stack barrier. We solve
83 // this in two ways. In many cases, the runtime can perform an
84 // explicit write barrier operation like in case 2. However, in the
85 // case of bulk memory move (typedmemmove), the runtime doesn't
86 // necessary have ready access to a pointer bitmap for the memory
87 // being copied, so it simply unwinds any stack barriers below the
93 // Anything that inspects or manipulates the stack potentially needs
94 // to understand stack barriers. The most obvious case is that
95 // gentraceback needs to use the original return PC when it encounters
96 // the stack barrier trampoline. Anything that unwinds the stack such
97 // as panic/recover must unwind stack barriers in tandem with
98 // unwinding the stack.
100 // Stack barriers require that any goroutine whose stack has been
101 // scanned must execute write barriers. Go solves this by simply
102 // enabling write barriers globally during the concurrent scan phase.
103 // However, traditionally, write barriers are not enabled during this
109 // For the most part, accessing and modifying stack barriers is
110 // synchronized around GC safe points. Installing stack barriers
111 // forces the G to a safe point, while all other operations that
112 // modify stack barriers run on the G and prevent it from reaching a
115 // Subtlety arises when a G may be tracebacked when *not* at a safe
116 // point. This happens during sigprof. For this, each G has a "stack
117 // barrier lock" (see gcLockStackBarriers, gcUnlockStackBarriers).
118 // Operations that manipulate stack barriers acquire this lock, while
119 // sigprof tries to acquire it and simply skips the traceback if it
120 // can't acquire it. There is one exception for performance and
121 // complexity reasons: hitting a stack barrier manipulates the stack
122 // barrier list without acquiring the stack barrier lock. For this,
123 // gentraceback performs a special fix up if the traceback starts in
124 // the stack barrier function.
129 "runtime/internal/atomic"
130 "runtime/internal/sys"
134 const debugStackBarrier
= false
136 // firstStackBarrierOffset is the approximate byte offset at
137 // which to place the first stack barrier from the current SP.
138 // This is a lower bound on how much stack will have to be
139 // re-scanned during mark termination. Subsequent barriers are
140 // placed at firstStackBarrierOffset * 2^n offsets.
142 // For debugging, this can be set to 0, which will install a
143 // stack barrier at every frame. If you do this, you may also
144 // have to raise _StackMin, since the stack barrier
145 // bookkeeping will use a large amount of each stack.
146 var firstStackBarrierOffset
= 1024
148 // gcMaxStackBarriers returns the maximum number of stack barriers
149 // that can be installed in a stack of stackSize bytes.
150 func gcMaxStackBarriers(stackSize
int) (n
int) {
151 if firstStackBarrierOffset
== 0 {
152 // Special debugging case for inserting stack barriers
153 // at every frame. Steal half of the stack for the
154 // []stkbar. Technically, if the stack were to consist
155 // solely of return PCs we would need two thirds of
156 // the stack, but stealing that much breaks things and
157 // this doesn't happen in practice.
158 return stackSize
/ 2 / int(unsafe
.Sizeof(stkbar
{}))
161 offset
:= firstStackBarrierOffset
162 for offset
< stackSize
{
169 // gcInstallStackBarrier installs a stack barrier over the return PC of frame.
171 func gcInstallStackBarrier(gp
*g
, frame
*stkframe
) bool {
173 if debugStackBarrier
{
174 print("not installing stack barrier with no LR, goid=", gp
.goid
, "\n")
179 if frame
.fn
.entry
== cgocallback_gofuncPC
{
180 // cgocallback_gofunc doesn't return to its LR;
181 // instead, its return path puts LR in g.sched.pc and
182 // switches back to the system stack on which
183 // cgocallback_gofunc was originally called. We can't
184 // have a stack barrier in g.sched.pc, so don't
185 // install one in this frame.
186 if debugStackBarrier
{
187 print("not installing stack barrier over LR of cgocallback_gofunc, goid=", gp
.goid
, "\n")
192 // Save the return PC and overwrite it with stackBarrier.
193 var lrUintptr
uintptr
197 lrUintptr
= frame
.fp
- sys
.RegSize
199 lrPtr
:= (*sys
.Uintreg
)(unsafe
.Pointer(lrUintptr
))
200 if debugStackBarrier
{
201 print("install stack barrier at ", hex(lrUintptr
), " over ", hex(*lrPtr
), ", goid=", gp
.goid
, "\n")
202 if uintptr(*lrPtr
) != frame
.lr
{
203 print("frame.lr=", hex(frame
.lr
))
204 throw("frame.lr differs from stack LR")
208 gp
.stkbar
= gp
.stkbar
[:len(gp
.stkbar
)+1]
209 stkbar
:= &gp
.stkbar
[len(gp
.stkbar
)-1]
210 stkbar
.savedLRPtr
= lrUintptr
211 stkbar
.savedLRVal
= uintptr(*lrPtr
)
212 *lrPtr
= sys
.Uintreg(stackBarrierPC
)
216 // gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
218 // gp's stack barriers must be locked.
221 func gcRemoveStackBarriers(gp
*g
) {
222 if debugStackBarrier
&& gp
.stkbarPos
!= 0 {
223 print("hit ", gp
.stkbarPos
, " stack barriers, goid=", gp
.goid
, "\n")
226 // Remove stack barriers that we didn't hit.
227 for _
, stkbar
:= range gp
.stkbar
[gp
.stkbarPos
:] {
228 gcRemoveStackBarrier(gp
, stkbar
)
231 // Clear recorded stack barriers so copystack doesn't try to
234 gp
.stkbar
= gp
.stkbar
[:0]
237 // gcRemoveStackBarrier removes a single stack barrier. It is the
238 // inverse operation of gcInstallStackBarrier.
240 // This is nosplit to ensure gp's stack does not move.
244 func gcRemoveStackBarrier(gp
*g
, stkbar stkbar
) {
245 if debugStackBarrier
{
246 print("remove stack barrier at ", hex(stkbar
.savedLRPtr
), " with ", hex(stkbar
.savedLRVal
), ", goid=", gp
.goid
, "\n")
248 lrPtr
:= (*sys
.Uintreg
)(unsafe
.Pointer(stkbar
.savedLRPtr
))
249 if val
:= *lrPtr
; val
!= sys
.Uintreg(stackBarrierPC
) {
251 print("at *", hex(stkbar
.savedLRPtr
), " expected stack barrier PC ", hex(stackBarrierPC
), ", found ", hex(val
), ", goid=", gp
.goid
, "\n")
253 gcPrintStkbars(gp
, -1)
254 print(", gp.stack=[", hex(gp
.stack
.lo
), ",", hex(gp
.stack
.hi
), ")\n")
255 throw("stack barrier lost")
257 *lrPtr
= sys
.Uintreg(stkbar
.savedLRVal
)
260 // gcTryRemoveAllStackBarriers tries to remove stack barriers from all
261 // Gs in gps. It is best-effort and efficient. If it can't remove
262 // barriers from a G immediately, it will simply skip it.
263 func gcTryRemoveAllStackBarriers(gps
[]*g
) {
264 for _
, gp
:= range gps
{
267 switch s
:= readgstatus(gp
); s
{
271 case _Grunnable
, _Gsyscall
, _Gwaiting
:
272 if !castogscanstatus(gp
, s
, s|_Gscan
) {
275 gcLockStackBarriers(gp
)
276 gcRemoveStackBarriers(gp
)
277 gcUnlockStackBarriers(gp
)
285 // gcPrintStkbars prints the stack barriers of gp for debugging. It
286 // places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also
287 // place a "==>" marker before the marker'th entry.
288 func gcPrintStkbars(gp
*g
, marker
int) {
290 for i
, s
:= range gp
.stkbar
{
294 if i
== int(gp
.stkbarPos
) {
300 print("*", hex(s
.savedLRPtr
), "=", hex(s
.savedLRVal
))
302 if int(gp
.stkbarPos
) == len(gp
.stkbar
) {
305 if marker
== len(gp
.stkbar
) {
311 // gcUnwindBarriers marks all stack barriers up the frame containing
312 // sp as hit and removes them. This is used during stack unwinding for
313 // panic/recover and by heapBitsBulkBarrier to force stack re-scanning
314 // when its destination is on the stack.
316 // This is nosplit to ensure gp's stack does not move.
319 func gcUnwindBarriers(gp
*g
, sp
uintptr) {
320 gcLockStackBarriers(gp
)
321 // On LR machines, if there is a stack barrier on the return
322 // from the frame containing sp, this will mark it as hit even
323 // though it isn't, but it's okay to be conservative.
324 before
:= gp
.stkbarPos
325 for int(gp
.stkbarPos
) < len(gp
.stkbar
) && gp
.stkbar
[gp
.stkbarPos
].savedLRPtr
< sp
{
326 gcRemoveStackBarrier(gp
, gp
.stkbar
[gp
.stkbarPos
])
329 gcUnlockStackBarriers(gp
)
330 if debugStackBarrier
&& gp
.stkbarPos
!= before
{
331 print("skip barriers below ", hex(sp
), " in goid=", gp
.goid
, ": ")
332 // We skipped barriers between the "==>" marker
333 // (before) and the "@@@" marker (gp.stkbarPos).
334 gcPrintStkbars(gp
, int(before
))
339 // nextBarrierPC returns the original return PC of the next stack barrier.
340 // Used by getcallerpc, so it must be nosplit.
342 func nextBarrierPC() uintptr {
344 return gp
.stkbar
[gp
.stkbarPos
].savedLRVal
347 // setNextBarrierPC sets the return PC of the next stack barrier.
348 // Used by setcallerpc, so it must be nosplit.
350 func setNextBarrierPC(pc
uintptr) {
352 gcLockStackBarriers(gp
)
353 gp
.stkbar
[gp
.stkbarPos
].savedLRVal
= pc
354 gcUnlockStackBarriers(gp
)
357 // gcLockStackBarriers synchronizes with tracebacks of gp's stack
358 // during sigprof for installation or removal of stack barriers. It
359 // blocks until any current sigprof is done tracebacking gp's stack
360 // and then disallows profiling tracebacks of gp's stack.
362 // This is necessary because a sigprof during barrier installation or
363 // removal could observe inconsistencies between the stkbar array and
364 // the stack itself and crash.
367 func gcLockStackBarriers(gp
*g
) {
368 // Disable preemption so scanstack cannot run while the caller
369 // is manipulating the stack barriers.
371 for !atomic
.Cas(&gp
.stackLock
, 0, 1) {
377 func gcTryLockStackBarriers(gp
*g
) bool {
379 result
:= atomic
.Cas(&gp
.stackLock
, 0, 1)
386 func gcUnlockStackBarriers(gp
*g
) {
387 atomic
.Store(&gp
.stackLock
, 0)