mirror of
https://github.com/golang/go
synced 2024-11-18 13:54:59 -07:00
runtime: make mSpanList more go:notinheap-friendly
Currently mspan links to its previous mspan using a **mspan field that points to the previous span's next field. This simplifies some of the list manipulation code, but is going to make it very hard to convince the compiler that mspan list manipulations don't need write barriers. Fix this by using a more traditional ("boring") linked list that uses a simple *mspan pointer to the previous mspan. This complicates some of the list manipulation slightly, but it will let us eliminate all write barriers from the mspan list manipulation code by marking mspan go:notinheap. Change-Id: I0d0b212db5f20002435d2a0ed2efc8aa0364b905 Reviewed-on: https://go-review.googlesource.com/30940 Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
77527a316b
commit
991a85c889
@ -122,15 +122,14 @@ var mSpanStateNames = []string{
|
|||||||
|
|
||||||
// mSpanList heads a linked list of spans.
|
// mSpanList heads a linked list of spans.
|
||||||
//
|
//
|
||||||
// Linked list structure is based on BSD's "tail queue" data structure.
|
|
||||||
type mSpanList struct {
|
type mSpanList struct {
|
||||||
first *mspan // first span in list, or nil if none
|
first *mspan // first span in list, or nil if none
|
||||||
last **mspan // last span's next field, or first if none
|
last *mspan // last span in list, or nil if none
|
||||||
}
|
}
|
||||||
|
|
||||||
type mspan struct {
|
type mspan struct {
|
||||||
next *mspan // next span in list, or nil if none
|
next *mspan // next span in list, or nil if none
|
||||||
prev **mspan // previous span's next field, or list head's first field if none
|
prev *mspan // previous span in list, or nil if none
|
||||||
list *mSpanList // For debugging. TODO: Remove.
|
list *mSpanList // For debugging. TODO: Remove.
|
||||||
|
|
||||||
startAddr uintptr // address of first byte of span aka s.base()
|
startAddr uintptr // address of first byte of span aka s.base()
|
||||||
@ -997,28 +996,30 @@ func (span *mspan) init(base uintptr, npages uintptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (span *mspan) inList() bool {
|
func (span *mspan) inList() bool {
|
||||||
return span.prev != nil
|
return span.list != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize an empty doubly-linked list.
|
// Initialize an empty doubly-linked list.
|
||||||
func (list *mSpanList) init() {
|
func (list *mSpanList) init() {
|
||||||
list.first = nil
|
list.first = nil
|
||||||
list.last = &list.first
|
list.last = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *mSpanList) remove(span *mspan) {
|
func (list *mSpanList) remove(span *mspan) {
|
||||||
if span.prev == nil || span.list != list {
|
if span.list != list {
|
||||||
println("runtime: failed MSpanList_Remove", span, span.prev, span.list, list)
|
println("runtime: failed MSpanList_Remove", span, span.prev, span.list, list)
|
||||||
throw("MSpanList_Remove")
|
throw("MSpanList_Remove")
|
||||||
}
|
}
|
||||||
if span.next != nil {
|
if list.first == span {
|
||||||
span.next.prev = span.prev
|
list.first = span.next
|
||||||
} else {
|
} else {
|
||||||
// TODO: After we remove the span.list != list check above,
|
span.prev.next = span.next
|
||||||
// we could at least still check list.last == &span.next here.
|
}
|
||||||
list.last = span.prev
|
if list.last == span {
|
||||||
|
list.last = span.prev
|
||||||
|
} else {
|
||||||
|
span.next.prev = span.prev
|
||||||
}
|
}
|
||||||
*span.prev = span.next
|
|
||||||
span.next = nil
|
span.next = nil
|
||||||
span.prev = nil
|
span.prev = nil
|
||||||
span.list = nil
|
span.list = nil
|
||||||
@ -1035,12 +1036,14 @@ func (list *mSpanList) insert(span *mspan) {
|
|||||||
}
|
}
|
||||||
span.next = list.first
|
span.next = list.first
|
||||||
if list.first != nil {
|
if list.first != nil {
|
||||||
list.first.prev = &span.next
|
// The list contains at least one span; link it in.
|
||||||
|
// The last span in the list doesn't change.
|
||||||
|
list.first.prev = span
|
||||||
} else {
|
} else {
|
||||||
list.last = &span.next
|
// The list contains no spans, so this is also the last span.
|
||||||
|
list.last = span
|
||||||
}
|
}
|
||||||
list.first = span
|
list.first = span
|
||||||
span.prev = &list.first
|
|
||||||
span.list = list
|
span.list = list
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,10 +1052,15 @@ func (list *mSpanList) insertBack(span *mspan) {
|
|||||||
println("failed MSpanList_InsertBack", span, span.next, span.prev, span.list)
|
println("failed MSpanList_InsertBack", span, span.next, span.prev, span.list)
|
||||||
throw("MSpanList_InsertBack")
|
throw("MSpanList_InsertBack")
|
||||||
}
|
}
|
||||||
span.next = nil
|
|
||||||
span.prev = list.last
|
span.prev = list.last
|
||||||
*list.last = span
|
if list.last != nil {
|
||||||
list.last = &span.next
|
// The list contains at least one span.
|
||||||
|
list.last.next = span
|
||||||
|
} else {
|
||||||
|
// The list contains no spans, so this is also the first span.
|
||||||
|
list.first = span
|
||||||
|
}
|
||||||
|
list.last = span
|
||||||
span.list = list
|
span.list = list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user