linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql()
@ 2021-08-03 16:48 Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 1/7] libtracefs: Change the tracefs_hist API to not take an instance immediately Steven Rostedt
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

In preparation for tracefs_sql(), the histogram logic needs some updates.
Restructure the API a little better. Since the API has not been part of a
tagged release, it is still allowed to change.

Add a way to show a partially created synthetic event, which can be used by
tracefs_sql() for creating histograms.

Changes since v1:

 - Fixed tracefs_synth_get_start_hist() when more than one key existed.

Steven Rostedt (VMware) (7):
  libtracefs: Change the tracefs_hist API to not take an instance
    immediately
  libtracefs: Expose tracefs_hist_command() as an API
  libtracefs: Add API tracefs_hist_append_filter()
  libtracefs: Add API tracefs_hist_show()
  libtracefs: Split up libtracefs-synth man page
  libtracefs: Add API tracefs_synth_get_start_hist()
  libtracefs: Add API tracefs_synth_complete()

 Documentation/libtracefs-hist.txt   | 105 +++++++--
 Documentation/libtracefs-synth.txt  |  31 +--
 Documentation/libtracefs-synth2.txt | 247 +++++++++++++++++++++
 include/tracefs.h                   | 148 ++++++++++---
 src/tracefs-hist.c                  | 326 +++++++++++++++++-----------
 5 files changed, 665 insertions(+), 192 deletions(-)
 create mode 100644 Documentation/libtracefs-synth2.txt

-- 
2.30.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/7] libtracefs: Change the tracefs_hist API to not take an instance immediately
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 2/7] libtracefs: Expose tracefs_hist_command() as an API Steven Rostedt
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

After implementing tracefs_sql(), it became apparent that passing the
instance into the tracefs_hist API to create the descriptor was the wrong
approach. It's better to just pass in a tep_handle for verification
purposes, and then have the user pass in the instance when creating the
histogram. This also allows to easily create the same histogram in
different instances if need be.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-hist.txt | 40 +++++++++++-------
 include/tracefs.h                 | 16 ++++----
 src/tracefs-hist.c                | 68 +++++++++++++++++--------------
 3 files changed, 71 insertions(+), 53 deletions(-)

diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt
index 0254c5faea82..28b4c3d65cde 100644
--- a/Documentation/libtracefs-hist.txt
+++ b/Documentation/libtracefs-hist.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 --
 *#include <tracefs.h>*
 
-struct tracefs_hist pass:[*]tracefs_hist_alloc(struct tracefs_instance pass:[*] instance,
+struct tracefs_hist pass:[*]tracefs_hist_alloc(struct tracefs_tep pass:[*] tep,
 			const char pass:[*]system, const char pass:[*]event,
 			const char pass:[*]key, enum tracefs_hist_key_type type);
 void tracefs_hist_free(struct tracefs_hist pass:[*]hist);
@@ -25,8 +25,8 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist pass:[*]hist,
 				    const char pass:[*]sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist pass:[*]hist, const char pass:[*]name);
-int tracefs_hist_start(struct tracefs_hist pass:[*]hist);
-int tracefs_hist_destory(struct tracefs_hist pass:[*]hist);
+int tracefs_hist_start(struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist);
+int tracefs_hist_destory(struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist);
 --
 
 DESCRIPTION
@@ -38,10 +38,11 @@ See https://www.kernel.org/doc/html/latest/trace/histogram.html for more informa
 
 *tracefs_hist_alloc*() allocates a "struct tracefs_hist" descriptor and returns
 the address of it. This descriptor must be freed by *tracefs_hist_free*().
-The _instance_ is the instance that contains the event that the histogram will be
-attached to. The _system_ is the system or group of the event. The _event_ is the event
-to attach the histogram to. The _key_ is a field of the event that will be used as
-the key of the histogram. The _type_ is the type of the _key_. See KEY TYPES below.
+The _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the
+_system_ and _event_ that the histogram will be attached to. The _system_ is the
+system or group of the event. The _event_ is the event to attach the histogram to.
+The _key_ is a field of the event that will be used as the key of the histogram.
+The _type_ is the type of the _key_. See KEY TYPES below.
 
 *tracefs_hist_free*() frees the _tracefs_hist_ descriptor. Note, it does not stop
 or disable the running histogram if it was started. *tracefs_hist_destroy*() needs
@@ -81,15 +82,24 @@ into a single histogram (shown by either event's hist file). The _hist_
 is the histogram to name, and the _name_ is the name to give it.
 
 *tracefs_hist_start* is called to actually start the histogram _hist_.
+The _instance_ is the instance to start the histogram in, NULL if it
+should start at the top level.
 
 *tracefs_hist_pause* is called to pause the histogram _hist_.
+The _instance_ is the instance to pause the histogram in, NULL if it
+is in the top level.
 
 *tracefs_hist_continue* is called to continue a paused histogram _hist_.
+The _instance_ is the instance to continue the histogram, NULL if it
+is in the top level.
 
 *tracefs_hist_reset* is called to clear / reset the histogram _hist_.
+The _instance_ is the instance to clear the histogram, NULL if it
+is in the top level.
 
 *tracefs_hist_destory* is called to delete the histogram where it will no longer
-exist.
+exist.  The _instance_ is the instance to delete the histogram from, NULL if it
+is in the top level.
 
 
 KEY TYPES
@@ -152,6 +162,7 @@ int main (int argc, char **argv, char **env)
 {
 	struct tracefs_instance *instance;
 	struct tracefs_hist *hist;
+	struct tep_handle *tep;
 	enum commands cmd;
 	char *cmd_str;
 	int ret;
@@ -186,7 +197,8 @@ int main (int argc, char **argv, char **env)
 		exit(-1);
 	}
 
-	hist = tracefs_hist_alloc(instance, "kmem", "kmalloc",
+	tep = tracefs_local_events(NULL);
+	hist = tracefs_hist_alloc(tep, "kmem", "kmalloc",
 				  "call_site", TRACEFS_HIST_KEY_SYM);
 	if (!hist) {
 		fprintf(stderr, "Failed hist create\n");
@@ -208,7 +220,7 @@ int main (int argc, char **argv, char **env)
 
 	switch (cmd) {
 	case START:
-		ret = tracefs_hist_start(hist);
+		ret = tracefs_hist_start(instance, hist);
 		if (ret) {
 			char *err = tracefs_error_last(instance);
 			if (err)
@@ -216,16 +228,16 @@ int main (int argc, char **argv, char **env)
 		}
 		break;
 	case PAUSE:
-		ret = tracefs_hist_pause(hist);
+		ret = tracefs_hist_pause(instance, hist);
 		break;
 	case CONT:
-		ret = tracefs_hist_continue(hist);
+		ret = tracefs_hist_continue(instance, hist);
 		break;
 	case RESET:
-		ret = tracefs_hist_reset(hist);
+		ret = tracefs_hist_reset(instance, hist);
 		break;
 	case DELETE:
-		ret = tracefs_hist_destroy(hist);
+		ret = tracefs_hist_destroy(instance, hist);
 		break;
 	case SHOW: {
 		char *content;
diff --git a/include/tracefs.h b/include/tracefs.h
index 246647f6496d..ff115d6ce01d 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -282,9 +282,9 @@ struct tracefs_hist;
 void tracefs_hist_free
 (struct tracefs_hist *hist);
 struct tracefs_hist *
-tracefs_hist_alloc(struct tracefs_instance * instance,
-		       const char *system, const char *event,
-		       const char *key, enum tracefs_hist_key_type type);
+tracefs_hist_alloc(struct tep_handle *tep,
+		   const char *system, const char *event,
+		   const char *key, enum tracefs_hist_key_type type);
 int tracefs_hist_add_key(struct tracefs_hist *hist, const char *key,
 			 enum tracefs_hist_key_type type);
 int tracefs_hist_add_value(struct tracefs_hist *hist, const char *value);
@@ -294,11 +294,11 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist *hist,
 				    const char *sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist *hist, const char *name);
-int tracefs_hist_start(struct tracefs_hist *hist);
-int tracefs_hist_pause(struct tracefs_hist *hist);
-int tracefs_hist_continue(struct tracefs_hist *hist);
-int tracefs_hist_reset(struct tracefs_hist *hist);
-int tracefs_hist_destroy(struct tracefs_hist *hist);
+int tracefs_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist);
+int tracefs_hist_pause(struct tracefs_instance *instance,struct tracefs_hist *hist);
+int tracefs_hist_continue(struct tracefs_instance *instance,struct tracefs_hist *hist);
+int tracefs_hist_reset(struct tracefs_instance *instance,struct tracefs_hist *hist);
+int tracefs_hist_destroy(struct tracefs_instance *instance,struct tracefs_hist *hist);
 
 struct tracefs_synth;
 
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index 7292f89457c9..b72171af9577 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -23,9 +23,10 @@
 #define DESCENDING ".descending"
 
 struct tracefs_hist {
-	struct tracefs_instance *instance;
+	struct tep_handle	*tep;
+	struct tep_event	*event;
 	char			*system;
-	char			*event;
+	char			*event_name;
 	char			*name;
 	char			**keys;
 	char			**values;
@@ -65,15 +66,17 @@ static void add_list(struct trace_seq *seq, const char *start,
  * Returns 0 on succes -1 on error.
  */
 static int
-trace_hist_start(struct tracefs_hist *hist,
+trace_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist,
 		 enum tracefs_hist_command command)
 {
-	struct tracefs_instance *instance = hist->instance;
 	const char *system = hist->system;
-	const char *event = hist->event;
+	const char *event = hist->event_name;
 	struct trace_seq seq;
 	int ret;
 
+	if (!tracefs_event_file_exists(instance, system, event, HIST_FILE))
+		return -1;
+
 	errno = -EINVAL;
 	if (!hist->keys)
 		return -1;
@@ -129,9 +132,9 @@ void tracefs_hist_free(struct tracefs_hist *hist)
 	if (!hist)
 		return;
 
-	trace_put_instance(hist->instance);
+	tep_unref(hist->tep);
 	free(hist->system);
-	free(hist->event);
+	free(hist->event_name);
 	free(hist->name);
 	free(hist->filter);
 	tracefs_list_free(hist->keys);
@@ -142,9 +145,9 @@ void tracefs_hist_free(struct tracefs_hist *hist)
 
 /**
  * tracefs_hist_alloc - Initialize a histogram
- * @instance: The instance the histogram will be in (NULL for toplevel)
+ * @tep: The tep handle that has the @system and @event.
  * @system: The system the histogram event is in.
- * @event: The event that the histogram will be attached to.
+ * @event_name: The name of the event that the histogram will be attached to.
  * @key: The primary key the histogram will use
  * @type: The format type of the key.
  *
@@ -157,33 +160,31 @@ void tracefs_hist_free(struct tracefs_hist *hist)
  * NULL on failure.
  */
 struct tracefs_hist *
-tracefs_hist_alloc(struct tracefs_instance * instance,
-			const char *system, const char *event,
+tracefs_hist_alloc(struct tep_handle *tep,
+			const char *system, const char *event_name,
 			const char *key, enum tracefs_hist_key_type type)
 {
+	struct tep_event *event;
 	struct tracefs_hist *hist;
 	int ret;
 
-	if (!system || !event || !key)
+	if (!system || !event_name || !key)
 		return NULL;
 
-	if (!tracefs_event_file_exists(instance, system, event, HIST_FILE))
+	event = tep_find_event_by_name(tep, system, event_name);
+	if (!event)
 		return NULL;
 
 	hist = calloc(1, sizeof(*hist));
 	if (!hist)
 		return NULL;
 
-	ret = trace_get_instance(instance);
-	if (ret < 0) {
-		free(hist);
-		return NULL;
-	}
-
-	hist->instance = instance;
+	tep_ref(tep);
+	hist->tep = tep;
 
+	hist->event = event;
 	hist->system = strdup(system);
-	hist->event = strdup(event);
+	hist->event_name = strdup(event_name);
 
 	ret = tracefs_hist_add_key(hist, key, type);
 
@@ -302,58 +303,63 @@ int tracefs_hist_add_name(struct tracefs_hist *hist, const char *name)
 
 /**
  * tracefs_hist_start - enable a histogram
+ * @instance: The instance the histogram will be in (NULL for toplevel)
  * @hist: The histogram to start
  *
  * Starts executing a histogram.
  *
  * Returns 0 on success, -1 on error.
  */
-int tracefs_hist_start(struct tracefs_hist *hist)
+int tracefs_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist)
 {
-	return trace_hist_start(hist, 0);
+	return trace_hist_start(instance, hist, 0);
 }
 
 /**
  * tracefs_hist_pause - pause a histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
  * @hist: The histogram to pause
  *
  * Pause a histogram.
  *
  * Returns 0 on success, -1 on error.
  */
-int tracefs_hist_pause(struct tracefs_hist *hist)
+int tracefs_hist_pause(struct tracefs_instance *instance, struct tracefs_hist *hist)
 {
-	return trace_hist_start(hist, HIST_CMD_PAUSE);
+	return trace_hist_start(instance, hist, HIST_CMD_PAUSE);
 }
 
 /**
  * tracefs_hist_continue - continue a paused histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
  * @hist: The histogram to continue
  *
  * Continue a histogram.
  *
  * Returns 0 on success, -1 on error.
  */
-int tracefs_hist_continue(struct tracefs_hist *hist)
+int tracefs_hist_continue(struct tracefs_instance *instance, struct tracefs_hist *hist)
 {
-	return trace_hist_start(hist, HIST_CMD_CONT);
+	return trace_hist_start(instance, hist, HIST_CMD_CONT);
 }
 
 /**
  * tracefs_hist_reset - clear a histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
  * @hist: The histogram to reset
  *
  * Resets a histogram.
  *
  * Returns 0 on success, -1 on error.
  */
-int tracefs_hist_reset(struct tracefs_hist *hist)
+int tracefs_hist_reset(struct tracefs_instance *instance, struct tracefs_hist *hist)
 {
-	return trace_hist_start(hist, HIST_CMD_CLEAR);
+	return trace_hist_start(instance, hist, HIST_CMD_CLEAR);
 }
 
 /**
  * tracefs_hist_destroy - deletes a histogram (needs to be enabled again)
+ * @instance: The instance the histogram is in (NULL for toplevel)
  * @hist: The histogram to delete
  *
  * Deletes (removes) a running histogram. This is different than
@@ -363,9 +369,9 @@ int tracefs_hist_reset(struct tracefs_hist *hist)
  *
  * Returns 0 on success, -1 on error.
  */
-int tracefs_hist_destroy(struct tracefs_hist *hist)
+int tracefs_hist_destroy(struct tracefs_instance *instance, struct tracefs_hist *hist)
 {
-	return trace_hist_start(hist, HIST_CMD_DESTROY);
+	return trace_hist_start(instance, hist, HIST_CMD_DESTROY);
 }
 
 static char **
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/7] libtracefs: Expose tracefs_hist_command() as an API
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 1/7] libtracefs: Change the tracefs_hist API to not take an instance immediately Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 3/7] libtracefs: Add API tracefs_hist_append_filter() Steven Rostedt
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Expose trace_hist_start() as tracefs_hist_command() and make the following
functions wrappers that call this function:

 tracefs_hist_start()
 tracefs_hist_pause()
 tracefs_hist_reset()
 tracefs_hist_destroy()

Exposing the enum for the above commands can make it easier for
applications to run them depending on the input from the user.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-hist.txt |  20 ++++++
 include/tracefs.h                 |  93 ++++++++++++++++++++++++--
 src/tracefs-hist.c                | 104 ++++--------------------------
 3 files changed, 120 insertions(+), 97 deletions(-)

diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt
index 28b4c3d65cde..e5861f2f0842 100644
--- a/Documentation/libtracefs-hist.txt
+++ b/Documentation/libtracefs-hist.txt
@@ -25,6 +25,9 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist pass:[*]hist,
 				    const char pass:[*]sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist pass:[*]hist, const char pass:[*]name);
+int tracefs_hist_command(struct tracefs_instance pass:[*]instance,
+			 struct tracefs_hist pass:[*]hist,
+			 enum tracefs_hist_command command);
 int tracefs_hist_start(struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist);
 int tracefs_hist_destory(struct tracefs_instance pass:[*]instance, struct tracefs_hist pass:[*]hist);
 --
@@ -81,6 +84,23 @@ compatible keys, the multiple histograms with the same name will be merged
 into a single histogram (shown by either event's hist file). The _hist_
 is the histogram to name, and the _name_ is the name to give it.
 
+*tracefs_hist_command*() is called to process a command on the histogram
+_hist_ for its event in the given _instance_, or NULL for the top level.
+The _cmd_ can be one of:
+
+*TRACEFS_HIST_CMD_START* or zero to start execution of the histogram.
+
+*TRACEFS_HIST_CMD_PAUSE* to pause the given histogram.
+
+*TRACEFS_HIST_CMD_CONT* to continue a paused histogram.
+
+*TRACEFS_HIST_CMD_CLEAR* to reset the values of a histogram.
+
+*TRACEFS_HIST_CMD_DESTROY* to destroy the histogram (undo a START).
+
+The below functions are wrappers to tracefs_hist_command() to make the
+calling conventions a bit easier to understand what is happening.
+
 *tracefs_hist_start* is called to actually start the histogram _hist_.
 The _instance_ is the instance to start the histogram in, NULL if it
 should start at the top level.
diff --git a/include/tracefs.h b/include/tracefs.h
index ff115d6ce01d..302833722a99 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -279,6 +279,14 @@ enum tracefs_hist_sort_direction {
 
 struct tracefs_hist;
 
+enum tracefs_hist_command {
+	TRACEFS_HIST_CMD_START = 0,
+	TRACEFS_HIST_CMD_PAUSE,
+	TRACEFS_HIST_CMD_CONT,
+	TRACEFS_HIST_CMD_CLEAR,
+	TRACEFS_HIST_CMD_DESTROY,
+};
+
 void tracefs_hist_free
 (struct tracefs_hist *hist);
 struct tracefs_hist *
@@ -294,11 +302,86 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist *hist,
 				    const char *sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist *hist, const char *name);
-int tracefs_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist);
-int tracefs_hist_pause(struct tracefs_instance *instance,struct tracefs_hist *hist);
-int tracefs_hist_continue(struct tracefs_instance *instance,struct tracefs_hist *hist);
-int tracefs_hist_reset(struct tracefs_instance *instance,struct tracefs_hist *hist);
-int tracefs_hist_destroy(struct tracefs_instance *instance,struct tracefs_hist *hist);
+int tracefs_hist_command(struct tracefs_instance *instance,
+			 struct tracefs_hist *hist, enum tracefs_hist_command cmd);
+
+/**
+ * tracefs_hist_start - enable a histogram
+ * @instance: The instance the histogram will be in (NULL for toplevel)
+ * @hist: The histogram to start
+ *
+ * Starts executing a histogram.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static inline int tracefs_hist_start(struct tracefs_instance *instance,
+				     struct tracefs_hist *hist)
+{
+	return tracefs_hist_command(instance, hist, 0);
+}
+
+/**
+ * tracefs_hist_pause - pause a histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
+ * @hist: The histogram to pause
+ *
+ * Pause a histogram.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static inline int tracefs_hist_pause(struct tracefs_instance *instance,
+				     struct tracefs_hist *hist)
+{
+	return tracefs_hist_command(instance, hist, TRACEFS_HIST_CMD_PAUSE);
+}
+
+/**
+ * tracefs_hist_continue - continue a paused histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
+ * @hist: The histogram to continue
+ *
+ * Continue a histogram.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static inline int tracefs_hist_continue(struct tracefs_instance *instance,
+					struct tracefs_hist *hist)
+{
+	return tracefs_hist_command(instance, hist, TRACEFS_HIST_CMD_CONT);
+}
+
+/**
+ * tracefs_hist_reset - clear a histogram
+ * @instance: The instance the histogram is in (NULL for toplevel)
+ * @hist: The histogram to reset
+ *
+ * Resets a histogram.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static inline int tracefs_hist_reset(struct tracefs_instance *instance,
+				     struct tracefs_hist *hist)
+{
+	return tracefs_hist_command(instance, hist, TRACEFS_HIST_CMD_CLEAR);
+}
+
+/**
+ * tracefs_hist_destroy - deletes a histogram (needs to be enabled again)
+ * @instance: The instance the histogram is in (NULL for toplevel)
+ * @hist: The histogram to delete
+ *
+ * Deletes (removes) a running histogram. This is different than
+ * clear, as clear only clears the data but the histogram still exists.
+ * This deletes the histogram and should be called before
+ * tracefs_hist_free() to clean up properly.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static inline int tracefs_hist_destroy(struct tracefs_instance *instance,
+				       struct tracefs_hist *hist)
+{
+	return tracefs_hist_command(instance, hist, TRACEFS_HIST_CMD_DESTROY);
+}
 
 struct tracefs_synth;
 
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index b72171af9577..ccd331c1f52d 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -35,14 +35,6 @@ struct tracefs_hist {
 	int			size;
 };
 
-enum tracefs_hist_command {
-	HIST_CMD_NONE = 0,
-	HIST_CMD_PAUSE,
-	HIST_CMD_CONT,
-	HIST_CMD_CLEAR,
-	HIST_CMD_DESTROY,
-};
-
 static void add_list(struct trace_seq *seq, const char *start,
 		     char **list)
 {
@@ -57,17 +49,18 @@ static void add_list(struct trace_seq *seq, const char *start,
 }
 
 /*
- * trace_hist_start - Create and start a histogram for an event
+ * tracefs_hist_command - Create, start, pause, destroy a histogram for an event
+ * @instance: The instance the histogram will be in (NULL for toplevel)
  * @hist: The histogram to write into the trigger file
- * @command: If not zero, can pause, continue or clear the histogram
+ * @command: Command to perform on a histogram.
  *
- * This creates a histogram for an event with the given fields.
+ * Creates, pause, continue, clears, or destroys a histogram.
  *
  * Returns 0 on succes -1 on error.
  */
-static int
-trace_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist,
-		 enum tracefs_hist_command command)
+int tracefs_hist_command(struct tracefs_instance *instance,
+			 struct tracefs_hist *hist,
+			 enum tracefs_hist_command command)
 {
 	const char *system = hist->system;
 	const char *event = hist->event_name;
@@ -83,7 +76,7 @@ trace_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist,
 
 	trace_seq_init(&seq);
 
-	if (command == HIST_CMD_DESTROY)
+	if (command == TRACEFS_HIST_CMD_DESTROY)
 		trace_seq_putc(&seq, '!');
 
 	add_list(&seq, "hist:keys=", hist->keys);
@@ -98,10 +91,10 @@ trace_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist,
 		trace_seq_printf(&seq, ":size=%d", hist->size);
 
 	switch(command) {
-	case HIST_CMD_NONE: break;
-	case HIST_CMD_PAUSE: trace_seq_puts(&seq, ":pause"); break;
-	case HIST_CMD_CONT: trace_seq_puts(&seq, ":cont"); break;
-	case HIST_CMD_CLEAR: trace_seq_puts(&seq, ":clear"); break;
+	case TRACEFS_HIST_CMD_START: break;
+	case TRACEFS_HIST_CMD_PAUSE: trace_seq_puts(&seq, ":pause"); break;
+	case TRACEFS_HIST_CMD_CONT: trace_seq_puts(&seq, ":cont"); break;
+	case TRACEFS_HIST_CMD_CLEAR: trace_seq_puts(&seq, ":clear"); break;
 	default: break;
 	}
 
@@ -301,79 +294,6 @@ int tracefs_hist_add_name(struct tracefs_hist *hist, const char *name)
 	return hist->name ? 0 : -1;
 }
 
-/**
- * tracefs_hist_start - enable a histogram
- * @instance: The instance the histogram will be in (NULL for toplevel)
- * @hist: The histogram to start
- *
- * Starts executing a histogram.
- *
- * Returns 0 on success, -1 on error.
- */
-int tracefs_hist_start(struct tracefs_instance *instance, struct tracefs_hist *hist)
-{
-	return trace_hist_start(instance, hist, 0);
-}
-
-/**
- * tracefs_hist_pause - pause a histogram
- * @instance: The instance the histogram is in (NULL for toplevel)
- * @hist: The histogram to pause
- *
- * Pause a histogram.
- *
- * Returns 0 on success, -1 on error.
- */
-int tracefs_hist_pause(struct tracefs_instance *instance, struct tracefs_hist *hist)
-{
-	return trace_hist_start(instance, hist, HIST_CMD_PAUSE);
-}
-
-/**
- * tracefs_hist_continue - continue a paused histogram
- * @instance: The instance the histogram is in (NULL for toplevel)
- * @hist: The histogram to continue
- *
- * Continue a histogram.
- *
- * Returns 0 on success, -1 on error.
- */
-int tracefs_hist_continue(struct tracefs_instance *instance, struct tracefs_hist *hist)
-{
-	return trace_hist_start(instance, hist, HIST_CMD_CONT);
-}
-
-/**
- * tracefs_hist_reset - clear a histogram
- * @instance: The instance the histogram is in (NULL for toplevel)
- * @hist: The histogram to reset
- *
- * Resets a histogram.
- *
- * Returns 0 on success, -1 on error.
- */
-int tracefs_hist_reset(struct tracefs_instance *instance, struct tracefs_hist *hist)
-{
-	return trace_hist_start(instance, hist, HIST_CMD_CLEAR);
-}
-
-/**
- * tracefs_hist_destroy - deletes a histogram (needs to be enabled again)
- * @instance: The instance the histogram is in (NULL for toplevel)
- * @hist: The histogram to delete
- *
- * Deletes (removes) a running histogram. This is different than
- * clear, as clear only clears the data but the histogram still exists.
- * This deletes the histogram and should be called before
- * tracefs_hist_free() to clean up properly.
- *
- * Returns 0 on success, -1 on error.
- */
-int tracefs_hist_destroy(struct tracefs_instance *instance, struct tracefs_hist *hist)
-{
-	return trace_hist_start(instance, hist, HIST_CMD_DESTROY);
-}
-
 static char **
 add_sort_key(struct tracefs_hist *hist, const char *sort_key, char **list)
 {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/7] libtracefs: Add API tracefs_hist_append_filter()
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 1/7] libtracefs: Change the tracefs_hist API to not take an instance immediately Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 2/7] libtracefs: Expose tracefs_hist_command() as an API Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 4/7] libtracefs: Add API tracefs_hist_show() Steven Rostedt
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add an API that will append a filter to the histogram just like filters
can be added to the synthetic event's start and end events.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-hist.txt | 37 +++++++++++++++++++++++++
 include/tracefs.h                 | 45 +++++++++++++++++--------------
 src/tracefs-hist.c                | 14 ++++++++++
 3 files changed, 76 insertions(+), 20 deletions(-)

diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt
index e5861f2f0842..9bf13ac03af7 100644
--- a/Documentation/libtracefs-hist.txt
+++ b/Documentation/libtracefs-hist.txt
@@ -25,6 +25,11 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist pass:[*]hist,
 				    const char pass:[*]sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist pass:[*]hist, const char pass:[*]name);
+int tracefs_hist_append_filter(struct tracefs_hist pass:[*]hist,
+			       enum tracefs_filter type,
+			       const char pass:[*]field,
+			       enum tracefs_compare compare,
+			       const char pass:[*]val);
 int tracefs_hist_command(struct tracefs_instance pass:[*]instance,
 			 struct tracefs_hist pass:[*]hist,
 			 enum tracefs_hist_command command);
@@ -84,6 +89,38 @@ compatible keys, the multiple histograms with the same name will be merged
 into a single histogram (shown by either event's hist file). The _hist_
 is the histogram to name, and the _name_ is the name to give it.
 
+*tracefs_hist_append_filter*() creates a filter or appends to it for the
+histogram  event. Depending on _type_, it will build a string of tokens for
+parenthesis or logic statemens, or it may add a comparison of _field_
+to _val_ based on _compare_.
+
+If _type_ is:
+*TRACEFS_FILTER_COMPARE*     -  See below
+*TRACEFS_FILTER_AND*         -  Append "&&" to the filter
+*TRACEFS_FILTER_OR*          -  Append "||" to the filter
+*TRACEFS_FILTER_NOT*         -  Append "!" to the filter
+*TRACEFS_FILTER_OPEN_PAREN*  -  Append "(" to the filter
+*TRACEFS_FILTER_CLOSE_PAREN* -  Append ")" to the filter
+
+_field_, _compare_, and _val_ are ignored unless _type_ is equal to
+*TRACEFS_FILTER_COMPARE*, then _compare will be used for the following:
+
+*TRACEFS_COMPARE_EQ* - _field_ == _val_
+
+*TRACEFS_COMPARE_NE* - _field_ != _val_
+
+*TRACEFS_COMPARE_GT* - _field_ > _val_
+
+*TRACEFS_COMPARE_GE* - _field_ >= _val_
+
+*TRACEFS_COMPARE_LT* - _field_ < _val_
+
+*TRACEFS_COMPARE_LE* - _field_ <pass:[=] _val_
+
+*TRACEFS_COMPARE_RE* - _field_ ~ "_val_" : where _field_ is a string.
+
+*TRACEFS_COMPARE_AND* - _field_ & _val_ : where _field_ is a flags field.
+
 *tracefs_hist_command*() is called to process a command on the histogram
 _hist_ for its event in the given _instance_, or NULL for the top level.
 The _cmd_ can be one of:
diff --git a/include/tracefs.h b/include/tracefs.h
index 302833722a99..0be6e907d29b 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -287,6 +287,26 @@ enum tracefs_hist_command {
 	TRACEFS_HIST_CMD_DESTROY,
 };
 
+enum tracefs_filter {
+	TRACEFS_FILTER_COMPARE,
+	TRACEFS_FILTER_AND,
+	TRACEFS_FILTER_OR,
+	TRACEFS_FILTER_NOT,
+	TRACEFS_FILTER_OPEN_PAREN,
+	TRACEFS_FILTER_CLOSE_PAREN,
+};
+
+enum tracefs_compare {
+	TRACEFS_COMPARE_EQ,
+	TRACEFS_COMPARE_NE,
+	TRACEFS_COMPARE_GT,
+	TRACEFS_COMPARE_GE,
+	TRACEFS_COMPARE_LT,
+	TRACEFS_COMPARE_LE,
+	TRACEFS_COMPARE_RE,
+	TRACEFS_COMPARE_AND,
+};
+
 void tracefs_hist_free
 (struct tracefs_hist *hist);
 struct tracefs_hist *
@@ -302,6 +322,11 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist *hist,
 				    const char *sort_key,
 				    enum tracefs_hist_sort_direction dir);
 int tracefs_hist_add_name(struct tracefs_hist *hist, const char *name);
+int tracefs_hist_append_filter(struct tracefs_hist *hist,
+			       enum tracefs_filter type,
+			       const char *field,
+			       enum tracefs_compare compare,
+			       const char *val);
 int tracefs_hist_command(struct tracefs_instance *instance,
 			 struct tracefs_hist *hist, enum tracefs_hist_command cmd);
 
@@ -396,26 +421,6 @@ enum tracefs_synth_calc {
 	TRACEFS_SYNTH_ADD,
 };
 
-enum tracefs_compare {
-	TRACEFS_COMPARE_EQ,
-	TRACEFS_COMPARE_NE,
-	TRACEFS_COMPARE_GT,
-	TRACEFS_COMPARE_GE,
-	TRACEFS_COMPARE_LT,
-	TRACEFS_COMPARE_LE,
-	TRACEFS_COMPARE_RE,
-	TRACEFS_COMPARE_AND,
-};
-
-enum tracefs_filter {
-	TRACEFS_FILTER_COMPARE,
-	TRACEFS_FILTER_AND,
-	TRACEFS_FILTER_OR,
-	TRACEFS_FILTER_NOT,
-	TRACEFS_FILTER_OPEN_PAREN,
-	TRACEFS_FILTER_CLOSE_PAREN,
-};
-
 int tracefs_event_append_filter(struct tep_event *event, char **filter,
 				enum tracefs_filter type,
 				const char *field, enum tracefs_compare compare,
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index ccd331c1f52d..1be14362f407 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -33,6 +33,8 @@ struct tracefs_hist {
 	char			**sort;
 	char			*filter;
 	int			size;
+	unsigned int		filter_parens;
+	unsigned int		filter_state;
 };
 
 static void add_list(struct trace_seq *seq, const char *start,
@@ -454,6 +456,18 @@ int tracefs_hist_sort_key_direction(struct tracefs_hist *hist,
 	return 0;
 }
 
+int tracefs_hist_append_filter(struct tracefs_hist *hist,
+			       enum tracefs_filter type,
+			       const char *field,
+			       enum tracefs_compare compare,
+			       const char *val)
+{
+	return trace_append_filter(&hist->filter, &hist->filter_state,
+				   &hist->filter_parens,
+				   hist->event,
+				   type, field, compare, val);
+}
+
 /*
  * @name: name of the synthetic event
  * @start_system: system of the starting event
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 4/7] libtracefs: Add API tracefs_hist_show()
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
                   ` (2 preceding siblings ...)
  2021-08-03 16:48 ` [PATCH v2 3/7] libtracefs: Add API tracefs_hist_append_filter() Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 5/7] libtracefs: Split up libtracefs-synth man page Steven Rostedt
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add tracefs_hist_show() that will display the commands that would be
executed in order to create the given histogram.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-hist.txt |   8 +++
 include/tracefs.h                 |   2 +
 src/tracefs-hist.c                | 102 ++++++++++++++++++++++--------
 3 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/Documentation/libtracefs-hist.txt b/Documentation/libtracefs-hist.txt
index 9bf13ac03af7..03ac07743d1c 100644
--- a/Documentation/libtracefs-hist.txt
+++ b/Documentation/libtracefs-hist.txt
@@ -30,6 +30,9 @@ int tracefs_hist_append_filter(struct tracefs_hist pass:[*]hist,
 			       const char pass:[*]field,
 			       enum tracefs_compare compare,
 			       const char pass:[*]val);
+int tracefs_hist_show(struct trace_seq pass:[*]s, struct tracefs_instance pass:[*]instance,
+			 struct tracefs_hist pass:[*]hist,
+			 enum tracefs_hist_command command);
 int tracefs_hist_command(struct tracefs_instance pass:[*]instance,
 			 struct tracefs_hist pass:[*]hist,
 			 enum tracefs_hist_command command);
@@ -121,6 +124,11 @@ _field_, _compare_, and _val_ are ignored unless _type_ is equal to
 
 *TRACEFS_COMPARE_AND* - _field_ & _val_ : where _field_ is a flags field.
 
+*trace_hist_show*() prints the commands needed to create the given histogram
+in the given _instance_, or NULL for the top level, into the _seq_.
+The command that is printed is described by _command_ and shows the functionality
+that would be done by *tracefs_hist_command*(3).
+
 *tracefs_hist_command*() is called to process a command on the histogram
 _hist_ for its event in the given _instance_, or NULL for the top level.
 The _cmd_ can be one of:
diff --git a/include/tracefs.h b/include/tracefs.h
index 0be6e907d29b..ab781764b0ed 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -327,6 +327,8 @@ int tracefs_hist_append_filter(struct tracefs_hist *hist,
 			       const char *field,
 			       enum tracefs_compare compare,
 			       const char *val);
+int tracefs_hist_show(struct trace_seq *seq,  struct tracefs_instance *instance,
+		      struct tracefs_hist *hist, enum tracefs_hist_command command);
 int tracefs_hist_command(struct tracefs_instance *instance,
 			 struct tracefs_hist *hist, enum tracefs_hist_command cmd);
 
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index 1be14362f407..7c84e942d58b 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -50,6 +50,79 @@ static void add_list(struct trace_seq *seq, const char *start,
 	}
 }
 
+static void add_hist_commands(struct trace_seq *seq, struct tracefs_hist *hist,
+			     enum tracefs_hist_command command)
+{
+	if (command == TRACEFS_HIST_CMD_DESTROY)
+		trace_seq_putc(seq, '!');
+
+	add_list(seq, "hist:keys=", hist->keys);
+
+	if (hist->values)
+		add_list(seq, ":vals=", hist->values);
+
+	if (hist->sort)
+		add_list(seq, ":sort=", hist->sort);
+
+	if (hist->size)
+		trace_seq_printf(seq, ":size=%d", hist->size);
+
+	switch(command) {
+	case TRACEFS_HIST_CMD_START: break;
+	case TRACEFS_HIST_CMD_PAUSE: trace_seq_puts(seq, ":pause"); break;
+	case TRACEFS_HIST_CMD_CONT: trace_seq_puts(seq, ":cont"); break;
+	case TRACEFS_HIST_CMD_CLEAR: trace_seq_puts(seq, ":clear"); break;
+	default: break;
+	}
+
+	if (hist->name)
+		trace_seq_printf(seq, ":name=%s", hist->name);
+
+	if (hist->filter)
+		trace_seq_printf(seq, " if %s", hist->filter);
+
+}
+
+/*
+ * trace_hist_show - show how to start the histogram
+ * @seq: A trace_seq to store the commands to create
+ * @hist: The histogram to write into the trigger file
+ * @command: If not zero, can pause, continue or clear the histogram
+ *
+ * This shows the commands to create the histogram for an event
+ * with the given fields.
+ *
+ * Returns 0 on succes -1 on error.
+ */
+int
+tracefs_hist_show(struct trace_seq *seq, struct tracefs_instance *instance,
+		  struct tracefs_hist *hist,
+		  enum tracefs_hist_command command)
+{
+	const char *system = hist->system;
+	const char *event = hist->event_name;
+	char *path;
+
+	if (!hist->keys) {
+		errno = -EINVAL;
+		return -1;
+	}
+
+	path = tracefs_event_get_file(instance, system, event, "trigger");
+	if (!path)
+		return -1;
+
+	trace_seq_puts(seq, "echo '");
+
+	add_hist_commands(seq, hist, command);
+
+	trace_seq_printf(seq, "' > %s\n", path);
+
+	tracefs_put_tracing_file(path);
+
+	return 0;
+}
+
 /*
  * tracefs_hist_command - Create, start, pause, destroy a histogram for an event
  * @instance: The instance the histogram will be in (NULL for toplevel)
@@ -78,34 +151,9 @@ int tracefs_hist_command(struct tracefs_instance *instance,
 
 	trace_seq_init(&seq);
 
-	if (command == TRACEFS_HIST_CMD_DESTROY)
-		trace_seq_putc(&seq, '!');
-
-	add_list(&seq, "hist:keys=", hist->keys);
-
-	if (hist->values)
-		add_list(&seq, ":vals=", hist->values);
-
-	if (hist->sort)
-		add_list(&seq, ":sort=", hist->sort);
-
-	if (hist->size)
-		trace_seq_printf(&seq, ":size=%d", hist->size);
-
-	switch(command) {
-	case TRACEFS_HIST_CMD_START: break;
-	case TRACEFS_HIST_CMD_PAUSE: trace_seq_puts(&seq, ":pause"); break;
-	case TRACEFS_HIST_CMD_CONT: trace_seq_puts(&seq, ":cont"); break;
-	case TRACEFS_HIST_CMD_CLEAR: trace_seq_puts(&seq, ":clear"); break;
-	default: break;
-	}
-
-	if (hist->name)
-		trace_seq_printf(&seq, ":name=%s", hist->name);
-
-	if (hist->filter)
-		trace_seq_printf(&seq, " if %s\n", hist->filter);
+	add_hist_commands(&seq, hist, command);
 
+	trace_seq_putc(&seq, '\n');
 	trace_seq_terminate(&seq);
 
 	ret = -1;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 5/7] libtracefs: Split up libtracefs-synth man page
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
                   ` (3 preceding siblings ...)
  2021-08-03 16:48 ` [PATCH v2 4/7] libtracefs: Add API tracefs_hist_show() Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 6/7] libtracefs: Add API tracefs_synth_get_start_hist() Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 7/7] libtracefs: Add API tracefs_synth_complete() Steven Rostedt
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

The man page for the synthetic event functions has more than 9, which
causes errors when creating them. Create a libtracefs-synth2.txt file and
move the descriptions of tracefs_synth_create(), tracefs_synth_destroy()
and tracefs_synth_show() to it.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-synth.txt  |  31 +---
 Documentation/libtracefs-synth2.txt | 239 ++++++++++++++++++++++++++++
 2 files changed, 246 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/libtracefs-synth2.txt

diff --git a/Documentation/libtracefs-synth.txt b/Documentation/libtracefs-synth.txt
index 47e93bd42674..77076e1aa5e2 100644
--- a/Documentation/libtracefs-synth.txt
+++ b/Documentation/libtracefs-synth.txt
@@ -4,8 +4,8 @@ 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_append_start_filter, tracefs_synth_append_end_filter, tracefs_synth_create,
-tracefs_synth_destroy, tracefs_synth_free, tracefs_synth_show - Creation of synthetic events
+tracefs_synth_add_end_field, tracefs_synth_append_start_filter, tracefs_synth_append_end_filter, tracefs_synth_free,
+- Creation of a synthetic event descriptor
 
 SYNOPSIS
 --------
@@ -47,14 +47,7 @@ int tracefs_synth_append_end_filter(struct tracefs_synth pass:[*]synth,
 				    const char pass:[*]field,
 				    enum tracefs_synth_compare compare,
 				    const char pass:[*]val);
-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);
-
+-void tracefs_synth_free(struct tracefs_synth pass:[*]synth);
 --
 
 DESCRIPTION
@@ -78,7 +71,7 @@ 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
+to do so. See *tracefs_synth_create*(3) 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
@@ -162,22 +155,9 @@ _field_, _compare_, and _val_ are ignored unless _type_ is equal to
 *tracefs_synth_append_end_filter*() is the same as *tracefs_synth_append_start_filter* but
 filters on the ending event.
 
-*tracefs_synth_create*() creates the synthetic event in the system in the system
-in the _instance_ provided. Note, synthetic events apply across all instances,
-but some creation requires histograms to be established, which are local to
-instances.
-
-*tracefs_synth_destroy*() destroys the synthetic event. It will attempt to stop
-the running of it in the given _instance_, but if its running in another instance
-this may fail as busy.
-
 *tracefs_synth_free*() frees the allocated descriptor returned by
 *tracefs_synth_init*().
 
-*tracefs_synth_show*() acts like *tracefs_synth_create*(), but instead of creating
-the synthetic event in the given _instance_, it will write the echo commands to
-manually create it in the _seq_ given.
-
 RETURN VALUE
 ------------
 *tracefs_synth_init*() returns an allocated struct tracefs_synth descriptor
@@ -330,6 +310,9 @@ FILES
 
 SEE ALSO
 --------
+_tracefs_synth_create_(3),
+_tracefs_synth_destroy_(3),
+_tracfes_synth_show_(3),
 _libtracefs(3)_,
 _libtraceevent(3)_,
 _trace-cmd(1)_,
diff --git a/Documentation/libtracefs-synth2.txt b/Documentation/libtracefs-synth2.txt
new file mode 100644
index 000000000000..41680d5b9cba
--- /dev/null
+++ b/Documentation/libtracefs-synth2.txt
@@ -0,0 +1,239 @@
+libtracefs(3)
+=============
+
+NAME
+----
+tracefs_synth_create, tracefs_synth_destroy, tracefs_synth_show - Creation of synthetic events
+
+SYNOPSIS
+--------
+[verse]
+--
+*#include <tracefs.h>*
+
+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);
+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_create*() creates the synthetic event in the system in the system
+in the _instance_ provided. Note, synthetic events apply across all instances,
+but some creation requires histograms to be established, which are local to
+instances.
+
+*tracefs_synth_destroy*() destroys the synthetic event. It will attempt to stop
+the running of it in the given _instance_, but if its running in another instance
+this may fail as busy.
+
+*tracefs_synth_show*() acts like *tracefs_synth_create*(), but instead of creating
+the synthetic event in the given _instance_, it will write the echo commands to
+manually create it in the _seq_ given.
+
+RETURN VALUE
+------------
+Returns zero on success or -1 on error.
+
+ERRORS
+------
+The following errors are for all the above calls:
+
+*EPERM* Not run as root user when required.
+
+*EINVAL* Either a parameter is not valid (NULL when it should not be)
+  or a field that is not compatible for calculations.
+
+*ENODEV* An event or one of its fields is not found.
+
+*EBADE* The fields of the start and end events are not compatible for
+  either matching or comparing.
+
+*ENOMEM* not enough memory is available.
+
+And more errors may have happened from the system calls to the system.
+
+EXAMPLE
+-------
+[source,c]
+--
+#include <stdlib.h>
+#include <tracefs.h>
+
+#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_append_start_filter(synth, TRACEFS_FILTER_COMPARE,
+					  "prio", TRACEFS_COMPARE_LT, "100");
+
+	/*
+	 * Only record if end event "next_prio" is less than 50
+	 * or the previous task's prio was not greater than or equal to 100.
+	 *   next_prio < 50 || !(prev_prio >= 100)
+	 */
+	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
+					"next_prio", TRACEFS_COMPARE_LT, "50");
+	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL);
+	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL);
+	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL);
+	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
+					"prev_prio", TRACEFS_COMPARE_GE, "100");
+	/*
+	 * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100"
+	 * That's because, when the synth is executed, the remaining close parenthesis
+	 * will be added. That is, the string will end up being:
+	 * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create()
+	 * or tracefs_sync_show() is run.
+	 */
+}
+
+/* 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* <rostedt@goodmis.org>
+*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>
+*sameeruddin shaik* <sameeruddin.shaik8@gmail.com>
+--
+REPORTING BUGS
+--------------
+Report bugs to  <linux-trace-devel@vger.kernel.org>
+
+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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 6/7] libtracefs: Add API tracefs_synth_get_start_hist()
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
                   ` (4 preceding siblings ...)
  2021-08-03 16:48 ` [PATCH v2 5/7] libtracefs: Split up libtracefs-synth man page Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  2021-08-03 16:48 ` [PATCH v2 7/7] libtracefs: Add API tracefs_synth_complete() Steven Rostedt
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add the API tracefs_synth_get_start_hist() that returns a tracefs_hist
descriptor describing the start event of a tracefs_synth.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-synth2.txt |  4 ++
 include/tracefs.h                   |  1 +
 src/tracefs-hist.c                  | 73 +++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)

diff --git a/Documentation/libtracefs-synth2.txt b/Documentation/libtracefs-synth2.txt
index 41680d5b9cba..5d34c4f60469 100644
--- a/Documentation/libtracefs-synth2.txt
+++ b/Documentation/libtracefs-synth2.txt
@@ -17,6 +17,7 @@ int tracefs_synth_destroy(struct tracefs_instance pass:[*]instance,
 			  struct tracefs_synth pass:[*]synth);
 int tracefs_synth_show(struct trace_seq pass:[*]seq, struct tracefs_instance pass:[*]instance,
 		       struct tracefs_synth pass:[*]synth);
+struct tracefs_hist pass:[*]tracefs_synth_get_start_hist(struct tracefs_synth pass:[*]synth);
 
 --
 
@@ -52,6 +53,9 @@ this may fail as busy.
 the synthetic event in the given _instance_, it will write the echo commands to
 manually create it in the _seq_ given.
 
+*tracefs_synth_get_start_hist*() returns a struct tracefs_hist descriptor describing
+the histogram used to create the synthetic event.
+
 RETURN VALUE
 ------------
 Returns zero on success or -1 on error.
diff --git a/include/tracefs.h b/include/tracefs.h
index ab781764b0ed..8148bd57224b 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -467,6 +467,7 @@ int tracefs_synth_append_end_filter(struct tracefs_synth *synth,
 				    const char *field,
 				    enum tracefs_compare compare,
 				    const char *val);
+struct tracefs_hist *tracefs_synth_get_start_hist(struct tracefs_synth *synth);
 int tracefs_synth_create(struct tracefs_instance *instance,
 			 struct tracefs_synth *synth);
 int tracefs_synth_destroy(struct tracefs_instance *instance,
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index 7c84e942d58b..379f75c7de24 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -543,6 +543,7 @@ struct tracefs_synth {
 	char			*name;
 	char			**synthetic_fields;
 	char			**synthetic_args;
+	char			**start_selection;
 	char			**start_keys;
 	char			**end_keys;
 	char			**start_vars;
@@ -1061,6 +1062,7 @@ int tracefs_synth_add_start_field(struct tracefs_synth *synth,
 {
 	const struct tep_format_field *field;
 	char *start_arg;
+	char **tmp;
 	int ret;
 
 	if (!synth || !start_field) {
@@ -1087,7 +1089,14 @@ int tracefs_synth_add_start_field(struct tracefs_synth *synth,
 		goto out_free;
 
 	ret = add_synth_fields(synth, field, name);
+	if (ret)
+		goto out_free;
 
+	tmp = tracefs_list_add(synth->start_selection, start_field);
+	if (tmp)
+		synth->start_selection = tmp;
+	else
+		ret = -1;
  out_free:
 	free(start_arg);
 	return ret;
@@ -1345,6 +1354,70 @@ static int verify_state(struct tracefs_synth *synth)
 	return 0;
 }
 
+/**
+ * tracefs_synth_get_start_hist - Return the histogram of the start event
+ * @synth: The synthetic event to get the start hist from.
+ *
+ * On success, returns a tracefs_hist descriptor that holds the
+ * histogram information of the start_event of the synthetic event
+ * structure. Returns NULL on failure.
+ */
+struct tracefs_hist *
+tracefs_synth_get_start_hist(struct tracefs_synth *synth)
+{
+	struct tracefs_hist *hist = NULL;
+	struct tep_handle *tep;
+	const char *system;
+	const char *event;
+	const char *key;
+	char **keys;
+	int ret;
+	int i;
+
+	if (!synth) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	system = synth->start_event->system;
+	event = synth->start_event->name;
+	keys = synth->start_keys;
+	tep = synth->tep;
+
+	if (!keys)
+		keys = synth->start_selection;
+
+	if (!keys)
+		return NULL;
+
+	for (i = 0; keys[i]; i++) {
+		key = keys[i];
+
+		if (i) {
+			ret = tracefs_hist_add_key(hist, key, 0);
+			if (ret < 0) {
+				tracefs_hist_free(hist);
+				return NULL;
+			}
+		} else {
+			hist = tracefs_hist_alloc(tep, system, event,
+						  key, 0);
+			if (!hist)
+				return NULL;
+		}
+	}
+
+	if (synth->start_filter) {
+		hist->filter = strdup(synth->start_filter);
+		if (!hist->filter) {
+			tracefs_hist_free(hist);
+			return NULL;
+		}
+	}
+
+	return hist;
+}
+
 /**
  * tracefs_synth_create - creates the synthetic event on the system
  * @instance: The instance to modify the start and end events
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 7/7] libtracefs: Add API tracefs_synth_complete()
  2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
                   ` (5 preceding siblings ...)
  2021-08-03 16:48 ` [PATCH v2 6/7] libtracefs: Add API tracefs_synth_get_start_hist() Steven Rostedt
@ 2021-08-03 16:48 ` Steven Rostedt
  6 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-08-03 16:48 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add tracefs_synth_complete() to tell if the synthetic event is a full
synthetic event (can create a synthetic event) or not, where it has only
enough information to create the starting histogram.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-synth2.txt |  4 ++++
 include/tracefs.h                   |  1 +
 src/tracefs-hist.c                  | 13 +++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/Documentation/libtracefs-synth2.txt b/Documentation/libtracefs-synth2.txt
index 5d34c4f60469..44693b394f29 100644
--- a/Documentation/libtracefs-synth2.txt
+++ b/Documentation/libtracefs-synth2.txt
@@ -17,6 +17,7 @@ int tracefs_synth_destroy(struct tracefs_instance pass:[*]instance,
 			  struct tracefs_synth pass:[*]synth);
 int tracefs_synth_show(struct trace_seq pass:[*]seq, struct tracefs_instance pass:[*]instance,
 		       struct tracefs_synth pass:[*]synth);
+bool tracefs_synth_complete(struct tracefs_synth pass:[*]synth);
 struct tracefs_hist pass:[*]tracefs_synth_get_start_hist(struct tracefs_synth pass:[*]synth);
 
 --
@@ -53,6 +54,9 @@ this may fail as busy.
 the synthetic event in the given _instance_, it will write the echo commands to
 manually create it in the _seq_ given.
 
+*tracefs_synth_complete*() returns true if the synthetic event _synth_ has both
+a starting and ending event.
+
 *tracefs_synth_get_start_hist*() returns a struct tracefs_hist descriptor describing
 the histogram used to create the synthetic event.
 
diff --git a/include/tracefs.h b/include/tracefs.h
index 8148bd57224b..55f82392b004 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -467,6 +467,7 @@ int tracefs_synth_append_end_filter(struct tracefs_synth *synth,
 				    const char *field,
 				    enum tracefs_compare compare,
 				    const char *val);
+bool tracefs_synth_complete(struct tracefs_synth *synth);
 struct tracefs_hist *tracefs_synth_get_start_hist(struct tracefs_synth *synth);
 int tracefs_synth_create(struct tracefs_instance *instance,
 			 struct tracefs_synth *synth);
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index 379f75c7de24..305e3e720341 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -1354,6 +1354,19 @@ static int verify_state(struct tracefs_synth *synth)
 	return 0;
 }
 
+/**
+ * tracefs_synth_complete - tell if the tracefs_synth is complete or not
+ * @synth: The synthetic event to get the start hist from.
+ *
+ * Retruns true if the synthetic event @synth has both a start and
+ * end event (ie. a synthetic event, or just a histogram), and
+ * false otherwise.
+ */
+bool tracefs_synth_complete(struct tracefs_synth *synth)
+{
+	return synth && synth->start_event && synth->end_event;
+}
+
 /**
  * tracefs_synth_get_start_hist - Return the histogram of the start event
  * @synth: The synthetic event to get the start hist from.
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-08-03 16:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-03 16:48 [PATCH v2 0/7] libtracefs: Updates to the histograms for tracefs_sql() Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 1/7] libtracefs: Change the tracefs_hist API to not take an instance immediately Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 2/7] libtracefs: Expose tracefs_hist_command() as an API Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 3/7] libtracefs: Add API tracefs_hist_append_filter() Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 4/7] libtracefs: Add API tracefs_hist_show() Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 5/7] libtracefs: Split up libtracefs-synth man page Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 6/7] libtracefs: Add API tracefs_synth_get_start_hist() Steven Rostedt
2021-08-03 16:48 ` [PATCH v2 7/7] libtracefs: Add API tracefs_synth_complete() Steven Rostedt

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 NNTP newsgroup(s).