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  }