Re: [PATCH 06/12] perf: Return empty callchain instead of NULL

From: Peter Zijlstra
Date: Mon Jan 08 2018 - 07:15:27 EST


On Sun, Jan 07, 2018 at 05:03:50PM +0100, Jiri Olsa wrote:
> It simplifies the code a bit, because we dump the callchain
> even if it's empty. With 'empty' callchain we can remove
> all the NULL-checking code paths.

Acked-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>

>
> Original-patch-from: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> Link: http://lkml.kernel.org/n/tip-n4t869o2qc1b31v4wwvmxznb@xxxxxxxxxxxxxx
> Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
> ---
> kernel/events/core.c | 30 ++++++++++++------------------
> 1 file changed, 12 insertions(+), 18 deletions(-)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 5fc1ded4b450..4e1a1bf8d867 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5815,19 +5815,11 @@ void perf_output_sample(struct perf_output_handle *handle,
> perf_output_read(handle, event);
>
> if (sample_type & PERF_SAMPLE_CALLCHAIN) {
> - if (data->callchain) {
> - int size = 1;
> -
> - if (data->callchain)
> - size += data->callchain->nr;
> -
> - size *= sizeof(u64);
> + int size = 1;
>
> - __output_copy(handle, data->callchain, size);
> - } else {
> - u64 nr = 0;
> - perf_output_put(handle, nr);
> - }
> + size += data->callchain->nr;
> + size *= sizeof(u64);
> + __output_copy(handle, data->callchain, size);
> }
>
> if (sample_type & PERF_SAMPLE_RAW) {
> @@ -5980,6 +5972,8 @@ static u64 perf_virt_to_phys(u64 virt)
> return phys_addr;
> }
>
> +static struct perf_callchain_entry __empty_callchain = { .nr = 0, };
> +
> static struct perf_callchain_entry *
> perf_callchain(struct perf_event *event, struct pt_regs *regs)
> {
> @@ -5988,12 +5982,14 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs)
> /* Disallow cross-task user callchains. */
> bool crosstask = event->ctx->task && event->ctx->task != current;
> const u32 max_stack = event->attr.sample_max_stack;
> + struct perf_callchain_entry *callchain;
>
> if (!kernel && !user)
> - return NULL;
> + return &__empty_callchain;
>
> - return get_perf_callchain(regs, 0, kernel, user,
> - max_stack, crosstask, true);
> + callchain = get_perf_callchain(regs, 0, kernel, user,
> + max_stack, crosstask, true);
> + return callchain ?: &__empty_callchain;
> }
>
> void perf_prepare_sample(struct perf_event_header *header,
> @@ -6018,9 +6014,7 @@ void perf_prepare_sample(struct perf_event_header *header,
> int size = 1;
>
> data->callchain = perf_callchain(event, regs);
> -
> - if (data->callchain)
> - size += data->callchain->nr;
> + size += data->callchain->nr;
>
> header->size += size * sizeof(u64);
> }
> --
> 2.13.6
>