aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2015-12-17 16:31:56 -0800
committerAustin Clements <austin@google.com>2015-12-18 17:08:52 +0000
commitd446ba99a4e2b147de3afc29ff8d6ddfa4041203 (patch)
treef7fa275374ec1a55e8402aa1172872eda3278c3c /src/runtime
parentf90b48e0d347077cee4b6ea81671bfa04ddf681b (diff)
downloadgo-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.go22
-rw-r--r--src/runtime/runtime2.go2
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