Willy Tarreau | 946ebbb | 2021-11-17 15:30:04 +0100 | [diff] [blame] | 1 | 2021-11-09 - List API |
| 2 | |
| 3 | |
| 4 | 1. Background |
| 5 | ------------- |
| 6 | |
| 7 | HAProxy's lists are almost all doubly-linked and circular so that it is always |
| 8 | possible to insert at the beginning, append at the end, scan them in any order |
| 9 | and delete any element without having to scan to search the predecessor nor the |
| 10 | successor. |
| 11 | |
| 12 | A list's head is just a regular list element, and an element always points to |
| 13 | another list element. Such elements only have two pointers, the next and the |
| 14 | previous elements. The object being pointed to is retrieved by subtracting the |
| 15 | list element's offset in its structure from the list element's pointer. This |
| 16 | way there is no need for any separate allocation for the list element, for a |
| 17 | pointer to the object in the list, nor for a pointer to the list element from |
| 18 | the object, as the list is embedded into the object. |
| 19 | |
| 20 | All basic operations are provided, as well as some iterators. Some iterators |
| 21 | are safe for removal of the current element within the loop, others not. In any |
| 22 | case a list cannot be freely modified while iterating over it (e.g. the current |
| 23 | element's successor cannot not be freed if it's saved as the restart point). |
| 24 | |
| 25 | Extreme care is taken nowadays in HAProxy to make sure that no dangling |
| 26 | pointers are left in elements, so it is important to always initialize list |
| 27 | heads and list elements, as well as elements that are removed from a list if |
| 28 | they are not immediately freed, so that their deletion is idempotent. A rule of |
| 29 | thumb is that a list pointer's validity never has to be checked, it is always |
| 30 | valid to dereference it. A lot of complex bugs have been caused in the past by |
| 31 | incorrect list manipulation, such as an element being deleted twice, resulting |
| 32 | in damaging previously adjacent elements' neighbours. This usually has serious |
| 33 | consequences at locations that are totally different from the one of the bug, |
| 34 | and that are only detected much later, so it is required to be particularly |
| 35 | strict on using lists safely. |
| 36 | |
| 37 | The lists are not thread-safe, but mt_lists may be used instead. |
| 38 | |
| 39 | |
| 40 | 2. API description |
| 41 | ------------------ |
| 42 | |
| 43 | A list is defined like this, both for the list's head, and for any other |
| 44 | element: |
| 45 | |
| 46 | struct list { |
| 47 | struct list *n; /* next */ |
| 48 | struct list *p; /* prev */ |
| 49 | }; |
| 50 | |
| 51 | An empty list points to itself for both pointers. I.e. a list's head is both |
| 52 | its own successor and its own predecessor. This guarantees that insertions |
| 53 | and deletions can be done without any check and that deletion is idempotent. |
| 54 | For this reason and by convention, a detached element ought to be represented |
| 55 | like an empty head. |
| 56 | |
| 57 | Lists are manipulated using a set of macros which are used to initialize, add, |
| 58 | remove, or iterate over elements. Most of these macros are extremely simple and |
| 59 | are not even protected against multiple evaluation, so it is fundamentally |
| 60 | important that the expressions used in the arguments are idempotent and that |
| 61 | the result does not depend on the evaluation order of the arguments. |
| 62 | |
| 63 | Macro Description |
| 64 | |
| 65 | ILH |
| 66 | Initialized List Head : this is a non-NULL, non-empty list element used |
| 67 | to prevent the compiler from moving an empty list head declaration to |
| 68 | BSS, typically when it appears in an array of keywords Without this, |
| 69 | some older versions of gcc tend to trim all the array and cause |
| 70 | corruption. |
| 71 | |
| 72 | LIST_INIT(l) |
| 73 | Initialize the list as an empty list head |
| 74 | |
| 75 | LIST_HEAD_INIT(l) |
| 76 | Return a valid initialized empty list head pointing to this |
| 77 | element. Essentially used with assignments in declarations. |
| 78 | |
| 79 | LIST_INSERT(l, e) |
| 80 | Add an element at the beginning of a list and return it |
| 81 | |
| 82 | LIST_APPEND(l, e) |
| 83 | Add an element at the end of a list and return it |
| 84 | |
| 85 | LIST_SPLICE(n, o) |
| 86 | Add the contents of a list <o> at the beginning of another list <n>. |
| 87 | The old list head remains untouched. |
| 88 | |
| 89 | LIST_SPLICE_END_DETACHED(n, o) |
| 90 | Add the contents of a list whose first element is is <o> and last one |
| 91 | is <o->p> at the end of another list <n>. The old list DOES NOT have |
| 92 | any head here. |
| 93 | |
| 94 | LIST_DELETE(e) |
| 95 | Remove an element from a list and return it. Safe to call on |
| 96 | initialized elements, but will not change the element itself so it is |
| 97 | not idempotent. Consider using LIST_DEL_INIT() instead unless called |
| 98 | immediately after a free(). |
| 99 | |
| 100 | LIST_DEL_INIT(e) |
| 101 | Remove an element from a list, initialize it and return it so that a |
| 102 | subsequent LIST_DELETE() is safe. This is faster than performing a |
| 103 | LIST_DELETE() followed by a LIST_INIT() as pointers are not reloaded. |
| 104 | |
| 105 | LIST_ELEM(l, t, m) |
| 106 | Return a pointer of type <t> to a structure containing a list head |
| 107 | member called <m> at address <l>. Note that <l> can be the result of a |
| 108 | function or macro since it's used only once. |
| 109 | |
| 110 | LIST_ISEMPTY(l) |
Ilya Shipitsin | 5e87bcf | 2021-12-25 11:45:52 +0500 | [diff] [blame] | 111 | Check if the list head <l> is empty (=initialized) or not, and return |
Willy Tarreau | 946ebbb | 2021-11-17 15:30:04 +0100 | [diff] [blame] | 112 | non-zero only if so. |
| 113 | |
| 114 | LIST_INLIST(e) |
| 115 | Check if the list element <e> was added to a list or not, thus return |
| 116 | true unless the element was initialized. |
| 117 | |
| 118 | LIST_INLIST_ATOMIC(e) |
| 119 | Atomically check if the list element's next pointer points to anything |
| 120 | different from itself, implying the element should be part of a |
| 121 | list. This usually is similar to LIST_INLIST() except that while that |
| 122 | one might be instrumented using debugging code to perform further |
| 123 | consistency checks, the macro below guarantees to always perform a |
| 124 | single atomic test and is safe to use with barriers. |
| 125 | |
| 126 | LIST_NEXT(l, t, m) |
| 127 | Return a pointer of type <t> to a structure following the element which |
| 128 | contains list head <l>, which is known as member <m> in struct <t>. |
| 129 | |
| 130 | LIST_PREV(l, t, m) |
| 131 | Return a pointer of type <t> to a structure preceding the element which |
| 132 | contains list head <l>, which is known as member <m> in struct <t>. |
| 133 | Note that this macro is first undefined as it happened to already exist |
| 134 | on some old OSes. |
| 135 | |
| 136 | list_for_each_entry(i, l, m) |
| 137 | Iterate local variable <i> through a list of items of type "typeof(*i)" |
| 138 | which are linked via a "struct list" member named <m>. A pointer to the |
| 139 | head of the list is passed in <l>. No temporary variable is needed. |
| 140 | Note that <i> must not be modified during the loop. |
| 141 | |
| 142 | list_for_each_entry_from(i, l, m) |
| 143 | Same as list_for_each_entry() but starting from current value of <i> |
| 144 | instead of the list's head. |
| 145 | |
| 146 | list_for_each_entry_from_rev(i, l, m) |
| 147 | Same as list_for_each_entry_rev() but starting from current value of <i> |
| 148 | instead of the list's head. |
| 149 | |
| 150 | list_for_each_entry_rev(i, l, m) |
| 151 | Iterate backwards local variable <i> through a list of items of type |
| 152 | "typeof(*i)" which are linked via a "struct list" member named <m>. A |
| 153 | pointer to the head of the list is passed in <l>. No temporary variable |
| 154 | is needed. Note that <i> must not be modified during the loop. |
| 155 | |
| 156 | list_for_each_entry_safe(i, b, l, m) |
| 157 | Iterate variable <i> through a list of items of type "typeof(*i)" which |
| 158 | are linked via a "struct list" member named <m>. A pointer to the head |
| 159 | of the list is passed in <l>. A temporary backup variable <b> of same |
| 160 | type as <i> is needed so that <i> may safely be deleted if needed. Note |
| 161 | that it is only permitted to delete <i> and no other element during |
| 162 | this operation! |
| 163 | |
| 164 | list_for_each_entry_safe_from(i, b, l, m) |
| 165 | Same as list_for_each_entry_safe() but starting from current value of |
| 166 | <i> instead of the list's head. |
| 167 | |
| 168 | list_for_each_entry_safe_from_rev(i, b, l, m) |
| 169 | Same as list_for_each_entry_safe_rev() but starting from current value |
| 170 | of <i> instead of the list's head. |
| 171 | |
| 172 | list_for_each_entry_safe_rev(i, b, l, m) |
| 173 | Iterate backwards local variable <i> through a list of items of type |
| 174 | "typeof(*i)" which are linked via a "struct list" member named <m>. A |
| 175 | pointer to the head of the list is passed in <l>. A temporary variable |
| 176 | <b> of same type as <i> is needed so that <i> may safely be deleted if |
| 177 | needed. Note that it is only permitted to delete <i> and no other |
| 178 | element during this operation! |
| 179 | |
| 180 | 3. Notes |
| 181 | -------- |
| 182 | |
| 183 | - This API is quite old and some macros are missing. For example there's still |
| 184 | no list_first() so it's common to use LIST_ELEM(head->n, ...) instead. Some |
| 185 | older parts of the code also used to rely on list_for_each() followed by a |
| 186 | break to stop on the first element. |
| 187 | |
| 188 | - Some parts were recently renamed because LIST_ADD() used to do what |
| 189 | LIST_INSERT() currently does and was often mistaken with LIST_ADDQ() which is |
| 190 | what LIST_APPEND() now is. As such it is not totally impossible that some |
| 191 | places use a LIST_INSERT() where a LIST_APPEND() would be desired. |
| 192 | |
| 193 | - The structure must not be modified at all (even to add debug info). Some |
| 194 | parts of the code assume that its layout is exactly this one, particularly |
| 195 | the parts ensuring the casting between MT lists and lists. |