MINOR: list: Add MT_LIST_DEL_SAFE_NOINIT() and MT_LIST_ADDQ_NOCHECK()
authorOlivier Houchard <cognet@ci0.org>
Mon, 29 Jun 2020 18:14:28 +0000 (20:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 1 Jul 2020 15:04:00 +0000 (17:04 +0200)
Add two new macros, MT_LIST_DEL_SAFE_NOINIT makes sure we remove the
element from the list, without reinitializing its next and prev, and
MT_LIST_ADDQ_NOCHECK is similar to MT_LIST_ADDQ(), except it doesn't check
if the element is already in a list.
The goal is to be able to move an element from a list we're currently
parsing to another, keeping it locked in the meanwhile.

include/haproxy/list.h

index 2f2699f..98d9f69 100644 (file)
     })
 
 /*
+ * Add an item at the end of a list.
+ * It is assumed the element can't already be in a list, so it isn't checked
+ */
+#define MT_LIST_ADDQ_NOCHECK(_lh, _el)                                     \
+    ({                                                                     \
+       int _ret = 0;                                                      \
+       struct mt_list *lh = (_lh), *el = (_el);                           \
+       while (1) {                                                        \
+               struct mt_list *n;                                         \
+               struct mt_list *p;                                         \
+               p = _HA_ATOMIC_XCHG(&(lh)->prev, MT_LIST_BUSY);            \
+               if (p == MT_LIST_BUSY)                                     \
+                       continue;                                          \
+               n = _HA_ATOMIC_XCHG(&p->next, MT_LIST_BUSY);               \
+               if (n == MT_LIST_BUSY) {                                   \
+                       (lh)->prev = p;                                    \
+                       __ha_barrier_store();                              \
+                       continue;                                          \
+               }                                                          \
+               (el)->next = n;                                            \
+               (el)->prev = p;                                            \
+               __ha_barrier_store();                                      \
+               p->next = (el);                                            \
+               __ha_barrier_store();                                      \
+               n->prev = (el);                                            \
+               __ha_barrier_store();                                      \
+               _ret = 1;                                                  \
+               break;                                                     \
+       }                                                                  \
+       (_ret);                                                            \
+    })
+
+/*
  * Detach a list from its head. A pointer to the first element is returned
  * and the list is closed. If the list was empty, NULL is returned. This may
  * exclusively be used with lists modified by MT_LIST_ADD/MT_LIST_ADDQ. This
                (_el) = NULL;                                              \
        } while (0)
 
+/* Safe as MT_LIST_DEL_SAFE, but it won't reinit the element */
+#define MT_LIST_DEL_SAFE_NOINIT(_el)                                       \
+       do {                                                               \
+               (_el) = NULL;                                              \
+       } while (0)
+
 /* Simpler FOREACH_ITEM_SAFE macro inspired from Linux sources.
  * Iterates <item> through a list of items of type "typeof(*item)" which are
  * linked via a "struct list" member named <member>. A pointer to the head of