git: 34740937f7a4 - main - queue: New debug macros for STAILQ
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 16 Dec 2024 14:45:06 UTC
The branch main has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=34740937f7a46c7475bb57e804701ba8830bf6ed commit 34740937f7a46c7475bb57e804701ba8830bf6ed Author: Olivier Certner <olce@FreeBSD.org> AuthorDate: 2024-07-08 16:15:49 +0000 Commit: Olivier Certner <olce@FreeBSD.org> CommitDate: 2024-12-16 14:42:26 +0000 queue: New debug macros for STAILQ The new STAILQ_ASSERT_EMPTY() macro allows callers to assert that some STAILQ is empty. It leverages the new QMD_STAILQ_CHECK_EMPTY() internal macro. QMD_STAILQ_CHECK_EMPTY() is a check for empty STAILQ, where heads's 'stqh_last' field must point to the 'stqh_first' one. Use it in STAILQ_ASSERT_EMPTY(). QMD_STAILQ_CHECK_TAIL() checks that the tail pointed by 'head' does not have a next element. It is similar to the already existing QMD_TAILQ_CHECK_TAIL(), but without the superfluous 'field' argument and clearer documentation. Use it in STAILQ_INSERT_TAIL(). Approved by: markj (mentor) MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D46889 --- sys/sys/queue.h | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/sys/sys/queue.h b/sys/sys/queue.h index 0479d780fd85..8a1c6cd7afbb 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -339,6 +339,40 @@ struct { \ /* * Singly-linked Tail queue functions. */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_STAILQ_CHECK_EMPTY(STAILQ_HEAD *head) + * + * Validates that the stailq head's pointer to the last element's next pointer + * actually points to the head's first element pointer field. + */ +#define QMD_STAILQ_CHECK_EMPTY(head) do { \ + if ((head)->stqh_last != &(head)->stqh_first) \ + panic("Empty stailq %p->stqh_last is %p, not head's " \ + "first field address", (head), (head)->stqh_last); \ +} while (0) + +#define STAILQ_ASSERT_EMPTY(head) do { \ + if (!STAILQ_EMPTY((head))) \ + panic("stailq %p is not empty", (head)); \ +} + +/* + * QMD_STAILQ_CHECK_TAIL(STAILQ_HEAD *head) + * + * Validates that the stailq's last element's next pointer is NULL. + */ +#define QMD_STAILQ_CHECK_TAIL(head) do { \ + if (*(head)->stqh_last != NULL) \ + panic("Stailq %p last element's next pointer is %p, " \ + "not NULL", (head), *(head)->stqh_last); \ +} while (0) +#else +#define QMD_STAILQ_CHECK_EMPTY(head) +#define STAILQ_ASSERT_EMPTY(head) +#define QMD_STAILQ_CHECK_TAIL(head) +#endif /* (_KERNEL && INVARIANTS) */ + #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ @@ -347,7 +381,11 @@ struct { \ } \ } while (0) -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) +#define STAILQ_EMPTY(head) ({ \ + if (STAILQ_FIRST(head) == NULL) \ + QMD_STAILQ_CHECK_EMPTY(head); \ + STAILQ_FIRST(head) == NULL; \ +}) #define STAILQ_FIRST(head) ((head)->stqh_first) @@ -389,6 +427,7 @@ struct { \ } while (0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_STAILQ_CHECK_TAIL(head); \ STAILQ_NEXT((elm), field) = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \