helper/list: Replace Linux code with FreeBSD one
[openocd.git] / src / helper / list.h
index c9de0569bc9b4faf1dfd2326515f59888d7c37ad..eb8858e74b6f4d1be3c6a44d5f1b96d154117310 100644 (file)
@@ -1,15 +1,31 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: BSD-2-Clause */
 
 /*
- * 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.
+ * Copyright (c) 2010 Isilon Systems, Inc.
+ * Copyright (c) 2010 iX Systems, Inc.
+ * Copyright (c) 2010 Panasas, Inc.
+ * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
+ * Copyright (c) 2021-2024 by Antonio Borneo <borneo.antonio@gmail.com>
+ * All rights reserved.
+ */
+
+/*
+ * Circular doubly linked list implementation.
+ *
+ * The content of this file is mainly copied/inspired from FreeBSD code in:
+ * https://cgit.freebsd.org/src/tree/
+ * files:
+ * sys/compat/linuxkpi/common/include/linux/list.h
+ * sys/compat/linuxkpi/common/include/linux/types.h
+ *
+ * Last aligned with release/13.3.0:
+ *
+ * - Skip 'hlist_*' double linked lists with a single pointer list head.
+ * - Expand WRITE_ONCE().
+ * - Use TAB for indentation.
+ * - Put macro arguments within parenthesis.
+ * - Remove blank lines after an open brace '{'.
+ * - Remove multiple assignment.
  *
  * There is an example of using this file in contrib/list_example.c.
  */
 #ifndef OPENOCD_HELPER_LIST_H
 #define OPENOCD_HELPER_LIST_H
 
-/* begin local changes */
-#include <helper/types.h>
+/* begin OpenOCD changes */
 
-#define LIST_POISON1 NULL
-#define LIST_POISON2 NULL
+#include <helper/types.h>
 
 struct list_head {
-       struct list_head *next, *prev;
+       struct list_head *next;
+       struct list_head *prev;
 };
 
-/* end local changes */
-
-/*
- * Circular doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
+/* end OpenOCD changes */
 
 #define LIST_HEAD_INIT(name) { &(name), &(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)
+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)
+static inline int
+list_empty(const struct list_head *head)
 {
-       return true;
+       return (head->next == head);
 }
-#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!
- */
-static inline void __list_add(struct list_head *new,
-                             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;
-}
-
-/**
- * list_add - add a new entry
- * @param new new entry to be added
- * @param head list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
+static inline int
+list_empty_careful(const struct list_head *head)
 {
-       __list_add(new, head, head->next);
-}
-
+       struct list_head *next = head->next;
 
-/**
- * list_add_tail - add a new entry
- * @param new new entry to be added
- * @param head list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-       __list_add(new, head->prev, head);
+       return ((next == head) && (next == head->prev));
 }
 
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
 {
        next->prev = prev;
        prev->next = next;
 }
 
-/* Ignore kernel __list_del_clearprev() */
-
-static inline void __list_del_entry(struct list_head *entry)
+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.
- */
-static inline void list_del(struct list_head *entry)
+static inline void
+list_del(struct list_head *entry)
 {
-       __list_del_entry(entry);
-       entry->next = LIST_POISON1;
-       entry->prev = LIST_POISON2;
+       __list_del(entry->prev, entry->next);
 }
 
-/**
- * list_replace - replace old entry by new 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(struct list_head *old,
-                               struct list_head *new)
+static inline void
+list_replace(struct list_head *old, struct list_head *new)
 {
        new->next = old->next;
        new->next->prev = new;
@@ -173,205 +98,189 @@ 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)
+static inline void
+list_replace_init(struct list_head *old, 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)
+static inline void
+linux_list_add(struct list_head *new, struct list_head *prev,
+       struct list_head *next)
 {
-       struct list_head *pos = entry2->prev;
-
-       list_del(entry2);
-       list_replace(entry1, entry2);
-       if (pos == entry1)
-               pos = entry2;
-       list_add(entry1, pos);
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
 }
 
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @param entry the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
+static inline void
+list_del_init(struct list_head *entry)
 {
-       __list_del_entry(entry);
+       list_del(entry);
        INIT_LIST_HEAD(entry);
 }
 
-/**
- * list_move - delete from one list and add as another's head
- * @param list the entry to move
- * @param head the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
+#define        list_entry(ptr, type, field)    container_of(ptr, type, field)
+
+#define        list_first_entry(ptr, type, member) \
+       list_entry((ptr)->next, type, member)
+
+#define        list_last_entry(ptr, type, member)      \
+       list_entry((ptr)->prev, type, member)
+
+#define        list_first_entry_or_null(ptr, type, member) \
+       (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+#define        list_next_entry(ptr, member)                                    \
+       list_entry(((ptr)->member.next), typeof(*(ptr)), member)
+
+#define        list_safe_reset_next(ptr, n, member) \
+       (n) = list_next_entry(ptr, member)
+
+#define        list_prev_entry(ptr, member)                                    \
+       list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
+
+#define        list_for_each(p, head)                                          \
+       for (p = (head)->next; p != (head); p = (p)->next)
+
+#define        list_for_each_safe(p, n, head)                                  \
+       for (p = (head)->next, n = (p)->next; p != (head); p = n, n = (p)->next)
+
+#define list_for_each_entry(p, h, field)                               \
+       for (p = list_entry((h)->next, typeof(*p), field); &(p)->field != (h); \
+           p = list_entry((p)->field.next, typeof(*p), field))
+
+#define list_for_each_entry_safe(p, n, h, field)                       \
+       for (p = list_entry((h)->next, typeof(*p), field),              \
+           n = list_entry((p)->field.next, typeof(*p), field); &(p)->field != (h);\
+           p = n, n = list_entry(n->field.next, typeof(*n), field))
+
+#define        list_for_each_entry_from(p, h, field) \
+       for ( ; &(p)->field != (h); \
+           p = list_entry((p)->field.next, typeof(*p), field))
+
+#define        list_for_each_entry_continue(p, h, field)                       \
+       for (p = list_next_entry((p), field); &(p)->field != (h);       \
+           p = list_next_entry((p), field))
+
+#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))
+
+#define        list_for_each_entry_reverse(p, h, field)                        \
+       for (p = list_entry((h)->prev, typeof(*p), field); &(p)->field != (h); \
+           p = list_entry((p)->field.prev, typeof(*p), field))
+
+#define        list_for_each_entry_safe_reverse(p, n, h, field)                \
+       for (p = list_entry((h)->prev, typeof(*p), field),              \
+           n = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
+           p = n, n = list_entry(n->field.prev, typeof(*n), field))
+
+#define        list_for_each_entry_continue_reverse(p, h, field) \
+       for (p = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
+           p = list_entry((p)->field.prev, typeof(*p), field))
+
+#define        list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev)
+
+#define        list_for_each_entry_from_reverse(p, h, field)   \
+       for (; &p->field != (h);                        \
+            p = list_prev_entry(p, field))
+
+static inline void
+list_add(struct list_head *new, struct list_head *head)
 {
-       __list_del_entry(list);
-       list_add(list, head);
+       linux_list_add(new, head, head->next);
 }
 
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @param list the entry to move
- * @param head the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
-                                 struct list_head *head)
+static inline void
+list_add_tail(struct list_head *new, struct list_head *head)
 {
-       __list_del_entry(list);
-       list_add_tail(list, head);
+       linux_list_add(new, head->prev, 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)
+static inline void
+list_move(struct list_head *list, struct list_head *head)
 {
-       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_del(list);
+       list_add(list, head);
 }
 
-/**
- * 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)
+static inline void
+list_move_tail(struct list_head *entry, struct list_head *head)
 {
-       return list->prev == head;
+       list_del(entry);
+       list_add_tail(entry, 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)
+static inline void
+list_rotate_to_front(struct list_head *entry, struct list_head *head)
 {
-       return list->next == head;
+       list_move_tail(entry, head);
 }
 
-/**
- * list_is_head - tests whether @a list is the list @a head
- * @param list the entry to test
- * @param head the head of the list
- */
-static inline int list_is_head(const struct list_head *list, const struct list_head *head)
+static inline void
+list_bulk_move_tail(struct list_head *head, struct list_head *first,
+       struct list_head *last)
 {
-       return list == head;
+       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_empty - tests whether a list is empty
- * @param head the list to test.
- */
-static inline int list_empty(const struct list_head *head)
+static inline void
+linux_list_splice(const struct list_head *list, struct list_head *prev,
+       struct list_head *next)
 {
-       return head->next == head;
+       struct list_head *first;
+       struct list_head *last;
+
+       if (list_empty(list))
+               return;
+       first = list->next;
+       last = list->prev;
+       first->prev = prev;
+       prev->next = first;
+       last->next = next;
+       next->prev = last;
 }
 
-/**
- * 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)
+static inline void
+list_splice(const struct list_head *list, struct list_head *head)
 {
-       __list_del_entry(entry);
-       entry->prev = entry;
-       entry->next = entry;
+       linux_list_splice(list, head, head->next);
 }
 
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @param head the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
+static inline void
+list_splice_tail(struct list_head *list, struct list_head *head)
 {
-       struct list_head *next = head->next;
-       return (next == head) && (next == head->prev);
+       linux_list_splice(list, head->prev, head);
 }
 
-/**
- * list_rotate_left - rotate the list to the left
- * @param head the head of the list
- */
-static inline void list_rotate_left(struct list_head *head)
+static inline void
+list_splice_init(struct list_head *list, struct list_head *head)
 {
-       struct list_head *first;
-
-       if (!list_empty(head)) {
-               first = head->next;
-               list_move_tail(first, head);
-       }
+       linux_list_splice(list, head, head->next);
+       INIT_LIST_HEAD(list);
 }
 
-/**
- * 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)
+static inline void
+list_splice_tail_init(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);
+       linux_list_splice(list, head->prev, head);
+       INIT_LIST_HEAD(list);
 }
 
-/**
- * list_is_singular - tests whether a list has just one entry.
- * @param head the list to test.
+/*
+ * Double linked lists with a single pointer list head.
+ * IGNORED
  */
+
 static inline int list_is_singular(const struct list_head *head)
 {
        return !list_empty(head) && (head->next == head->prev);
@@ -389,472 +298,79 @@ static inline void __list_cut_position(struct list_head *list,
        new_first->prev = head;
 }
 
-/**
- * list_cut_position - cut a list into two
- * @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
- *     and if so we won't cut the list
- *
- * This helper moves the initial part of @a head, up to and
- * including @a entry, from @a head to @a list. You should
- * pass on @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.
- *
- */
 static inline void list_cut_position(struct list_head *list,
                struct list_head *head, struct list_head *entry)
 {
        if (list_empty(head))
                return;
-       if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next))
+       if (list_is_singular(head) &&
+               (head->next != entry && head != entry))
                return;
-       if (list_is_head(entry, head))
+       if (entry == head)
                INIT_LIST_HEAD(list);
        else
                __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)
+static inline int list_is_first(const struct list_head *list,
+                               const struct list_head *head)
 {
-       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;
+       return (list->prev == head);
 }
 
-static inline void __list_splice(const struct list_head *list,
-                                struct list_head *prev,
-                                struct list_head *next)
+static inline int list_is_last(const struct list_head *list,
+                               const struct list_head *head)
 {
-       struct list_head *first = list->next;
-       struct list_head *last = list->prev;
-
-       first->prev = prev;
-       prev->next = first;
-
-       last->next = next;
-       next->prev = last;
-}
-
-/**
- * list_splice - join two lists, this is designed for stacks
- * @param list the new list to add.
- * @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)
-{
-       if (!list_empty(list))
-               __list_splice(list, head, head->next);
+       return list->next == head;
 }
 
-/**
- * list_splice_tail - join two lists, each list being a queue
- * @param list the new list to add.
- * @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)
+static inline size_t
+list_count_nodes(const struct list_head *list)
 {
-       if (!list_empty(list))
-               __list_splice(list, head->prev, head);
-}
+       const struct list_head *lh;
+       size_t count;
 
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- *
- * The list at @a list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
-                                   struct list_head *head)
-{
-       if (!list_empty(list)) {
-               __list_splice(list, head, head->next);
-               INIT_LIST_HEAD(list);
+       count = 0;
+       list_for_each(lh, list) {
+               count++;
        }
-}
 
-/**
- * list_splice_tail_init - join two lists and reinitialise the emptied list
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- *
- * Each of the lists is a queue.
- * The list at @a list is reinitialised
- */
-static inline void list_splice_tail_init(struct list_head *list,
-                                        struct list_head *head)
-{
-       if (!list_empty(list)) {
-               __list_splice(list, head->prev, head);
-               INIT_LIST_HEAD(list);
-       }
+       return (count);
 }
 
-/**
- * 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_head within the struct.
- */
-#define list_entry(ptr, type, member) \
-       container_of(ptr, type, member)
-
-/**
- * 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_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_next_entry_circular - get the next element in list
- * @param pos    the type * to cursor.
- * @param head   the list head to take the element from.
- * @param member the name of the list_head within the struct.
- *
- * Wraparound if pos is the last element (return the first element).
- * Note, that list is expected to be not empty.
- */
-#define list_next_entry_circular(pos, head, member) \
-       (list_is_last(&(pos)->member, head) ? \
-       list_first_entry(head, typeof(*(pos)), member) : list_next_entry(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_prev_entry_circular - get the prev element in list
- * @param pos    the type * to cursor.
- * @param head   the list head to take the element from.
- * @param member the name of the list_head within the struct.
- *
- * Wraparound if pos is the first element (return the last element).
- * Note, that list is expected to be not empty.
- */
-#define list_prev_entry_circular(pos, head, member) \
-       (list_is_first(&(pos)->member, head) ? \
-       list_last_entry(head, typeof(*(pos)), member) : list_prev_entry(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; !list_is_head(pos, (head)); pos = pos->next)
-
-/* Ignore kernel list_for_each_rcu() */
-
-/**
- * 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.
- *
- * Continue to iterate over a list, continuing after the current position.
+/*
+ * Double linked lists with a single pointer list head.
+ * IGNORED
  */
-#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
- * @param pos  the &struct list_head to use as a loop cursor.
- * @param head the head for your list.
- */
-#define list_for_each_prev(pos, head) \
-       for (pos = (head)->prev; pos != (head); pos = pos->prev)
+/* begin OpenOCD extensions */
 
 /**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @param pos  the &struct list_head to use as a loop cursor.
- * @param n    another &struct list_head to use as temporary storage
- * @param head the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-       for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, n = pos->next)
-
-/**
- * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @param pos  the &struct list_head to use as a loop cursor.
- * @param n    another &struct list_head to use as temporary storage
- * @param head the head for your list.
+ * list_for_each_entry_direction - iterate forward/backward over list of given type
+ * @param is_fwd the iterate direction, true for forward, false for backward.
+ * @param p      the type * to use as a loop cursor.
+ * @param h      the head of the list.
+ * @param field  the name of the list_head within the struct.
  */
-#define list_for_each_prev_safe(pos, n, head) \
-       for (pos = (head)->prev, n = pos->prev; \
-            pos != (head); \
-            pos = n, n = pos->prev)
+#define list_for_each_entry_direction(is_fwd, p, h, field)                                     \
+       for (p = list_entry(is_fwd ? (h)->next : (h)->prev, typeof(*p), field); \
+               &(p)->field != (h);                                                                                                     \
+               p = list_entry(is_fwd ? (p)->field.next : (p)->field.prev, typeof(*p), field))
 
 /**
- * list_count_nodes - count nodes in the list
- * @param head the head for your list.
+ * list_rotate_left - rotate the list to the left
+ * @param h the head of the list
  */
-static inline size_t list_count_nodes(struct list_head *head)
+static inline void list_rotate_left(struct list_head *h)
 {
-       struct list_head *pos;
-       size_t count = 0;
-
-       list_for_each(pos, head)
-               count++;
+       struct list_head *first;
 
-       return count;
+       if (!list_empty(h)) {
+               first = h->next;
+               list_move_tail(first, h);
+       }
 }
 
-/**
- * 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_head within the struct.
- */
-#define list_for_each_entry(pos, head, 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_head within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member)                 \
-       for (pos = list_last_entry(head, typeof(*pos), member);         \
-            !list_entry_is_head(pos, head, member);                    \
-            pos = list_prev_entry(pos, member))
-
-/**
- * list_for_each_entry_direction - iterate forward/backward over list of given type
- * @param forward the iterate direction, true for forward, false for backward.
- * @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.
- */
-#define list_for_each_entry_direction(forward, pos, head, member)              \
-       for (pos = forward ? list_first_entry(head, typeof(*pos), member)       \
-                                          : list_last_entry(head, typeof(*pos), member);       \
-                !list_entry_is_head(pos, head, member);                                                \
-                pos = forward ? list_next_entry(pos, member)                                   \
-                                          : 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_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) ? (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_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_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_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_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_head within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, 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_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, 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_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_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_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_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_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_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_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
- * exception to this is if the cursor element (pos) is pinned in the list,
- * and list_safe_reset_next is called after re-taking the lock and before
- * completing the current iteration of the loop body.
- */
-#define list_safe_reset_next(pos, n, member)                           \
-       n = list_next_entry(pos, member)
-
-/*
- * Double linked lists with a single pointer list head.
- * IGNORED
- */
+/* end OpenOCD extensions */
 
 #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)