]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/sys/queue.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / sys / queue.h
index 8791385d7d4b31959fa21089c50c81f909bf5b23..46b382ed77f9ac928e464b1c64c87f7aecd1064e 100644 (file)
@@ -207,14 +207,44 @@ struct qm_trace {
 #define __MISMATCH_TAGS_POP
 #endif
 
+/*!
+ * Ensures that these macros can safely be used in structs when compiling with
+ * clang. The macros do not allow for nullability attributes to be specified due
+ * to how they are expanded. For example:
+ *
+ *     SLIST_HEAD(, foo _Nullable) bar;
+ *
+ * expands to
+ *
+ *     struct {
+ *         struct foo _Nullable *slh_first;
+ *     }
+ *
+ * which is not valid because the nullability specifier has to apply to the
+ * pointer. So just ignore nullability completeness in all the places where this
+ * is an issue.
+ */
+#if defined(__clang__)
+#define __NULLABILITY_COMPLETENESS_PUSH \
+       _Pragma("clang diagnostic push") \
+       _Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
+#define __NULLABILITY_COMPLETENESS_POP \
+       _Pragma("clang diagnostic pop")
+#else
+#define __NULLABILITY_COMPLETENESS_PUSH
+#define __NULLABILITY_COMPLETENESS_POP
+#endif
+
 /*
  * Singly-linked List declarations.
  */
 #define SLIST_HEAD(name, type)                                          \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *slh_first; /* first element */                     \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define SLIST_HEAD_INITIALIZER(head)                                    \
@@ -222,9 +252,11 @@ __MISMATCH_TAGS_POP
 
 #define SLIST_ENTRY(type)                                               \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *sle_next;  /* next element */                      \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -267,6 +299,7 @@ __MISMATCH_TAGS_POP
 
 #define SLIST_REMOVE(head, elm, type, field)                            \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        if (SLIST_FIRST((head)) == (elm)) {                             \
                SLIST_REMOVE_HEAD((head), field);                       \
@@ -279,6 +312,7 @@ do {                                                                    \
        }                                                               \
        TRASHIT((elm)->field.sle_next);                                 \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                      \
 __MISMATCH_TAGS_POP
 
 #define SLIST_REMOVE_AFTER(elm, field) do {                             \
@@ -295,10 +329,12 @@ __MISMATCH_TAGS_POP
  */
 #define STAILQ_HEAD(name, type)                                         \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *stqh_first;/* first element */                     \
        struct type **stqh_last;/* addr of last next element */         \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_HEAD_INITIALIZER(head)                                   \
@@ -306,9 +342,11 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_ENTRY(type)                                              \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *stqe_next; /* next element */                      \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 /*
@@ -362,16 +400,19 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_LAST(head, type, field)                                  \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (STAILQ_EMPTY((head)) ?                                         \
                NULL :                                                  \
                ((struct type *)(void *)                                \
                ((char *)((head)->stqh_last) - __offsetof(struct type, field))))\
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
 
 #define STAILQ_REMOVE(head, elm, type, field)                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        if (STAILQ_FIRST((head)) == (elm)) {                            \
                STAILQ_REMOVE_HEAD((head), field);                      \
@@ -384,6 +425,7 @@ do {                                                                    \
        }                                                               \
        TRASHIT((elm)->field.stqe_next);                                \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                      \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_REMOVE_HEAD(head, field) do {                            \
@@ -405,6 +447,7 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_SWAP(head1, head2, type)                                 \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_first = STAILQ_FIRST(head1);                  \
        struct type **swap_last = (head1)->stqh_last;                   \
@@ -417,6 +460,7 @@ do {                                                                    \
        if (STAILQ_EMPTY(head2))                                        \
                (head2)->stqh_last = &STAILQ_FIRST(head2);              \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 
@@ -425,9 +469,11 @@ __MISMATCH_TAGS_POP
  */
 #define LIST_HEAD(name, type)                                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *lh_first;  /* first element */                     \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define LIST_HEAD_INITIALIZER(head)                                     \
@@ -435,10 +481,12 @@ __MISMATCH_TAGS_POP
 
 #define LIST_ENTRY(type)                                                \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *le_next;   /* next element */                      \
        struct type **le_prev;  /* address of previous next element */  \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -451,7 +499,8 @@ __MISMATCH_TAGS_POP
              LIST_FIRST((head)) != NULL &&                             \
              LIST_FIRST((head))->field.le_prev !=                      \
              &LIST_FIRST((head))))                                     \
-                    panic("Bad list head %p first->prev != head", (head));     \
+                    panic("Bad list head %p first->prev != head @%u",  \
+                        (head), __LINE__);                             \
 } while (0)
 
 #define LIST_CHECK_NEXT(elm, field) do {                                \
@@ -459,12 +508,14 @@ __MISMATCH_TAGS_POP
              LIST_NEXT((elm), field) != NULL &&                        \
              LIST_NEXT((elm), field)->field.le_prev !=                 \
              &((elm)->field.le_next)))                                 \
-                    panic("Bad link elm %p next->prev != elm", (elm)); \
+                    panic("Bad link elm %p next->prev != elm @%u",     \
+                        (elm), __LINE__);                              \
 } while (0)
 
 #define LIST_CHECK_PREV(elm, field) do {                                \
        if (__improbable(*(elm)->field.le_prev != (elm)))               \
-               panic("Bad link elm %p prev->next != elm", (elm));      \
+               panic("Bad link elm %p prev->next != elm @%u",          \
+                   (elm), __LINE__);                                   \
 } while (0)
 #else
 #define LIST_CHECK_HEAD(head, field)
@@ -530,6 +581,7 @@ __MISMATCH_TAGS_POP
 
 #define LIST_SWAP(head1, head2, type, field)                            \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_tmp = LIST_FIRST((head1));                    \
        LIST_FIRST((head1)) = LIST_FIRST((head2));                      \
@@ -539,6 +591,7 @@ do {                                                                    \
        if ((swap_tmp = LIST_FIRST((head2))) != NULL)                   \
                swap_tmp->field.le_prev = &LIST_FIRST((head2));         \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -546,11 +599,13 @@ __MISMATCH_TAGS_POP
  */
 #define TAILQ_HEAD(name, type)                                          \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *tqh_first; /* first element */                     \
        struct type **tqh_last; /* addr of last next element */         \
        TRACEBUF                                                        \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_HEAD_INITIALIZER(head)                                    \
@@ -558,11 +613,13 @@ __MISMATCH_TAGS_POP
 
 #define TAILQ_ENTRY(type)                                               \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *tqe_next;  /* next element */                      \
        struct type **tqe_prev; /* address of previous next element */  \
        TRACEBUF                                                        \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -574,7 +631,8 @@ __MISMATCH_TAGS_POP
              TAILQ_FIRST((head)) != NULL &&                            \
              TAILQ_FIRST((head))->field.tqe_prev !=                    \
              &TAILQ_FIRST((head))))                                    \
-                    panic("Bad tailq head %p first->prev != head", (head));    \
+                    panic("Bad tailq head %p first->prev != head @%u", \
+                        (head), __LINE__);                             \
 } while (0)
 
 #define TAILQ_CHECK_NEXT(elm, field) do {                               \
@@ -582,12 +640,14 @@ __MISMATCH_TAGS_POP
              TAILQ_NEXT((elm), field) != NULL &&                       \
              TAILQ_NEXT((elm), field)->field.tqe_prev !=               \
              &((elm)->field.tqe_next)))                                \
-                    panic("Bad tailq elm %p next->prev != elm", (elm));        \
+                    panic("Bad tailq elm %p next->prev != elm @%u",    \
+                        (elm), __LINE__);                              \
 } while(0)
 
 #define TAILQ_CHECK_PREV(elm, field) do {                               \
        if (__improbable(*(elm)->field.tqe_prev != (elm)))               \
-             panic("Bad tailq elm %p prev->next != elm", (elm));       \
+             panic("Bad tailq elm %p prev->next != elm @%u",           \
+                 (elm), __LINE__);                                     \
 } while(0)
 #else
 #define TAILQ_CHECK_HEAD(head, field)
@@ -630,6 +690,17 @@ __MISMATCH_TAGS_POP
            (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);  \
            (var) = (tvar))
 
+#if XNU_KERNEL_PRIVATE
+/*
+ * Can be used when the initialized HEAD was just bzeroed
+ * Works around deficiencies in clang analysis of initialization patterns.
+ * See: <rdar://problem/47939050>
+ */
+#define TAILQ_INIT_AFTER_BZERO(head) do {                               \
+       (head)->tqh_last = &TAILQ_FIRST((head));                        \
+} while (0)
+#endif /* XNU_KERNEL_PRIVATE */
+
 #define TAILQ_INIT(head) do {                                           \
        TAILQ_FIRST((head)) = NULL;                                     \
        (head)->tqh_last = &TAILQ_FIRST((head));                        \
@@ -686,14 +757,18 @@ __MISMATCH_TAGS_POP
 
 #define TAILQ_LAST(head, headname)                                      \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (*(((struct headname *)((head)->tqh_last))->tqh_last))          \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
 
 #define TAILQ_PREV(elm, headname, field)                                \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))     \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_REMOVE(head, elm, field) do {                             \
@@ -717,6 +792,7 @@ __MISMATCH_TAGS_POP
  */
 #define TAILQ_SWAP(head1, head2, type, field)                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_first = (head1)->tqh_first;                   \
        struct type **swap_last = (head1)->tqh_last;                    \
@@ -733,6 +809,7 @@ do {                                                                    \
        else                                                            \
                (head2)->tqh_last = &(head2)->tqh_first;                \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -740,18 +817,22 @@ __MISMATCH_TAGS_POP
  */
 #define CIRCLEQ_HEAD(name, type)                                        \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *cqh_first;         /* first element */             \
        struct type *cqh_last;          /* last element */              \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define CIRCLEQ_ENTRY(type)                                             \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *cqe_next;          /* next element */              \
        struct type *cqe_prev;          /* previous element */          \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 /*
@@ -762,19 +843,22 @@ __MISMATCH_TAGS_POP
        if (__improbable(                                                \
              CIRCLEQ_FIRST((head)) != ((void*)(head)) &&               \
              CIRCLEQ_FIRST((head))->field.cqe_prev != ((void*)(head))))\
-                    panic("Bad circleq head %p first->prev != head", (head));  \
+                    panic("Bad circleq head %p first->prev != head @%u", \
+                        (head), __LINE__);                             \
 } while(0)
 #define CIRCLEQ_CHECK_NEXT(head, elm, field) do {                       \
        if (__improbable(                                                \
              CIRCLEQ_NEXT((elm), field) != ((void*)(head)) &&          \
              CIRCLEQ_NEXT((elm), field)->field.cqe_prev != (elm)))     \
-                    panic("Bad circleq elm %p next->prev != elm", (elm));      \
+                    panic("Bad circleq elm %p next->prev != elm @%u",  \
+                        (elm), __LINE__);                              \
 } while(0)
 #define CIRCLEQ_CHECK_PREV(head, elm, field) do {                       \
        if (__improbable(                                                \
              CIRCLEQ_PREV((elm), field) != ((void*)(head)) &&          \
              CIRCLEQ_PREV((elm), field)->field.cqe_next != (elm)))     \
-                    panic("Bad circleq elm %p prev->next != elm", (elm));      \
+                    panic("Bad circleq elm %p prev->next != elm @%u",  \
+                        (elm), __LINE__);                              \
 } while(0)
 #else
 #define CIRCLEQ_CHECK_HEAD(head, field)