From: Austin Clements Date: Sun, 21 Feb 2016 15:40:39 +0000 (-0500) Subject: runtime: define lock order between G status and channel lock X-Git-Tag: go1.7beta1~1283 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d45bf7228f742e63a30eef03e5288df332906838;p=gostls13.git runtime: define lock order between G status and channel lock Currently, locking a G's stack by setting its status to _Gcopystack or _Gscan is unordered with respect to channel locks. However, when we make stack shrinking concurrent, stack shrinking will need to lock the G and then acquire channel locks, which imposes an order on these. Document this lock ordering and fix closechan to respect it. Everything else already happens to respect it. For #12967. Change-Id: I4dd02675efffb3e7daa5285cf75bf24f987d90d4 Reviewed-on: https://go-review.googlesource.com/20041 Reviewed-by: Rick Hudson Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot --- diff --git a/src/runtime/chan.go b/src/runtime/chan.go index e89831783e..954b389f47 100644 --- a/src/runtime/chan.go +++ b/src/runtime/chan.go @@ -36,6 +36,10 @@ type hchan struct { // lock protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. + // + // Do not change another G's status while holding this lock + // (in particular, do not ready a G), as this can deadlock + // with stack shrinking. lock mutex } @@ -315,6 +319,8 @@ func closechan(c *hchan) { c.closed = 1 + var glist *g + // release all readers for { sg := c.recvq.dequeue() @@ -333,7 +339,8 @@ func closechan(c *hchan) { if raceenabled { raceacquireg(gp, unsafe.Pointer(c)) } - goready(gp, 3) + gp.schedlink.set(glist) + glist = gp } // release all writers (they will panic) @@ -351,9 +358,18 @@ func closechan(c *hchan) { if raceenabled { raceacquireg(gp, unsafe.Pointer(c)) } - goready(gp, 3) + gp.schedlink.set(glist) + glist = gp } unlock(&c.lock) + + // Ready all Gs now that we've dropped the channel lock. + for glist != nil { + gp := glist + glist = glist.schedlink.ptr() + gp.schedlink = 0 + goready(gp, 3) + } } // entry points for <- c from compiled code