diff mbox series

[ovs-dev,v5,12/15] rculist: use multi-variable helpers for loop macros

Message ID 20220323115624.1469085-13-amorenoz@redhat.com
State Accepted
Commit d293965d7b06bd47a1b016e0a90461acaabb1b6e
Headers show
Series Fix undefined behavior in loop macros | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test fail github build: failed
ovsrobot/intel-ovs-compilation fail test: fail

Commit Message

Adrian Moreno March 23, 2022, 11:56 a.m. UTC
Use multi-variable iteration helpers to rewrite rculist loops macros.

There is an important behavior change compared with the previous
implementation: When the loop ends normally (i.e: not via "break;"),
the object pointer provided by the user is NULL. This is safer
because it's not guaranteed that it would end up pointing a valid
address.

Acked-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 lib/rculist.h | 82 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 52 insertions(+), 30 deletions(-)

Comments

Dumitru Ceara March 24, 2022, 9:23 a.m. UTC | #1
On 3/23/22 12:56, Adrian Moreno wrote:
> Use multi-variable iteration helpers to rewrite rculist loops macros.
> 
> There is an important behavior change compared with the previous
> implementation: When the loop ends normally (i.e: not via "break;"),
> the object pointer provided by the user is NULL. This is safer
> because it's not guaranteed that it would end up pointing a valid
> address.
> 
> Acked-by: Eelco Chaudron <echaudro@redhat.com>
> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> ---

Acked-by: Dumitru Ceara <dceara@redhat.com>
diff mbox series

Patch

diff --git a/lib/rculist.h b/lib/rculist.h
index 1072b87af..c0d77acf9 100644
--- a/lib/rculist.h
+++ b/lib/rculist.h
@@ -365,35 +365,57 @@  rculist_is_singleton_protected(const struct rculist *list)
     return list_next == list->prev && list_next != list;
 }
 
-#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)                         \
-    for (INIT_CONTAINER(ITER, rculist_next(RCULIST), MEMBER);           \
-         &(ITER)->MEMBER != (RCULIST);                                  \
-         ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)                \
-    for (ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER); \
-         &(ITER)->MEMBER != (RCULIST);                                  \
-         ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)       \
-    for (INIT_CONTAINER(ITER, (RCULIST)->prev, MEMBER);                 \
-         &(ITER)->MEMBER != (RCULIST);                                  \
-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \
-    for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);           \
-         &(ITER)->MEMBER != (RCULIST);                                  \
-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-
-#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)               \
-    for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
-         &(ITER)->MEMBER != (RCULIST);                                  \
-         ASSIGN_CONTAINER(ITER, rculist_next_protected(&(ITER)->MEMBER), \
-                          MEMBER))
-
-#define RCULIST_FOR_EACH_SAFE_PROTECTED(ITER, NEXT, MEMBER, RCULIST)    \
-    for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
-         (&(ITER)->MEMBER != (RCULIST)                                  \
-          ? INIT_CONTAINER(NEXT, rculist_next_protected(&(ITER)->MEMBER), \
-                           MEMBER), 1 : 0);                             \
-         (ITER) = (NEXT))
+#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)                               \
+    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST),                   \
+                       const struct rculist);                                 \
+         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
+         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
+
+#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)                      \
+    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER),           \
+                       const struct rculist);                                 \
+         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
+         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)             \
+    for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev, struct rculist);        \
+         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
+         UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST)    \
+    for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev, struct rculist);    \
+         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
+         UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)                     \
+    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST),         \
+                       struct rculist);                                       \
+         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
+         UPDATE_MULTIVAR(ITER, rculist_next_protected(ITER_VAR(ITER)))        \
+
+#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST)          \
+    for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                               \
+                                  rculist_next_protected(RCULIST),            \
+                                  struct rculist);                            \
+         CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                          \
+                                       ITER_VAR(ITER) != (RCULIST),           \
+             ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR)));    \
+        UPDATE_MULTIVAR_SHORT(ITER))
+
+#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST)     \
+    for (INIT_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER,                          \
+                                 rculist_next_protected(RCULIST)              \
+                                 struct rculist);                             \
+         CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER                       \
+                                      ITER_VAR(ITER) != (RCULIST),            \
+             ITER_VAR(NEXT) = rculist_next_protected(ITER_VAR(VAR)),          \
+                                      ITER_VAR(NEXT) != (RCULIST));           \
+        UPDATE_MULTIVAR_LONG(ITER))
+
+#define RCULIST_FOR_EACH_SAFE_PROTECTED(...)                                  \
+    OVERLOAD_SAFE_MACRO(RCULIST_FOR_EACH_SAFE_LONG_PROTECTED,                 \
+                        RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED,                \
+                        4, __VA_ARGS__)
+
 
 #endif /* rculist.h */