From: Willy Tarreau Date: Wed, 6 Mar 2019 18:32:11 +0000 (+0100) Subject: MINOR: lists: add a LIST_DEL_INIT() macro X-Git-Tag: v2.0-dev2~115 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c5bd311b2a2caa2435ec8b830a492d9e8f0aa131;p=thirdparty%2Fhaproxy.git MINOR: lists: add a LIST_DEL_INIT() macro 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. --- diff --git a/include/common/mini-clist.h b/include/common/mini-clist.h index 23c1600db2..62a62d78b5 100644 --- a/include/common/mini-clist.h +++ b/include/common/mini-clist.h @@ -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 to a structure containing a list head called * at address . Note that can be the result of a function or macro * since it's used only once.