From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-21.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B609BC63797 for ; Thu, 22 Jul 2021 13:36:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C94F6135F for ; Thu, 22 Jul 2021 13:36:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232105AbhGVM4M (ORCPT ); Thu, 22 Jul 2021 08:56:12 -0400 Received: from mail.kernel.org ([198.145.29.99]:46570 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232159AbhGVMzo (ORCPT ); Thu, 22 Jul 2021 08:55:44 -0400 Received: from gandalf.local.home (cpe-66-24-58-225.stny.res.rr.com [66.24.58.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id E27EE61353; Thu, 22 Jul 2021 13:36:19 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.94.2) (envelope-from ) id 1m6Ys6-001atA-Q9; Thu, 22 Jul 2021 09:36:18 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Tom Zanussi , Masami Hiramatsu , Namhyung Kim , Daniel Bristot de Oliveira , "Steven Rostedt (VMware)" Subject: [PATCH v2 4/4] libtracefs: Add man pages for creating synthetic events Date: Thu, 22 Jul 2021 09:36:10 -0400 Message-Id: <20210722133610.379933-5-rostedt@goodmis.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210722133610.379933-1-rostedt@goodmis.org> References: <20210722133610.379933-1-rostedt@goodmis.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Add the man pages that describe all the synthetic event operations. Signed-off-by: Steven Rostedt (VMware) --- Documentation/libtracefs-synth.txt | 353 +++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 Documentation/libtracefs-synth.txt diff --git a/Documentation/libtracefs-synth.txt b/Documentation/libtracefs-synth.txt new file mode 100644 index 000000000000..7497dc16756c --- /dev/null +++ b/Documentation/libtracefs-synth.txt @@ -0,0 +1,353 @@ +libtracefs(3) +============= + +NAME +---- +tracefs_synth_init, tracefs_synth_add_match_field, tracefs_synth_add_compare_field, tracefs_synth_add_start_field, +tracefs_synth_add_end_field, tracefs_synth_add_start_filter, tracefs_synth_add_end_filter, tracefs_synth_create, +tracefs_synth_destroy, tracefs_synth_free, tracefs_synth_show - Creation of synthetic events + +SYNOPSIS +-------- +[verse] +-- +*#include * + +struct tracefs_synth pass:[*]tracefs_synth_init(struct tep_handle pass:[*]tep, + const char pass:[*]name, + const char pass:[*]start_system, + const char pass:[*]start_event, + const char pass:[*]end_system, + const char pass:[*]end_event, + const char pass:[*]start_match_field, + const char pass:[*]end_match_field, + const char pass:[*]match_name); +int tracefs_synth_add_match_field(struct tracefs_synth pass:[*]synth, + const char pass:[*]start_match_field, + const char pass:[*]end_match_field, + const char pass:[*]name); +int tracefs_synth_add_compare_field(struct tracefs_synth pass:[*]synth, + const char pass:[*]start_compare_field, + const char pass:[*]end_compare_field, + enum tracefs_synth_calc calc, + const char pass:[*]name); +int tracefs_synth_add_start_field(struct tracefs_synth pass:[*]synth, + const char pass:[*]start_field, + const char pass:[*]name); +int tracefs_synth_add_end_field(struct tracefs_synth pass:[*]synth, + const char pass:[*]end_field, + const char pass:[*]name); +int tracefs_synth_add_start_filter(struct tracefs_synth pass:[*]synth, + const char pass:[*]field, + enum tracefs_synth_compare compare, + const char pass:[*]val, + bool neg, bool or); +int tracefs_synth_add_end_filter(struct tracefs_synth pass:[*]synth, + const char pass:[*]field, + enum tracefs_synth_compare compare, + const char pass:[*]val, + bool neg, bool or); +int tracefs_synth_create(struct tracefs_instance pass:[*]instance, + struct tracefs_synth pass:[*]synth); +int tracefs_synth_destroy(struct tracefs_instance pass:[*]instance, + struct tracefs_synth pass:[*]synth); +void tracefs_synth_free(struct tracefs_synth pass:[*]synth); +int tracefs_synth_show(struct trace_seq pass:[*]seq, struct tracefs_instance pass:[*]instance, + struct tracefs_synth pass:[*]synth); + +-- + +DESCRIPTION +----------- +Synthetic events are dynamic events that are created by matching +two other events which triggers a synthetic event. One event is the starting +event which some field is recorded, and when the second event is executed, +if it has a field (or fields) that matches the starting event's field (or fields) +then it will trigger the synthetic event. The field values other than the matching +fields may be passed from the starting event to the end event to perform calculations +on, or to simply pass as a parameter to the synthetic event. + +One common use case is to set "sched_waking" as the starting event. This event is +triggered when a process is awoken. Then set "sched_switch" as the ending event. +This event is triggered when a new task is scheduled on the CPU. By setting +the "common_pid" of both events as the matching fields, the time between the +two events is considered the wake up latency of that process. Use *TRACEFS_TIMESTAMP* +as a field for both events to calculate the delta in nanoseconds, or use +*TRACEFS_TIMESTAMP_USECS" as the compare fields for both events to calculate the +delta in microseconds. This is used as the example below. + +*tracefs_synth_init*() allocates and initializes a synthetic event. +It does not create the synthetic event, but supplies the minimal information +to do so. See *tracefs_synth_create*() below for how to create the synthetic +event in the system. It requires a _tep_ handler that can be created by +*tracefs_local_events*(3) for more information. The _name_ holds the name +of the synthetic event that will be created. The _start_system is the name +of the system for the starting event. It may be NULL and the first event +with the name of _start_event_ will be chosen. The _end_system_ is the +name of the system for theh ending event. It may be NULL and the first event +with the name of _end_event_ will be chosen as the ending event. If _match_name_ +is given, then this will be the field of the created synthetic event that +holds the matching keys of the starting event's _start_match_field_ and +the ending event's _end_match_field_. If _match_name_ is NULL, then it will +not be recorded in the created synthetic event. + +*tracefs_synth_add_match_field*() will add a second key to match between the +starting event and the ending event. If _name_ is given, then the content +of the matching field will be saved by this _name_ in the synthetic event. +The _start_match_field_ is the field of the starting event to mach with the +ending event's _end_match_field. + +*tracefs_synth_add_compare_field*() is used to compare the _start_compare_field_ +of the starting event with the _end_compare_field_ of the ending event. The _name_ +must be given so that the result will be saved by the synthetic event. It makes +no sense to not pass this to the synthetic event after doing the work of +the compared fields, as it serves no other purpose. The _calc_ parameter +can be one of: + +*TRACEFS_SYNTH_DELTA_END* - calculate the difference between the content in + the _end_compare_field_ from the content of the _start_compare_field_. + + _name_ = _end_compare_field_ - _start_compare_field_ + +*TRACEFS_SYNTH_DELTA_START* - calculate the difference between the content in + the _start_compare_field_ from the content of the _end_compare_field_. + + _name_ = _start_compare_field_ - _end_compare_field_ + +*TRACEFS_SYNTH_ADD* - Add the content of the _start_compare_field_ to the + content of the _end_compare_field_. + + _name_ = _start_compare_field_ + _end_compare_field_ + +*tracefs_synth_add_start_field*() - Records the _start_field_ of the starting +event as _name_ in the synthetic event. If _name_ is NULL, then the name used +will be the same as _start_field_. + +*tracefs_synth_add_end_field*() - Records the _end_field_ of the ending +event as _name_ in the synthetic event. If _name_ is NULL, then the name used +will be the same as _end_field_. + +*tracefs_synth_add_start_filter*() adds a filter to the starting event +comparing the content of the starting event's _field_ to _val_ based +on _compare_. If _neg_ is set, then the compare is wrapped in parenthesis +and negated. The _or_ field only is used if more than one call to +*tracefs_synth_add_start_filter*() is done, and if _or_ is set, the +next compare is "or'd" (||), otherwise it is "and'd" (&&). _compare_ +may be one of: + +*TRACEFS_COMPARE_EQ* - _field_ == _val_ + +*TRACEFS_COMPARE_NQ* - _field_ != _val_ + +*TRACEFS_COMPARE_GR* - _field_ > _val_ + +*TRACEFS_COMPARE_GE* - _field_ >= _val_ + +*TRACEFS_COMPARE_LT* - _field_ < _val_ + +*TRACEFS_COMPARE_LE* - _field_ +#include + +#define start_event "sched_waking" +#define start_field "pid" + +#define end_event "sched_switch" +#define end_field "next_pid" + +#define match_name "pid" + +static struct tracefs_synth *synth; + +static void make_event(void) +{ + struct tep_handle *tep; + + /* Load all events from the system */ + tep = tracefs_local_events(NULL); + + /* Initialize the synthetic event */ + synth = tracefs_synth_init(tep, "wakeup_lat", + NULL, start_event, + NULL, end_event, + start_field, end_field, + match_name); + + /* The tep is no longer needed */ + tep_free(tep); + + + /* Save the "prio" field as "prio" from the start event */ + tracefs_synth_add_start_field(synth, "prio", NULL); + + /* Save the "next_comm" as "comm" from the end event */ + tracefs_synth_add_end_field(synth, "next_comm", "comm"); + + /* Save the "prev_prio" as "prev_prio" from the end event */ + tracefs_synth_add_end_field(synth, "prev_prio", NULL); + + /* + * Take a microsecond time difference between end and start + * and record as "delta" + */ + tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS, + TRACEFS_TIMESTAMP_USECS, + TRACEFS_SYNTH_DELTA_END, "delta"); + + /* Only record if start event "prio" is less than 100 */ + tracefs_synth_add_start_filter(synth, "prio", + TRACEFS_COMPARE_LT, "100", + false, false); + + /* + * Only record if end event "next_prio" is less than 50 + * or the previous task's prio was less than 100. + */ + tracefs_synth_add_end_filter(synth, "next_prio", + TRACEFS_COMPARE_LT, "50", + false, false); + tracefs_synth_add_end_filter(synth, "prev_prio", + TRACEFS_COMPARE_LT, "100", + false, true); +} + +/* Display how to create the synthetic event */ +static void show_event(void) +{ + struct trace_seq s; + + trace_seq_init(&s); + + tracefs_synth_show(&s, NULL, synth); + trace_seq_terminate(&s); + trace_seq_do_printf(&s); + trace_seq_destroy(&s); +} + +int main (int argc, char **argv) +{ + make_event(); + + if (argc > 1) { + if (!strcmp(argv[1], "create")) { + /* Create the synthetic event */ + tracefs_synth_create(NULL, synth); + } else if (!strcmp(argv[1], "delete")) { + /* Delete the synthetic event */ + tracefs_synth_destroy(NULL, synth); + } else { + printf("usage: %s [create|delete]\n", argv[0]); + exit(-1); + } + } else + show_event(); + + tracefs_synth_free(synth); + + return 0; +} +-- + +FILES +----- +[verse] +-- +*tracefs.h* + Header file to include in order to have access to the library APIs. +*-ltracefs* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +_libtracefs(3)_, +_libtraceevent(3)_, +_trace-cmd(1)_, +_tracefs_hist_alloc(3)_, +_tracefs_hist_free(3)_, +_tracefs_hist_add_key(3)_, +_tracefs_hist_add_value(3)_, +_tracefs_hist_add_name(3)_, +_tracefs_hist_start(3)_, +_tracefs_hist_destory(3)_, +_tracefs_hist_add_sort_key(3)_, +_tracefs_hist_sort_key_direction(3)_ + +AUTHOR +------ +[verse] +-- +*Steven Rostedt* +*Tzvetomir Stoyanov* +*sameeruddin shaik* +-- +REPORTING BUGS +-------------- +Report bugs to + +LICENSE +------- +libtracefs is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ + +COPYING +------- +Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL). -- 2.30.2