From patchwork Tue Dec 13 16:56:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Schneider X-Patchwork-Id: 13072246 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4913C10F1B for ; Tue, 13 Dec 2022 17:04:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235172AbiLMRED (ORCPT ); Tue, 13 Dec 2022 12:04:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236311AbiLMRDC (ORCPT ); Tue, 13 Dec 2022 12:03:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BCBE22BD0 for ; Tue, 13 Dec 2022 08:58:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670950722; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pajEUW+e2kGpIy2WjVXpBvH/EVcKDyakZt4OPG6bn5I=; b=PDZCSY+iBhR6O541fctiaelt+VVxDE2IB8zpuFqVCD9QvbcCVIQlTl/F6Vuy2flftwWD8N +V2q/KQf7wZmdVE+AJOvWnPnq9h/NM4eSFwlrQmwc0GGYc1zJBSPGHQlxlcyZW/+bfNygQ af12WZ+pdTSzO+LbIhTXkTP6CJcTrv4= Received: from mimecast-mx02.redhat.com (66.187.233.88 [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-575-TdbiB_hNMK-3jEK8rTGm5g-1; Tue, 13 Dec 2022 11:57:07 -0500 X-MC-Unique: TdbiB_hNMK-3jEK8rTGm5g-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6E519806003; Tue, 13 Dec 2022 16:57:05 +0000 (UTC) Received: from vschneid.remote.csb (unknown [10.33.36.185]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 951351121314; Tue, 13 Dec 2022 16:57:04 +0000 (UTC) From: Valentin Schneider To: linux-trace-devel@vger.kernel.org Cc: Steven Rostedt , Daniel Bristot de Oliveira , Clark Williams , Douglas RAILLARD Subject: [PATCH v3 1/4] libtraceevent: Ensure print_field_raw() terminates with '\0' Date: Tue, 13 Dec 2022 16:56:17 +0000 Message-Id: <20221213165620.1034287-2-vschneid@redhat.com> In-Reply-To: <20221213165620.1034287-1-vschneid@redhat.com> References: <20221213165620.1034287-1-vschneid@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Testing printing cpumasks reveals an issue in print_field_raw()'s handling of arrays: its final operation is trace_seq_putc(']'), which omits a final '\0'. The other cases in the function invoke trace_seq_printf() which does the right thing, only the TEP_FIELD_IS_ARRAY case has that issue. Still, to prevent any future surprises, add a call to trace_seq_terminate() at the end of print_field_raw(). Signed-off-by: Valentin Schneider --- src/event-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/event-parse.c b/src/event-parse.c index a6e9e93..093b345 100644 --- a/src/event-parse.c +++ b/src/event-parse.c @@ -5681,6 +5681,7 @@ static void print_field_raw(struct trace_seq *s, void *data, int size, trace_seq_printf(s, "%llu", val); } } + trace_seq_terminate(s); } static int print_parse_data(struct tep_print_parse *parse, struct trace_seq *s, From patchwork Tue Dec 13 16:56:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Schneider X-Patchwork-Id: 13072241 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3632C10F1D for ; Tue, 13 Dec 2022 17:02:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235551AbiLMRCY (ORCPT ); Tue, 13 Dec 2022 12:02:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235875AbiLMRBO (ORCPT ); Tue, 13 Dec 2022 12:01:14 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7BFF324F18 for ; Tue, 13 Dec 2022 08:57:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670950628; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LiZjRFZPyEIQsuTzfYOxj7UrpVMrvcaaOcKi05q53Hw=; b=UvCu2DBnIihfPlwHAsZtbCvbJ7zJ5KuzAuxNTC2Aa74bJEPoAwsrQYZxBPlDd83TXBfu2q qeujbE1oXz1xVeiMRfhsckXaohiQC6Vyjt1Ptm3QfkkHrYVKE6+ZLQBAB4aGMeF1d01Two lY02dd4mFBCAKaUF8OOBC+mt50P0Pds= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-408-AZFHin3hN66DIRb4NkhO8g-1; Tue, 13 Dec 2022 11:57:07 -0500 X-MC-Unique: AZFHin3hN66DIRb4NkhO8g-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 54EC6803911; Tue, 13 Dec 2022 16:57:06 +0000 (UTC) Received: from vschneid.remote.csb (unknown [10.33.36.185]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9C4741121319; Tue, 13 Dec 2022 16:57:05 +0000 (UTC) From: Valentin Schneider To: linux-trace-devel@vger.kernel.org Cc: Steven Rostedt , Daniel Bristot de Oliveira , Clark Williams , Douglas RAILLARD Subject: [PATCH v3 2/4] libtraceevent: Add boiler-plate code for cpumask types Date: Tue, 13 Dec 2022 16:56:18 +0000 Message-Id: <20221213165620.1034287-3-vschneid@redhat.com> In-Reply-To: <20221213165620.1034287-1-vschneid@redhat.com> References: <20221213165620.1034287-1-vschneid@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org A cpumask event field type was recently added to Linux, which helps distinguish any odd bitmask from a cpumask. Right now this field type is not recognized by libtraceevent: [ipi:ipi_send_cpumask] function __get_cpumask not defined CPU 0 is empty CPU 1 is empty CPU 3 is empty cpus=4 echo-173 [002] 11.859745: ipi_send_cpumask: [FAILED TO PARSE] cpumask=ARRAY[02, 00, 00, 00, 00, 00, 00, 00] callsite=0xffffffff81121013 Since a cpumask is still a bitmask, define the boiler plate code for this new field type and wire it all to bitmask handling. Signed-off-by: Valentin Schneider --- include/traceevent/event-parse.h | 1 + src/event-parse.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/traceevent/event-parse.h b/include/traceevent/event-parse.h index 3be98b0..2171ad7 100644 --- a/include/traceevent/event-parse.h +++ b/include/traceevent/event-parse.h @@ -244,6 +244,7 @@ enum tep_print_arg_type { TEP_PRINT_BITMASK, TEP_PRINT_DYNAMIC_ARRAY_LEN, TEP_PRINT_HEX_STR, + TEP_PRINT_CPUMASK, }; struct tep_print_arg { diff --git a/src/event-parse.c b/src/event-parse.c index 093b345..ba8e727 100644 --- a/src/event-parse.c +++ b/src/event-parse.c @@ -1120,6 +1120,7 @@ static void free_arg(struct tep_print_arg *arg) free(arg->string.string); break; case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: free(arg->bitmask.bitmask); break; case TEP_PRINT_DYNAMIC_ARRAY: @@ -2853,6 +2854,7 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val) case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; @@ -2882,6 +2884,7 @@ static char *arg_eval (struct tep_print_arg *arg) case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: default: do_warning("invalid eval type %d", arg->type); break; @@ -3362,6 +3365,17 @@ process_bitmask(struct tep_event *event __maybe_unused, struct tep_print_arg *ar return TEP_EVENT_ERROR; } +static enum tep_event_type +process_cpumask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, + char **tok) +{ + enum tep_event_type type = process_bitmask(event, arg, tok); + if (type != TEP_EVENT_ERROR) + arg->type = TEP_PRINT_CPUMASK; + + return type; +} + static struct tep_function_handler * find_func_handler(struct tep_handle *tep, char *func_name) { @@ -3521,6 +3535,11 @@ process_function(struct tep_event *event, struct tep_print_arg *arg, free_token(token); return process_bitmask(event, arg, tok); } + if (strcmp(token, "__get_cpumask") == 0 || + strcmp(token, "__get_rel_cpumask") == 0) { + free_token(token); + return process_cpumask(event, arg, tok); + } if (strcmp(token, "__get_dynamic_array") == 0 || strcmp(token, "__get_rel_dynamic_array") == 0 || strcmp(token, "__get_sockaddr") == 0 || @@ -4181,6 +4200,7 @@ eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: return 0; case TEP_PRINT_FUNC: { struct trace_seq s; @@ -4674,6 +4694,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, case TEP_PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; + case TEP_PRINT_CPUMASK: case TEP_PRINT_BITMASK: { if (!arg->bitmask.field) { arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); @@ -7196,6 +7217,9 @@ static void print_args(struct tep_print_arg *args) case TEP_PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; + case TEP_PRINT_CPUMASK: + printf("__get_cpumask(%s)", args->bitmask.bitmask); + break; case TEP_PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); From patchwork Tue Dec 13 16:56:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Schneider X-Patchwork-Id: 13072240 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23BCEC10F1B for ; Tue, 13 Dec 2022 17:02:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229999AbiLMRCY (ORCPT ); Tue, 13 Dec 2022 12:02:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236109AbiLMRBU (ORCPT ); Tue, 13 Dec 2022 12:01:20 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3499F22506 for ; Tue, 13 Dec 2022 08:57:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670950629; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SRu5GBwkrPlWnMueKheHDziQfSXO0ZGGE3sEIVBOPJ4=; b=UFcnrkP6Z4MY7tRbLwzSCU20jAKFb4USMZxpjRitbCCmDGeHbcdqbtJoUWT5zffUkbhRQS W9QhouRuevSDcVYtAaCly/7SGVCAwBE5xdIAIwk2fVENT8Iv6JHnowK/P1ApcMIJ6GitK8 OTNBH0Vs2ygIlGVj/9uS3IMMDnKcyP4= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-383-VVCFzYgSPeWV12DJwf78NA-1; Tue, 13 Dec 2022 11:57:07 -0500 X-MC-Unique: VVCFzYgSPeWV12DJwf78NA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4361F1C075A3; Tue, 13 Dec 2022 16:57:07 +0000 (UTC) Received: from vschneid.remote.csb (unknown [10.33.36.185]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 897FB1121314; Tue, 13 Dec 2022 16:57:06 +0000 (UTC) From: Valentin Schneider To: linux-trace-devel@vger.kernel.org Cc: Steven Rostedt , Daniel Bristot de Oliveira , Clark Williams , Douglas RAILLARD Subject: [PATCH v3 3/4] libtraceevent: Pretty-print cpumask fields as a cpulist Date: Tue, 13 Dec 2022 16:56:19 +0000 Message-Id: <20221213165620.1034287-4-vschneid@redhat.com> In-Reply-To: <20221213165620.1034287-1-vschneid@redhat.com> References: <20221213165620.1034287-1-vschneid@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Now that we can denote which bitmasks are cpumasks, it makes sense to pretty-print them to a more user-friendly format: a cpulist. There's two hurdles to that: 1) Estimating the required string buffer size. I've tried to condense it down to an estimator function that is computationally simple enough, though it overestimates by ~1/3. For reference, this estimates: 180 bytes for NR_CPUS=64 (x86 defconfig) 911 bytes for NR_CPUS=256 (arm64 defconfig) 2) Iterating through the bits and bytes. The kernel has a collection of carefully crafted bitmask iterators which make this relatively simple (cf. bitmap_list_string()), but I didn't feel justified in importing half a dozen helpers just for one function. I've implemented a "homegrown" byte-parsing logic which isn't the fastest, but is at least condensed to a single function. Signed-off-by: Valentin Schneider --- src/event-parse.c | 168 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) diff --git a/src/event-parse.c b/src/event-parse.c index ba8e727..d1363a5 100644 --- a/src/event-parse.c +++ b/src/event-parse.c @@ -4491,6 +4491,161 @@ static void print_bitmask_to_seq(struct tep_handle *tep, free(str); } +#define log10(n) \ +( \ + n < 10UL ? 0 : \ + n < 100UL ? 1 : \ + n < 1000UL ? 2 : \ + n < 10000UL ? 3 : \ + n < 100000UL ? 4 : \ + n < 1000000UL ? 5 : \ + n < 10000000UL ? 6 : \ + n < 100000000UL ? 7 : \ + n < 1000000000UL ? 8 : \ + 9 \ +) + +/* ilog10(0) should be 1 but the 0 simplifies below math */ +#define ilog10(n) \ +( \ + n == 0 ? 0UL : \ + n == 1 ? 10UL : \ + n == 2 ? 100UL : \ + n == 3 ? 1000UL : \ + n == 4 ? 10000UL : \ + n == 5 ? 100000UL : \ + n == 6 ? 1000000UL : \ + n == 7 ? 10000000UL : \ + n == 8 ? 100000000UL : \ + 1000000000UL \ +) + +static unsigned int cpumask_worst_size(unsigned int nr_bits) +{ + /* + * Printing all the CPUs separated by a comma is a decent bound for the + * maximum memory required to print a cpumask (a slightly better bound + * is chunks of 2 bits set, i.e. 0-1,3-4,6-7...). + * + * e.g. for nr_bits=132: + * - 131 commas + * - 10 * 1 chars for CPUS [0, 9] + * - 90 * 2 chars for CPUS [10-99] + * - 32 * 3 chars for CPUS [100-131] + */ + unsigned int last_cpu = nr_bits - 1; + unsigned int nr_chars = nr_bits - 1; + int last_lvl = log10(last_cpu); + + /* All log10 levels before the last one have all values used */ + for (int lvl = 0; lvl < last_lvl; lvl++) { + int nr_values = ilog10(lvl + 1) - ilog10(lvl); + + nr_chars += nr_values * (lvl + 1); + } + /* Last level is incomplete */ + nr_chars += (nr_bits - ilog10(last_lvl)) * (last_lvl + 1); + + return nr_chars; +} + +static void print_cpumask_to_seq(struct tep_handle *tep, + struct trace_seq *s, const char *format, + int len_arg, const void *data, int size) +{ + int firstone = -1, firstzero = -1; + int nr_bits = size * 8; + bool first = true; + int str_size = 0; + char buf[12]; /* '-' + log10(2^32) + 1 digits + '\0' */ + char *str; + int index; + int i; + + str = malloc(cpumask_worst_size(nr_bits) + 1); + if (!str) { + do_warning("%s: not enough memory!", __func__); + return; + } + + for (i = 0; i < size; i++) { + unsigned char byte; + int fmtsize; + + if (tep->file_bigendian) + index = size - (i + 1); + else + index = i; + + /* Byte by byte scan, not the best... */ + byte = *(((unsigned char *)data) + index); +more: + /* First find a bit set to one...*/ + if (firstone < 0 && byte) { + /* + * Set all lower bits, so a later ffz on this same byte + * is guaranteed to find a later bit. + */ + firstone = ffs(byte) - 1; + byte |= (1 << firstone) - 1; + firstone += i * 8; + } + + if (firstone < 0) + continue; + + /* ...Then find a bit set to zero */ + if ((~byte) & 0xFF) { + /* + * Clear all lower bits, so a later ffs on this same + * byte is guaranteed to find a later bit. + */ + firstzero = ffs(~byte) - 1; + byte &= ~((1 << (firstzero)) - 1); + firstzero += i * 8; + } else if (i == size - 1) { /* ...Or reach the end of the mask */ + firstzero = nr_bits; + byte = 0; + } else { + continue; + } + + /* We've found a bit set to one, and a later bit set to zero. */ + if (!first) { + str[str_size] = ','; + str_size++; + } + first = false; + + /* It takes {log10(number) + 1} chars to format a number */ + fmtsize = log10(firstone) + 1; + snprintf(buf, fmtsize + 1, "%d", firstone); + memcpy(str + str_size, buf, fmtsize); + str_size += fmtsize; + + if (firstzero > firstone + 1) { + fmtsize = log10(firstzero - 1) + 2; + snprintf(buf, fmtsize + 1, "-%d", firstzero - 1); + memcpy(str + str_size, buf, fmtsize); + str_size += fmtsize; + } + + firstzero = firstone = -1; + if (byte) + goto more; + } + + str[str_size] = 0; + str_size++; + + if (len_arg >= 0) + trace_seq_printf(s, format, len_arg, str); + else + trace_seq_printf(s, format, str); + + free(str); +} + static void print_str_arg(struct trace_seq *s, void *data, int size, struct tep_event *event, const char *format, int len_arg, struct tep_print_arg *arg) @@ -4694,7 +4849,6 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, case TEP_PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; - case TEP_PRINT_CPUMASK: case TEP_PRINT_BITMASK: { if (!arg->bitmask.field) { arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); @@ -4707,6 +4861,18 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, data + offset, len); break; } + case TEP_PRINT_CPUMASK: { + if (!arg->bitmask.field) { + arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); + arg->bitmask.offset = arg->bitmask.field->offset; + } + if (!arg->bitmask.field) + break; + dynamic_offset_field(tep, arg->bitmask.field, data, size, &offset, &len); + print_cpumask_to_seq(tep, s, format, len_arg, + data + offset, len); + break; + } case TEP_PRINT_OP: /* * The only op for string should be ? : From patchwork Tue Dec 13 16:56:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Schneider X-Patchwork-Id: 13072242 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE906C4167B for ; Tue, 13 Dec 2022 17:02:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235907AbiLMRC0 (ORCPT ); Tue, 13 Dec 2022 12:02:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236117AbiLMRBU (ORCPT ); Tue, 13 Dec 2022 12:01:20 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6EC3F24F10 for ; Tue, 13 Dec 2022 08:57:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1670950631; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MEPpq5y0HbnJK7RSA2BlFjngIbfDjick2Z9K3NQ41KE=; b=Ly4OL1klTcSZ6nD3pbWSgFMWXmHtlYOdG1JTu0psS19zAUj34yImhEqmMhA/LjSkQEpx3n Pj4dtdbKX5QzKibMF5Cf2S4/G2gpc4z7QpeSD5XvK/ktuq033aIdx80ZQRVGE2jt6xN+VI pd3zx+1BBa92m7ZVD9Xe3UltI3aEhWQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-631-gPFwBuK9MUm6_qzCl42yKw-1; Tue, 13 Dec 2022 11:57:08 -0500 X-MC-Unique: gPFwBuK9MUm6_qzCl42yKw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2F2C98038E7; Tue, 13 Dec 2022 16:57:08 +0000 (UTC) Received: from vschneid.remote.csb (unknown [10.33.36.185]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 769B11121314; Tue, 13 Dec 2022 16:57:07 +0000 (UTC) From: Valentin Schneider To: linux-trace-devel@vger.kernel.org Cc: Steven Rostedt , Daniel Bristot de Oliveira , Clark Williams , Douglas RAILLARD Subject: [PATCH v3 4/4] libtraceevent: Add unit tests for cpumask processing Date: Tue, 13 Dec 2022 16:56:20 +0000 Message-Id: <20221213165620.1034287-5-vschneid@redhat.com> In-Reply-To: <20221213165620.1034287-1-vschneid@redhat.com> References: <20221213165620.1034287-1-vschneid@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Add units tests that cover the TEP_PRINT_CPUMASK cases. Sicne print_cpumask_to_seq() is based on a per-byte scan, add some tests that cross byte boundaries when looking for the next non-zero byte. Signed-off-by: Valentin Schneider --- utest/traceevent-utest.c | 161 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/utest/traceevent-utest.c b/utest/traceevent-utest.c index 99900de..4fc09e5 100644 --- a/utest/traceevent-utest.c +++ b/utest/traceevent-utest.c @@ -100,6 +100,86 @@ static char dyn_str_old_data[] = { }; static void *dyn_str_old_event_data = (void *)dyn_str_old_data; +#define CPUMASK_EVENT_SYSTEM "ipi" +#define CPUMASK_EVENT_FIELD "cpumask" +static const char cpumask_event_format[] = + "name: ipi_send_cpumask\n" + "ID: 3\n" + "format:\n" + "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\n" + "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\n" + "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\n" + "\tfield:int common_pid;\toffset:4;\tsize:4;\n" + "\n" + "\tfield:__data_loc cpumask_t *[] cpumask;\toffset:8;\tsize:4;\tsigned:0;\n" + "\n" + "print fmt: \"cpumask=%s\", __get_cpumask(cpumask)\n"; + +/* Mind the endianness! */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define DECL_CPUMASK_EVENT_DATA(name, args...) \ + static char cpumask_##name##_event_data[] = { \ + /* common type */ 3, 0x00, \ + /* common flags */ 0x00, \ + /* common_preempt_count */ 0x00, \ + /* common_pid */ 0x00, 0x00, 0x00, 0x00, \ + /* [offset, size] */ 16, 0x00, 8, 0x00, \ + /* padding */ 0x00, 0x00, 0x00, 0x00, \ + /* cpumask */ args, \ +} +#else +#define DECL_CPUMASK_EVENT_DATA(name, args...) \ +static char cpumask_##name##_event_data[] = { \ + /* common type */ 0x00, 3, \ + /* common flags */ 0x00, \ + /* common_preempt_count */ 0x00, \ + /* common_pid */ 0x00, 0x00, 0x00, 0x00, \ + /* [offset, size] */ 0x00, 8, 0x00, 16, \ + /* padding */ 0x00, 0x00, 0x00, 0x00, \ + /* cpumask */ args, \ +} +#endif + +DECL_CPUMASK_EVENT_DATA(full, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); +#define CPUMASK_FULL "ARRAY[ff, ff, ff, ff, ff, ff, ff, ff]" +#define CPUMASK_FULL_FMT "cpumask=0-63" + +DECL_CPUMASK_EVENT_DATA(empty, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_EMPTY "ARRAY[00, 00, 00, 00, 00, 00, 00, 00]" +#define CPUMASK_EMPTY_FMT "cpumask=" + +DECL_CPUMASK_EVENT_DATA(half, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); +#define CPUMASK_HALF "ARRAY[55, 55, 55, 55, 55, 55, 55, 55]" +#define CPUMASK_HALF_FMT "cpumask=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62" + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +DECL_CPUMASK_EVENT_DATA(bytep1, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_BYTEP1 "ARRAY[01, 80, 00, 00, 00, 00, 00, 00]" +#define CPUMASK_BYTEP1_FMT "cpumask=0,15" + +DECL_CPUMASK_EVENT_DATA(bytep2, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_BYTEP2 "ARRAY[01, 00, 80, 00, 00, 00, 00, 00]" +#define CPUMASK_BYTEP2_FMT "cpumask=0,23" + +DECL_CPUMASK_EVENT_DATA(bytepn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80); +#define CPUMASK_BYTEPN "ARRAY[01, 00, 00, 00, 00, 00, 00, 80]" +#define CPUMASK_BYTEPN_FMT "cpumask=0,63" + +#else + +DECL_CPUMASK_EVENT_DATA(bytep1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01); +#define CPUMASK_BYTEP1 "ARRAY[00, 00, 00, 00, 00, 00, 80, 01]" +#define CPUMASK_BYTEP1_FMT "cpumask=0,15" + +DECL_CPUMASK_EVENT_DATA(bytep2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01); +#define CPUMASK_BYTEP2 "ARRAY[00, 00, 00, 00, 00, 80, 00, 01]" +#define CPUMASK_BYTEP2_FMT "cpumask=0,23" + +DECL_CPUMASK_EVENT_DATA(bytepn, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01); +#define CPUMASK_BYTEPN "ARRAY[80, 00, 00, 00, 00, 00, 80, 01]" +#define CPUMASK_BYTEPN_FMT "cpumask=0,63" +#endif + static struct tep_handle *test_tep; static struct trace_seq *test_seq; static struct trace_seq seq_storage; @@ -139,6 +219,75 @@ static void test_parse_dyn_str_old_event(void) parse_dyn_str(dyn_str_old_event, dyn_str_old_event_data, sizeof(dyn_str_old_data)); } +static void parse_cpumask(const char *format, void *data, int size, + const char* expected_raw, const char* expected) +{ + struct tep_format_field *field; + struct tep_event *event; + struct tep_record record; + + record.data = data; + record.size = size; + + CU_TEST(tep_parse_format(test_tep, &event, + format, strlen(format), + CPUMASK_EVENT_SYSTEM) == TEP_ERRNO__SUCCESS); + + field = tep_find_any_field(event, CPUMASK_EVENT_FIELD); + CU_TEST(field != NULL); + + trace_seq_reset(test_seq); + tep_print_field_content(test_seq, data, size, field); + CU_TEST(strcmp(test_seq->buffer, expected_raw) == 0); + + trace_seq_reset(test_seq); + tep_print_event(test_tep, test_seq, &record, "%s", TEP_PRINT_INFO); + trace_seq_do_printf(test_seq); + CU_TEST(strcmp(test_seq->buffer, expected) == 0); +} + +static void test_parse_cpumask_full(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_full_event_data, sizeof(cpumask_full_event_data), + CPUMASK_FULL, CPUMASK_FULL_FMT); +} + +static void test_parse_cpumask_empty(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_empty_event_data, sizeof(cpumask_empty_event_data), + CPUMASK_EMPTY, CPUMASK_EMPTY_FMT); +} + +static void test_parse_cpumask_half(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_half_event_data, sizeof(cpumask_half_event_data), + CPUMASK_HALF, CPUMASK_HALF_FMT); +} + +static void test_parse_cpumask_bytep1(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytep1_event_data, sizeof(cpumask_bytep1_event_data), + CPUMASK_BYTEP1, CPUMASK_BYTEP1_FMT); +} + +static void test_parse_cpumask_bytep2(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytep2_event_data, sizeof(cpumask_bytep2_event_data), + CPUMASK_BYTEP2, CPUMASK_BYTEP2_FMT); +} + +static void test_parse_cpumask_bytepn(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytepn_event_data, sizeof(cpumask_bytepn_event_data), + CPUMASK_BYTEPN, CPUMASK_BYTEPN_FMT); +} + static int test_suite_destroy(void) { tep_free(test_tep); @@ -169,4 +318,16 @@ void test_traceevent_lib(void) test_parse_dyn_str_event); CU_add_test(suite, "parse old dynamic string event", test_parse_dyn_str_old_event); + CU_add_test(suite, "parse full cpumask", + test_parse_cpumask_full); + CU_add_test(suite, "parse empty cpumask", + test_parse_cpumask_empty); + CU_add_test(suite, "parse half-filled cpumask", + test_parse_cpumask_half); + CU_add_test(suite, "parse cpumask spanning 2 bytes", + test_parse_cpumask_bytep1); + CU_add_test(suite, "parse cpumask spanning 3 bytes", + test_parse_cpumask_bytep2); + CU_add_test(suite, "parse cpumask spanning all bytes", + test_parse_cpumask_bytepn); }