Skip to content

Commit 046dce0

Browse files
prattmicgopherbot
authored andcommitted
runtime: use new list type for spanSPMCs
Now that we have a reusable list type, use it to replace the custom linked list code for spanSPMCs. Change-Id: I6a6a636ca54f2ba4b5c7dddba607c94ebf3c3ac8 Reviewed-on: https://go-review.googlesource.com/c/go/+/714021 Reviewed-by: Michael Knyszek <[email protected]> Auto-Submit: Michael Pratt <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 5f11275 commit 046dce0

File tree

3 files changed

+15
-45
lines changed

3 files changed

+15
-45
lines changed

src/runtime/mgc.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ func gcinit() {
195195

196196
work.startSema = 1
197197
work.markDoneSema = 1
198+
work.spanSPMCs.list.init(unsafe.Offsetof(spanSPMC{}.allnode))
198199
lockInit(&work.sweepWaiters.lock, lockRankSweepWaiters)
199200
lockInit(&work.assistQueue.lock, lockRankAssistQueue)
200201
lockInit(&work.strongFromWeak.lock, lockRankStrongFromWeakQueue)
@@ -354,7 +355,7 @@ type workType struct {
354355
// Only used if goexperiment.GreenTeaGC.
355356
spanSPMCs struct {
356357
lock mutex
357-
all *spanSPMC
358+
list listHeadManual // *spanSPMC
358359
}
359360

360361
// Restore 64-bit alignment on 32-bit.

src/runtime/mgcmark_greenteagc.go

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -635,20 +635,9 @@ func (q *spanQueue) destroy() {
635635

636636
lock(&work.spanSPMCs.lock)
637637

638-
// Remove and free each ring.
638+
// Remove, deinitialize, and free each ring.
639639
for r := (*spanSPMC)(q.chain.tail.Load()); r != nil; r = (*spanSPMC)(r.prev.Load()) {
640-
prev := r.allprev
641-
next := r.allnext
642-
if prev != nil {
643-
prev.allnext = next
644-
}
645-
if next != nil {
646-
next.allprev = prev
647-
}
648-
if work.spanSPMCs.all == r {
649-
work.spanSPMCs.all = next
650-
}
651-
640+
work.spanSPMCs.list.remove(unsafe.Pointer(r))
652641
r.deinit()
653642
mheap_.spanSPMCAlloc.free(unsafe.Pointer(r))
654643
}
@@ -688,15 +677,10 @@ func (q *spanQueue) destroy() {
688677
type spanSPMC struct {
689678
_ sys.NotInHeap
690679

691-
// allnext is the link to the next spanSPMC on the work.spanSPMCs list.
692-
// This is used to find and free dead spanSPMCs. Protected by
693-
// work.spanSPMCs.lock.
694-
allnext *spanSPMC
695-
696-
// allprev is the link to the previous spanSPMC on the work.spanSPMCs
697-
// list. This is used to find and free dead spanSPMCs. Protected by
680+
// allnode is the linked list node for work.spanSPMCs list. This is
681+
// used to find and free dead spanSPMCs. Protected by
698682
// work.spanSPMCs.lock.
699-
allprev *spanSPMC
683+
allnode listNodeManual
700684

701685
// dead indicates whether the spanSPMC is no longer in use.
702686
// Protected by the CAS to the prev field of the spanSPMC pointing
@@ -724,12 +708,7 @@ type spanSPMC struct {
724708
func newSpanSPMC(cap uint32) *spanSPMC {
725709
lock(&work.spanSPMCs.lock)
726710
r := (*spanSPMC)(mheap_.spanSPMCAlloc.alloc())
727-
next := work.spanSPMCs.all
728-
r.allnext = next
729-
if next != nil {
730-
next.allprev = r
731-
}
732-
work.spanSPMCs.all = r
711+
work.spanSPMCs.list.push(unsafe.Pointer(r))
733712
unlock(&work.spanSPMCs.lock)
734713

735714
// If cap < the capacity of a single physical page, round up.
@@ -765,8 +744,7 @@ func (r *spanSPMC) deinit() {
765744
r.head.Store(0)
766745
r.tail.Store(0)
767746
r.cap = 0
768-
r.allnext = nil
769-
r.allprev = nil
747+
r.allnode = listNodeManual{}
770748
}
771749

772750
// slot returns a pointer to slot i%r.cap.
@@ -795,26 +773,16 @@ func freeDeadSpanSPMCs() {
795773
// GOMAXPROCS, or if this list otherwise gets long, it would be nice to
796774
// have a way to batch work that allows preemption during processing.
797775
lock(&work.spanSPMCs.lock)
798-
if gcphase != _GCoff || work.spanSPMCs.all == nil {
776+
if gcphase != _GCoff || work.spanSPMCs.list.empty() {
799777
unlock(&work.spanSPMCs.lock)
800778
return
801779
}
802-
r := work.spanSPMCs.all
780+
r := (*spanSPMC)(work.spanSPMCs.list.head())
803781
for r != nil {
804-
next := r.allnext
782+
next := (*spanSPMC)(unsafe.Pointer(r.allnode.next))
805783
if r.dead.Load() {
806-
// It's dead. Deinitialize and free it.
807-
prev := r.allprev
808-
if prev != nil {
809-
prev.allnext = next
810-
}
811-
if next != nil {
812-
next.allprev = prev
813-
}
814-
if work.spanSPMCs.all == r {
815-
work.spanSPMCs.all = next
816-
}
817-
784+
// It's dead. Remove, deinitialize and free it.
785+
work.spanSPMCs.list.remove(unsafe.Pointer(r))
818786
r.deinit()
819787
mheap_.spanSPMCAlloc.free(unsafe.Pointer(r))
820788
}

src/runtime/mgcmark_nogreenteagc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func (q *spanQueue) destroy() {
6868

6969
type spanSPMC struct {
7070
_ sys.NotInHeap
71+
allnode listNodeManual
7172
}
7273

7374
func freeDeadSpanSPMCs() {

0 commit comments

Comments
 (0)