github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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  }