[PATCH 6/7] kernel-shark-qt: Add filtering to the C API of KernelShark

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instruments for trace data filtering are added to the C API of
the Qt-based version of KernelShark. The following patch will
introduces an example, demonstrating the usage of this instruments.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx>
---
 kernel-shark-qt/src/libkshark.c | 141 ++++++++++++++++++++++++++++++++
 kernel-shark-qt/src/libkshark.h |  75 +++++++++++++++++
 2 files changed, 216 insertions(+)

diff --git a/kernel-shark-qt/src/libkshark.c b/kernel-shark-qt/src/libkshark.c
index f112a50..c6e03a8 100644
--- a/kernel-shark-qt/src/libkshark.c
+++ b/kernel-shark-qt/src/libkshark.c
@@ -28,6 +28,14 @@ static bool kshark_default_context(struct kshark_context **context)
 	if (!kshark_ctx)
 		return false;
 
+	kshark_ctx->show_task_filter = tracecmd_filter_id_hash_alloc();
+	kshark_ctx->hide_task_filter = tracecmd_filter_id_hash_alloc();
+
+	kshark_ctx->show_event_filter = tracecmd_filter_id_hash_alloc();
+	kshark_ctx->hide_event_filter = tracecmd_filter_id_hash_alloc();
+
+	kshark_ctx->filter_mask = 0x0;
+
 	/* Free the existing context (if any). */
 	if (*context && *context != kshark_context_handler) {
 		free(*context);
@@ -112,6 +120,15 @@ void kshark_close(struct kshark_context *kshark_ctx)
 	if (!kshark_ctx || !kshark_ctx->handle)
 		return;
 
+	/*
+	 * All Id filters are file specific. Make sure that the Pids and Event Ids
+	 * from this file are not going to be used with another file.
+	 */
+	tracecmd_filter_id_clear(kshark_ctx->show_task_filter);
+	tracecmd_filter_id_clear(kshark_ctx->hide_task_filter);
+	tracecmd_filter_id_clear(kshark_ctx->show_event_filter);
+	tracecmd_filter_id_clear(kshark_ctx->hide_event_filter);
+
 	tracecmd_close(kshark_ctx->handle);
 	kshark_ctx->handle = NULL;
 	kshark_ctx->pevt = NULL;
@@ -129,6 +146,12 @@ void kshark_free(struct kshark_context *kshark_ctx)
 		kshark_context_handler = NULL;
 	}
 
+	tracecmd_filter_id_hash_free(kshark_ctx->show_task_filter);
+	tracecmd_filter_id_hash_free(kshark_ctx->hide_task_filter);
+
+	tracecmd_filter_id_hash_free(kshark_ctx->show_event_filter);
+	tracecmd_filter_id_hash_free(kshark_ctx->hide_event_filter);
+
 	kshark_free_task_list(kshark_ctx);
 
 	if (seq.buffer)
@@ -171,6 +194,113 @@ kshark_add_task(struct kshark_context *kshark_ctx, int pid)
 	return list;
 }
 
+static bool kshark_show_task(struct kshark_context *kshark_ctx, int pid)
+{
+	return (!kshark_ctx->show_task_filter ||
+		!kshark_ctx->show_task_filter->count ||
+		tracecmd_filter_id_find(kshark_ctx->show_task_filter, pid)) &&
+		(!kshark_ctx->hide_task_filter ||
+		 !kshark_ctx->hide_task_filter->count ||
+		 !tracecmd_filter_id_find(kshark_ctx->hide_task_filter, pid));
+}
+
+static bool kshark_show_event(struct kshark_context *kshark_ctx, int event_id)
+{
+	return (!kshark_ctx->show_event_filter ||
+		!kshark_ctx->show_event_filter->count ||
+		tracecmd_filter_id_find(kshark_ctx->show_event_filter, event_id)) &&
+		(!kshark_ctx->hide_event_filter ||
+		 !kshark_ctx->hide_event_filter->count ||
+		 !tracecmd_filter_id_find(kshark_ctx->hide_event_filter, event_id));
+}
+
+void kshark_filter_add_id(struct kshark_context *kshark_ctx, int filter_id, int id)
+{
+	switch (filter_id) {
+		case SHOW_EVENT_FILTER:
+			tracecmd_filter_id_add(kshark_ctx->show_event_filter, id);
+			break;
+
+		case HIDE_EVENT_FILTER:
+			tracecmd_filter_id_add(kshark_ctx->hide_event_filter, id);
+			break;
+
+		case SHOW_TASK_FILTER:
+			tracecmd_filter_id_add(kshark_ctx->show_task_filter, id);
+			break;
+
+		case HIDE_TASK_FILTER:
+			tracecmd_filter_id_add(kshark_ctx->hide_task_filter, id);
+			break;
+
+		default:
+			break;
+	}
+}
+
+void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id)
+{
+	switch (filter_id) {
+		case SHOW_EVENT_FILTER:
+			tracecmd_filter_id_clear(kshark_ctx->show_event_filter);
+			break;
+
+		case HIDE_EVENT_FILTER:
+			tracecmd_filter_id_clear(kshark_ctx->hide_event_filter);
+			break;
+
+		case SHOW_TASK_FILTER:
+			tracecmd_filter_id_clear(kshark_ctx->show_task_filter);
+			break;
+
+		case HIDE_TASK_FILTER:
+			tracecmd_filter_id_clear(kshark_ctx->hide_task_filter);
+			break;
+
+		default:
+			break;
+	}
+}
+
+static bool kshark_filter_is_set(struct kshark_context *kshark_ctx)
+{
+	if ((kshark_ctx->show_task_filter &&
+	     kshark_ctx->show_task_filter->count) ||
+	    (kshark_ctx->hide_task_filter &&
+	     kshark_ctx->hide_task_filter->count) ||
+	    (kshark_ctx->show_event_filter &&
+	     kshark_ctx->show_event_filter->count) ||
+	    (kshark_ctx->hide_event_filter &&
+	     kshark_ctx->hide_event_filter->count)) {
+		return true;
+	}
+
+	return false;
+}
+
+void kshark_filter_entries(struct kshark_context *kshark_ctx,
+			   struct kshark_entry **data,
+			   size_t n_entries)
+{
+	if (!kshark_filter_is_set(kshark_ctx))
+		return;
+
+	int i;
+	for (i = 0; i < n_entries; ++i) {
+		data[i]->visible = 0xFF;
+		if (!kshark_show_task(kshark_ctx, data[i]->pid)) {
+			data[i]->visible &= ~kshark_ctx->filter_mask;
+		}
+
+		if (!kshark_show_event(kshark_ctx, data[i]->event_id)) {
+			int mask = kshark_ctx->filter_mask;
+			mask &= ~KS_GRAPH_VIEW_FILTER_MASK;
+			mask |= KS_EVENT_VIEW_FILTER_MASK;
+			data[i]->visible &= ~mask;
+		}
+	}
+}
+
 static void kshark_set_entry_values(struct kshark_context *kshark_ctx,
 				    struct pevent_record *record,
 				    struct kshark_entry *entry)
@@ -224,6 +354,17 @@ size_t kshark_load_data_entries(struct kshark_context *kshark_ctx,
 			kshark_set_entry_values(kshark_ctx, rec, entry);
 			kshark_add_task(kshark_ctx, entry->pid);
 
+			if (!kshark_show_task(kshark_ctx, entry->pid)) {
+				entry->visible &= ~kshark_ctx->filter_mask;
+			}
+
+			if (!kshark_show_event(kshark_ctx, entry->event_id)) {
+				int mask = kshark_ctx->filter_mask;
+				mask &= ~KS_GRAPH_VIEW_FILTER_MASK;
+				mask |= KS_EVENT_VIEW_FILTER_MASK;
+				entry->visible &= ~mask;
+			}
+
 			entry->next = NULL;
 			next = &(entry->next);
 			free_record(rec);
diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h
index d6e41bb..460c0c5 100644
--- a/kernel-shark-qt/src/libkshark.h
+++ b/kernel-shark-qt/src/libkshark.h
@@ -22,6 +22,7 @@ extern "C" {
 
 // trace-cmd
 #include "trace-cmd.h"
+// #include "trace-filter-hash.h"
 #include "event-parse.h"
 
 /**
@@ -82,6 +83,25 @@ struct kshark_context {
 
 	/** A mutex, used to protect the access to the input file. */
 	pthread_mutex_t input_mutex;
+
+	/** Hash of tasks to filter on. */
+	struct tracecmd_filter_id	*show_task_filter;
+
+	/** Hash of tasks to not display. */
+	struct tracecmd_filter_id	*hide_task_filter;
+
+	/** Hash of events to filter on. */
+	struct tracecmd_filter_id	*show_event_filter;
+
+	/** Hash of events to not display. */
+	struct tracecmd_filter_id	*hide_event_filter;
+
+	/**
+	 * Bit mask, controlling the visibility of the entries after filtering. If given
+	 * bit is set here, all entries which are filtered-out will have this bit unset
+	 * in their "visible" fields.
+	 */
+	uint8_t				filter_mask;
 };
 
 /**
@@ -150,6 +170,61 @@ void kshark_free(struct kshark_context *kshark_ctx);
  */
 char* kshark_dump_entry(struct kshark_entry *entry);
 
+/** Bit masks used to control the visibility of the entry after filtering. */
+enum kshark_filter_masks {
+	/** Use this mask to check the visibility of the entry in the text view. */
+	KS_TEXT_VIEW_FILTER_MASK	= (1 << 0),
+
+	/** Use this mask to check the visibility of the entry in the graph view. */
+	KS_GRAPH_VIEW_FILTER_MASK	= (1 << 1),
+
+	/** Special mask used whene filtering events. */
+	KS_EVENT_VIEW_FILTER_MASK	= (1 << 2),
+};
+
+/** Filter type identifier. */
+enum kshark_filter_type {
+	/** Identifier of the filter, used to specified the events to be shown. */
+	SHOW_EVENT_FILTER,
+
+	/** Identifier of the filter, used to specified the events to be filtered-out. */
+	HIDE_EVENT_FILTER,
+
+	/** Identifier of the filter, used to specified the tasks to be shown. */
+	SHOW_TASK_FILTER,
+
+	/** Identifier of the filter, used to specified the tasks to be filtered-out. */
+	HIDE_TASK_FILTER,
+};
+
+/**
+ * @brief Add an Id value to the filster specified by "filter_id".
+ * @param kshark_ctx: kshark_ctx: Input location for the session context pointer.
+ * @param filter_id: Identifier of the filter.
+ * @param id: Id value to be added to the filter.
+ */
+void kshark_filter_add_id(struct kshark_context *kshark_ctx, int filter_id, int id);
+
+/**
+ * @brief Clear (reset) the filster specified by "filter_id".
+ * @param kshark_ctx: kshark_ctx: Input location for the session context pointer.
+ * @param filter_id: Identifier of the filter.
+ */
+void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id);
+
+/**
+ * @brief This function loops over the array of entries specified by "data" and "n_entries"
+ * and sets the "visible" fields of each entry according to the criteria provided by the
+ * filters of the session's context. The field "filter_mask" of the session's context is
+ * used to control the level of visibility/invisibility of the entries which are filtered-out.
+ * @param kshark_ctx: kshark_ctx: Input location for the session context pointer.
+ * @param data: Input location for the trace data to be filtered.
+ * @param n_entries: The size of the inputted data.
+ */
+void kshark_filter_entries(struct kshark_context *kshark_ctx,
+			   struct kshark_entry **data,
+			   size_t n_entries);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.17.1




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux