]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: list: adding MT_LIST_APPEND_LOCKED macro
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 20 Oct 2022 15:37:51 +0000 (17:37 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 21 Oct 2022 14:26:27 +0000 (16:26 +0200)
adding a new mt macro: MT_LIST_APPEND_LOCKED.

This macro may be used to append an item to an existing
list, like MT_LIST_APPEND.

But here the item will be forced into locked/busy state
prior to appending, so that it is already referenced
in the list while still preventing concurrent accesses
until we decide to unlock it.

The macro returns a struct mt_list "np", that is needed
at unlock time using regular MT_LIST_UNLOCK_ELT macro.

include/haproxy/list.h

index bc741d27e58b9e22918e59d48bec2e215986a8e4..6d3de64e031e660ebc5d0f686be0c1e958bc4c17 100644 (file)
        (_ret);                                                            \
     })
 
+/*
+ * 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
+ * Item will be added in busy/locked state, so that it is already
+ * referenced in the list but no other thread can use it until we're ready.
+ *
+ * This returns a struct mt_list, that will be needed at unlock time.
+ * (using MT_LIST_UNLOCK_ELT)
+ */
+#define MT_LIST_APPEND_LOCKED(_lh, _el)                                           \
+    ({                                                                    \
+       struct mt_list np;                                                 \
+       struct mt_list *lh = (_lh), *el = (_el);                           \
+       (el)->next = MT_LIST_BUSY;                                         \
+       (el)->prev = MT_LIST_BUSY;                                         \
+       for (;;__ha_cpu_relax()) {                                         \
+               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;                                          \
+               }                                                          \
+               np.prev = p;                                               \
+               np.next = n;                                               \
+               break;                                                     \
+       }                                                                  \
+       (np);                                                              \
+    })
+
 /*
  * 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