helper/list.h: align file to Linux v5.12 76/6276/3
authorAntonio Borneo <borneo.antonio@gmail.com>
Wed, 26 May 2021 12:48:10 +0000 (14:48 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 4 Jun 2021 16:41:32 +0000 (17:41 +0100)
Main improvement is in the doxygen comments.
Minimize the delta with kernel file.
Skip the functions hlist_unhashed_lockless() and
__list_del_clearprev() that are relevant only in kernel.
Remove gcc extension "omitted conditional operand".

Change-Id: I2e9ddb54cfe2fa5f7cf18f44726acd144e1f98b9
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/6276
Reviewed-by: <rdiezmail-openocd@yahoo.de>
Tested-by: jenkins
Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
src/helper/list.h

index 7f6046441d729145d4bfbdef237eb82601c78817..0949636b918372734f11222bcb0d991532ed19d9 100644 (file)
@@ -1,26 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The content of this file is mainly copied/inspired from Linux kernel
+ * code in include/linux/list.h, include/linux/types.h
+ * Last aligned with kernel v5.12:
+ * - skip the functions hlist_unhashed_lockless() and __list_del_clearprev()
+ *   that are relevant only in kernel;
+ * - Remove non-standard GCC extension "omitted conditional operand" from
+ *   list_prepare_entry;
+ * - expand READ_ONCE, WRITE_ONCE, smp_load_acquire, smp_store_release;
+ * - make comments compatible with doxygen.
+ */
+
 #ifndef OPENOCD_HELPER_LIST_H
 #define OPENOCD_HELPER_LIST_H
 
 /* begin local changes */
 #include <helper/types.h>
 
-#define prefetch(x) ((void)x)
 #define LIST_POISON1 NULL
 #define LIST_POISON2 NULL
 
 struct list_head {
        struct list_head *next, *prev;
 };
+
 struct hlist_head {
        struct hlist_node *first;
 };
+
 struct hlist_node {
        struct hlist_node *next, **pprev;
 };
 /* end local changes */
 
 /*
- * Simple doubly linked list implementation.
+ * Circular doubly linked list implementation.
  *
  * Some of the internal functions ("__xxx") are useful when
  * manipulating whole lists rather than single entries, as
@@ -31,36 +46,58 @@ struct hlist_node {
 
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
-#define LIST_HEAD(name)        \
+#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)
 
+/**
+ * INIT_LIST_HEAD - Initialize a list_head structure
+ * @param list list_head structure to be initialized.
+ *
+ * Initializes the list_head to point to itself.  If it is a list header,
+ * the result is an empty list.
+ */
 static inline void INIT_LIST_HEAD(struct list_head *list)
 {
        list->next = list;
        list->prev = list;
 }
 
+#ifdef CONFIG_DEBUG_LIST
+extern bool __list_add_valid(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next);
+extern bool __list_del_entry_valid(struct list_head *entry);
+#else
+static inline bool __list_add_valid(struct list_head *new,
+                               struct list_head *prev,
+                               struct list_head *next)
+{
+       return true;
+}
+static inline bool __list_del_entry_valid(struct list_head *entry)
+{
+       return true;
+}
+#endif
+
 /*
  * Insert a new entry between two known consecutive entries.
  *
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add(struct list_head *new,
-       struct list_head *prev,
-       struct list_head *next)
+                             struct list_head *prev,
+                             struct list_head *next)
 {
+       if (!__list_add_valid(new, prev, next))
+               return;
+
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
 }
-#else
-extern void __list_add(struct list_head *new,
-                      struct list_head *prev,
-                      struct list_head *next);
-#endif
 
 /**
  * list_add - add a new entry
@@ -102,28 +139,28 @@ static inline void __list_del(struct list_head *prev, struct list_head *next)
        prev->next = next;
 }
 
+/* Ignore kernel __list_del_clearprev() */
+
+static inline void __list_del_entry(struct list_head *entry)
+{
+       if (!__list_del_entry_valid(entry))
+               return;
+
+       __list_del(entry->prev, entry->next);
+}
+
 /**
  * list_del - deletes entry from list.
  * @param entry the element to delete from the list.
  * Note: list_empty() on entry does not return true after this, the entry is
  * in an undefined state.
  */
-#ifndef CONFIG_DEBUG_LIST
-static inline void __list_del_entry(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-}
-
 static inline void list_del(struct list_head *entry)
 {
-       __list_del(entry->prev, entry->next);
+       __list_del_entry(entry);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
 }
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
 
 /**
  * list_replace - replace old entry by new one
@@ -133,7 +170,7 @@ extern void list_del(struct list_head *entry);
  * If @a old was empty, it will be overwritten.
  */
 static inline void list_replace(struct list_head *old,
-       struct list_head *new)
+                               struct list_head *new)
 {
        new->next = old->next;
        new->next->prev = new;
@@ -141,13 +178,37 @@ static inline void list_replace(struct list_head *old,
        new->prev->next = new;
 }
 
+/**
+ * list_replace_init - replace old entry by new one and initialize the old one
+ * @param old the element to be replaced
+ * @param new the new element to insert
+ *
+ * If @a old was empty, it will be overwritten.
+ */
 static inline void list_replace_init(struct list_head *old,
-       struct list_head *new)
+                                    struct list_head *new)
 {
        list_replace(old, new);
        INIT_LIST_HEAD(old);
 }
 
+/**
+ * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
+ * @param entry1 the location to place entry2
+ * @param entry2 the location to place entry1
+ */
+static inline void list_swap(struct list_head *entry1,
+                            struct list_head *entry2)
+{
+       struct list_head *pos = entry2->prev;
+
+       list_del(entry2);
+       list_replace(entry1, entry2);
+       if (pos == entry1)
+               pos = entry2;
+       list_add(entry1, pos);
+}
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @param entry the element to delete from the list.
@@ -175,19 +236,53 @@ static inline void list_move(struct list_head *list, struct list_head *head)
  * @param head the head that will follow our entry
  */
 static inline void list_move_tail(struct list_head *list,
-       struct list_head *head)
+                                 struct list_head *head)
 {
        __list_del_entry(list);
        list_add_tail(list, head);
 }
 
+/**
+ * list_bulk_move_tail - move a subsection of a list to its tail
+ * @param head  the head that will follow our entry
+ * @param first the first entry to move
+ * @param last  the last entry to move, can be the same as first
+ *
+ * Move all entries between @a first and including @a last before @a head.
+ * All three entries must belong to the same linked list.
+ */
+static inline void list_bulk_move_tail(struct list_head *head,
+                                      struct list_head *first,
+                                      struct list_head *last)
+{
+       first->prev->next = last->next;
+       last->next->prev = first->prev;
+
+       head->prev->next = first;
+       first->prev = head->prev;
+
+       last->next = head;
+       head->prev = last;
+}
+
+/**
+ * list_is_first -- tests whether @a list is the first entry in list @a head
+ * @param list the entry to test
+ * @param head the head of the list
+ */
+static inline int list_is_first(const struct list_head *list,
+                                       const struct list_head *head)
+{
+       return list->prev == head;
+}
+
 /**
  * list_is_last - tests whether @a list is the last entry in list @a head
  * @param list the entry to test
  * @param head the head of the list
  */
 static inline int list_is_last(const struct list_head *list,
-       const struct list_head *head)
+                               const struct list_head *head)
 {
        return list->next == head;
 }
@@ -201,6 +296,24 @@ static inline int list_empty(const struct list_head *head)
        return head->next == head;
 }
 
+/**
+ * list_del_init_careful - deletes entry from list and reinitialize it.
+ * @param entry the element to delete from the list.
+ *
+ * This is the same as list_del_init(), except designed to be used
+ * together with list_empty_careful() in a way to guarantee ordering
+ * of other memory operations.
+ *
+ * Any memory operations done before a list_del_init_careful() are
+ * guaranteed to be visible after a list_empty_careful() test.
+ */
+static inline void list_del_init_careful(struct list_head *entry)
+{
+       __list_del_entry(entry);
+       entry->prev = entry;
+       entry->next = entry;
+}
+
 /**
  * list_empty_careful - tests whether a list is empty and not being modified
  * @param head the list to test
@@ -234,6 +347,24 @@ static inline void list_rotate_left(struct list_head *head)
        }
 }
 
+/**
+ * list_rotate_to_front() - Rotate list to specific item.
+ * @param list The desired new front of the list.
+ * @param head The head of the list.
+ *
+ * Rotates list so that @a list becomes the new front of the list.
+ */
+static inline void list_rotate_to_front(struct list_head *list,
+                                       struct list_head *head)
+{
+       /*
+        * Deletes the list head from the list denoted by @a head and
+        * places it as the tail of @a list, this effectively rotates the
+        * list so that @a list is at the front.
+        */
+       list_move_tail(head, list);
+}
+
 /**
  * list_is_singular - tests whether a list has just one entry.
  * @param head the list to test.
@@ -244,7 +375,7 @@ static inline int list_is_singular(const struct list_head *head)
 }
 
 static inline void __list_cut_position(struct list_head *list,
-       struct list_head *head, struct list_head *entry)
+               struct list_head *head, struct list_head *entry)
 {
        struct list_head *new_first = entry->next;
        list->next = head->next;
@@ -270,12 +401,12 @@ static inline void __list_cut_position(struct list_head *list,
  *
  */
 static inline void list_cut_position(struct list_head *list,
-       struct list_head *head, struct list_head *entry)
+               struct list_head *head, struct list_head *entry)
 {
        if (list_empty(head))
                return;
        if (list_is_singular(head) &&
-           (head->next != entry && head != entry))
+               (head->next != entry && head != entry))
                return;
        if (entry == head)
                INIT_LIST_HEAD(list);
@@ -283,9 +414,39 @@ static inline void list_cut_position(struct list_head *list,
                __list_cut_position(list, head, entry);
 }
 
+/**
+ * list_cut_before - cut a list into two, before given entry
+ * @param list  a new list to add all removed entries
+ * @param head  a list with entries
+ * @param entry an entry within head, could be the head itself
+ *
+ * This helper moves the initial part of @a head, up to but
+ * excluding @a entry, from @a head to @a list.  You should pass
+ * in @a entry an element you know is on @a head.  @a list should
+ * be an empty list or a list you do not care about losing
+ * its data.
+ * If @a entry == @a head, all entries on @a head are moved to
+ * @a list.
+ */
+static inline void list_cut_before(struct list_head *list,
+                                  struct list_head *head,
+                                  struct list_head *entry)
+{
+       if (head->next == entry) {
+               INIT_LIST_HEAD(list);
+               return;
+       }
+       list->next = head->next;
+       list->next->prev = list;
+       list->prev = entry->prev;
+       list->prev->next = list;
+       head->next = entry;
+       entry->prev = head;
+}
+
 static inline void __list_splice(const struct list_head *list,
-       struct list_head *prev,
-       struct list_head *next)
+                                struct list_head *prev,
+                                struct list_head *next)
 {
        struct list_head *first = list->next;
        struct list_head *last = list->prev;
@@ -303,7 +464,7 @@ static inline void __list_splice(const struct list_head *list,
  * @param head the place to add it in the first list.
  */
 static inline void list_splice(const struct list_head *list,
-       struct list_head *head)
+                               struct list_head *head)
 {
        if (!list_empty(list))
                __list_splice(list, head, head->next);
@@ -315,7 +476,7 @@ static inline void list_splice(const struct list_head *list,
  * @param head the place to add it in the first list.
  */
 static inline void list_splice_tail(struct list_head *list,
-       struct list_head *head)
+                               struct list_head *head)
 {
        if (!list_empty(list))
                __list_splice(list, head->prev, head);
@@ -329,7 +490,7 @@ static inline void list_splice_tail(struct list_head *list,
  * The list at @a list is reinitialised
  */
 static inline void list_splice_init(struct list_head *list,
-       struct list_head *head)
+                                   struct list_head *head)
 {
        if (!list_empty(list)) {
                __list_splice(list, head, head->next);
@@ -346,7 +507,7 @@ static inline void list_splice_init(struct list_head *list,
  * The list at @a list is reinitialised
  */
 static inline void list_splice_tail_init(struct list_head *list,
-       struct list_head *head)
+                                        struct list_head *head)
 {
        if (!list_empty(list)) {
                __list_splice(list, head->prev, head);
@@ -358,7 +519,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * list_entry - get the struct for this entry
  * @param ptr    the &struct list_head pointer.
  * @param type   the type of the struct this is embedded in.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  */
 #define list_entry(ptr, type, member) \
        container_of(ptr, type, member)
@@ -367,34 +528,71 @@ static inline void list_splice_tail_init(struct list_head *list,
  * list_first_entry - get the first element from a list
  * @param ptr    the list head to take the element from.
  * @param type   the type of the struct this is embedded in.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Note, that list is expected to be not empty.
  */
 #define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)
 
+/**
+ * list_last_entry - get the last element from a list
+ * @param ptr    the list head to take the element from.
+ * @param type   the type of the struct this is embedded in.
+ * @param member the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+       list_entry((ptr)->prev, type, member)
+
+/**
+ * list_first_entry_or_null - get the first element from a list
+ * @param ptr    the list head to take the element from.
+ * @param type   the type of the struct this is embedded in.
+ * @param member the name of the list_head within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) ({ \
+       struct list_head *head__ = (ptr); \
+       struct list_head *pos__ = head__->next; \
+       pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
+})
+
+/**
+ * list_next_entry - get the next element in list
+ * @param pos    the type * to cursor
+ * @param member the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+       list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @param pos    the type * to cursor
+ * @param member the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+       list_entry((pos)->member.prev, typeof(*(pos)), member)
+
 /**
  * list_for_each       -       iterate over a list
  * @param pos  the &struct list_head to use as a loop cursor.
  * @param head the head for your list.
  */
 #define list_for_each(pos, head) \
-       for (pos = (head)->next; prefetch(pos->next), pos != (head); \
-            pos = pos->next)
+       for (pos = (head)->next; pos != (head); pos = pos->next)
 
 /**
- * __list_for_each     -       iterate over a list
+ * list_for_each_continue - continue iteration over a list
  * @param pos  the &struct list_head to use as a loop cursor.
  * @param head the head for your list.
  *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
+ * Continue to iterate over a list, continuing after the current position.
  */
-#define __list_for_each(pos, head) \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
+#define list_for_each_continue(pos, head) \
+       for (pos = pos->next; pos != (head); pos = pos->next)
 
 /**
  * list_for_each_prev  -       iterate over a list backwards
@@ -402,8 +600,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @param head the head for your list.
  */
 #define list_for_each_prev(pos, head) \
-       for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
-            pos = pos->prev)
+       for (pos = (head)->prev; pos != (head); pos = pos->prev)
 
 /**
  * list_for_each_safe - iterate over a list safe against removal of list entry
@@ -413,7 +610,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  */
 #define list_for_each_safe(pos, n, head) \
        for (pos = (head)->next, n = pos->next; pos != (head); \
-            pos = n, n = pos->next)
+               pos = n, n = pos->next)
 
 /**
  * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
@@ -422,148 +619,170 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @param head the head for your list.
  */
 #define list_for_each_prev_safe(pos, n, head) \
-       for (pos = (head)->prev, n = pos->prev; \
-            prefetch(pos->prev), pos != (head); \
+       for (pos = (head)->prev, n = pos->prev; \
+            pos != (head); \
             pos = n, n = pos->prev)
 
+/**
+ * list_entry_is_head - test if the entry points to the head of the list
+ * @param pos    the type * to cursor
+ * @param head   the head for your list.
+ * @param member the name of the list_head within the struct.
+ */
+#define list_entry_is_head(pos, head, member)                          \
+       (&pos->member == (head))
+
 /**
  * list_for_each_entry -       iterate over list of given type
  * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  */
 #define list_for_each_entry(pos, head, member)                         \
-       for (pos = list_entry((head)->next, typeof(*pos), member);      \
-            prefetch(pos->member.next), &pos->member != (head);        \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (pos = list_first_entry(head, typeof(*pos), member);        \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_reverse - iterate backwards over list of given type.
  * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  */
 #define list_for_each_entry_reverse(pos, head, member)                 \
-       for (pos = list_entry((head)->prev, typeof(*pos), member);      \
-            prefetch(pos->member.prev), &pos->member != (head);        \
-            pos = list_entry(pos->member.prev, typeof(*pos), member))
+       for (pos = list_last_entry(head, typeof(*pos), member);         \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
  * @param pos    the type * to use as a start point
  * @param head   the head of the list
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
  */
 #define list_prepare_entry(pos, head, member) \
-       ((pos) ? : list_entry(head, typeof(*pos), member))
+       ((pos) ? (pos) : list_entry(head, typeof(*pos), member))
 
 /**
  * list_for_each_entry_continue - continue iteration over list of given type
  * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Continue to iterate over list of given type, continuing after
  * the current position.
  */
-#define list_for_each_entry_continue(pos, head, member)                        \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
-            prefetch(pos->member.next), &pos->member != (head);        \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry_continue(pos, head, member)                \
+       for (pos = list_next_entry(pos, member);                        \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_continue_reverse - iterate backwards from the given point
  * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Start to iterate over list of given type backwards, continuing after
  * the current position.
  */
 #define list_for_each_entry_continue_reverse(pos, head, member)                \
-       for (pos = list_entry(pos->member.prev, typeof(*pos), member);  \
-            prefetch(pos->member.prev), &pos->member != (head);        \
-            pos = list_entry(pos->member.prev, typeof(*pos), member))
+       for (pos = list_prev_entry(pos, member);                        \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_for_each_entry_from - iterate over list of given type from the current point
  * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Iterate over list of given type, continuing from current position.
  */
 #define list_for_each_entry_from(pos, head, member)                    \
-       for (; prefetch(pos->member.next), &pos->member != (head);      \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (; !list_entry_is_head(pos, head, member);                  \
+            pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_from_reverse - iterate backwards over list of given type
+ *                                    from the current point
+ * @param pos    the type * to use as a loop cursor.
+ * @param head   the head for your list.
+ * @param member the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from_reverse(pos, head, member)            \
+       for (; !list_entry_is_head(pos, head, member);                  \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
  * @param pos    the type * to use as a loop cursor.
  * @param n      another type * to use as temporary storage
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  */
 #define list_for_each_entry_safe(pos, n, head, member)                 \
-       for (pos = list_entry((head)->next, typeof(*pos), member),      \
-            n = list_entry(pos->member.next, typeof(*pos), member); \
-            &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+       for (pos = list_first_entry(head, typeof(*pos), member),        \
+               n = list_next_entry(pos, member);                       \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_continue - continue list iteration safe against removal
  * @param pos    the type * to use as a loop cursor.
  * @param n      another type * to use as temporary storage
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Iterate over list of given type, continuing after current point,
  * safe against removal of list entry.
  */
-#define list_for_each_entry_safe_continue(pos, n, head, member)                        \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member),          \
-            n = list_entry(pos->member.next, typeof(*pos), member);         \
-            &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#define list_for_each_entry_safe_continue(pos, n, head, member)                \
+       for (pos = list_next_entry(pos, member),                                \
+               n = list_next_entry(pos, member);                               \
+            !list_entry_is_head(pos, head, member);                            \
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
  * @param pos    the type * to use as a loop cursor.
  * @param n      another type * to use as temporary storage
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Iterate over list of given type from current point, safe against
  * removal of list entry.
  */
 #define list_for_each_entry_safe_from(pos, n, head, member)                    \
-       for (n = list_entry(pos->member.next, typeof(*pos), member);            \
-            &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+       for (n = list_next_entry(pos, member);                                  \
+            !list_entry_is_head(pos, head, member);                            \
+            pos = n, n = list_next_entry(n, member))
 
 /**
  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
  * @param pos    the type * to use as a loop cursor.
  * @param n      another type * to use as temporary storage
  * @param head   the head for your list.
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * Iterate backwards over list of given type, safe against removal
  * of list entry.
  */
 #define list_for_each_entry_safe_reverse(pos, n, head, member)         \
-       for (pos = list_entry((head)->prev, typeof(*pos), member),      \
-            n = list_entry(pos->member.prev, typeof(*pos), member); \
-            &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+       for (pos = list_last_entry(head, typeof(*pos), member),         \
+               n = list_prev_entry(pos, member);                       \
+            !list_entry_is_head(pos, head, member);                    \
+            pos = n, n = list_prev_entry(n, member))
 
 /**
  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
  * @param pos    the loop cursor used in the list_for_each_entry_safe loop
  * @param n      temporary storage used in list_for_each_entry_safe
- * @param member the name of the list_struct within the struct.
+ * @param member the name of the list_head within the struct.
  *
  * list_safe_reset_next is not safe to use in general if the list may be
  * modified concurrently (eg. the lock is dropped in the loop body). An
@@ -572,7 +791,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * completing the current iteration of the loop body.
  */
 #define list_safe_reset_next(pos, n, member)                           \
-       n = list_entry(pos->member.next, typeof(*pos), member)
+       n = list_next_entry(pos, member)
 
 /*
  * Double linked lists with a single pointer list head.
@@ -590,11 +809,25 @@ static inline void INIT_HLIST_NODE(struct hlist_node *h)
        h->pprev = NULL;
 }
 
+/**
+ * hlist_unhashed - Has node been removed from list and reinitialized?
+ * @param h Node to be checked
+ *
+ * Not that not all removal functions will leave a node in unhashed
+ * state.  For example, hlist_nulls_del_init_rcu() does leave the
+ * node in unhashed state, but hlist_nulls_del() does not.
+ */
 static inline int hlist_unhashed(const struct hlist_node *h)
 {
        return !h->pprev;
 }
 
+/* Ignore kernel hlist_unhashed_lockless() */
+
+/**
+ * hlist_empty - Is the specified hlist_head structure an empty hlist?
+ * @param h Structure to check.
+ */
 static inline int hlist_empty(const struct hlist_head *h)
 {
        return !h->first;
@@ -604,11 +837,19 @@ static inline void __hlist_del(struct hlist_node *n)
 {
        struct hlist_node *next = n->next;
        struct hlist_node **pprev = n->pprev;
+
        *pprev = next;
        if (next)
                next->pprev = pprev;
 }
 
+/**
+ * hlist_del - Delete the specified hlist_node from its list
+ * @param n Node to delete.
+ *
+ * Note that this function leaves the node in hashed state.  Use
+ * hlist_del_init() or similar instead to unhash @a n.
+ */
 static inline void hlist_del(struct hlist_node *n)
 {
        __hlist_del(n);
@@ -616,6 +857,12 @@ static inline void hlist_del(struct hlist_node *n)
        n->pprev = LIST_POISON2;
 }
 
+/**
+ * hlist_del_init - Delete the specified hlist_node from its list and initialize
+ * @param n Node to delete.
+ *
+ * Note that this function leaves the node in unhashed state.
+ */
 static inline void hlist_del_init(struct hlist_node *n)
 {
        if (!hlist_unhashed(n)) {
@@ -624,6 +871,14 @@ static inline void hlist_del_init(struct hlist_node *n)
        }
 }
 
+/**
+ * hlist_add_head - add a new entry at the beginning of the hlist
+ * @param n new entry to be added
+ * @param h hlist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
 {
        struct hlist_node *first = h->first;
@@ -634,9 +889,13 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
        n->pprev = &h->first;
 }
 
-/* next must be != NULL */
+/**
+ * hlist_add_before - add a new entry before the one specified
+ * @param n    new entry to be added
+ * @param next hlist node to add it before, which must be non-NULL
+ */
 static inline void hlist_add_before(struct hlist_node *n,
-       struct hlist_node *next)
+                                   struct hlist_node *next)
 {
        n->pprev = next->pprev;
        n->next = next;
@@ -644,29 +903,68 @@ static inline void hlist_add_before(struct hlist_node *n,
        *(n->pprev) = n;
 }
 
-static inline void hlist_add_after(struct hlist_node *n,
-       struct hlist_node *next)
+/**
+ * hlist_add_behind - add a new entry after the one specified
+ * @param n    new entry to be added
+ * @param prev hlist node to add it after, which must be non-NULL
+ */
+static inline void hlist_add_behind(struct hlist_node *n,
+                                   struct hlist_node *prev)
 {
-       next->next = n->next;
-       n->next = next;
-       next->pprev = &n->next;
+       n->next = prev->next;
+       prev->next = n;
+       n->pprev = &prev->next;
 
-       if (next->next)
-               next->next->pprev  = &next->next;
+       if (n->next)
+               n->next->pprev = &n->next;
 }
 
-/* after that we'll appear to be on some hlist and hlist_del will work */
+/**
+ * hlist_add_fake - create a fake hlist consisting of a single headless node
+ * @param n Node to make a fake list out of
+ *
+ * This makes @a n appear to be its own predecessor on a headless hlist.
+ * The point of this is to allow things like hlist_del() to work correctly
+ * in cases where there is no list.
+ */
 static inline void hlist_add_fake(struct hlist_node *n)
 {
        n->pprev = &n->next;
 }
 
-/*
+/**
+ * hlist_fake: Is this node a fake hlist?
+ * @param h Node to check for being a self-referential fake hlist.
+ */
+static inline bool hlist_fake(struct hlist_node *h)
+{
+       return h->pprev == &h->next;
+}
+
+/**
+ * hlist_is_singular_node - is node the only element of the specified hlist?
+ * @param n Node to check for singularity.
+ * @param h Header for potentially singular list.
+ *
+ * Check whether the node is the only node of the head without
+ * accessing head, thus avoiding unnecessary cache misses.
+ */
+static inline bool
+hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
+{
+       return !n->next && n->pprev == &h->first;
+}
+
+/**
+ * hlist_move_list - Move an hlist
+ * @param old hlist_head for old list.
+ * @param new hlist_head for new list.
+ *
  * Move a list from one list head to another. Fixup the pprev
  * reference of the first entry if it exists.
  */
 static inline void hlist_move_list(struct hlist_head *old,
-       struct hlist_head *new)
+                                  struct hlist_head *new)
 {
        new->first = old->first;
        if (new->first)
@@ -677,61 +975,57 @@ static inline void hlist_move_list(struct hlist_head *old,
 #define hlist_entry(ptr, type, member) container_of(ptr, type, member)
 
 #define hlist_for_each(pos, head) \
-       for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
-            pos = pos->next)
+       for (pos = (head)->first; pos ; pos = pos->next)
 
 #define hlist_for_each_safe(pos, n, head) \
        for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
             pos = n)
 
+#define hlist_entry_safe(ptr, type, member) \
+       ({ typeof(ptr) ____ptr = (ptr); \
+          ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+       })
+
 /**
  * hlist_for_each_entry        - iterate over list of given type
- * @param tpos   the type * to use as a loop cursor.
- * @param pos    the &struct hlist_node to use as a loop cursor.
+ * @param pos    the type * to use as a loop cursor.
  * @param head   the head for your list.
  * @param member the name of the hlist_node within the struct.
  */
-#define hlist_for_each_entry(tpos, pos, head, member)                   \
-       for (pos = (head)->first;                                        \
-            pos && ({ prefetch(pos->next); 1; }) &&                     \
-            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-            pos = pos->next)
+#define hlist_for_each_entry(pos, head, member)                                \
+       for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+            pos;                                                       \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
 
 /**
  * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @param tpos   the type * to use as a loop cursor.
- * @param pos    the &struct hlist_node to use as a loop cursor.
+ * @param pos    the type * to use as a loop cursor.
  * @param member the name of the hlist_node within the struct.
  */
-#define hlist_for_each_entry_continue(tpos, pos, member)                \
-       for (pos = (pos)->next;                                          \
-            pos && ({ prefetch(pos->next); 1; }) &&                     \
-            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-            pos = pos->next)
+#define hlist_for_each_entry_continue(pos, member)                     \
+       for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
+            pos;                                                       \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
 
 /**
  * hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @param tpos   the type * to use as a loop cursor.
- * @param pos    the &struct hlist_node to use as a loop cursor.
+ * @param pos    the type * to use as a loop cursor.
  * @param member the name of the hlist_node within the struct.
  */
-#define hlist_for_each_entry_from(tpos, pos, member)                    \
-       for (; pos && ({ prefetch(pos->next); 1; }) &&                   \
-            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-            pos = pos->next)
+#define hlist_for_each_entry_from(pos, member)                         \
+       for (; pos;                                                     \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
 
 /**
  * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @param tpos   the type * to use as a loop cursor.
- * @param pos    the &struct hlist_node to use as a loop cursor.
- * @param n      another &struct hlist_node to use as temporary storage
+ * @param pos    the type * to use as a loop cursor.
+ * @param n      a &struct hlist_node to use as temporary storage
  * @param head   the head for your list.
  * @param member the name of the hlist_node within the struct.
  */
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member)           \
-       for (pos = (head)->first;                                        \
-            pos && ({ n = pos->next; 1; }) &&                           \
-            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-            pos = n)
+#define hlist_for_each_entry_safe(pos, n, head, member)                \
+       for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
+            pos && ({ n = pos->member.next; 1; });                     \
+            pos = hlist_entry_safe(n, typeof(*pos), member))
 
 #endif /* OPENOCD_HELPER_LIST_H */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)