[PATCH 1/2] bsdqueue.h: Update bsdqueue.h header file

10 views
Skip to first unread message

Clement Ramirez

unread,
Oct 14, 2025, 12:39:49 PM (8 days ago) Oct 14
to swup...@googlegroups.com, Clement Ramirez
From: Clement Ramirez <clement...@actia.fr>

Updating the original queue.h from bsd lib from 1.68 to 1.77.

It mainly fixes the LIST_MOVE macro which was not updating the chained
list's prev member.

Signed-off-by: Clement Ramirez <clement...@actia.fr>
---
include/bsdqueue.h | 288 ++++++++-------------------------------------
1 file changed, 48 insertions(+), 240 deletions(-)

diff --git a/include/bsdqueue.h b/include/bsdqueue.h
index 6c705f15..2a1d8674 100644
--- a/include/bsdqueue.h
+++ b/include/bsdqueue.h
@@ -3,8 +3,7 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-
-/* $NetBSD: queue.h,v 1.68 2014/11/19 08:10:01 uebayasi Exp $ */
+/* $NetBSD: queue.h,v 1.77 2024/05/12 10:34:56 rillig Exp $ */

/*
* Copyright (c) 1991, 1993
@@ -75,14 +74,6 @@
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
* For details on the use of these macros, see the queue(3) manual page.
*/

@@ -97,6 +88,10 @@
#include <sys/null.h>
#endif

+#if defined(_KERNEL) && defined(DIAGNOSTIC)
+#define QUEUEDEBUG 1
+#endif
+
#if defined(QUEUEDEBUG)
# if defined(_KERNEL)
# define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__)
@@ -146,26 +141,26 @@ struct { \
*/
#define SLIST_INIT(head) do { \
(head)->slh_first = SLIST_END(head); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SLIST_REMOVE_AFTER(slistelm, field) do { \
(slistelm)->field.sle_next = \
SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
@@ -178,7 +173,7 @@ struct { \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
} \
-} while (/*CONSTCOND*/0)
+} while (0)


/*
@@ -217,13 +212,14 @@ struct { \
((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))

-#define LIST_MOVE(head1, head2) do { \
+#define LIST_MOVE(head1, head2, field) do { \
LIST_INIT((head2)); \
if (!LIST_EMPTY((head1))) { \
(head2)->lh_first = (head1)->lh_first; \
+ (head2)->lh_first->field.le_prev = &(head2)->lh_first; \
LIST_INIT((head1)); \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

/*
* List functions.
@@ -254,7 +250,7 @@ struct { \

#define LIST_INIT(head) do { \
(head)->lh_first = LIST_END(head); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QUEUEDEBUG_LIST_OP((listelm), field) \
@@ -264,7 +260,7 @@ struct { \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QUEUEDEBUG_LIST_OP((listelm), field) \
@@ -272,7 +268,7 @@ struct { \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define LIST_INSERT_HEAD(head, elm, field) do { \
QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
@@ -280,7 +276,7 @@ struct { \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define LIST_REMOVE(elm, field) do { \
QUEUEDEBUG_LIST_OP((elm), field) \
@@ -289,7 +285,7 @@ struct { \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
-} while (/*CONSTCOND*/0)
+} while (0)

#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
@@ -298,7 +294,7 @@ struct { \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
-} while (/*CONSTCOND*/0)
+} while (0)

/*
* Simple queue definitions.
@@ -342,36 +338,36 @@ struct { \
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
== NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
if ((head)->sqh_first == (elm)) { \
@@ -384,7 +380,7 @@ struct { \
curelm->field.sqe_next->field.sqe_next) == NULL) \
(head)->sqh_last = &(curelm)->field.sqe_next; \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_CONCAT(head1, head2) do { \
if (!SIMPLEQ_EMPTY((head2))) { \
@@ -392,7 +388,7 @@ struct { \
(head1)->sqh_last = (head2)->sqh_last; \
SIMPLEQ_INIT((head2)); \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

#define SIMPLEQ_LAST(head, type, field) \
(SIMPLEQ_EMPTY((head)) ? \
@@ -427,9 +423,9 @@ struct { \
#define TAILQ_END(head) (NULL)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
+ (*(((struct headname *)(void *)((head)->tqh_last))->tqh_last))
#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+ (*(((struct headname *)(void *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head))


@@ -444,9 +440,9 @@ struct { \
((next) = TAILQ_NEXT(var, field), 1); (var) = (next))

#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
+ for ((var) = TAILQ_LAST((head), headname); \
(var) != TAILQ_END(head); \
- (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+ (var) = TAILQ_PREV((var), headname, field))

#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
for ((var) = TAILQ_LAST((head), headname); \
@@ -494,7 +490,7 @@ struct { \
#define TAILQ_INIT(head) do { \
(head)->tqh_first = TAILQ_END(head); \
(head)->tqh_last = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
@@ -505,7 +501,7 @@ struct { \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
@@ -513,7 +509,7 @@ struct { \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QUEUEDEBUG_TAILQ_OP((listelm), field) \
@@ -525,7 +521,7 @@ struct { \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QUEUEDEBUG_TAILQ_OP((listelm), field) \
@@ -533,7 +529,7 @@ struct { \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_REMOVE(head, elm, field) do { \
QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
@@ -545,7 +541,7 @@ struct { \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \
@@ -557,7 +553,7 @@ struct { \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
@@ -566,7 +562,7 @@ struct { \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

/*
* Singly-linked Tail queue declarations.
@@ -599,30 +595,30 @@ struct { \
#define STAILQ_INIT(head) do { \
(head)->stqh_first = NULL; \
(head)->stqh_last = &(head)->stqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
(head)->stqh_last = &(elm)->field.stqe_next; \
(head)->stqh_first = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.stqe_next = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &(elm)->field.stqe_next; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
(head)->stqh_last = &(elm)->field.stqe_next; \
(listelm)->field.stqe_next = (elm); \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_REMOVE_HEAD(head, field) do { \
if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
(head)->stqh_last = &(head)->stqh_first; \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_REMOVE(head, elm, type, field) do { \
if ((head)->stqh_first == (elm)) { \
@@ -635,7 +631,7 @@ struct { \
curelm->field.stqe_next->field.stqe_next) == NULL) \
(head)->stqh_last = &(curelm)->field.stqe_next; \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->stqh_first); \
@@ -653,7 +649,7 @@ struct { \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
-} while (/*CONSTCOND*/0)
+} while (0)

#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
@@ -661,192 +657,4 @@ struct { \
((struct type *)(void *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))

-
-#ifndef _KERNEL
-/*
- * Circular queue definitions. Do not use. We still keep the macros
- * for compatibility but because of pointer aliasing issues their use
- * is discouraged!
- */
-
-/*
- * __launder_type(): We use this ugly hack to work around the compiler
- * noticing that two types may not alias each other and elide tests in code.
- * We hit this in the CIRCLEQ macros when comparing 'struct name *' and
- * 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC
- * 4.8) declare these comparisons as always false, causing the code to
- * not run as designed.
- *
- * This hack is only to be used for comparisons and thus can be fully const.
- * Do not use for assignment.
- *
- * If we ever choose to change the ABI of the CIRCLEQ macros, we could fix
- * this by changing the head/tail sentinal values, but see the note above
- * this one.
- */
-static __inline const void * __launder_type(const void *);
-static __inline const void *
-__launder_type(const void *__x)
-{
- __asm __volatile("" : "+r" (__x));
- return __x;
-}
-
-#if defined(QUEUEDEBUG)
-#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
- if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \
- (head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \
- QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \
- __FILE__, __LINE__); \
- if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \
- (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \
- QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \
- __FILE__, __LINE__);
-#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
- if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \
- if ((head)->cqh_last != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } else { \
- if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } \
- if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \
- if ((head)->cqh_first != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } else { \
- if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- }
-#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
- (elm)->field.cqe_next = (void *)1L; \
- (elm)->field.cqe_prev = (void *)1L;
-#else
-#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
-#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
-#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
-#endif
-
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = CIRCLEQ_END(head); \
- (head)->cqh_last = CIRCLEQ_END(head); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = CIRCLEQ_END(head); \
- if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- (elm)->field.cqe_next = CIRCLEQ_END(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
- if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
- QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->cqh_first); \
- (var) != CIRCLEQ_ENDC(head); \
- (var) = ((var)->field.cqe_next))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for ((var) = ((head)->cqh_last); \
- (var) != CIRCLEQ_ENDC(head); \
- (var) = ((var)->field.cqe_prev))
-
-/*
- * Circular queue access methods.
- */
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-/* For comparisons */
-#define CIRCLEQ_ENDC(head) (__launder_type(head))
-/* For assignments */
-#define CIRCLEQ_END(head) ((void *)(head))
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-#define CIRCLEQ_EMPTY(head) \
- (CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head))
-
-#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
- (((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- ? ((head)->cqh_first) \
- : (elm->field.cqe_next))
-#define CIRCLEQ_LOOP_PREV(head, elm, field) \
- (((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- ? ((head)->cqh_last) \
- : (elm->field.cqe_prev))
-#endif /* !_KERNEL */
-
-#endif /* !_SYS_QUEUE_H_ */
+#endif /* !_SYS_QUEUE_H_ */
\ No newline at end of file
--
2.35.7

Clement Ramirez

unread,
Oct 14, 2025, 12:39:55 PM (8 days ago) Oct 14
to swup...@googlegroups.com, Clement Ramirez
From: Clement Ramirez <clement...@actia.fr>

The former implementation was updating a common list of installed
software versions each time an artifact was successfully
installed/executed.

This patch separate the software versions currently considered
installed and active (config files) from those brought by the
current update (runtime ones).

Signed-off-by: Clement Ramirez <clement...@actia.fr>
---
core/artifacts_versions.c | 44 +++++++++++++++++++++++++++++++++++----
core/installer.c | 35 +++++++++++++++++++++++++++----
core/stream_interface.c | 7 +++++++
corelib/lua_interface.c | 6 +++---
include/swupdate.h | 1 +
include/swupdate_image.h | 3 ++-
include/versions.h | 2 ++
parser/parse_external.c | 4 ++--
parser/parser.c | 28 ++++++++++++-------------
9 files changed, 102 insertions(+), 28 deletions(-)

diff --git a/core/artifacts_versions.c b/core/artifacts_versions.c
index 18422b70..73d1799e 100644
--- a/core/artifacts_versions.c
+++ b/core/artifacts_versions.c
@@ -64,12 +64,13 @@ static int read_sw_version_file(struct swupdate_cfg *sw)
return -ENOMEM;
}
strlcpy(swcomp->name, name, sizeof(swcomp->name));
- strlcpy(swcomp->version, version, sizeof(swcomp->version));
+ strlcpy(swcomp->config_version, version, sizeof(swcomp->config_version));
+ swcomp->runtime_version[0] = '\0';

LIST_INSERT_HEAD(&sw->installed_sw_list, swcomp, next);
TRACE("Installed %s: Version %s",
swcomp->name,
- swcomp->version);
+ swcomp->config_version);
free(name);
free(version);
} else {
@@ -115,12 +116,13 @@ static int versions_settings(void *setting, void *data)
}

GET_FIELD_STRING(LIBCFG_PARSER, elem, "name", swcomp->name);
- GET_FIELD_STRING(LIBCFG_PARSER, elem, "version", swcomp->version);
+ GET_FIELD_STRING(LIBCFG_PARSER, elem, "version", swcomp->config_version);
+ swcomp->runtime_version[0] = '\0';

LIST_INSERT_HEAD(&sw->installed_sw_list, swcomp, next);
TRACE("Installed %s: Version %s",
swcomp->name,
- swcomp->version);
+ swcomp->config_version);
}

return 0;
@@ -261,3 +263,37 @@ int compare_versions(const char* left_version, const char* right_version)
DEBUG("Comparing lexicographically '%s' <-> '%s'", left_version, right_version);
return strcmp(left_version, right_version);
}
+
+int backup_artifacts_versions(struct swver *dest, struct swver *src)
+{
+ struct sw_version *swcomp, *swcomp_copy;
+
+ LIST_INIT(dest);
+
+ LIST_FOREACH(swcomp, src, next) {
+ swcomp_copy = (struct sw_version *)calloc(1, sizeof(struct sw_version));
+ if (!swcomp_copy) {
+ ERROR("Could not create new version entry.");
+ free_image(swcomp_copy);
+ return -ENOMEM;
+ }
+
+ strlcpy(swcomp_copy->name, swcomp->name, sizeof(swcomp_copy->name));
+ strlcpy(swcomp_copy->runtime_version, swcomp->runtime_version,
+ sizeof(swcomp_copy->runtime_version));
+ strlcpy(swcomp_copy->config_version, swcomp->config_version,
+ sizeof(swcomp_copy->config_version));
+ LIST_INSERT_HEAD(dest, swcomp_copy, next);
+ }
+
+ return 0;
+}
+
+void restore_artifacts_versions(struct swver *dest, struct swver *src)
+{
+ struct swver tmp;
+
+ LIST_MOVE(src, &tmp, next);
+ LIST_MOVE(dest, src, next);
+ LIST_MOVE(&tmp, dest, next);
+}
\ No newline at end of file
diff --git a/core/installer.c b/core/installer.c
index 8cba1790..1b879373 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -205,13 +205,23 @@ static int generate_swversions(struct swupdate_cfg *cfg)
FILE *fp;
struct sw_version *swver;
struct swver *sw_ver_list = &cfg->installed_sw_list;
+ char *selected_version[SWUPDATE_GENERAL_STRING_SIZE];

fp = fopen(cfg->output_swversions, "w");
if (!fp)
return -EACCES;

LIST_FOREACH(swver, sw_ver_list, next) {
- fprintf(fp, "%s\t\t%s\n", swver->name, swver->version);
+ if (!strlen(swver->runtime_version))
+ {
+ strncpy(selected_version, swver->config_version, sizeof(selected_version));
+ }
+ else
+ {
+ strncpy(selected_version, swver->runtime_version, sizeof(selected_version));
+ }
+
+ fprintf(fp, "%s\t\t%s\n", swver->name, selected_version);
}
fclose(fp);

@@ -324,12 +334,12 @@ static int update_installed_image_version(struct swver *sw_ver_list,
* If component is already installed, update the version
*/
if (!strncmp(img->id.name, swver->name, sizeof(img->id.name))) {
- strncpy(swver->version, img->id.version, sizeof(img->id.version));
+ strncpy(swver->runtime_version, img->id.runtime_version, sizeof(swver->runtime_version));
return true;
}
}

- if (!strlen(img->id.version))
+ if (!strlen(img->id.runtime_version))
return false;

/*
@@ -342,7 +352,7 @@ static int update_installed_image_version(struct swver *sw_ver_list,
}

strlcpy(swcomp->name, img->id.name, sizeof(swcomp->name));
- strlcpy(swcomp->version, img->id.version, sizeof(swcomp->version));
+ strlcpy(swcomp->runtime_version, img->id.runtime_version, sizeof(swcomp->runtime_version));
LIST_INSERT_HEAD(sw_ver_list, swcomp, next);

return true;
@@ -364,6 +374,13 @@ int install_images(struct swupdate_cfg *sw)
bool dry_run = sw->parms.dry_run;
bool dropimg;

+ /* In case of failure, we must restore the previous versions */
+ ret = backup_artifacts_versions(&sw->installed_sw_list_backup, &sw->installed_sw_list);
+ if (ret) {
+ ERROR("Could not backup current installed software versions");
+ return ret;
+ }
+
/* Extract all scripts, preinstall scripts must be run now */
const char* tmpdir_scripts = get_tmpdirscripts();
ret = extract_scripts(&sw->scripts);
@@ -526,6 +543,8 @@ void cleanup_files(struct swupdate_cfg *software) {
struct img_type *img_tmp;
struct hw_type *hw;
struct hw_type *hw_tmp;
+ struct sw_version *swver;
+ struct sw_version *swver_tmp;
const char* TMPDIR = get_tmpdir();
struct imglist *list[] = {&software->scripts};

@@ -557,6 +576,14 @@ void cleanup_files(struct swupdate_cfg *software) {
dict_drop_db(&software->bootloader);
dict_drop_db(&software->vars);

+ /*
+ * Cleanup backup of installed software versions
+ */
+ LIST_FOREACH_SAFE(swver, &software->installed_sw_list_backup, next, swver_tmp) {
+ LIST_REMOVE(swver, next);
+ free(swver);
+ }
+
/*
* Drop Lua State if instantiated
*/
diff --git a/core/stream_interface.c b/core/stream_interface.c
index 8fadde3d..267bc2e6 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -760,6 +760,13 @@ void *network_initializer(void *data)
WARN("execute POST FAILURE scripts return error, ignoring..");
}
}
+
+ /*
+ * Restore the previous software versions list
+ * if the installation failed
+ */
+ restore_artifacts_versions(&software->installed_sw_list,
+ &software->installed_sw_list_backup);
} else {
/*
* Clear the recovery variable to indicate to bootloader
diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index 6543dff7..2bf5fc11 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -297,8 +297,8 @@ static void lua_string_to_img(struct img_type *img, const char *key,
sizeof(img->id.name));
}
if (!strcmp(key, "version")) {
- strncpy(img->id.version, value,
- sizeof(img->id.version));
+ strncpy(img->id.runtime_version, value,
+ sizeof(img->id.runtime_version));
}
if (!strcmp(key, "filename")) {
strncpy(img->fname, value,
@@ -506,7 +506,7 @@ static void update_table(lua_State* L, struct img_type *img)
luaL_checktype(L, -1, LUA_TTABLE);

LUA_PUSH_IMG_STRING(img, "name", id.name);
- LUA_PUSH_IMG_STRING(img, "version", id.version);
+ LUA_PUSH_IMG_STRING(img, "version", id.runtime_version);
LUA_PUSH_IMG_STRING(img, "filename", fname);
LUA_PUSH_IMG_STRING(img, "volume", volname);
LUA_PUSH_IMG_STRING(img, "type", type);
diff --git a/include/swupdate.h b/include/swupdate.h
index 59b085b6..356d30dc 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -98,6 +98,7 @@ struct swupdate_cfg {
struct hw_type hw;
struct hwlist hardware;
struct swver installed_sw_list;
+ struct swver installed_sw_list_backup;
struct swupdate_type_list swupdate_types;
struct imglist images;
struct imglist scripts;
diff --git a/include/swupdate_image.h b/include/swupdate_image.h
index 1bb37dc8..d204226a 100644
--- a/include/swupdate_image.h
+++ b/include/swupdate_image.h
@@ -32,7 +32,8 @@ typedef enum {

struct sw_version {
char name[SWUPDATE_GENERAL_STRING_SIZE];
- char version[SWUPDATE_GENERAL_STRING_SIZE];
+ char runtime_version[SWUPDATE_GENERAL_STRING_SIZE]; /*Version installed since swupdate is running*/
+ char config_version[SWUPDATE_GENERAL_STRING_SIZE]; /*Version referenced into versions config files*/
bool install_if_different;
bool install_if_higher;
LIST_ENTRY(sw_version) next;
diff --git a/include/versions.h b/include/versions.h
index 7f883be2..bf7f7f89 100644
--- a/include/versions.h
+++ b/include/versions.h
@@ -9,4 +9,6 @@

#include "swupdate_settings.h"
void get_sw_versions(swupdate_cfg_handle *handle, struct swupdate_cfg *sw);
+int backup_artifacts_versions(struct swver *dest, struct swver *src);
+void restore_artifacts_versions(struct swver *dest, struct swver *src);

diff --git a/parser/parse_external.c b/parser/parse_external.c
index d67bcca0..abdb835d 100644
--- a/parser/parse_external.c
+++ b/parser/parse_external.c
@@ -47,8 +47,8 @@ static void sw_append_stream(struct img_type *img, const char *key,
sizeof(img->id.name));
}
if (!strcmp(key, "version")) {
- strlcpy(img->id.version, value,
- sizeof(img->id.version));
+ strlcpy(img->id.runtime_version, value,
+ sizeof(img->id.runtime_version));
}
if (!strcmp(key, "mtdname") || !strcmp(key, "dest"))
strlcpy(img->mtdname, value,
diff --git a/parser/parser.c b/parser/parser.c
index 84bf036c..6c869a24 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -349,7 +349,7 @@ static int is_image_installed(struct swver *sw_ver_list,
if (!sw_ver_list)
return false;

- if (!strlen(img->id.name) || !strlen(img->id.version) ||
+ if (!strlen(img->id.name) || !strlen(img->id.runtime_version) ||
!img->id.install_if_different)
return false;

@@ -358,10 +358,10 @@ static int is_image_installed(struct swver *sw_ver_list,
* Check if name and version are identical
*/
if (!strncmp(img->id.name, swver->name, sizeof(img->id.name)) &&
- !compare_versions(img->id.version, swver->version)) {
+ !compare_versions(img->id.runtime_version, swver->config_version)) {
TRACE("%s(%s) already installed, skipping...",
img->id.name,
- img->id.version);
+ img->id.runtime_version);

return true;
}
@@ -378,13 +378,13 @@ static int is_image_higher(struct swver *sw_ver_list,
if (!sw_ver_list)
return false;

- if (!strlen(img->id.name) || !strlen(img->id.version) ||
+ if (!strlen(img->id.name) || !strlen(img->id.runtime_version) ||
!img->id.install_if_higher)
return false;

LIST_FOREACH(swver, sw_ver_list, next) {
- const char* current_version = swver->version;
- const char* proposed_version = img->id.version;
+ const char* current_version = swver->config_version;
+ const char* proposed_version = img->id.runtime_version;

/*
* Check if name are identical and the new version is lower
@@ -394,7 +394,7 @@ static int is_image_higher(struct swver *sw_ver_list,
(compare_versions(proposed_version, current_version) <= 0)) {
TRACE("%s(%s) has a higher or same version installed, skipping...",
img->id.name,
- img->id.version);
+ img->id.runtime_version);

return true;
}
@@ -472,7 +472,7 @@ static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
seek_str[0] = '\0';

GET_FIELD_STRING(p, elem, "name", image->id.name);
- GET_FIELD_STRING(p, elem, "version", image->id.version);
+ GET_FIELD_STRING(p, elem, "version", image->id.runtime_version);
GET_FIELD_STRING(p, elem, "filename", image->fname);
GET_FIELD_STRING(p, elem, "path", image->path);
GET_FIELD_STRING(p, elem, "volume", image->volname);
@@ -757,13 +757,13 @@ static int _parse_bootloader(parsertype p, void *cfg, void *setting, const char
* to let allocate the place for the strings
*/
GET_FIELD_STRING(p, elem, "name", dummy.id.name);
- GET_FIELD_STRING(p, elem, "value", dummy.id.version);
+ GET_FIELD_STRING(p, elem, "value", dummy.id.runtime_version);
skip = run_embscript(p, elem, &dummy, L, swcfg->embscript);
if (skip < 0) {
return -1;
}
if (!skip) {
- dict_set_value(&swcfg->bootloader, dummy.id.name, dummy.id.version);
+ dict_set_value(&swcfg->bootloader, dummy.id.name, dummy.id.runtime_version);
TRACE("Bootloader var: %s = %s",
dummy.id.name,
dict_get_value(&swcfg->bootloader, dummy.id.name));
@@ -832,7 +832,7 @@ static int _parse_vars(parsertype p, void *cfg, void *setting, const char **node
* to let allocate the place for the strings
*/
GET_FIELD_STRING(p, elem, "name", dummy.id.name);
- GET_FIELD_STRING(p, elem, "value", dummy.id.version);
+ GET_FIELD_STRING(p, elem, "value", dummy.id.runtime_version);
skip = run_embscript(p, elem, &dummy, L, swcfg->embscript);
if (skip < 0)
return -1;
@@ -842,7 +842,7 @@ static int _parse_vars(parsertype p, void *cfg, void *setting, const char **node
/*
* Store the variable in dictionary
*/
- dict_set_value(&swcfg->vars, dummy.id.name, dummy.id.version);
+ dict_set_value(&swcfg->vars, dummy.id.name, dummy.id.runtime_version);

TRACE("SWUpdate var: %s = %s",
dummy.id.name,
@@ -929,7 +929,7 @@ static int _parse_images(parsertype p, void *cfg, void *setting, const char **no
skip ? "Skip" : "Found",
image->compressed ? "compressed " : "",
strlen(image->id.name) ? " " : "", image->id.name,
- strlen(image->id.version) ? " " : "", image->id.version,
+ strlen(image->id.runtime_version) ? " " : "", image->id.runtime_version,
image->fname,
strlen(image->volname) ? "volume" : "device",
strlen(image->volname) ? image->volname :
@@ -1025,7 +1025,7 @@ static int _parse_files(parsertype p, void *cfg, void *setting, const char **nod
skip ? "Skip" : "Found",
file->compressed ? "compressed " : "",
strlen(file->id.name) ? " " : "", file->id.name,
- strlen(file->id.version) ? " " : "", file->id.version,
+ strlen(file->id.runtime_version) ? " " : "", file->id.runtime_version,
file->fname,
file->path,
strlen(file->device) ? file->device : "ROOTFS",
--
2.35.7

Reply all
Reply to author
Forward
0 new messages