diff options
| author | Austin Clements <austin@google.com> | 2015-12-17 16:31:56 -0800 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2015-12-18 17:08:52 +0000 |
| commit | d446ba99a4e2b147de3afc29ff8d6ddfa4041203 (patch) | |
| tree | f7fa275374ec1a55e8402aa1172872eda3278c3c /src/runtime | |
| parent | f90b48e0d347077cee4b6ea81671bfa04ddf681b (diff) | |
| download | go-d446ba99a4e2b147de3afc29ff8d6ddfa4041203.tar.xz | |
runtime: document stack barrier synchronization rules
Change-Id: I545e53561f37bceabd26d814d272cecc3ff19847
Reviewed-on: https://go-review.googlesource.com/18024
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/mstkbar.go | 22 | ||||
| -rw-r--r-- | src/runtime/runtime2.go | 2 |
2 files changed, 23 insertions, 1 deletions
diff --git a/src/runtime/mstkbar.go b/src/runtime/mstkbar.go index 7d7235d259..016625ae92 100644 --- a/src/runtime/mstkbar.go +++ b/src/runtime/mstkbar.go @@ -102,6 +102,26 @@ // enabling write barriers globally during the concurrent scan phase. // However, traditionally, write barriers are not enabled during this // phase. +// +// Synchronization +// --------------- +// +// For the most part, accessing and modifying stack barriers is +// synchronized around GC safe points. Installing stack barriers +// forces the G to a safe point, while all other operations that +// modify stack barriers run on the G and prevent it from reaching a +// safe point. +// +// Subtlety arises when a G may be tracebacked when *not* at a safe +// point. This happens during sigprof. For this, each G has a "stack +// barrier lock" (see gcLockStackBarriers, gcUnlockStackBarriers). +// Operations that manipulate stack barriers acquire this lock, while +// sigprof tries to acquire it and simply skips the traceback if it +// can't acquire it. There is one exception for performance and +// complexity reasons: hitting a stack barrier manipulates the stack +// barrier list without acquiring the stack barrier lock. For this, +// gentraceback performs a special fix up if the traceback starts in +// the stack barrier function. package runtime @@ -321,6 +341,8 @@ func setNextBarrierPC(pc uintptr) { // //go:nosplit func gcLockStackBarriers(gp *g) { + // Disable preemption so scanstack cannot run while the caller + // is manipulating the stack barriers. acquirem() for !atomic.Cas(&gp.stackLock, 0, 1) { osyield() diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 4a4d5f81ba..9549d1f531 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -233,7 +233,7 @@ type g struct { sched gobuf syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc - stkbar []stkbar // stack barriers, from low to high + stkbar []stkbar // stack barriers, from low to high (see top of mstkbar.go) stkbarPos uintptr // index of lowest stack barrier not hit stktopsp uintptr // expected sp at top of stack, to check in traceback param unsafe.Pointer // passed parameter on wakeup |
