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