github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/platform/systrap/context_list.go (about) 1 package systrap 2 3 // ElementMapper provides an identity mapping by default. 4 // 5 // This can be replaced to provide a struct that maps elements to linker 6 // objects, if they are not the same. An ElementMapper is not typically 7 // required if: Linker is left as is, Element is left as is, or Linker and 8 // Element are the same type. 9 type contextElementMapper struct{} 10 11 // linkerFor maps an Element to a Linker. 12 // 13 // This default implementation should be inlined. 14 // 15 //go:nosplit 16 func (contextElementMapper) linkerFor(elem *sharedContext) *sharedContext { return elem } 17 18 // List is an intrusive list. Entries can be added to or removed from the list 19 // in O(1) time and with no additional memory allocations. 20 // 21 // The zero value for List is an empty list ready to use. 22 // 23 // To iterate over a list (where l is a List): 24 // 25 // for e := l.Front(); e != nil; e = e.Next() { 26 // // do something with e. 27 // } 28 // 29 // +stateify savable 30 type contextList struct { 31 head *sharedContext 32 tail *sharedContext 33 } 34 35 // Reset resets list l to the empty state. 36 func (l *contextList) Reset() { 37 l.head = nil 38 l.tail = nil 39 } 40 41 // Empty returns true iff the list is empty. 42 // 43 //go:nosplit 44 func (l *contextList) Empty() bool { 45 return l.head == nil 46 } 47 48 // Front returns the first element of list l or nil. 49 // 50 //go:nosplit 51 func (l *contextList) Front() *sharedContext { 52 return l.head 53 } 54 55 // Back returns the last element of list l or nil. 56 // 57 //go:nosplit 58 func (l *contextList) Back() *sharedContext { 59 return l.tail 60 } 61 62 // Len returns the number of elements in the list. 63 // 64 // NOTE: This is an O(n) operation. 65 // 66 //go:nosplit 67 func (l *contextList) Len() (count int) { 68 for e := l.Front(); e != nil; e = (contextElementMapper{}.linkerFor(e)).Next() { 69 count++ 70 } 71 return count 72 } 73 74 // PushFront inserts the element e at the front of list l. 75 // 76 //go:nosplit 77 func (l *contextList) PushFront(e *sharedContext) { 78 linker := contextElementMapper{}.linkerFor(e) 79 linker.SetNext(l.head) 80 linker.SetPrev(nil) 81 if l.head != nil { 82 contextElementMapper{}.linkerFor(l.head).SetPrev(e) 83 } else { 84 l.tail = e 85 } 86 87 l.head = e 88 } 89 90 // PushFrontList inserts list m at the start of list l, emptying m. 91 // 92 //go:nosplit 93 func (l *contextList) PushFrontList(m *contextList) { 94 if l.head == nil { 95 l.head = m.head 96 l.tail = m.tail 97 } else if m.head != nil { 98 contextElementMapper{}.linkerFor(l.head).SetPrev(m.tail) 99 contextElementMapper{}.linkerFor(m.tail).SetNext(l.head) 100 101 l.head = m.head 102 } 103 m.head = nil 104 m.tail = nil 105 } 106 107 // PushBack inserts the element e at the back of list l. 108 // 109 //go:nosplit 110 func (l *contextList) PushBack(e *sharedContext) { 111 linker := contextElementMapper{}.linkerFor(e) 112 linker.SetNext(nil) 113 linker.SetPrev(l.tail) 114 if l.tail != nil { 115 contextElementMapper{}.linkerFor(l.tail).SetNext(e) 116 } else { 117 l.head = e 118 } 119 120 l.tail = e 121 } 122 123 // PushBackList inserts list m at the end of list l, emptying m. 124 // 125 //go:nosplit 126 func (l *contextList) PushBackList(m *contextList) { 127 if l.head == nil { 128 l.head = m.head 129 l.tail = m.tail 130 } else if m.head != nil { 131 contextElementMapper{}.linkerFor(l.tail).SetNext(m.head) 132 contextElementMapper{}.linkerFor(m.head).SetPrev(l.tail) 133 134 l.tail = m.tail 135 } 136 m.head = nil 137 m.tail = nil 138 } 139 140 // InsertAfter inserts e after b. 141 // 142 //go:nosplit 143 func (l *contextList) InsertAfter(b, e *sharedContext) { 144 bLinker := contextElementMapper{}.linkerFor(b) 145 eLinker := contextElementMapper{}.linkerFor(e) 146 147 a := bLinker.Next() 148 149 eLinker.SetNext(a) 150 eLinker.SetPrev(b) 151 bLinker.SetNext(e) 152 153 if a != nil { 154 contextElementMapper{}.linkerFor(a).SetPrev(e) 155 } else { 156 l.tail = e 157 } 158 } 159 160 // InsertBefore inserts e before a. 161 // 162 //go:nosplit 163 func (l *contextList) InsertBefore(a, e *sharedContext) { 164 aLinker := contextElementMapper{}.linkerFor(a) 165 eLinker := contextElementMapper{}.linkerFor(e) 166 167 b := aLinker.Prev() 168 eLinker.SetNext(a) 169 eLinker.SetPrev(b) 170 aLinker.SetPrev(e) 171 172 if b != nil { 173 contextElementMapper{}.linkerFor(b).SetNext(e) 174 } else { 175 l.head = e 176 } 177 } 178 179 // Remove removes e from l. 180 // 181 //go:nosplit 182 func (l *contextList) Remove(e *sharedContext) { 183 linker := contextElementMapper{}.linkerFor(e) 184 prev := linker.Prev() 185 next := linker.Next() 186 187 if prev != nil { 188 contextElementMapper{}.linkerFor(prev).SetNext(next) 189 } else if l.head == e { 190 l.head = next 191 } 192 193 if next != nil { 194 contextElementMapper{}.linkerFor(next).SetPrev(prev) 195 } else if l.tail == e { 196 l.tail = prev 197 } 198 199 linker.SetNext(nil) 200 linker.SetPrev(nil) 201 } 202 203 // Entry is a default implementation of Linker. Users can add anonymous fields 204 // of this type to their structs to make them automatically implement the 205 // methods needed by List. 206 // 207 // +stateify savable 208 type contextEntry struct { 209 next *sharedContext 210 prev *sharedContext 211 } 212 213 // Next returns the entry that follows e in the list. 214 // 215 //go:nosplit 216 func (e *contextEntry) Next() *sharedContext { 217 return e.next 218 } 219 220 // Prev returns the entry that precedes e in the list. 221 // 222 //go:nosplit 223 func (e *contextEntry) Prev() *sharedContext { 224 return e.prev 225 } 226 227 // SetNext assigns 'entry' as the entry that follows e in the list. 228 // 229 //go:nosplit 230 func (e *contextEntry) SetNext(elem *sharedContext) { 231 e.next = elem 232 } 233 234 // SetPrev assigns 'entry' as the entry that precedes e in the list. 235 // 236 //go:nosplit 237 func (e *contextEntry) SetPrev(elem *sharedContext) { 238 e.prev = elem 239 }