]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lists: add a LIST_DEL_INIT() macro
authorWilly Tarreau <w@1wt.eu>
Wed, 6 Mar 2019 18:32:11 +0000 (19:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 7 Mar 2019 10:45:44 +0000 (11:45 +0100)
It turns out that we call LIST_DEL+LIST_INIT very frequently and that
the compiler doesn't know what pointers get modified in the e->n->p
and e->p->n dance, so when LIST_INIT() is called, it reloads these
pointers, which is quite a bit of a mess in terms of performance.

This patch adds LIST_DEL_INIT() to perform the two operations at once
using local temporary variables so that the compiler knows these
pointers are left unaffected.

include/common/mini-clist.h

index 23c1600db29b1b2dfca8816b818f49a765d437f9..62a62d78b5d32a3740fcebaacd0485809ae57ea9 100644 (file)
@@ -89,6 +89,18 @@ struct cond_wordlist {
 /* removes an element from a list and returns it */
 #define LIST_DEL(el) ({ typeof(el) __ret = (el); (el)->n->p = (el)->p; (el)->p->n = (el)->n; (__ret); })
 
+/* removes an element from a list, initializes it and returns it.
+ * This is faster than LIST_DEL+LIST_INIT as we avoid reloading the pointers.
+ */
+#define LIST_DEL_INIT(el) ({ \
+       typeof(el) __ret = (el);                        \
+       typeof(__ret->n) __n = __ret->n;                \
+       typeof(__ret->p) __p = __ret->p;                \
+       __n->p = __p; __p->n = __n;                     \
+       __ret->n = __ret->p = __ret;                    \
+       __ret;                                          \
+})
+
 /* returns a pointer of type <pt> to a structure containing a list head called
  * <el> at address <lh>. Note that <lh> can be the result of a function or macro
  * since it's used only once.