]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: document stack barrier synchronization rules
authorAustin Clements <austin@google.com>
Fri, 18 Dec 2015 00:31:56 +0000 (16:31 -0800)
committerAustin Clements <austin@google.com>
Fri, 18 Dec 2015 17:08:52 +0000 (17:08 +0000)
Change-Id: I545e53561f37bceabd26d814d272cecc3ff19847
Reviewed-on: https://go-review.googlesource.com/18024
Reviewed-by: Russ Cox <rsc@golang.org>
src/runtime/mstkbar.go
src/runtime/runtime2.go

index 7d7235d259347fd4b040a96aaa6b2fd864b3a1e8..016625ae9255fff364ae925d8d7c502761d00a7d 100644 (file)
 // 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()
index 4a4d5f81ba33278f6e186c5e245d0841126442e8..9549d1f531b3dda31d38e293b434bfdf67b826e9 100644 (file)
@@ -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