diff options
Diffstat (limited to 'libgo/go/runtime/mcentral.go')
-rw-r--r-- | libgo/go/runtime/mcentral.go | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/libgo/go/runtime/mcentral.go b/libgo/go/runtime/mcentral.go index cd20dec..6013c94 100644 --- a/libgo/go/runtime/mcentral.go +++ b/libgo/go/runtime/mcentral.go @@ -81,8 +81,6 @@ func (c *mcentral) cacheSpan() *mspan { spanBytes := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) * _PageSize deductSweepCredit(spanBytes, 0) - sg := mheap_.sweepgen - traceDone := false if trace.enabled { traceGCSweepStart() @@ -104,6 +102,8 @@ func (c *mcentral) cacheSpan() *mspan { spanBudget := 100 var s *mspan + sl := newSweepLocker() + sg := sl.sweepGen // Try partial swept spans first. if s = c.partialSwept(sg).pop(); s != nil { @@ -116,9 +116,10 @@ func (c *mcentral) cacheSpan() *mspan { if s == nil { break } - if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { // We got ownership of the span, so let's sweep it and use it. s.sweep(true) + sl.dispose() goto havespan } // We failed to get ownership of the span, which means it's being or @@ -135,20 +136,22 @@ func (c *mcentral) cacheSpan() *mspan { if s == nil { break } - if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { // We got ownership of the span, so let's sweep it. s.sweep(true) // Check if there's any free space. freeIndex := s.nextFreeIndex() if freeIndex != s.nelems { s.freeindex = freeIndex + sl.dispose() goto havespan } // Add it to the swept list, because sweeping didn't give us any free space. - c.fullSwept(sg).push(s) + c.fullSwept(sg).push(s.mspan) } // See comment for partial unswept spans. } + sl.dispose() if trace.enabled { traceGCSweepDone() traceDone = true @@ -211,7 +214,13 @@ func (c *mcentral) uncacheSpan(s *mspan) { if stale { // It's stale, so just sweep it. Sweeping will put it on // the right list. - s.sweep(false) + // + // We don't use a sweepLocker here. Stale cached spans + // aren't in the global sweep lists, so mark termination + // itself holds up sweep completion until all mcaches + // have been swept. + ss := sweepLocked{s} + ss.sweep(false) } else { if int(s.nelems)-int(s.allocCount) > 0 { // Put it back on the partial swept list. @@ -229,14 +238,14 @@ func (c *mcentral) grow() *mspan { npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) size := uintptr(class_to_size[c.spanclass.sizeclass()]) - s := mheap_.alloc(npages, c.spanclass, true) + s, _ := mheap_.alloc(npages, c.spanclass, true) if s == nil { return nil } // Use division by multiplication and shifts to quickly compute: // n := (npages << _PageShift) / size - n := (npages << _PageShift) >> s.divShift * uintptr(s.divMul) >> s.divShift2 + n := s.divideByElemSize(npages << _PageShift) s.limit = s.base() + size*n heapBitsForAddr(s.base()).initSpan(s) return s |