diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/runtime/chan.go | 1 | ||||
| -rw-r--r-- | src/runtime/mgc0.go | 16 | ||||
| -rw-r--r-- | src/runtime/proc.go | 10 | ||||
| -rw-r--r-- | src/runtime/select.go | 2 | ||||
| -rw-r--r-- | src/runtime/sema.go | 2 |
5 files changed, 31 insertions, 0 deletions
diff --git a/src/runtime/chan.go b/src/runtime/chan.go index 0049701826..0eb87df74f 100644 --- a/src/runtime/chan.go +++ b/src/runtime/chan.go @@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog { return nil } q.first = sgp.next + sgp.next = nil if q.last == sgp { q.last = nil } diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 3a7204b54f..cbf5e9cfde 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -51,10 +51,26 @@ func clearpools() { if c := p.mcache; c != nil { c.tiny = nil c.tinysize = 0 + + // disconnect cached list before dropping it on the floor, + // so that a dangling ref to one entry does not pin all of them. + var sg, sgnext *sudog + for sg = c.sudogcache; sg != nil; sg = sgnext { + sgnext = sg.next + sg.next = nil + } c.sudogcache = nil } + // clear defer pools for i := range p.deferpool { + // disconnect cached list before dropping it on the floor, + // so that a dangling ref to one entry does not pin all of them. + var d, dlink *_defer + for d = p.deferpool[i]; d != nil; d = dlink { + dlink = d.link + d.link = nil + } p.deferpool[i] = nil } } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 5b8c7d8ae9..517ca03df6 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -152,6 +152,7 @@ func acquireSudog() *sudog { gothrow("acquireSudog: found s.elem != nil in cache") } c.sudogcache = s.next + s.next = nil return s } @@ -177,6 +178,15 @@ func releaseSudog(s *sudog) { if s.selectdone != nil { gothrow("runtime: sudog with non-nil selectdone") } + if s.next != nil { + gothrow("runtime: sudog with non-nil next") + } + if s.prev != nil { + gothrow("runtime: sudog with non-nil prev") + } + if s.waitlink != nil { + gothrow("runtime: sudog with non-nil waitlink") + } gp := getg() if gp.param != nil { gothrow("runtime: releaseSudog with non-nil gp.param") diff --git a/src/runtime/select.go b/src/runtime/select.go index efe68c1f5c..f735a71e2f 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -404,6 +404,7 @@ loop: } } sgnext = sglist.waitlink + sglist.waitlink = nil releaseSudog(sglist) sglist = sgnext } @@ -641,6 +642,7 @@ func (q *waitq) dequeueSudoG(s *sudog) { if q.last == sgp { q.last = prevsgp } + s.next = nil return } l = &sgp.next diff --git a/src/runtime/sema.go b/src/runtime/sema.go index d2a028c01b..26dbd30ea3 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) { } unlock(&s.lock) if wake != nil { + wake.next = nil goready(wake.g) } } else { @@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) { if wake.releasetime != 0 { wake.releasetime = cputicks() } + wake.next = nil goready(wake.g) n-- } |
