diff --git a/pkg/ilist/BUILD b/pkg/ilist/BUILD index b26a39132..1bd71b800 100644 --- a/pkg/ilist/BUILD +++ b/pkg/ilist/BUILD @@ -28,6 +28,7 @@ go_template_instance( prefix = "direct", template = ":generic_list", types = { + "Element": "*direct", "Linker": "*direct", }, ) @@ -47,6 +48,10 @@ go_template( srcs = [ "list.go", ], - opt_types = ["Linker"], + opt_types = [ + "Element", + "ElementMapper", + "Linker", + ], visibility = ["//visibility:public"], ) diff --git a/pkg/ilist/list.go b/pkg/ilist/list.go index a88b82196..4ae02eee9 100644 --- a/pkg/ilist/list.go +++ b/pkg/ilist/list.go @@ -21,12 +21,34 @@ package ilist // N.B. When substituted in a template instantiation, Linker doesn't need to // be an interface, and in most cases won't be. type Linker interface { - Next() Linker - Prev() Linker - SetNext(Linker) - SetPrev(Linker) + Next() Element + Prev() Element + SetNext(Element) + SetPrev(Element) } +// Element the item that is used at the API level. +// +// N.B. Like Linker, this is unlikely to be an interface in most cases. +type Element interface { + Linker +} + +// ElementMapper provides an identity mapping by default. +// +// This can be replaced to provide a struct that maps elements to linker +// objects, if they are not the same. An ElementMapper is not typically +// required if: Linker is left as is, Element is left as is, or Linker and +// Element are the same type. +type ElementMapper struct{} + +// linkerFor maps an Element to a Linker. +// +// This default implementation should be inlined. +// +//go:nosplit +func (ElementMapper) linkerFor(elem Element) Linker { return elem } + // List is an intrusive list. Entries can be added to or removed from the list // in O(1) time and with no additional memory allocations. // @@ -39,8 +61,8 @@ type Linker interface { // // +stateify savable type List struct { - head Linker - tail Linker + head Element + tail Element } // Reset resets list l to the empty state. @@ -55,22 +77,22 @@ func (l *List) Empty() bool { } // Front returns the first element of list l or nil. -func (l *List) Front() Linker { +func (l *List) Front() Element { return l.head } // Back returns the last element of list l or nil. -func (l *List) Back() Linker { +func (l *List) Back() Element { return l.tail } // PushFront inserts the element e at the front of list l. -func (l *List) PushFront(e Linker) { - e.SetNext(l.head) - e.SetPrev(nil) +func (l *List) PushFront(e Element) { + ElementMapper{}.linkerFor(e).SetNext(l.head) + ElementMapper{}.linkerFor(e).SetPrev(nil) if l.head != nil { - l.head.SetPrev(e) + ElementMapper{}.linkerFor(l.head).SetPrev(e) } else { l.tail = e } @@ -79,12 +101,12 @@ func (l *List) PushFront(e Linker) { } // PushBack inserts the element e at the back of list l. -func (l *List) PushBack(e Linker) { - e.SetNext(nil) - e.SetPrev(l.tail) +func (l *List) PushBack(e Element) { + ElementMapper{}.linkerFor(e).SetNext(nil) + ElementMapper{}.linkerFor(e).SetPrev(l.tail) if l.tail != nil { - l.tail.SetNext(e) + ElementMapper{}.linkerFor(l.tail).SetNext(e) } else { l.head = e } @@ -98,8 +120,8 @@ func (l *List) PushBackList(m *List) { l.head = m.head l.tail = m.tail } else if m.head != nil { - l.tail.SetNext(m.head) - m.head.SetPrev(l.tail) + ElementMapper{}.linkerFor(l.tail).SetNext(m.head) + ElementMapper{}.linkerFor(m.head).SetPrev(l.tail) l.tail = m.tail } @@ -109,46 +131,46 @@ func (l *List) PushBackList(m *List) { } // InsertAfter inserts e after b. -func (l *List) InsertAfter(b, e Linker) { - a := b.Next() - e.SetNext(a) - e.SetPrev(b) - b.SetNext(e) +func (l *List) InsertAfter(b, e Element) { + a := ElementMapper{}.linkerFor(b).Next() + ElementMapper{}.linkerFor(e).SetNext(a) + ElementMapper{}.linkerFor(e).SetPrev(b) + ElementMapper{}.linkerFor(b).SetNext(e) if a != nil { - a.SetPrev(e) + ElementMapper{}.linkerFor(a).SetPrev(e) } else { l.tail = e } } // InsertBefore inserts e before a. -func (l *List) InsertBefore(a, e Linker) { - b := a.Prev() - e.SetNext(a) - e.SetPrev(b) - a.SetPrev(e) +func (l *List) InsertBefore(a, e Element) { + b := ElementMapper{}.linkerFor(a).Prev() + ElementMapper{}.linkerFor(e).SetNext(a) + ElementMapper{}.linkerFor(e).SetPrev(b) + ElementMapper{}.linkerFor(a).SetPrev(e) if b != nil { - b.SetNext(e) + ElementMapper{}.linkerFor(b).SetNext(e) } else { l.head = e } } // Remove removes e from l. -func (l *List) Remove(e Linker) { - prev := e.Prev() - next := e.Next() +func (l *List) Remove(e Element) { + prev := ElementMapper{}.linkerFor(e).Prev() + next := ElementMapper{}.linkerFor(e).Next() if prev != nil { - prev.SetNext(next) + ElementMapper{}.linkerFor(prev).SetNext(next) } else { l.head = next } if next != nil { - next.SetPrev(prev) + ElementMapper{}.linkerFor(next).SetPrev(prev) } else { l.tail = prev } @@ -160,26 +182,26 @@ func (l *List) Remove(e Linker) { // // +stateify savable type Entry struct { - next Linker - prev Linker + next Element + prev Element } // Next returns the entry that follows e in the list. -func (e *Entry) Next() Linker { +func (e *Entry) Next() Element { return e.next } // Prev returns the entry that precedes e in the list. -func (e *Entry) Prev() Linker { +func (e *Entry) Prev() Element { return e.prev } // SetNext assigns 'entry' as the entry that follows e in the list. -func (e *Entry) SetNext(entry Linker) { - e.next = entry +func (e *Entry) SetNext(elem Element) { + e.next = elem } // SetPrev assigns 'entry' as the entry that precedes e in the list. -func (e *Entry) SetPrev(entry Linker) { - e.prev = entry +func (e *Entry) SetPrev(elem Element) { + e.prev = elem } diff --git a/pkg/refs/BUILD b/pkg/refs/BUILD index 3ea877ccf..98150ba8f 100644 --- a/pkg/refs/BUILD +++ b/pkg/refs/BUILD @@ -1,16 +1,29 @@ package(licenses = ["notice"]) # Apache 2.0 +load("//tools/go_generics:defs.bzl", "go_template_instance") load("//tools/go_stateify:defs.bzl", "go_library", "go_test") +go_template_instance( + name = "weak_ref_list", + out = "weak_ref_list.go", + package = "refs", + prefix = "weakRef", + template = "//pkg/ilist:generic_list", + types = { + "Element": "*WeakRef", + "Linker": "*WeakRef", + }, +) + go_library( name = "refs", srcs = [ "refcounter.go", "refcounter_state.go", + "weak_ref_list.go", ], importpath = "gvisor.googlesource.com/gvisor/pkg/refs", visibility = ["//:sandbox"], - deps = ["//pkg/ilist"], ) go_test( diff --git a/pkg/refs/refcounter.go b/pkg/refs/refcounter.go index 0d44c2499..638a93bab 100644 --- a/pkg/refs/refcounter.go +++ b/pkg/refs/refcounter.go @@ -20,8 +20,6 @@ import ( "reflect" "sync" "sync/atomic" - - "gvisor.googlesource.com/gvisor/pkg/ilist" ) // RefCounter is the interface to be implemented by objects that are reference @@ -61,7 +59,7 @@ type WeakRefUser interface { // // +stateify savable type WeakRef struct { - ilist.Entry `state:"nosave"` + weakRefEntry `state:"nosave"` // obj is an atomic value that points to the refCounter. obj atomic.Value `state:".(savedReference)"` @@ -195,7 +193,7 @@ type AtomicRefCount struct { mu sync.Mutex `state:"nosave"` // weakRefs is our collection of weak references. - weakRefs ilist.List `state:"nosave"` + weakRefs weakRefList `state:"nosave"` } // ReadRefs returns the current number of references. The returned count is @@ -276,7 +274,7 @@ func (r *AtomicRefCount) DecRefWithDestructor(destroy func()) { // return false due to the reference count check. r.mu.Lock() for !r.weakRefs.Empty() { - w := r.weakRefs.Front().(*WeakRef) + w := r.weakRefs.Front() // Capture the callback because w cannot be touched // after it's zapped -- the owner is free it reuse it // after that. diff --git a/pkg/sentry/fs/BUILD b/pkg/sentry/fs/BUILD index 18cd5ae8e..a949fffbf 100644 --- a/pkg/sentry/fs/BUILD +++ b/pkg/sentry/fs/BUILD @@ -78,6 +78,7 @@ go_template_instance( template = "//pkg/ilist:generic_list", types = { "Linker": "*Dirent", + "Element": "*Dirent", }, ) diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD index 0bc735550..7eb2bffeb 100644 --- a/pkg/sentry/kernel/BUILD +++ b/pkg/sentry/kernel/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "pendingSignal", template = "//pkg/ilist:generic_list", types = { + "Element": "*pendingSignal", "Linker": "*pendingSignal", }, ) @@ -21,6 +22,7 @@ go_template_instance( prefix = "processGroup", template = "//pkg/ilist:generic_list", types = { + "Element": "*ProcessGroup", "Linker": "*ProcessGroup", }, ) @@ -43,6 +45,7 @@ go_template_instance( prefix = "session", template = "//pkg/ilist:generic_list", types = { + "Element": "*Session", "Linker": "*Session", }, ) @@ -54,6 +57,7 @@ go_template_instance( prefix = "task", template = "//pkg/ilist:generic_list", types = { + "Element": "*Task", "Linker": "*Task", }, ) diff --git a/pkg/sentry/kernel/futex/BUILD b/pkg/sentry/kernel/futex/BUILD index b44a26974..0ff5b0a95 100644 --- a/pkg/sentry/kernel/futex/BUILD +++ b/pkg/sentry/kernel/futex/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "waiter", template = "//pkg/ilist:generic_list", types = { + "Element": "*Waiter", "Linker": "*Waiter", }, ) diff --git a/pkg/sentry/kernel/semaphore/BUILD b/pkg/sentry/kernel/semaphore/BUILD index e7fa44e2c..bdcf4ce5c 100644 --- a/pkg/sentry/kernel/semaphore/BUILD +++ b/pkg/sentry/kernel/semaphore/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "waiter", template = "//pkg/ilist:generic_list", types = { + "Element": "*waiter", "Linker": "*waiter", }, ) diff --git a/pkg/sentry/mm/BUILD b/pkg/sentry/mm/BUILD index bbdfae247..ad9231774 100644 --- a/pkg/sentry/mm/BUILD +++ b/pkg/sentry/mm/BUILD @@ -67,6 +67,7 @@ go_template_instance( prefix = "io", template = "//pkg/ilist:generic_list", types = { + "Element": "*ioResult", "Linker": "*ioResult", }, ) diff --git a/pkg/tcpip/network/fragmentation/BUILD b/pkg/tcpip/network/fragmentation/BUILD index 83b4d253f..aaabfcb9a 100644 --- a/pkg/tcpip/network/fragmentation/BUILD +++ b/pkg/tcpip/network/fragmentation/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "reassembler", template = "//pkg/ilist:generic_list", types = { + "Element": "*reassembler", "Linker": "*reassembler", }, ) diff --git a/pkg/tcpip/transport/ping/BUILD b/pkg/tcpip/transport/ping/BUILD index 117532fea..982b6795c 100644 --- a/pkg/tcpip/transport/ping/BUILD +++ b/pkg/tcpip/transport/ping/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "pingPacket", template = "//pkg/ilist:generic_list", types = { + "Element": "*pingPacket", "Linker": "*pingPacket", }, ) diff --git a/pkg/tcpip/transport/tcp/BUILD b/pkg/tcpip/transport/tcp/BUILD index 8b911c295..c7943f08e 100644 --- a/pkg/tcpip/transport/tcp/BUILD +++ b/pkg/tcpip/transport/tcp/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "segment", template = "//pkg/ilist:generic_list", types = { + "Element": "*segment", "Linker": "*segment", }, ) diff --git a/pkg/tcpip/transport/udp/BUILD b/pkg/tcpip/transport/udp/BUILD index 1a3a62d3d..4225e28dc 100644 --- a/pkg/tcpip/transport/udp/BUILD +++ b/pkg/tcpip/transport/udp/BUILD @@ -10,6 +10,7 @@ go_template_instance( prefix = "udpPacket", template = "//pkg/ilist:generic_list", types = { + "Element": "*udpPacket", "Linker": "*udpPacket", }, )