From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: "Jose E. Marchesi" <jose.marchesi@oracle.com>
Cc: bpf <bpf@vger.kernel.org>, David Faust <david.faust@oracle.com>,
Cupertino Miranda <cupertino.miranda@oracle.com>
Subject: Re: [PATCH bpf-next V2] bpf: make list_for_each_entry portable
Date: Sun, 12 May 2024 17:46:12 -0700 [thread overview]
Message-ID: <CAADnVQKUytdTK5ri4WUcB9VCmX4S+Hjkx7YkcDAPwP3UX05jBQ@mail.gmail.com> (raw)
In-Reply-To: <20240511212243.23477-1-jose.marchesi@oracle.com>
On Sat, May 11, 2024 at 2:23 PM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
> [Changes from V1:
> - The __compat_break has been abandoned in favor of
> a more readable can_loop macro that can be used anywhere, including
> loop conditions.]
>
> The macro list_for_each_entry is defined in bpf_arena_list.h as
> follows:
>
> #define list_for_each_entry(pos, head, member) \
> for (void * ___tmp = (pos = list_entry_safe((head)->first, \
> typeof(*(pos)), member), \
> (void *)0); \
> pos && ({ ___tmp = (void *)pos->member.next; 1; }); \
> cond_break, \
> pos = list_entry_safe((void __arena *)___tmp, typeof(*(pos)), member))
>
> The macro cond_break, in turn, expands to a statement expression that
> contains a `break' statement. Compound statement expressions, and the
> subsequent ability of placing statements in the header of a `for'
> loop, are GNU extensions.
>
> Unfortunately, clang implements this GNU extension differently than
> GCC:
>
> - In GCC the `break' statement is bound to the containing "breakable"
> context in which the defining `for' appears. If there is no such
> context, GCC emits a warning: break statement without enclosing `for'
> o `switch' statement.
>
> - In clang the `break' statement is bound to the defining `for'. If
> the defining `for' is itself inside some breakable construct, then
> clang emits a -Wgcc-compat warning.
>
> This patch adds a new macro can_loop to bpf_experimental, that
> implements the same logic than cond_break but evaluates to a boolean
> expression. The patch also changes all the current instances of usage
> of cond_break withing the header of loop accordingly.
>
> Tested in bpf-next master.
> No regressions.
>
> Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
> Cc: david.faust@oracle.com
> Cc: cupertino.miranda@oracle.com
> Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
> ---
> tools/testing/selftests/bpf/bpf_arena_list.h | 4 +--
> .../testing/selftests/bpf/bpf_experimental.h | 28 +++++++++++++++++++
> .../testing/selftests/bpf/progs/arena_list.c | 2 +-
> .../bpf/progs/verifier_iterating_callbacks.c | 9 +++---
> 4 files changed, 35 insertions(+), 8 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/bpf_arena_list.h b/tools/testing/selftests/bpf/bpf_arena_list.h
> index b99b9f408eff..85dbc3ea4da5 100644
> --- a/tools/testing/selftests/bpf/bpf_arena_list.h
> +++ b/tools/testing/selftests/bpf/bpf_arena_list.h
> @@ -29,6 +29,7 @@ static inline void *bpf_iter_num_new(struct bpf_iter_num *it, int i, int j) { re
> static inline void bpf_iter_num_destroy(struct bpf_iter_num *it) {}
> static inline bool bpf_iter_num_next(struct bpf_iter_num *it) { return true; }
> #define cond_break ({})
> +#define can_loop true
> #endif
>
> /* Safely walk link list elements. Deletion of elements is allowed. */
> @@ -36,8 +37,7 @@ static inline bool bpf_iter_num_next(struct bpf_iter_num *it) { return true; }
> for (void * ___tmp = (pos = list_entry_safe((head)->first, \
> typeof(*(pos)), member), \
> (void *)0); \
> - pos && ({ ___tmp = (void *)pos->member.next; 1; }); \
> - cond_break, \
> + pos && ({ ___tmp = (void *)pos->member.next; 1; }) && can_loop; \
> pos = list_entry_safe((void __arena *)___tmp, typeof(*(pos)), member))
>
> static inline void list_add_head(arena_list_node_t *n, arena_list_head_t *h)
> diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
> index 8b9cc87be4c4..13e79af0a17c 100644
> --- a/tools/testing/selftests/bpf/bpf_experimental.h
> +++ b/tools/testing/selftests/bpf/bpf_experimental.h
> @@ -326,7 +326,21 @@ l_true: \
> })
> #endif
>
> +/* Note that cond_break can only be portably used in the body of a
> + breakable construct, whereas can_loop can be used anywhere. */
I fixed this comment to be proper kernel style.
> +
> #ifdef __BPF_FEATURE_MAY_GOTO
> +#define can_loop \
> + ({ __label__ l_break, l_continue; \
fixed white space damage.
> + bool ret = true; \
> + asm volatile goto("may_goto %l[l_break]" \
fixed broken formatting.
> + :::: l_break); \
> + goto l_continue; \
> + l_break: ret = false; \
> + l_continue:; \
> + ret; \
> + })
> +
> #define cond_break \
> ({ __label__ l_break, l_continue; \
> asm volatile goto("may_goto %l[l_break]" \
> @@ -336,6 +350,20 @@ l_true: \
> l_continue:; \
> })
> #else
> +#define can_loop \
> + ({ __label__ l_break, l_continue; \
> + bool ret = true; \
> + asm volatile goto("1:.byte 0xe5; \
> + .byte 0; \
> + .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \
> + .short 0" \
> + :::: l_break); \
> + goto l_continue; \
> + l_break: ret = false; \
> + l_continue:; \
> + ret; \
> + })
> +
This copy paste of the macro is a bit annoying,
but I don't see a clean way to make can_loop and cond_break
to use a common macro without being unreadable.
So applied with the above fixes.
Thanks!
next prev parent reply other threads:[~2024-05-13 0:46 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-11 21:22 [PATCH bpf-next V2] bpf: make list_for_each_entry portable Jose E. Marchesi
2024-05-13 0:46 ` Alexei Starovoitov [this message]
2024-05-13 0:50 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAADnVQKUytdTK5ri4WUcB9VCmX4S+Hjkx7YkcDAPwP3UX05jBQ@mail.gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=cupertino.miranda@oracle.com \
--cc=david.faust@oracle.com \
--cc=jose.marchesi@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).