From: Aurelien DARRAGON Date: Thu, 20 Oct 2022 15:37:51 +0000 (+0200) Subject: MINOR: list: adding MT_LIST_APPEND_LOCKED macro X-Git-Tag: v2.7-dev9~143 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e951c3435c760142612461dc759b6fbb2ec69c21;p=thirdparty%2Fhaproxy.git MINOR: list: adding MT_LIST_APPEND_LOCKED macro 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. --- diff --git a/include/haproxy/list.h b/include/haproxy/list.h index bc741d27e5..6d3de64e03 100644 --- a/include/haproxy/list.h +++ b/include/haproxy/list.h @@ -416,6 +416,40 @@ (_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