From cf26745857d1c4bbaf6404f57c47bb7c114c6905 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Tue, 30 Sep 2025 14:39:01 +0200 Subject: [PATCH] MINOR: mt_list: Implement MT_LIST_POP_LOCKED() Implement MT_LIST_POP_LOCKED(), that behaves as MT_LIST_POP() and removes the first element from the list, if any, but keeps it locked. This should be backported to 3.2, as it will be use in a bug fix in the stick tables that affects 3.2 too. --- doc/internals/api/mt_list.txt | 24 ++++++++++++++++++++++++ include/import/mt_list.h | 34 +++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/doc/internals/api/mt_list.txt b/doc/internals/api/mt_list.txt index 46d86eaf7..734d0048c 100644 --- a/doc/internals/api/mt_list.txt +++ b/doc/internals/api/mt_list.txt @@ -245,6 +245,30 @@ mt_list_pop(l) #=========# +mt_list_pop_locked(l) + Removes the list's first element, returns it locked. If the list was empty, + NULL is returned. A macro MT_LIST_POP_LOCKED() is provided for a + more convenient use; instead of returning the list element, it will return + the structure holding the element, taking care of preserving the NULL. + + before: + +---+ +---+ +---+ +---+ +---+ +---+ +---+ + #=>| L |<===>| A |<===>| B |<===>| C |<===>| D |<===>| E |<===>| F |<=# + # +---+ +---+ +---+ +---+ +---+ +---+ +---+ # + #=====================================================================# + + after: + +---+ +---+ +---+ +---+ +---+ +---+ + #=>| L |<===>| B |<===>| C |<===>| D |<===>| E |<===>| F |<=# + # +---+ +---+ +---+ +---+ +---+ +---+ # + #===========================================================# + + +---+ + # x| A |x # + # +---+ # + #=========# + + _mt_list_lock_next(elt) Locks the link that starts at the next pointer of the designated element. The link is replaced by two locked pointers, and a pointer to the next diff --git a/include/import/mt_list.h b/include/import/mt_list.h index 09526eb0b..8b27e53d9 100644 --- a/include/import/mt_list.h +++ b/include/import/mt_list.h @@ -128,6 +128,19 @@ struct mt_list { (_n ? MT_LIST_ELEM(_n, t, m) : NULL); \ }) +/* Returns a pointer of type to the structure containing a member of type + * mt_list called that comes from the first element in list , that is + * atomically locked. If the list is empty, NULL is returned instead. + * Example: + * + * while ((conn = MT_LIST_POP_LOCKED(queue, struct conn *, list))) ... + */ +#define MT_LIST_POP_LOCKED(lh, t, m) \ + ({ \ + struct mt_list *_n = mt_list_pop_locked(lh); \ + (_n ? MT_LIST_ELEM(_n, t, m) : NULL); \ + }) + /* Iterates through a list of items of type "typeof(*item)" which are * linked via a "struct mt_list" member named . A pointer to the head * of the list is passed in . @@ -633,10 +646,10 @@ static MT_INLINE long mt_list_delete(struct mt_list *el) } -/* Removes the first element from the list , and returns it in detached +/* Removes the first element from the list , and returns it in locked * form. If the list is already empty, NULL is returned instead. */ -static MT_INLINE struct mt_list *mt_list_pop(struct mt_list *lh) +static MT_INLINE struct mt_list *mt_list_pop_locked(struct mt_list *lh) { struct mt_list *n, *n2; struct mt_list *p, *p2; @@ -687,15 +700,26 @@ static MT_INLINE struct mt_list *mt_list_pop(struct mt_list *lh) n2->prev = lh; __atomic_thread_fence(__ATOMIC_RELEASE); - n->prev = n->next = n; - __atomic_thread_fence(__ATOMIC_RELEASE); - /* return n */ break; } return n; } +/* Removes the first element from the list , and returns it in detached + * form. If the list is already empty, NULL is returned instead. + */ +static MT_INLINE struct mt_list *mt_list_pop(struct mt_list *lh) +{ + struct mt_list *ret = mt_list_pop_locked(lh); + + if (ret) { + ret->prev = ret->next = ret; + __atomic_thread_fence(__ATOMIC_RELEASE); + } + return ret; +} + /* Opens the list just after which usually is the list's head, but not * necessarily. The link between and its next element is cut and replaced -- 2.47.3