From patchwork Wed Nov 28 15:16:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760027 Return-Path: Received: from mail-eopbgr710070.outbound.protection.outlook.com ([40.107.71.70]:36576 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728664AbeK2CSK (ORCPT ); Wed, 28 Nov 2018 21:18:10 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 01/17] kernel-shark-qt: Updata Event filter mask when applaing filters to Graph Date: Wed, 28 Nov 2018 15:16:06 +0000 Message-ID: <20181128151530.21965-2-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: KS_GRAPH_VIEW_FILTER_MASK and KS_EVENT_VIEW_FILTER_MASK are two bit flags used to control the visibility of an entry inside the Graphs. Both flags have to be updated when the "Apply filters to Graph" checkbox is clicked. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsUtils.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-shark-qt/src/KsUtils.cpp b/kernel-shark-qt/src/KsUtils.cpp index 5e4c9c8..8bb0970 100644 --- a/kernel-shark-qt/src/KsUtils.cpp +++ b/kernel-shark-qt/src/KsUtils.cpp @@ -67,8 +67,10 @@ void graphFilterSync(bool state) if (state) { kshark_ctx->filter_mask |= KS_GRAPH_VIEW_FILTER_MASK; + kshark_ctx->filter_mask |= KS_EVENT_VIEW_FILTER_MASK; } else { kshark_ctx->filter_mask &= ~KS_GRAPH_VIEW_FILTER_MASK; + kshark_ctx->filter_mask &= ~KS_EVENT_VIEW_FILTER_MASK; } } From patchwork Wed Nov 28 15:16:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760029 Return-Path: Received: from mail-eopbgr710070.outbound.protection.outlook.com ([40.107.71.70]:36576 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727941AbeK2CSK (ORCPT ); Wed, 28 Nov 2018 21:18:10 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 02/17] kernel-shark-qt: Reprocess all CPU collections when the filtering changes Date: Wed, 28 Nov 2018 15:16:07 +0000 Message-ID: <20181128151530.21965-3-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: The CPU data collections are processed according to the visibility of the entries. If the filtering condition changes, we need to reprocess those data collections. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsUtils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel-shark-qt/src/KsUtils.cpp b/kernel-shark-qt/src/KsUtils.cpp index 8bb0970..25e7fdb 100644 --- a/kernel-shark-qt/src/KsUtils.cpp +++ b/kernel-shark-qt/src/KsUtils.cpp @@ -186,10 +186,14 @@ void KsDataStore::update() if (!kshark_instance(&kshark_ctx)) return; + _unregisterCPUCollections(); + if (kshark_filter_is_set(kshark_ctx)) { kshark_filter_entries(kshark_ctx, _rows, _dataSize); emit updateWidgets(this); } + + registerCPUCollections(); } /** Register a collection of visible entries for each CPU. */ From patchwork Wed Nov 28 15:16:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760037 Return-Path: Received: from mail-eopbgr710070.outbound.protection.outlook.com ([40.107.71.70]:36576 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728664AbeK2CSL (ORCPT ); Wed, 28 Nov 2018 21:18:11 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 03/17] kernel-shark-qt: Fix a byg in unset_event_filter_flag() Date: Wed, 28 Nov 2018 15:16:09 +0000 Message-ID: <20181128151530.21965-4-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1734 Currently the unset_event_filter_flag() function unsets explicitly the EVENT_VIEW visibility flag, ignoring the user's request for visibility of the data after the filtering. This is wrong. The value of the coresponging bit in the user-provided mask (kshark_ctx->filter_mask), has to be used instead. Since the function becames very simple now it is declared as inline. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/libkshark.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel-shark-qt/src/libkshark.c b/kernel-shark-qt/src/libkshark.c index fa85171..b4b3d5b 100644 --- a/kernel-shark-qt/src/libkshark.c +++ b/kernel-shark-qt/src/libkshark.c @@ -448,19 +448,18 @@ bool kshark_filter_is_set(struct kshark_context *kshark_ctx) filter_is_set(kshark_ctx->hide_event_filter); } -static void unset_event_filter_flag(struct kshark_context *kshark_ctx, - struct kshark_entry *e) +static inline void unset_event_filter_flag(struct kshark_context *kshark_ctx, + struct kshark_entry *e) { /* * All entries, filtered-out by the event filters, will be treated * differently, when visualized. Because of this, ignore the value * of the GRAPH_VIEW flag provided by the user via - * kshark_ctx->filter_mask and unset the EVENT_VIEW flag. + * kshark_ctx->filter_mask. The value of the EVENT_VIEW flag in + * kshark_ctx->filter_mask will be used instead. */ - int event_mask = kshark_ctx->filter_mask; + int event_mask = kshark_ctx->filter_mask & ~KS_GRAPH_VIEW_FILTER_MASK; - event_mask &= ~KS_GRAPH_VIEW_FILTER_MASK; - event_mask |= KS_EVENT_VIEW_FILTER_MASK; e->visible &= ~event_mask; } From patchwork Wed Nov 28 15:16:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760039 Return-Path: Received: from mail-eopbgr680057.outbound.protection.outlook.com ([40.107.68.57]:19256 "EHLO NAM04-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727941AbeK2CSM (ORCPT ); Wed, 28 Nov 2018 21:18:12 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 04/17] kernel-shark qt: No error when Record authentication dialog is closed Date: Wed, 28 Nov 2018 15:16:10 +0000 Message-ID: <20181128151530.21965-5-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1431 No error message must be shown in the case when the user dismissed the authentication dialog (clicked Cancel). Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsMainWindow.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel-shark-qt/src/KsMainWindow.cpp b/kernel-shark-qt/src/KsMainWindow.cpp index ffb10d4..8e8484f 100644 --- a/kernel-shark-qt/src/KsMainWindow.cpp +++ b/kernel-shark-qt/src/KsMainWindow.cpp @@ -959,13 +959,28 @@ void KsMainWindow::_captureStarted() _captureLocalServer.listen("KSCapture"); } -void KsMainWindow::_captureFinished(int exit, QProcess::ExitStatus st) +/** + * If the authorization could not be obtained because the user dismissed + * the authentication dialog (clicked Cancel), pkexec exits with a return + * value of 126. + */ +#define PKEXEC_DISMISS_RET 126 + +void KsMainWindow::_captureFinished(int ret, QProcess::ExitStatus st) { QProcess *capture = (QProcess *)sender(); _captureLocalServer.close(); - if (exit != 0 || st != QProcess::NormalExit) { + if (ret == PKEXEC_DISMISS_RET) { + /* + * Authorization could not be obtained because the user + * dismissed the authentication dialog. + */ + return; + } + + if (ret != 0 || st != QProcess::NormalExit) { QString message = "Capture process failed:
"; message += capture->errorString(); From patchwork Wed Nov 28 15:16:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760043 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727941AbeK2CSP (ORCPT ); Wed, 28 Nov 2018 21:18:15 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 05/17] kernel-shark-qt: Protect all calls of tep_read_number_field() Date: Wed, 28 Nov 2018 15:16:12 +0000 Message-ID: <20181128151530.21965-6-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 4753 tep_read_number_field() is being used to retrieve the value of a data field and this value has being used without checking if the function succeeded. This is a potential bug because tep_read_number_field() may fail and in such a case the retrieved field value will be arbitrary. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/plugins/sched_events.c | 52 +++++++++++++--------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/kernel-shark-qt/src/plugins/sched_events.c b/kernel-shark-qt/src/plugins/sched_events.c index 1851569..59ffcfe 100644 --- a/kernel-shark-qt/src/plugins/sched_events.c +++ b/kernel-shark-qt/src/plugins/sched_events.c @@ -97,10 +97,12 @@ int plugin_get_next_pid(struct tep_record *record) struct plugin_sched_context *plugin_ctx = plugin_sched_context_handler; unsigned long long val; + int ret; - tep_read_number_field(plugin_ctx->sched_switch_next_field, - record->data, &val); - return val; + ret = tep_read_number_field(plugin_ctx->sched_switch_next_field, + record->data, &val); + + return ret ? : val; } /** @@ -113,10 +115,12 @@ int plugin_get_rec_wakeup_pid(struct tep_record *record) struct plugin_sched_context *plugin_ctx = plugin_sched_context_handler; unsigned long long val; + int ret; + + ret = tep_read_number_field(plugin_ctx->sched_wakeup_pid_field, + record->data, &val); - tep_read_number_field(plugin_ctx->sched_wakeup_pid_field, - record->data, &val); - return val; + return ret ? : val; } static void plugin_register_command(struct kshark_context *kshark_ctx, @@ -145,11 +149,12 @@ static int plugin_get_rec_wakeup_new_pid(struct tep_record *record) struct plugin_sched_context *plugin_ctx = plugin_sched_context_handler; unsigned long long val; + int ret; - tep_read_number_field(plugin_ctx->sched_wakeup_new_pid_field, - record->data, &val); + ret = tep_read_number_field(plugin_ctx->sched_wakeup_new_pid_field, + record->data, &val); - return val; + return ret ? : val; } /** @@ -170,7 +175,7 @@ bool plugin_wakeup_match_rec_pid(struct kshark_context *kshark_ctx, struct plugin_sched_context *plugin_ctx; struct tep_record *record = NULL; unsigned long long val; - int wakeup_pid = -1; + int ret, wakeup_pid = -1; plugin_ctx = plugin_sched_context_handler; if (!plugin_ctx) @@ -181,10 +186,10 @@ bool plugin_wakeup_match_rec_pid(struct kshark_context *kshark_ctx, record = kshark_read_at(kshark_ctx, e->offset); /* We only want those that actually woke up the task. */ - tep_read_number_field(plugin_ctx->sched_wakeup_success_field, - record->data, &val); + ret = tep_read_number_field(plugin_ctx->sched_wakeup_success_field, + record->data, &val); - if (val) + if (ret == 0 && val) wakeup_pid = plugin_get_rec_wakeup_pid(record); } @@ -193,10 +198,10 @@ bool plugin_wakeup_match_rec_pid(struct kshark_context *kshark_ctx, record = kshark_read_at(kshark_ctx, e->offset); /* We only want those that actually woke up the task. */ - tep_read_number_field(plugin_ctx->sched_wakeup_new_success_field, - record->data, &val); + ret = tep_read_number_field(plugin_ctx->sched_wakeup_new_success_field, + record->data, &val); - if (val) + if (ret == 0 && val) wakeup_pid = plugin_get_rec_wakeup_new_pid(record); } @@ -224,7 +229,7 @@ bool plugin_switch_match_rec_pid(struct kshark_context *kshark_ctx, { struct plugin_sched_context *plugin_ctx; unsigned long long val; - int switch_pid = -1; + int ret, switch_pid = -1; plugin_ctx = plugin_sched_context_handler; @@ -233,10 +238,10 @@ bool plugin_switch_match_rec_pid(struct kshark_context *kshark_ctx, struct tep_record *record; record = kshark_read_at(kshark_ctx, e->offset); - tep_read_number_field(plugin_ctx->sched_switch_prev_state_field, - record->data, &val); + ret = tep_read_number_field(plugin_ctx->sched_switch_prev_state_field, + record->data, &val); - if (!(val & 0x7f)) + if (ret == 0 && !(val & 0x7f)) switch_pid = tep_data_pid(plugin_ctx->pevent, record); free_record(record); @@ -278,8 +283,11 @@ static void plugin_sched_action(struct kshark_context *kshark_ctx, struct tep_record *rec, struct kshark_entry *entry) { - entry->pid = plugin_get_next_pid(rec); - plugin_register_command(kshark_ctx, rec, entry->pid); + int pid = plugin_get_next_pid(rec); + if (pid >= 0) { + entry->pid = pid; + plugin_register_command(kshark_ctx, rec, entry->pid); + } } static int plugin_sched_init(struct kshark_context *kshark_ctx) From patchwork Wed Nov 28 15:16:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760049 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728732AbeK2CSR (ORCPT ); Wed, 28 Nov 2018 21:18:17 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 06/17] kernel-shark-qt: Ignore sched_wakeup events if the task is running. Date: Wed, 28 Nov 2018 15:16:14 +0000 Message-ID: <20181128151530.21965-7-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1195 The "Sched Events" plugin uses the sched_wakeup events to visualize the wake up latency of the task. This patch deals with the corner case, when we have a second sched_wakeup events which tries to wake up a task which is already running. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/plugins/SchedEvents.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel-shark-qt/src/plugins/SchedEvents.cpp b/kernel-shark-qt/src/plugins/SchedEvents.cpp index b4596c9..ea07662 100644 --- a/kernel-shark-qt/src/plugins/SchedEvents.cpp +++ b/kernel-shark-qt/src/plugins/SchedEvents.cpp @@ -139,6 +139,21 @@ static void pluginDraw(plugin_sched_context *plugin_ctx, ksmodel_get_entry_back(histo, bin, false, plugin_wakeup_match_rec_pid, pid, col, &indexOpen); + + if (entryOpen) { + int cpu = ksmodel_get_cpu_back(histo, bin, + pid, + false, + col, + nullptr); + if (cpu >= 0) { + /* + * The task is already running. Ignore + * this wakeup event. + */ + entryOpen = nullptr; + } + } } if (rec) { From patchwork Wed Nov 28 15:16:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760031 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727941AbeK2CSR (ORCPT ); Wed, 28 Nov 2018 21:18:17 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 07/17] kernel-shark-qt: Fix the documentation of libkshark-model Date: Wed, 28 Nov 2018 15:16:15 +0000 Message-ID: <20181128151530.21965-8-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1455 This patch fixes a simple copy/paste mistake in the Doxygen documentation of the ksmodel_get_cpu_xxx() functions. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/libkshark-model.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel-shark-qt/src/libkshark-model.c b/kernel-shark-qt/src/libkshark-model.c index 461f88e..76e2940 100644 --- a/kernel-shark-qt/src/libkshark-model.c +++ b/kernel-shark-qt/src/libkshark-model.c @@ -1070,7 +1070,7 @@ static int ksmodel_get_entry_cpu(const struct kshark_entry *entry) * @param index: Optional output location for the index of the requested * entry inside the array. * - * @returns Process Id of the task if an entry has been found. Else a negative + * @returns The CPU Id of the task if an entry has been found. Else a negative * Identifier (KS_EMPTY_BIN or KS_FILTERED_BIN). */ int ksmodel_get_cpu_front(struct kshark_trace_histo *histo, @@ -1103,7 +1103,7 @@ int ksmodel_get_cpu_front(struct kshark_trace_histo *histo, * @param index: Optional output location for the index of the requested * entry inside the array. * - * @returns Process Id of the task if an entry has been found. Else a negative + * @returns The CPU Id of the task if an entry has been found. Else a negative * Identifier (KS_EMPTY_BIN or KS_FILTERED_BIN). */ int ksmodel_get_cpu_back(struct kshark_trace_histo *histo, From patchwork Wed Nov 28 15:16:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760055 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728732AbeK2CST (ORCPT ); Wed, 28 Nov 2018 21:18:19 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 08/17] kernel-shark-qt: Add a method for easy retrieve of all Ids of a filter Date: Wed, 28 Nov 2018 15:16:16 +0000 Message-ID: <20181128151530.21965-9-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1649 This patch adds to KsUtils a method which can be used to retrieve a vector of sorted Id values associated with a given filter. The method will be used by the Quick Context Menu widget. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsUtils.cpp | 21 +++++++++++++++++++++ kernel-shark-qt/src/KsUtils.hpp | 2 ++ 2 files changed, 23 insertions(+) diff --git a/kernel-shark-qt/src/KsUtils.cpp b/kernel-shark-qt/src/KsUtils.cpp index 25e7fdb..c0e0f7d 100644 --- a/kernel-shark-qt/src/KsUtils.cpp +++ b/kernel-shark-qt/src/KsUtils.cpp @@ -36,6 +36,27 @@ QVector getPidList() return pids; } +/** @brief Get a sorted vector of Id values of a filter. */ +QVector getFilterIds(tracecmd_filter_id *filter) +{ + kshark_context *kshark_ctx(nullptr); + int *cpuFilter, n; + QVector v; + + if (!kshark_instance(&kshark_ctx)) + return v; + + cpuFilter = tracecmd_filter_ids(filter); + n = filter->count; + for (int i = 0; i < n; ++i) + v.append(cpuFilter[i]); + + qSort(v); + + free(cpuFilter); + return v; +} + /** * Set the bit of the filter mask of the kshark session context responsible * for the visibility of the events in the Table View. diff --git a/kernel-shark-qt/src/KsUtils.hpp b/kernel-shark-qt/src/KsUtils.hpp index b14cd6a..888ed56 100644 --- a/kernel-shark-qt/src/KsUtils.hpp +++ b/kernel-shark-qt/src/KsUtils.hpp @@ -84,6 +84,8 @@ namespace KsUtils { QVector getPidList(); +QVector getFilterIds(tracecmd_filter_id *filter); + /** @brief Geat the list of plugins. */ inline QStringList getPluginList() {return plugins.split(";");} From patchwork Wed Nov 28 15:16:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760045 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727941AbeK2CSf (ORCPT ); Wed, 28 Nov 2018 21:18:35 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 09/17] kernel-shark-qt: Add centralized context menu for View and Graph widgets Date: Wed, 28 Nov 2018 15:16:18 +0000 Message-ID: <20181128151530.21965-10-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 32031 This patch redesigns the context menu, used so far by the View (table) widget. The goal is to make this menu universal and to make possible to open it from both View and Graph widgets. The context menu gets open by a right mouse click. The problem here was, that so far the right mouse click in the Graph widget was used for deselecting the Active marker. Now the Active marker can be unset via the menu. Because the new design of the Context menu requires significant modification of the flow of signals between the widgets, the changes cannot be broken into smaller patches. Also the implementation of the menu is more complex now (much more code), hence its source code has been moved from KsWidgetsLib into separate header and source files. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/CMakeLists.txt | 2 + kernel-shark-qt/src/KsGLWidget.cpp | 46 ++-- kernel-shark-qt/src/KsGLWidget.hpp | 22 +- kernel-shark-qt/src/KsMainWindow.cpp | 17 +- kernel-shark-qt/src/KsMainWindow.hpp | 2 + kernel-shark-qt/src/KsQuickContextMenu.cpp | 274 +++++++++++++++++++++ kernel-shark-qt/src/KsQuickContextMenu.hpp | 136 ++++++++++ kernel-shark-qt/src/KsTraceGraph.cpp | 94 +++++++ kernel-shark-qt/src/KsTraceGraph.hpp | 14 ++ kernel-shark-qt/src/KsTraceViewer.cpp | 30 ++- kernel-shark-qt/src/KsTraceViewer.hpp | 32 ++- kernel-shark-qt/src/KsWidgetsLib.cpp | 120 --------- kernel-shark-qt/src/KsWidgetsLib.hpp | 44 ---- 13 files changed, 622 insertions(+), 211 deletions(-) create mode 100644 kernel-shark-qt/src/KsQuickContextMenu.cpp create mode 100644 kernel-shark-qt/src/KsQuickContextMenu.hpp diff --git a/kernel-shark-qt/src/CMakeLists.txt b/kernel-shark-qt/src/CMakeLists.txt index ef0aa71..3eddaed 100644 --- a/kernel-shark-qt/src/CMakeLists.txt +++ b/kernel-shark-qt/src/CMakeLists.txt @@ -40,6 +40,7 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND) KsTraceViewer.hpp KsMainWindow.hpp KsCaptureDialog.hpp + KsQuickContextMenu.hpp KsAdvFilteringDialog.hpp) QT5_WRAP_CPP(ks-guiLib_hdr_moc ${ks-guiLib_hdr}) @@ -54,6 +55,7 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND) KsTraceViewer.cpp KsMainWindow.cpp KsCaptureDialog.cpp + KsQuickContextMenu.cpp KsAdvFilteringDialog.cpp) target_link_libraries(kshark-gui kshark-plot diff --git a/kernel-shark-qt/src/KsGLWidget.cpp b/kernel-shark-qt/src/KsGLWidget.cpp index 2a0b16b..917e86d 100644 --- a/kernel-shark-qt/src/KsGLWidget.cpp +++ b/kernel-shark-qt/src/KsGLWidget.cpp @@ -115,11 +115,6 @@ void KsGLWidget::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) { _posMousePress = _posInRange(event->pos().x()); _rangeBoundInit(_posMousePress); - } else if (event->button() == Qt::RightButton) { - emit deselect(); - _mState->activeMarker().remove(); - _mState->updateLabels(); - _model.update(); } } @@ -189,8 +184,8 @@ void KsGLWidget::mouseMoveEvent(QMouseEvent *event) _rangeBoundStretched(_posInRange(event->pos().x())); bin = event->pos().x() - _hMargin; - cpu = _getCPU(event->pos().y()); - pid = _getPid(event->pos().y()); + cpu = getPlotCPU(event->pos()); + pid = getPlotPid(event->pos()); ret = _find(bin, cpu, pid, 5, false, &row); if (ret) { @@ -613,18 +608,30 @@ KsPlot::Graph *KsGLWidget::_newTaskGraph(int pid) return graph; } -bool KsGLWidget::_find(QMouseEvent *event, int variance, bool joined, - size_t *row) +/** + * @brief Find the KernelShark entry under the the cursor. + * + * @param point: The position of the cursor. + * @param variance: The variance of the position (range) in which an entry will + * be searched. + * @param joined: It True, search also in the associated CPU/Task graph. + * @param index: Output location for the index of the entry under the cursor. + * If no entry has been found, the outputted value is zero. + * + * @returns True, if an entry has been found, otherwise False. + */ +bool KsGLWidget::find(const QPoint &point, int variance, bool joined, + size_t *index) { /* * Get the bin, pid and cpu numbers. * Remember that one bin corresponds to one pixel. */ - int bin = event->pos().x() - _hMargin; - int cpu = _getCPU(event->pos().y()); - int pid = _getPid(event->pos().y()); + int bin = point.x() - _hMargin; + int cpu = getPlotCPU(point); + int pid = getPlotPid(point); - return _find(bin, cpu, pid, variance, joined, row); + return _find(bin, cpu, pid, variance, joined, index); } int KsGLWidget::_getNextCPU(int pid, int bin) @@ -766,9 +773,8 @@ bool KsGLWidget::_find(int bin, int cpu, int pid, bool KsGLWidget::_findAndSelect(QMouseEvent *event) { size_t row; - bool found = _find(event, 10, true, &row); + bool found = find(event->pos(), 10, true, &row); - emit deselect(); if (found) { emit select(row); emit updateView(row, true); @@ -892,9 +898,10 @@ int KsGLWidget::_posInRange(int x) return posX; } -int KsGLWidget::_getCPU(int y) +/** Get the CPU Id of the Graph plotted at given position. */ +int KsGLWidget::getPlotCPU(const QPoint &point) { - int cpuId; + int cpuId, y = point.y(); if (_cpuList.count() == 0) return -1; @@ -906,9 +913,10 @@ int KsGLWidget::_getCPU(int y) return _cpuList[cpuId]; } -int KsGLWidget::_getPid(int y) +/** Get the CPU Id of the Graph plotted at given position. */ +int KsGLWidget::getPlotPid(const QPoint &point) { - int pidId; + int pidId, y = point.y(); if (_taskList.count() == 0) return -1; diff --git a/kernel-shark-qt/src/KsGLWidget.hpp b/kernel-shark-qt/src/KsGLWidget.hpp index 662cd26..6fbf534 100644 --- a/kernel-shark-qt/src/KsGLWidget.hpp +++ b/kernel-shark-qt/src/KsGLWidget.hpp @@ -98,6 +98,13 @@ public: int *graphCPU, int *graphTask); + bool find(const QPoint &point, int variance, bool joined, + size_t *index); + + int getPlotCPU(const QPoint &point); + + int getPlotPid(const QPoint &point); + /** CPUs to be plotted. */ QVector _cpuList; @@ -141,13 +148,6 @@ signals: */ void select(size_t pos); - /** - * This signal is emitted in the case of a right mouse button click or - * in the case of a double click over an empty area (no visible - * KernelShark entries). - */ - void deselect(); - /** * This signal is emitted when the KsTraceViewer widget needs to be * updated. @@ -195,10 +195,6 @@ private: int _posInRange(int x); - int _getCPU(int y); - - int _getPid(int y); - void _rangeBoundInit(int x); void _rangeBoundStretched(int x); @@ -207,8 +203,6 @@ private: bool _findAndSelect(QMouseEvent *event); - bool _find(QMouseEvent *event, int variance, bool joined, size_t *row); - bool _find(int bin, int cpu, int pid, int variance, bool joined, size_t *row); @@ -217,6 +211,8 @@ private: int _getLastTask(struct kshark_trace_histo *histo, int bin, int cpu); int _getLastCPU(struct kshark_trace_histo *histo, int bin, int pid); + + void _deselect(); }; #endif diff --git a/kernel-shark-qt/src/KsMainWindow.cpp b/kernel-shark-qt/src/KsMainWindow.cpp index 8e8484f..5c9a0fa 100644 --- a/kernel-shark-qt/src/KsMainWindow.cpp +++ b/kernel-shark-qt/src/KsMainWindow.cpp @@ -93,14 +93,17 @@ KsMainWindow::KsMainWindow(QWidget *parent) connect(&_view, &KsTraceViewer::select, &_graph, &KsTraceGraph::markEntry); - connect(&_view, &KsTraceViewer::plotTask, + connect(&_view, &KsTraceViewer::addTaskPlot, &_graph, &KsTraceGraph::addTaskPlot); connect(_graph.glPtr(), &KsGLWidget::updateView, &_view, &KsTraceViewer::showRow); - connect(_graph.glPtr(), &KsGLWidget::deselect, - &_view, &KsTraceViewer::deselect); + connect(&_graph, &KsTraceGraph::deselect, + this, &KsMainWindow::_deselect); + + connect(&_view, &KsTraceViewer::deselect, + this, &KsMainWindow::_deselect); connect(&_data, &KsDataStore::updateWidgets, &_view, &KsTraceViewer::update); @@ -1040,3 +1043,11 @@ void KsMainWindow::_splitterMoved(int pos, int index) { _session.saveSplitterSize(_splitter); } + +void KsMainWindow::_deselect() +{ + _view.clearSelection(); + _mState.activeMarker().remove(); + _mState.updateLabels(); + _graph.glPtr()->model()->update(); +} diff --git a/kernel-shark-qt/src/KsMainWindow.hpp b/kernel-shark-qt/src/KsMainWindow.hpp index d711ec1..b9b681f 100644 --- a/kernel-shark-qt/src/KsMainWindow.hpp +++ b/kernel-shark-qt/src/KsMainWindow.hpp @@ -210,6 +210,8 @@ private: void _error(const QString &text, const QString &errCode, bool resize, bool unloadPlugins); + void _deselect(); + private slots: void _captureFinished(int, QProcess::ExitStatus); }; diff --git a/kernel-shark-qt/src/KsQuickContextMenu.cpp b/kernel-shark-qt/src/KsQuickContextMenu.cpp new file mode 100644 index 0000000..0a8e527 --- /dev/null +++ b/kernel-shark-qt/src/KsQuickContextMenu.cpp @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: LGPL-2.1 + +/* + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov + */ + +/** + * @file KsQuickContextMenu.cpp + * @brief Quick Context Menus for KernelShark. + */ + +#include "KsQuickContextMenu.hpp" +#include "KsTraceGraph.hpp" + +/** + * @brief Create KsQuickMarkerMenu. + * + * @param dm: The State machine of the Dual marker. + * @param parent: The parent of this widget. + */ +KsQuickMarkerMenu::KsQuickMarkerMenu(KsDualMarkerSM *dm, QWidget *parent) +: QMenu("Context Menu", parent), + _dm(dm), + _deselectAction(this) +{ + if (dm->activeMarker()._isSet) { + addSection("Marker menu"); + _deselectAction.setText("Deselect"); + + connect(&_deselectAction, &QAction::triggered, + this, &KsQuickMarkerMenu::deselect); + + addAction(&_deselectAction); + } +} + +/** + * @brief Create KsQuickContextMenu. + * + * @param data: Input location for the KsDataStore object. + * @param row: The index of the entry used to initialize the menu. + * @param dm: The State machine of the Dual marker. + * @param parent: The parent of this widget. + */ +KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row, + KsDualMarkerSM *dm, + QWidget *parent) +: KsQuickMarkerMenu(dm, parent), + _data(data), + _row(row), + _hideTaskAction(this), + _showTaskAction(this), + _hideEventAction(this), + _showEventAction(this), + _addCPUPlotAction(this), + _addTaskPlotAction(this), + _removeCPUPlotAction(this), + _removeTaskPlotAction(this), + _deselectAction(this) +{ + typedef void (KsQuickContextMenu::*mfp)(); + QString taskName, parentName, descr; + KsTraceGraph *graphs; + int pid, cpu; + + if (!parent || !_data) + return; + + taskName = kshark_get_task_easy(_data->rows()[_row]); + pid = kshark_get_pid_easy(_data->rows()[_row]); + cpu = _data->rows()[_row]->cpu; + + auto lamAddAction = [this, &descr] (QAction *action, mfp mf) { + action->setText(descr); + + connect(action, &QAction::triggered, + this, mf); + + addAction(action); + }; + + parentName = parent->metaObject()->className(); + + addSection("Pointer menu"); + descr = "Hide task ["; + descr += taskName; + descr += "-"; + descr += QString("%1").arg(pid); + descr += "]"; + lamAddAction(&_hideTaskAction, &KsQuickContextMenu::_hideTask); + + descr = "Show task ["; + descr += taskName; + descr += "-"; + descr += QString("%1").arg(pid); + descr += "] only"; + lamAddAction(&_showTaskAction, &KsQuickContextMenu::_showTask); + + descr = "Hide event ["; + descr += kshark_get_event_name_easy(_data->rows()[_row]); + descr += "]"; + lamAddAction(&_hideEventAction, &KsQuickContextMenu::_hideEvent); + + descr = "Show event ["; + descr += kshark_get_event_name_easy(_data->rows()[_row]); + descr += "] only"; + lamAddAction(&_showEventAction, &KsQuickContextMenu::_showEvent); + + if (parentName == "KsTraceViewer") { + descr = "Add ["; + descr += taskName; + descr += "-"; + descr += QString("%1").arg(pid); + descr += "] plot"; + lamAddAction(&_addTaskPlotAction, + &KsQuickContextMenu::_addTaskPlot); + } + + if (parentName == "KsTraceGraph" && + (graphs = dynamic_cast(parent))) { + if (graphs->glPtr()->_taskList.contains(pid)) { + descr = "Remove ["; + descr += taskName; + descr += "-"; + descr += QString("%1").arg(_data->rows()[_row]->pid); + descr += "] plot"; + lamAddAction(&_removeTaskPlotAction, + &KsQuickContextMenu::_removeTaskPlot); + } else { + descr = "Add ["; + descr += taskName; + descr += "-"; + descr += QString("%1").arg(_data->rows()[_row]->pid); + descr += "] plot"; + lamAddAction(&_addTaskPlotAction, + &KsQuickContextMenu::_addTaskPlot); + } + + if (graphs->glPtr()->_cpuList.contains(cpu)) { + descr = "Remove [CPU "; + descr += QString("%1").arg(cpu); + descr += "] plot"; + lamAddAction(&_removeCPUPlotAction, + &KsQuickContextMenu::_removeCPUPlot); + } else { + descr = "Add [CPU "; + descr += QString("%1").arg(cpu); + descr += "] plot"; + lamAddAction(&_addCPUPlotAction, + &KsQuickContextMenu::_addCPUPlot); + } + } +} + +void KsQuickContextMenu::_hideTask() +{ + int pid = kshark_get_pid_easy(_data->rows()[_row]); + kshark_context *kshark_ctx(nullptr); + QVector vec; + + if (!kshark_instance(&kshark_ctx)) + return; + + vec =_getFilterVector(kshark_ctx->hide_task_filter, pid); + _data->applyPosTaskFilter(vec); +} + +void KsQuickContextMenu::_showTask() +{ + int pid = kshark_get_pid_easy(_data->rows()[_row]); + + _data->applyPosTaskFilter(QVector(1, pid)); +} + +void KsQuickContextMenu::_hideEvent() +{ + int eventId = kshark_get_event_id_easy(_data->rows()[_row]); + kshark_context *kshark_ctx(nullptr); + QVector vec; + + if (!kshark_instance(&kshark_ctx)) + return; + + vec =_getFilterVector(kshark_ctx->hide_event_filter, eventId); + _data->applyNegEventFilter(vec); +} + +void KsQuickContextMenu::_showEvent() +{ + int eventId = kshark_get_event_id_easy(_data->rows()[_row]); + + _data->applyPosEventFilter(QVector(1, eventId)); +} + +void KsQuickContextMenu::_addTaskPlot() +{ + int pid = kshark_get_pid_easy(_data->rows()[_row]); + + emit addTaskPlot(pid); +} + +void KsQuickContextMenu::_addCPUPlot() +{ + emit addCPUPlot(_data->rows()[_row]->cpu); +} + +void KsQuickContextMenu::_removeTaskPlot() +{ + int pid = kshark_get_pid_easy(_data->rows()[_row]); + + emit removeTaskPlot(pid); +} + +void KsQuickContextMenu::_removeCPUPlot() +{ + emit removeCPUPlot(_data->rows()[_row]->cpu); +} + +/** + * @brief Create KsRmPlotContextMenu. + * + * @param dm: The State machine of the Dual marker. + * @param parent: The parent of this widget. + */ +KsRmPlotContextMenu::KsRmPlotContextMenu(KsDualMarkerSM *dm, + QWidget *parent) +: KsQuickMarkerMenu(dm, parent), + _removePlotAction(this) +{ + addSection("Plots"); + + connect(&_removePlotAction, &QAction::triggered, + this, &KsRmPlotContextMenu::removePlot); + + addAction(&_removePlotAction); +} + +/** + * @brief Create KsRmCPUPlotMenu. + * + * @param dm: The State machine of the Dual marker. + * @param cpu : CPU Id. + * @param parent: The parent of this widget. + */ +KsRmCPUPlotMenu::KsRmCPUPlotMenu(KsDualMarkerSM *dm, int cpu, + QWidget *parent) +: KsRmPlotContextMenu(dm, parent) +{ + _removePlotAction.setText(QString("Remove [CPU %1]").arg(cpu)); +} + +/** + * @brief Create KsRmTaskPlotMenu. + * + * @param dm: The State machine of the Dual marker. + * @param pid: Process Id. + * @param parent: The parent of this widget. + */ +KsRmTaskPlotMenu::KsRmTaskPlotMenu(KsDualMarkerSM *dm, int pid, + QWidget *parent) +: KsRmPlotContextMenu(dm, parent) +{ + kshark_context *kshark_ctx(nullptr); + QString descr("Remove [ "); + + if (!kshark_instance(&kshark_ctx)) + return; + + descr += tep_data_comm_from_pid(kshark_ctx->pevent, pid); + descr += "-"; + descr += QString("%1").arg(pid); + descr += "] plot"; + _removePlotAction.setText(descr); +} diff --git a/kernel-shark-qt/src/KsQuickContextMenu.hpp b/kernel-shark-qt/src/KsQuickContextMenu.hpp new file mode 100644 index 0000000..040942f --- /dev/null +++ b/kernel-shark-qt/src/KsQuickContextMenu.hpp @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ + +/* + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov + */ + +/** + * @file KsQuickContextMenu.hpp + * @brief Quick Context Menus for KernelShark. + */ + +#ifndef _KS_QUICK_CTX_MENU_H +#define _KS_QUICK_CTX_MENU_H + +#include "KsDualMarker.hpp" +#include "KsUtils.hpp" +#include "KsGLWidget.hpp" + +/** + * The KsQuickMarkerMenu class provides menu for quick Dual Marker related + * actions. + */ +class KsQuickMarkerMenu : public QMenu { + Q_OBJECT +public: + KsQuickMarkerMenu(KsDualMarkerSM *dm, QWidget *parent = nullptr); + +signals: + /** Signal to deselect the active marker. */ + void deselect(); + +private: + KsDualMarkerSM *_dm; + + QAction _deselectAction; +}; + +/** + * The KsQuickFilterMenu class provides a menu for easy filtering and plotting. + * The menu is initialized from a single kshark_entry and uses the content of + * this entry to provides quick actions for filtering and plottin. + */ +class KsQuickContextMenu : public KsQuickMarkerMenu { + Q_OBJECT +public: + KsQuickContextMenu() = delete; + + KsQuickContextMenu(KsDataStore *data, size_t row, + KsDualMarkerSM *dm, + QWidget *parent = nullptr); + +signals: + /** Signal to add a task plot. */ + void addTaskPlot(int); + + /** Signal to add a CPU plot. */ + void addCPUPlot(int); + + /** Signal to remove a task plot. */ + void removeTaskPlot(int); + + /** Signal to remove a CPU plot. */ + void removeCPUPlot(int); + +private: + void _hideTask(); + + void _showTask(); + + void _hideEvent(); + + void _showEvent(); + + void _addCPUPlot(); + + void _addTaskPlot(); + + void _removeCPUPlot(); + + void _removeTaskPlot(); + + KsDataStore *_data; + + size_t _row; + + QAction _hideTaskAction, _showTaskAction; + + QAction _hideEventAction, _showEventAction; + + QAction _addCPUPlotAction; + + QAction _addTaskPlotAction; + + QAction _removeCPUPlotAction; + + QAction _removeTaskPlotAction; + + QAction _deselectAction; +}; + +/** + * The KsQuickMarkerMenu is a baser class for Remove Plot menus. + */ +class KsRmPlotContextMenu : public KsQuickMarkerMenu { + Q_OBJECT +public: + KsRmPlotContextMenu() = delete; + + KsRmPlotContextMenu(KsDualMarkerSM *dm, QWidget *parent = nullptr); + +signals: + /** Signal to remove a plot. */ + void removePlot(int); + +protected: + /** Menu action. */ + QAction _removePlotAction; +}; + +/** + * The KsQuickMarkerMenu class provides CPU Plot remove menus. + */ +struct KsRmCPUPlotMenu : public KsRmPlotContextMenu { + KsRmCPUPlotMenu(KsDualMarkerSM *dm, int cpu, + QWidget *parent = nullptr); +}; + +/** + * The KsQuickMarkerMenu class provides Task Plot remove menus. + */ +struct KsRmTaskPlotMenu : public KsRmPlotContextMenu { + KsRmTaskPlotMenu(KsDualMarkerSM *dm, int pid, + QWidget *parent = nullptr); +}; + +#endif diff --git a/kernel-shark-qt/src/KsTraceGraph.cpp b/kernel-shark-qt/src/KsTraceGraph.cpp index 29a5950..09b322a 100644 --- a/kernel-shark-qt/src/KsTraceGraph.cpp +++ b/kernel-shark-qt/src/KsTraceGraph.cpp @@ -13,6 +13,7 @@ #include "KsUtils.hpp" #include "KsDualMarker.hpp" #include "KsTraceGraph.hpp" +#include "KsQuickContextMenu.hpp" /** Create a default (empty) Trace graph widget. */ KsTraceGraph::KsTraceGraph(QWidget *parent) @@ -134,6 +135,10 @@ KsTraceGraph::KsTraceGraph(QWidget *parent) connect(_glWindow.model(), &KsGraphModel::modelReset, this, &KsTraceGraph::_updateTimeLegends); + _glWindow.setContextMenuPolicy(Qt::CustomContextMenu); + connect(&_glWindow, &QTableView::customContextMenuRequested, + this, &KsTraceGraph::_onCustomContextMenu); + _scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); _scrollArea.setWidget(&_drawWindow); @@ -447,6 +452,26 @@ void KsTraceGraph::addTaskPlot(int pid) _selfUpdate(); } +/** Remove a CPU graph from the existing list of CPU graphs. */ +void KsTraceGraph::removeCPUPlot(int cpu) +{ + if (!_glWindow._cpuList.contains(cpu)) + return; + + _glWindow._cpuList.removeAll(cpu); + _selfUpdate(); +} + +/** Remove a Task graph from the existing list of Task graphs. */ +void KsTraceGraph::removeTaskPlot(int pid) +{ + if (!_glWindow._taskList.contains(pid)) + return; + + _glWindow._taskList.removeAll(pid); + _selfUpdate(); +} + /** Update the content of all graphs. */ void KsTraceGraph::update(KsDataStore *data) { @@ -689,3 +714,72 @@ void KsTraceGraph::_updateGraphs(GraphActions action) QCoreApplication::processEvents(); } } + +void KsTraceGraph::_onCustomContextMenu(const QPoint &point) +{ + KsQuickMarkerMenu *menu(nullptr); + int cpu, pid; + size_t row; + bool found; + + found = _glWindow.find(point, 20, true, &row); + if (found) { + /* KernelShark entry has been found under the cursor. */ + KsQuickContextMenu *entryMenu; + menu = entryMenu = new KsQuickContextMenu(_data, row, + _mState, this); + + connect(entryMenu, &KsQuickContextMenu::addTaskPlot, + this, &KsTraceGraph::addTaskPlot); + + connect(entryMenu, &KsQuickContextMenu::addCPUPlot, + this, &KsTraceGraph::addCPUPlot); + + connect(entryMenu, &KsQuickContextMenu::removeTaskPlot, + this, &KsTraceGraph::removeTaskPlot); + + connect(entryMenu, &KsQuickContextMenu::removeCPUPlot, + this, &KsTraceGraph::removeCPUPlot); + } else { + cpu = _glWindow.getPlotCPU(point); + if (cpu >= 0) { + /* + * This is a CPU plot, but we do not have an entry + * under the cursor. + */ + KsRmCPUPlotMenu *rmMenu; + menu = rmMenu = new KsRmCPUPlotMenu(_mState, cpu, this); + + auto lamRmPlot = [&cpu, this] () { + removeCPUPlot(cpu); + }; + + connect(rmMenu, &KsRmPlotContextMenu::removePlot, + lamRmPlot); + } + + pid = _glWindow.getPlotPid(point); + if (pid >= 0) { + /* + * This is a Task plot, but we do not have an entry + * under the cursor. + */ + KsRmTaskPlotMenu *rmMenu; + menu = rmMenu = new KsRmTaskPlotMenu(_mState, pid, this); + + auto lamRmPlot = [&pid, this] () { + removeTaskPlot(pid); + }; + + connect(rmMenu, &KsRmPlotContextMenu::removePlot, + lamRmPlot); + } + } + + if (menu) { + connect(menu, &KsQuickMarkerMenu::deselect, + this, &KsTraceGraph::deselect); + + menu->exec(mapToGlobal(point)); + } +} diff --git a/kernel-shark-qt/src/KsTraceGraph.hpp b/kernel-shark-qt/src/KsTraceGraph.hpp index 395cc1b..c53258c 100644 --- a/kernel-shark-qt/src/KsTraceGraph.hpp +++ b/kernel-shark-qt/src/KsTraceGraph.hpp @@ -60,6 +60,10 @@ public: void addTaskPlot(int); + void removeCPUPlot(int); + + void removeTaskPlot(int); + void update(KsDataStore *data); void updateGeom(); @@ -68,6 +72,14 @@ public: bool eventFilter(QObject* obj, QEvent* evt) override; +signals: + /** + * This signal is emitted in the case of a right mouse button click or + * in the case of a double click over an empty area (no visible + * KernelShark entries). + */ + void deselect(); + private: void _zoomIn(); @@ -105,6 +117,8 @@ private: void _updateGraphs(GraphActions action); + void _onCustomContextMenu(const QPoint &point); + QToolBar _pointerBar, _navigationBar; QPushButton _zoomInButton, _quickZoomInButton; diff --git a/kernel-shark-qt/src/KsTraceViewer.cpp b/kernel-shark-qt/src/KsTraceViewer.cpp index 64c9fb7..d52d7e3 100644 --- a/kernel-shark-qt/src/KsTraceViewer.cpp +++ b/kernel-shark-qt/src/KsTraceViewer.cpp @@ -14,9 +14,22 @@ #include // KernelShark +#include "KsQuickContextMenu.hpp" #include "KsTraceViewer.hpp" #include "KsWidgetsLib.hpp" +/** + * Reimplemented handler for mouse press events. Right mouse click events will + * be ignored. This is done because we want the Right click is being used to + * open a Context menu. + */ +void KsTableView::mousePressEvent(QMouseEvent *e) { + if(e->button() == Qt::RightButton) + return; + + QTableView::mousePressEvent(e); +} + /** Create a default (empty) Trace viewer widget. */ KsTraceViewer::KsTraceViewer(QWidget *parent) : QWidget(parent), @@ -248,10 +261,13 @@ void KsTraceViewer::_onCustomContextMenu(const QPoint &point) * of the row number in the source model. */ size_t row = _proxyModel.mapRowFromSource(i.row()); - KsQuickEntryMenu menu(_data, row, this); + KsQuickContextMenu menu(_data, row, _mState, this); - connect(&menu, &KsQuickEntryMenu::plotTask, - this, &KsTraceViewer::plotTask); + connect(&menu, &KsQuickContextMenu::addTaskPlot, + this, &KsTraceViewer::addTaskPlot); + + connect(&menu, &KsQuickMarkerMenu::deselect, + this, &KsTraceViewer::deselect); menu.exec(mapToGlobal(point)); } @@ -424,8 +440,10 @@ void KsTraceViewer::_clicked(const QModelIndex& i) */ size_t row = _proxyModel.mapRowFromSource(i.row()); - _setSearchIterator(row); - _updateSearchCount(); + if (_searchDone && _matchList.count()) { + _setSearchIterator(row); + _updateSearchCount(); + } if (_graphFollows) emit select(row); // Send a signal to the Graph widget. @@ -460,7 +478,7 @@ void KsTraceViewer::showRow(size_t r, bool mark) } /** Deselects the selected items (row) if any. */ -void KsTraceViewer::deselect() +void KsTraceViewer::clearSelection() { _view.clearSelection(); } diff --git a/kernel-shark-qt/src/KsTraceViewer.hpp b/kernel-shark-qt/src/KsTraceViewer.hpp index 50c9115..4e35c17 100644 --- a/kernel-shark-qt/src/KsTraceViewer.hpp +++ b/kernel-shark-qt/src/KsTraceViewer.hpp @@ -20,6 +20,21 @@ #include "KsModels.hpp" #include "KsDualMarker.hpp" +/** + * Table View class, needed in order to reimplemented the handler for mouse + * press events. + */ +class KsTableView : public QTableView +{ + Q_OBJECT +public: + /** Create KsTableView. */ + explicit KsTableView(QWidget *parent = nullptr) + : QTableView(parent) {}; + + void mousePressEvent(QMouseEvent *event) override; +}; + /** * The KsTraceViewer class provides a widget for browsing in the trace data * shown in a text form. @@ -48,7 +63,7 @@ public: void showRow(size_t r, bool mark); - void deselect(); + void clearSelection(); void update(KsDataStore *data); @@ -57,15 +72,21 @@ signals: void select(size_t); /** - * This signal is used to re-emitted the plotTask signal of the - * KsQuickEntryMenu. + * This signal is used to re-emitted the addTaskPlot signal of the + * KsQuickContextMenu. */ - void plotTask(int pid); + void addTaskPlot(int pid); + + /** + * This signal is used to re-emitted the deselect signal of the + * KsQuickMarkerMenu. + */ + void deselect(); private: QVBoxLayout _layout; - QTableView _view; + KsTableView _view; KsViewModel _model; @@ -145,7 +166,6 @@ private: int _getSelectedDataRow(); private slots: - void _searchEdit(int); }; diff --git a/kernel-shark-qt/src/KsWidgetsLib.cpp b/kernel-shark-qt/src/KsWidgetsLib.cpp index 191ea7d..4b41f86 100644 --- a/kernel-shark-qt/src/KsWidgetsLib.cpp +++ b/kernel-shark-qt/src/KsWidgetsLib.cpp @@ -798,123 +798,3 @@ KsPluginCheckBoxWidget::KsPluginCheckBoxWidget(QStringList pluginList, _adjustSize(); } - -/** - * @brief Create KsQuickEntryMenu. - * - * @param data: Input location for the KsDataStore object. - * @param row: The index of the entry used to initialize the menu. - * @param parent: The parent of this widget. - */ -KsQuickEntryMenu::KsQuickEntryMenu(KsDataStore *data, size_t row, - QWidget *parent) -: QMenu("Entry menu", parent), - _data(data), - _row(row), - _hideTaskAction(this), - _showTaskAction(this), - _hideEventAction(this), - _showEventAction(this), - _addTaskPlotAction(this) -{ - QString descr; - - addSection("Quick Filter menu"); - - descr = "Hide task ["; - descr += kshark_get_task_easy(_data->rows()[_row]); - descr += "-"; - descr += QString("%1").arg(_data->rows()[_row]->pid); - descr += "]"; - - _hideTaskAction.setText(descr); - - connect(&_hideTaskAction, &QAction::triggered, - this, &KsQuickEntryMenu::_hideTask); - - addAction(&_hideTaskAction); - - descr = "Show task ["; - descr += kshark_get_task_easy(_data->rows()[_row]); - descr += "-"; - descr += QString("%1").arg(_data->rows()[_row]->pid); - descr += "] only"; - - _showTaskAction.setText(descr); - - connect(&_showTaskAction, &QAction::triggered, - this, &KsQuickEntryMenu::_showTask); - - addAction(&_showTaskAction); - - descr = "Hide event ["; - descr += kshark_get_event_name_easy(_data->rows()[_row]); - descr += "]"; - - _hideEventAction.setText(descr); - - connect(&_hideEventAction, &QAction::triggered, - this, &KsQuickEntryMenu::_hideEvent); - - addAction(&_hideEventAction); - - descr = "Show event ["; - descr += kshark_get_event_name_easy(_data->rows()[_row]); - descr += "] only"; - - _showEventAction.setText(descr); - - connect(&_showEventAction, &QAction::triggered, - this, &KsQuickEntryMenu::_showEvent); - - addAction(&_showEventAction); - - addSection("Quick Plot menu"); - descr = "Add ["; - descr += kshark_get_task_easy(_data->rows()[_row]); - descr += "-"; - descr += QString("%1").arg(_data->rows()[_row]->pid); - descr += "] plot"; - - _addTaskPlotAction.setText(descr); - - connect(&_addTaskPlotAction, &QAction::triggered, - this, &KsQuickEntryMenu::_addTaskPlot); - - addAction(&_addTaskPlotAction); -} - -void KsQuickEntryMenu::_hideTask() -{ - int pid = kshark_get_pid_easy(_data->rows()[_row]); - - _data->applyNegTaskFilter(QVector(1, pid)); -} - -void KsQuickEntryMenu::_showTask() -{ - int pid = kshark_get_pid_easy(_data->rows()[_row]); - - _data->applyPosTaskFilter(QVector(1, pid)); -} - -void KsQuickEntryMenu::_hideEvent() -{ - int eventId = kshark_get_event_id_easy(_data->rows()[_row]); - - _data->applyNegEventFilter(QVector(1, eventId)); -} - -void KsQuickEntryMenu::_showEvent() -{ - int eventId = kshark_get_event_id_easy(_data->rows()[_row]); - - _data->applyPosEventFilter(QVector(1, eventId)); -} - -void KsQuickEntryMenu::_addTaskPlot() -{ - int pid = kshark_get_pid_easy(_data->rows()[_row]); - - emit plotTask(pid); -} diff --git a/kernel-shark-qt/src/KsWidgetsLib.hpp b/kernel-shark-qt/src/KsWidgetsLib.hpp index c09bcd5..6f22374 100644 --- a/kernel-shark-qt/src/KsWidgetsLib.hpp +++ b/kernel-shark-qt/src/KsWidgetsLib.hpp @@ -347,48 +347,4 @@ struct KsPluginCheckBoxWidget : public KsCheckBoxTableWidget QWidget *parent = nullptr); }; -class KsDataStore; -class KsGLWidget; - -/** - * The KsQuickFilterMenu class provides a menu for easy filtering and plotting. - * The menu is initialized from a single kshark_entry and uses the content of - * this entry to provides quick actions for filtering and plottin. - */ -class KsQuickEntryMenu : public QMenu -{ - Q_OBJECT -public: - KsQuickEntryMenu() = delete; - - explicit KsQuickEntryMenu(KsDataStore *data, - size_t row, - QWidget *parent = nullptr); - -signals: - /** Signal to add a task plot. */ - void plotTask(int); - -private: - void _hideTask(); - - void _showTask(); - - void _hideEvent(); - - void _showEvent(); - - void _addTaskPlot(); - - KsDataStore *_data; - - size_t _row; - - QAction _hideTaskAction, _showTaskAction; - - QAction _hideEventAction, _showEventAction; - - QAction _addTaskPlotAction; -}; - #endif From patchwork Wed Nov 28 15:16:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760033 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728732AbeK2CS3 (ORCPT ); Wed, 28 Nov 2018 21:18:29 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 10/17] kernel-shark-qt: Add keyboard shortcuts for deselecting the marker Date: Wed, 28 Nov 2018 15:16:19 +0000 Message-ID: <20181128151530.21965-11-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 2212 The active marker can now be deselected by pressing "Ctrl + D". Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsMainWindow.cpp | 7 ++++++- kernel-shark-qt/src/KsMainWindow.hpp | 2 ++ kernel-shark-qt/src/KsQuickContextMenu.cpp | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel-shark-qt/src/KsMainWindow.cpp b/kernel-shark-qt/src/KsMainWindow.cpp index 5c9a0fa..f4804bd 100644 --- a/kernel-shark-qt/src/KsMainWindow.cpp +++ b/kernel-shark-qt/src/KsMainWindow.cpp @@ -65,7 +65,8 @@ KsMainWindow::KsMainWindow(QWidget *parent) _colorPhaseSlider(Qt::Horizontal, this), _fullScreenModeAction("Full Screen Mode", this), _aboutAction("About", this), - _contentsAction("Contents", this) + _contentsAction("Contents", this), + _deselectShortcut(this) { setWindowTitle("Kernel Shark"); _createActions(); @@ -114,6 +115,10 @@ KsMainWindow::KsMainWindow(QWidget *parent) connect(&_plugins, &KsPluginManager::dataReload, &_data, &KsDataStore::reload); + _deselectShortcut.setKey(Qt::CTRL + Qt::Key_D); + connect(&_deselectShortcut, &QShortcut::activated, + this, &KsMainWindow::_deselect); + _resizeEmpty(); } diff --git a/kernel-shark-qt/src/KsMainWindow.hpp b/kernel-shark-qt/src/KsMainWindow.hpp index b9b681f..5938a25 100644 --- a/kernel-shark-qt/src/KsMainWindow.hpp +++ b/kernel-shark-qt/src/KsMainWindow.hpp @@ -147,6 +147,8 @@ private: QAction _contentsAction; + QShortcut _deselectShortcut; + void _open(); void _restorSession(); diff --git a/kernel-shark-qt/src/KsQuickContextMenu.cpp b/kernel-shark-qt/src/KsQuickContextMenu.cpp index 0a8e527..16b8d19 100644 --- a/kernel-shark-qt/src/KsQuickContextMenu.cpp +++ b/kernel-shark-qt/src/KsQuickContextMenu.cpp @@ -26,6 +26,8 @@ KsQuickMarkerMenu::KsQuickMarkerMenu(KsDualMarkerSM *dm, QWidget *parent) if (dm->activeMarker()._isSet) { addSection("Marker menu"); _deselectAction.setText("Deselect"); + _deselectAction.setShortcut(tr("Ctrl+D")); + _deselectAction.setStatusTip(tr("Deselect marker")); connect(&_deselectAction, &QAction::triggered, this, &KsQuickMarkerMenu::deselect); From patchwork Wed Nov 28 15:16:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760057 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728754AbeK2CSa (ORCPT ); Wed, 28 Nov 2018 21:18:30 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 11/17] kernel-shark-qt: Sort all graphs before plotting Date: Wed, 28 Nov 2018 15:16:20 +0000 Message-ID: <20181128151530.21965-12-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: The CPU/Task graphs are plotted in sorted order. The graph having smallest CPU id/Pid will be plotted first (on top). Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsTraceGraph.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-shark-qt/src/KsTraceGraph.cpp b/kernel-shark-qt/src/KsTraceGraph.cpp index 09b322a..0b5a8b1 100644 --- a/kernel-shark-qt/src/KsTraceGraph.cpp +++ b/kernel-shark-qt/src/KsTraceGraph.cpp @@ -439,6 +439,7 @@ void KsTraceGraph::addCPUPlot(int cpu) return; _glWindow._cpuList.append(cpu); + qSort(_glWindow._cpuList); _selfUpdate(); } @@ -449,6 +450,7 @@ void KsTraceGraph::addTaskPlot(int pid) return; _glWindow._taskList.append(pid); + qSort(_glWindow._taskList); _selfUpdate(); } From patchwork Wed Nov 28 15:16:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760041 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728732AbeK2CSe (ORCPT ); Wed, 28 Nov 2018 21:18:34 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 12/17] kernel-shark-qt: Add CPU-based filtering to the C API Date: Wed, 28 Nov 2018 15:16:22 +0000 Message-ID: <20181128151530.21965-13-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 5612 This patch adds "Show CPU" and "Hide CPU" filters to the C API of KernelShark. The implementation of those filters follows the pattern used to implement the Task (pid) and Event filters. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/libkshark.c | 37 +++++++++++++++++++++++++++++++++ kernel-shark-qt/src/libkshark.h | 17 +++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/kernel-shark-qt/src/libkshark.c b/kernel-shark-qt/src/libkshark.c index b4b3d5b..86d3e58 100644 --- a/kernel-shark-qt/src/libkshark.c +++ b/kernel-shark-qt/src/libkshark.c @@ -41,6 +41,9 @@ static bool kshark_default_context(struct kshark_context **context) kshark_ctx->show_event_filter = tracecmd_filter_id_hash_alloc(); kshark_ctx->hide_event_filter = tracecmd_filter_id_hash_alloc(); + kshark_ctx->show_cpu_filter = tracecmd_filter_id_hash_alloc(); + kshark_ctx->hide_cpu_filter = tracecmd_filter_id_hash_alloc(); + kshark_ctx->filter_mask = 0x0; /* Will free kshark_context_handler. */ @@ -180,6 +183,8 @@ void kshark_close(struct kshark_context *kshark_ctx) 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_filter_id_clear(kshark_ctx->show_cpu_filter); + tracecmd_filter_id_clear(kshark_ctx->hide_cpu_filter); if (kshark_ctx->advanced_event_filter) { tep_filter_reset(kshark_ctx->advanced_event_filter); @@ -226,6 +231,9 @@ void kshark_free(struct kshark_context *kshark_ctx) tracecmd_filter_id_hash_free(kshark_ctx->show_event_filter); tracecmd_filter_id_hash_free(kshark_ctx->hide_event_filter); + tracecmd_filter_id_hash_free(kshark_ctx->show_cpu_filter); + tracecmd_filter_id_hash_free(kshark_ctx->hide_cpu_filter); + if (kshark_ctx->plugins) { kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_CLOSE); kshark_free_plugin_list(kshark_ctx->plugins); @@ -366,6 +374,12 @@ static bool kshark_show_event(struct kshark_context *kshark_ctx, int pid) filter_find(kshark_ctx->hide_event_filter, pid, false); } +static bool kshark_show_cpu(struct kshark_context *kshark_ctx, int cpu) +{ + return filter_find(kshark_ctx->show_cpu_filter, cpu, true) && + filter_find(kshark_ctx->hide_cpu_filter, cpu, false); +} + /** * @brief Add an Id value to the filster specified by "filter_id". * @@ -379,6 +393,12 @@ void kshark_filter_add_id(struct kshark_context *kshark_ctx, struct tracecmd_filter_id *filter; switch (filter_id) { + case KS_SHOW_CPU_FILTER: + filter = kshark_ctx->show_cpu_filter; + break; + case KS_HIDE_CPU_FILTER: + filter = kshark_ctx->hide_cpu_filter; + break; case KS_SHOW_EVENT_FILTER: filter = kshark_ctx->show_event_filter; break; @@ -409,6 +429,12 @@ void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id) struct tracecmd_filter_id *filter; switch (filter_id) { + case KS_SHOW_CPU_FILTER: + filter = kshark_ctx->show_cpu_filter; + break; + case KS_HIDE_CPU_FILTER: + filter = kshark_ctx->hide_cpu_filter; + break; case KS_SHOW_EVENT_FILTER: filter = kshark_ctx->show_event_filter; break; @@ -444,6 +470,8 @@ bool kshark_filter_is_set(struct kshark_context *kshark_ctx) { return filter_is_set(kshark_ctx->show_task_filter) || filter_is_set(kshark_ctx->hide_task_filter) || + filter_is_set(kshark_ctx->show_cpu_filter) || + filter_is_set(kshark_ctx->hide_cpu_filter) || filter_is_set(kshark_ctx->show_event_filter) || filter_is_set(kshark_ctx->hide_event_filter); } @@ -505,6 +533,10 @@ void kshark_filter_entries(struct kshark_context *kshark_ctx, if (!kshark_show_event(kshark_ctx, data[i]->event_id)) unset_event_filter_flag(kshark_ctx, data[i]); + /* Apply CPU filtering. */ + if (!kshark_show_cpu(kshark_ctx, data[i]->cpu)) + data[i]->visible &= ~kshark_ctx->filter_mask; + /* Apply task filtering. */ if (!kshark_show_task(kshark_ctx, data[i]->pid)) data[i]->visible &= ~kshark_ctx->filter_mask; @@ -732,6 +764,11 @@ static size_t get_records(struct kshark_context *kshark_ctx, unset_event_filter_flag(kshark_ctx, entry); } + /* Apply CPU filtering. */ + if (!kshark_show_cpu(kshark_ctx, entry->pid)) { + entry->visible &= ~kshark_ctx->filter_mask; + } + /* Apply task filtering. */ if (!kshark_show_task(kshark_ctx, entry->pid)) { entry->visible &= ~kshark_ctx->filter_mask; diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h index b94bdc3..eb8c261 100644 --- a/kernel-shark-qt/src/libkshark.h +++ b/kernel-shark-qt/src/libkshark.h @@ -110,6 +110,12 @@ struct kshark_context { /** Hash of events to not display. */ struct tracecmd_filter_id *hide_event_filter; + /** Hash of CPUs to filter on. */ + struct tracecmd_filter_id *show_cpu_filter; + + /** Hash of CPUs to not display. */ + struct tracecmd_filter_id *hide_cpu_filter; + /** * Bit mask, controlling the visibility of the entries after filtering. * If given bit is set here, all entries which are filtered-out will @@ -232,6 +238,17 @@ enum kshark_filter_type { * filtered-out. */ KS_HIDE_TASK_FILTER, + + /** + * Identifier of the filter, used to specified the CPUs to be shown. + */ + KS_SHOW_CPU_FILTER, + + /** + * Identifier of the filter, used to specified the CPUs to be + * filtered-out. + */ + KS_HIDE_CPU_FILTER, }; void kshark_filter_add_id(struct kshark_context *kshark_ctx, From patchwork Wed Nov 28 15:16:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760047 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728413AbeK2CSf (ORCPT ); Wed, 28 Nov 2018 21:18:35 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 13/17] kernel-shark-qt: Add CPU-based filtering to KsDataStore Date: Wed, 28 Nov 2018 15:16:23 +0000 Message-ID: <20181128151530.21965-14-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 1957 This patch adds to the KsDataStore class methods for CPU filtering. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsUtils.cpp | 21 +++++++++++++++++++-- kernel-shark-qt/src/KsUtils.hpp | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kernel-shark-qt/src/KsUtils.cpp b/kernel-shark-qt/src/KsUtils.cpp index c0e0f7d..2ebbae3 100644 --- a/kernel-shark-qt/src/KsUtils.cpp +++ b/kernel-shark-qt/src/KsUtils.cpp @@ -269,12 +269,17 @@ void KsDataStore::_applyIdFilter(int filterId, QVector vec) kshark_filter_clear(kshark_ctx, KS_SHOW_TASK_FILTER); kshark_filter_clear(kshark_ctx, KS_HIDE_TASK_FILTER); break; + case KS_SHOW_CPU_FILTER: + case KS_HIDE_CPU_FILTER: + kshark_filter_clear(kshark_ctx, KS_SHOW_CPU_FILTER); + kshark_filter_clear(kshark_ctx, KS_HIDE_CPU_FILTER); + break; default: return; } - for (auto &&pid: vec) - kshark_filter_add_id(kshark_ctx, filterId, pid); + for (auto &&val: vec) + kshark_filter_add_id(kshark_ctx, filterId, val); if (!_tep) return; @@ -319,6 +324,18 @@ void KsDataStore::applyNegEventFilter(QVector vec) _applyIdFilter(KS_HIDE_EVENT_FILTER, vec); } +/** Apply Show CPU filter. */ +void KsDataStore::applyPosCPUFilter(QVector vec) +{ + _applyIdFilter(KS_SHOW_CPU_FILTER, vec); +} + +/** Apply Hide CPU filter. */ +void KsDataStore::applyNegCPUFilter(QVector vec) +{ + _applyIdFilter(KS_HIDE_CPU_FILTER, vec); +} + /** Disable all filters. */ void KsDataStore::clearAllFilters() { diff --git a/kernel-shark-qt/src/KsUtils.hpp b/kernel-shark-qt/src/KsUtils.hpp index 888ed56..052cc71 100644 --- a/kernel-shark-qt/src/KsUtils.hpp +++ b/kernel-shark-qt/src/KsUtils.hpp @@ -156,6 +156,10 @@ public: void applyNegEventFilter(QVector); + void applyPosCPUFilter(QVector); + + void applyNegCPUFilter(QVector); + void clearAllFilters(); signals: From patchwork Wed Nov 28 15:16:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760059 Return-Path: Received: from mail-eopbgr710043.outbound.protection.outlook.com ([40.107.71.43]:7840 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728732AbeK2CSs (ORCPT ); Wed, 28 Nov 2018 21:18:48 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 14/17] kernel-shark-qt: Add Hide CPU action to the Quick Context Menu Date: Wed, 28 Nov 2018 15:16:25 +0000 Message-ID: <20181128151530.21965-15-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 2729 Now the Quick Context Menu can be used to hide all data from a CPU core. The CPU Id value is added to the list of CPUs to be filtered-out. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsQuickContextMenu.cpp | 26 ++++++++++++++++++++++ kernel-shark-qt/src/KsQuickContextMenu.hpp | 6 +++++ 2 files changed, 32 insertions(+) diff --git a/kernel-shark-qt/src/KsQuickContextMenu.cpp b/kernel-shark-qt/src/KsQuickContextMenu.cpp index 16b8d19..95ffc4f 100644 --- a/kernel-shark-qt/src/KsQuickContextMenu.cpp +++ b/kernel-shark-qt/src/KsQuickContextMenu.cpp @@ -54,6 +54,7 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row, _showTaskAction(this), _hideEventAction(this), _showEventAction(this), + _hideCPUAction(this), _addCPUPlotAction(this), _addTaskPlotAction(this), _removeCPUPlotAction(this), @@ -108,6 +109,9 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row, descr += "] only"; lamAddAction(&_showEventAction, &KsQuickContextMenu::_showEvent); + descr = QString("Hide CPU [%1]").arg(_data->rows()[_row]->cpu); + lamAddAction(&_hideCPUAction, &KsQuickContextMenu::_hideCPU); + if (parentName == "KsTraceViewer") { descr = "Add ["; descr += taskName; @@ -194,6 +198,28 @@ void KsQuickContextMenu::_showEvent() _data->applyPosEventFilter(QVector(1, eventId)); } +void KsQuickContextMenu::_hideCPU() +{ + kshark_context *kshark_ctx(nullptr); + QVector vec; + + if (!kshark_instance(&kshark_ctx)) + return; + + vec =_getFilterVector(kshark_ctx->hide_cpu_filter, + _data->rows()[_row]->cpu); + _data->applyNegCPUFilter(vec); +} + +QVector KsQuickContextMenu::_getFilterVector(tracecmd_filter_id *filter, int newId) +{ + QVector vec = KsUtils::getFilterIds(filter); + if (!vec.contains(newId)) + vec.append(newId); + + return vec; +} + void KsQuickContextMenu::_addTaskPlot() { int pid = kshark_get_pid_easy(_data->rows()[_row]); diff --git a/kernel-shark-qt/src/KsQuickContextMenu.hpp b/kernel-shark-qt/src/KsQuickContextMenu.hpp index 040942f..6ca1b08 100644 --- a/kernel-shark-qt/src/KsQuickContextMenu.hpp +++ b/kernel-shark-qt/src/KsQuickContextMenu.hpp @@ -71,6 +71,8 @@ private: void _showEvent(); + void _hideCPU(); + void _addCPUPlot(); void _addTaskPlot(); @@ -79,6 +81,8 @@ private: void _removeTaskPlot(); + QVector _getFilterVector(tracecmd_filter_id *filter, int newId); + KsDataStore *_data; size_t _row; @@ -87,6 +91,8 @@ private: QAction _hideEventAction, _showEventAction; + QAction _hideCPUAction; + QAction _addCPUPlotAction; QAction _addTaskPlotAction; From patchwork Wed Nov 28 15:16:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760051 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728413AbeK2CSi (ORCPT ); Wed, 28 Nov 2018 21:18:38 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 15/17] kernel-shark-qt: Add the CPU filters to the Json config I/O Date: Wed, 28 Nov 2018 15:16:26 +0000 Message-ID: <20181128151530.21965-16-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 10927 This patch adds "Show CPU" and "Hide CPU" filters to the Json config I/O, making possible to import/export those filters. Saving/loading the CPU filters reuses some of the code used so far by the Task filters. Because of this some functions have been renamed. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/libkshark-configio.c | 133 +++++++++++++++++------ kernel-shark-qt/src/libkshark.h | 28 ++++- 2 files changed, 123 insertions(+), 38 deletions(-) diff --git a/kernel-shark-qt/src/libkshark-configio.c b/kernel-shark-qt/src/libkshark-configio.c index bf2a08b..a426e48 100644 --- a/kernel-shark-qt/src/libkshark-configio.c +++ b/kernel-shark-qt/src/libkshark-configio.c @@ -870,20 +870,20 @@ bool kshark_import_event_filter(struct tep_handle *pevent, } } -static bool kshark_task_filter_to_json(struct tracecmd_filter_id *filter, - const char *filter_name, - struct json_object *jobj) +static bool kshark_filter_array_to_json(struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) { json_object *jfilter_data, *jpid = NULL; int i, *ids; /* - * If this Json document already contains a description of the model, + * If this Json document already contains a description of the filter, * delete this description. */ json_del_if_exist(jobj, filter_name); - /* Get the array of Ids to be fitered. */ + /* Get the array of Ids to be filtered. */ ids = tracecmd_filter_ids(filter); if (!ids) return true; @@ -918,7 +918,7 @@ static bool kshark_task_filter_to_json(struct tracecmd_filter_id *filter, } /** - * @brief Record the current configuration of a Task Id filter into a + * @brief Record the current configuration of a simple Id filter into a * Configuration document. * * @param filter: Input location for an Id filter. @@ -928,14 +928,14 @@ static bool kshark_task_filter_to_json(struct tracecmd_filter_id *filter, * * @returns True on success, otherwise False. */ -bool kshark_export_task_filter(struct tracecmd_filter_id *filter, - const char *filter_name, - struct kshark_config_doc *conf) +bool kshark_export_filter_array(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) { switch (conf->format) { case KS_CONFIG_JSON: - return kshark_task_filter_to_json(filter, filter_name, - conf->conf_doc); + return kshark_filter_array_to_json(filter, filter_name, + conf->conf_doc); default: fprintf(stderr, "Document format %d not supported\n", @@ -944,9 +944,9 @@ bool kshark_export_task_filter(struct tracecmd_filter_id *filter, } } -static bool kshark_task_filter_from_json(struct tracecmd_filter_id *filter, - const char *filter_name, - struct json_object *jobj) +static bool kshark_filter_array_from_json(struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) { json_object *jfilter, *jpid; int i, length; @@ -981,7 +981,8 @@ static bool kshark_task_filter_from_json(struct tracecmd_filter_id *filter, } /** - * @brief Load from Configuration document the configuration of a Task Id filter. + * @brief Load from Configuration document the configuration of a simple + * Id filter. * * @param filter: Input location for an Id filter. * @param filter_name: The name of the filter as showing up in the Config. @@ -993,14 +994,14 @@ static bool kshark_task_filter_from_json(struct tracecmd_filter_id *filter, * document contains no data for this particular filter or in a case * of an error, the function returns False. */ -bool kshark_import_task_filter(struct tracecmd_filter_id *filter, - const char *filter_name, - struct kshark_config_doc *conf) +bool kshark_import_filter_array(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) { switch (conf->format) { case KS_CONFIG_JSON: - return kshark_task_filter_from_json(filter, filter_name, - conf->conf_doc); + return kshark_filter_array_from_json(filter, filter_name, + conf->conf_doc); default: fprintf(stderr, "Document format %d not supported\n", @@ -1269,14 +1270,52 @@ bool kshark_export_all_task_filters(struct kshark_context *kshark_ctx, /* Save a filter only if it contains Id values. */ if (filter_is_set(kshark_ctx->show_task_filter)) - ret &= kshark_export_task_filter(kshark_ctx->show_task_filter, - KS_SHOW_TASK_FILTER_NAME, - *conf); + ret &= kshark_export_filter_array(kshark_ctx->show_task_filter, + KS_SHOW_TASK_FILTER_NAME, + *conf); if (filter_is_set(kshark_ctx->hide_task_filter)) - ret &= kshark_export_task_filter(kshark_ctx->hide_task_filter, - KS_HIDE_TASK_FILTER_NAME, - *conf); + ret &= kshark_export_filter_array(kshark_ctx->hide_task_filter, + KS_HIDE_TASK_FILTER_NAME, + *conf); + + return ret; +} + + +/** + * @brief Record the current configuration of "show cpu" and "hide cpu" + * filters into a Configuration document. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. If NULL, a new Filter + * Configuration document will be created. + * + * @returns True, if a filter has been recorded. If both filters contain + * no Id values or in a case of an error, the function returns False. + */ +bool kshark_export_all_cpu_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf) +{ + bool ret = true; + + if (!*conf) + *conf = kshark_filter_config_new(KS_CONFIG_JSON); + + if (!*conf) + return false; + + /* Save a filter only if it contains Id values. */ + if (filter_is_set(kshark_ctx->show_task_filter)) + ret &= kshark_export_filter_array(kshark_ctx->show_cpu_filter, + KS_SHOW_CPU_FILTER_NAME, + *conf); + + if (filter_is_set(kshark_ctx->hide_task_filter)) + ret &= kshark_export_filter_array(kshark_ctx->hide_cpu_filter, + KS_HIDE_CPU_FILTER_NAME, + *conf); return ret; } @@ -1328,13 +1367,41 @@ bool kshark_import_all_task_filters(struct kshark_context *kshark_ctx, { bool ret = false; - ret |= kshark_import_task_filter(kshark_ctx->hide_task_filter, - KS_HIDE_TASK_FILTER_NAME, - conf); + ret |= kshark_import_filter_array(kshark_ctx->hide_task_filter, + KS_HIDE_TASK_FILTER_NAME, + conf); + + ret |= kshark_import_filter_array(kshark_ctx->show_task_filter, + KS_SHOW_TASK_FILTER_NAME, + conf); + + return ret; +} + +/** + * @brief Load from Configuration document the configuration of "show cpu" + * and "hide cpu" filters. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for any cpu filter or in a case of an + * error, the function returns False. + */ +bool kshark_import_all_cpu_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + bool ret = false; + + ret |= kshark_import_filter_array(kshark_ctx->hide_cpu_filter, + KS_HIDE_CPU_FILTER_NAME, + conf); - ret |= kshark_import_task_filter(kshark_ctx->show_task_filter, - KS_SHOW_TASK_FILTER_NAME, - conf); + ret |= kshark_import_filter_array(kshark_ctx->show_cpu_filter, + KS_SHOW_CPU_FILTER_NAME, + conf); return ret; } @@ -1362,6 +1429,7 @@ kshark_export_all_filters(struct kshark_context *kshark_ctx, if (!conf || !kshark_export_all_event_filters(kshark_ctx, &conf) || !kshark_export_all_task_filters(kshark_ctx, &conf) || + !kshark_export_all_cpu_filters(kshark_ctx, &conf) || !kshark_export_adv_filters(kshark_ctx, &conf)) { kshark_free_config_doc(conf); return NULL; @@ -1386,6 +1454,7 @@ bool kshark_import_all_filters(struct kshark_context *kshark_ctx, { bool ret; ret = kshark_import_all_task_filters(kshark_ctx, conf); + ret |= kshark_import_all_cpu_filters(kshark_ctx, conf); ret |= kshark_import_all_event_filters(kshark_ctx, conf); ret |= kshark_import_adv_filters(kshark_ctx, conf); diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h index eb8c261..6a3eba6 100644 --- a/kernel-shark-qt/src/libkshark.h +++ b/kernel-shark-qt/src/libkshark.h @@ -488,6 +488,16 @@ enum kshark_config_formats { */ #define KS_SHOW_TASK_FILTER_NAME "show task filter" +/** + * Field name for the Configuration document describing the Hide Task filter. + */ +#define KS_HIDE_CPU_FILTER_NAME "hide cpu filter" + +/** + * Field name for the Configuration document describing the Show Task filter. + */ +#define KS_SHOW_CPU_FILTER_NAME "show cpu filter" + /** * Field name for the Configuration document describing the Advanced event * filter. @@ -565,13 +575,13 @@ bool kshark_import_event_filter(struct tep_handle *pevent, const char *filter_name, struct kshark_config_doc *conf); -bool kshark_export_task_filter(struct tracecmd_filter_id *filter, - const char *filter_name, - struct kshark_config_doc *conf); +bool kshark_export_filter_array(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); -bool kshark_import_task_filter(struct tracecmd_filter_id *filter, - const char *filter_name, - struct kshark_config_doc *conf); +bool kshark_import_filter_array(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); bool kshark_export_all_event_filters(struct kshark_context *kshark_ctx, struct kshark_config_doc **conf); @@ -579,6 +589,9 @@ bool kshark_export_all_event_filters(struct kshark_context *kshark_ctx, bool kshark_export_all_task_filters(struct kshark_context *kshark_ctx, struct kshark_config_doc **conf); +bool kshark_export_all_cpu_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf); + struct kshark_config_doc * kshark_export_all_filters(struct kshark_context *kshark_ctx, enum kshark_config_formats format); @@ -589,6 +602,9 @@ bool kshark_import_all_event_filters(struct kshark_context *kshark_ctx, bool kshark_import_all_task_filters(struct kshark_context *kshark_ctx, struct kshark_config_doc *conf); +bool kshark_import_all_cpu_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + bool kshark_import_all_filters(struct kshark_context *kshark_ctx, struct kshark_config_doc *conf); From patchwork Wed Nov 28 15:16:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760061 Return-Path: Received: from mail-eopbgr710075.outbound.protection.outlook.com ([40.107.71.75]:2944 "EHLO NAM05-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728413AbeK2CSw (ORCPT ); Wed, 28 Nov 2018 21:18:52 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 16/17] kernel-shark-qt: Add "Hide CPU" checkbox dialog to the Main window menu Date: Wed, 28 Nov 2018 15:16:27 +0000 Message-ID: <20181128151530.21965-17-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 3020 "Hide CPU" checkbox dialog is added to Menu/Filtering. This dialog is complementary to the "Hide CPU" action of the Quick Context Menu. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsMainWindow.cpp | 39 ++++++++++++++++++++++++++++ kernel-shark-qt/src/KsMainWindow.hpp | 4 +++ 2 files changed, 43 insertions(+) diff --git a/kernel-shark-qt/src/KsMainWindow.cpp b/kernel-shark-qt/src/KsMainWindow.cpp index f4804bd..16ba8bb 100644 --- a/kernel-shark-qt/src/KsMainWindow.cpp +++ b/kernel-shark-qt/src/KsMainWindow.cpp @@ -54,6 +54,7 @@ KsMainWindow::KsMainWindow(QWidget *parent) _showEventsAction("Show events", this), _showTasksAction("Show tasks", this), _hideTasksAction("Hide tasks", this), + _hideCPUsAction("Hide CPUs", this), _advanceFilterAction("Advance Filtering", this), _clearAllFilters("Clear all filters", this), _cpuSelectAction("CPUs", this), @@ -207,6 +208,9 @@ void KsMainWindow::_createActions() connect(&_hideTasksAction, &QAction::triggered, this, &KsMainWindow::_hideTasks); + connect(&_hideCPUsAction, &QAction::triggered, + this, &KsMainWindow::_hideCPUs); + connect(&_advanceFilterAction, &QAction::triggered, this, &KsMainWindow::_advancedFiltering); @@ -329,6 +333,7 @@ void KsMainWindow::_createMenus() filter->addAction(&_showEventsAction); filter->addAction(&_showTasksAction); filter->addAction(&_hideTasksAction); + filter->addAction(&_hideCPUsAction); filter->addAction(&_advanceFilterAction); filter->addAction(&_clearAllFilters); @@ -603,6 +608,40 @@ void KsMainWindow::_hideTasks() dialog->show(); } +void KsMainWindow::_hideCPUs() +{ + kshark_context *kshark_ctx(nullptr); + KsCheckBoxWidget *cpu_cbd; + KsCheckBoxDialog *dialog; + + if (!kshark_instance(&kshark_ctx)) + return; + + cpu_cbd = new KsCPUCheckBoxWidget(_data.tep(), this); + dialog = new KsCheckBoxDialog(cpu_cbd, this); + + if (!kshark_ctx->hide_cpu_filter || + !kshark_ctx->hide_cpu_filter->count) { + cpu_cbd->setDefault(false); + } else { + int nCPUs = tep_get_cpus(_data.tep()); + QVector v(nCPUs, false); + + for (int i = 0; i < nCPUs; ++i) { + if (tracecmd_filter_id_find(kshark_ctx->hide_cpu_filter, + i)) + v[i] = true; + } + + cpu_cbd->set(v); + } + + connect(dialog, &KsCheckBoxDialog::apply, + &_data, &KsDataStore::applyNegCPUFilter); + + dialog->show(); +} + void KsMainWindow::_advancedFiltering() { KsAdvFilteringDialog *dialog; diff --git a/kernel-shark-qt/src/KsMainWindow.hpp b/kernel-shark-qt/src/KsMainWindow.hpp index 5938a25..b231b52 100644 --- a/kernel-shark-qt/src/KsMainWindow.hpp +++ b/kernel-shark-qt/src/KsMainWindow.hpp @@ -120,6 +120,8 @@ private: QAction _hideTasksAction; + QAction _hideCPUsAction; + QAction _advanceFilterAction; QAction _clearAllFilters; @@ -171,6 +173,8 @@ private: void _hideTasks(); + void _hideCPUs(); + void _advancedFiltering(); void _clearFilters(); From patchwork Wed Nov 28 15:16:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10760053 Return-Path: Received: from mail-eopbgr680061.outbound.protection.outlook.com ([40.107.68.61]:18880 "EHLO NAM04-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728754AbeK2CSi (ORCPT ); Wed, 28 Nov 2018 21:18:38 -0500 From: Yordan Karadzhov To: "rostedt@goodmis.org" CC: "linux-trace-devel@vger.kernel.org" Subject: [PATCH 17/17] kernel-shark-qt: Add the user filter mask to the Json config I/O Date: Wed, 28 Nov 2018 15:16:29 +0000 Message-ID: <20181128151530.21965-18-ykaradzhov@vmware.com> References: <20181128151530.21965-1-ykaradzhov@vmware.com> In-Reply-To: <20181128151530.21965-1-ykaradzhov@vmware.com> Content-Language: en-US MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 9186 This patch updates the Json config I/O, making possible to import/export the value of the user filter mask. When the filters are imported, the states of the "Apply filters to Graph" and "Apply filters to List" check-boxes are updated accordingly. Signed-off-by: Yordan Karadzhov --- kernel-shark-qt/src/KsMainWindow.cpp | 35 ++++++--- kernel-shark-qt/src/KsMainWindow.hpp | 6 ++ kernel-shark-qt/src/libkshark-configio.c | 99 ++++++++++++++++++++++++ kernel-shark-qt/src/libkshark.h | 11 +++ 4 files changed, 142 insertions(+), 9 deletions(-) diff --git a/kernel-shark-qt/src/KsMainWindow.cpp b/kernel-shark-qt/src/KsMainWindow.cpp index 16ba8bb..7213c01 100644 --- a/kernel-shark-qt/src/KsMainWindow.cpp +++ b/kernel-shark-qt/src/KsMainWindow.cpp @@ -50,7 +50,9 @@ KsMainWindow::KsMainWindow(QWidget *parent) _importFilterAction("Import Filter", this), _exportFilterAction("Export Filter", this), _graphFilterSyncAction(this), + _graphFilterSyncCBox(nullptr), _listFilterSyncAction(this), + _listFilterSyncCBox(nullptr), _showEventsAction("Show events", this), _showTasksAction("Show tasks", this), _hideTasksAction("Hide tasks", this), @@ -273,7 +275,6 @@ void KsMainWindow::_createMenus() { QMenu *file, *sessions, *filter, *plots, *tools, *help; kshark_context *kshark_ctx(nullptr); - QCheckBox *cbf2g, *cbf2l; if (!kshark_instance(&kshark_ctx)) return; @@ -316,17 +317,17 @@ void KsMainWindow::_createMenus() kshark_ctx->filter_mask |= KS_EVENT_VIEW_FILTER_MASK; - cbf2g = lamMakeCBAction(&_graphFilterSyncAction, - "Apply filters to Graph"); + _graphFilterSyncCBox = lamMakeCBAction(&_graphFilterSyncAction, + "Apply filters to Graph"); - connect(cbf2g, &QCheckBox::stateChanged, - this, &KsMainWindow::_graphFilterSync); + connect(_graphFilterSyncCBox, &QCheckBox::stateChanged, + this, &KsMainWindow::_graphFilterSync); - cbf2l = lamMakeCBAction(&_listFilterSyncAction, - "Apply filters to List"); + _listFilterSyncCBox = lamMakeCBAction(&_listFilterSyncAction, + "Apply filters to List"); - connect(cbf2l, &QCheckBox::stateChanged, - this, &KsMainWindow::_listFilterSync); + connect(_listFilterSyncCBox, &QCheckBox::stateChanged, + this, &KsMainWindow::_listFilterSync); filter->addAction(&_graphFilterSyncAction); filter->addAction(&_listFilterSyncAction); @@ -431,6 +432,20 @@ void KsMainWindow::_exportSession() _session.exportToFile(fileName); } +void KsMainWindow::_filterSyncCBoxUpdate(kshark_context *kshark_ctx) +{ + if (kshark_ctx->filter_mask & KS_TEXT_VIEW_FILTER_MASK) + _listFilterSyncCBox->setChecked(true); + else + _listFilterSyncCBox->setChecked(false); + + if (kshark_ctx->filter_mask & + (KS_GRAPH_VIEW_FILTER_MASK | KS_EVENT_VIEW_FILTER_MASK)) + _graphFilterSyncCBox->setChecked(true); + else + _graphFilterSyncCBox->setChecked(false); +} + void KsMainWindow::_importFilter() { kshark_context *kshark_ctx(nullptr); @@ -455,6 +470,7 @@ void KsMainWindow::_importFilter() kshark_free_config_doc(conf); kshark_filter_entries(kshark_ctx, _data.rows(), _data.size()); + _filterSyncCBoxUpdate(kshark_ctx); emit _data.updateWidgets(&_data); } @@ -960,6 +976,7 @@ void KsMainWindow::loadSession(const QString &fileName) pb.setValue(20); _session.loadFilters(kshark_ctx, &_data); + _filterSyncCBoxUpdate(kshark_ctx); pb.setValue(130); _session.loadSplitterSize(&_splitter); diff --git a/kernel-shark-qt/src/KsMainWindow.hpp b/kernel-shark-qt/src/KsMainWindow.hpp index b231b52..72f7059 100644 --- a/kernel-shark-qt/src/KsMainWindow.hpp +++ b/kernel-shark-qt/src/KsMainWindow.hpp @@ -112,8 +112,12 @@ private: QWidgetAction _graphFilterSyncAction; + QCheckBox *_graphFilterSyncCBox; + QWidgetAction _listFilterSyncAction; + QCheckBox *_listFilterSyncCBox; + QAction _showEventsAction; QAction _showTasksAction; @@ -218,6 +222,8 @@ private: void _deselect(); + void _filterSyncCBoxUpdate(kshark_context *kshark_ctx); + private slots: void _captureFinished(int, QProcess::ExitStatus); }; diff --git a/kernel-shark-qt/src/libkshark-configio.c b/kernel-shark-qt/src/libkshark-configio.c index a426e48..4fe7de3 100644 --- a/kernel-shark-qt/src/libkshark-configio.c +++ b/kernel-shark-qt/src/libkshark-configio.c @@ -1201,6 +1201,103 @@ bool kshark_import_adv_filters(struct kshark_context *kshark_ctx, } } +static bool kshark_user_mask_to_json(struct kshark_context *kshark_ctx, + struct json_object *jobj) +{ + uint8_t mask = kshark_ctx->filter_mask; + json_object *jmask; + + jmask = json_object_new_int((int) mask); + if (!jmask) + return false; + + /* Add the mask to the filter config document. */ + json_object_object_add(jobj, KS_USER_FILTER_MASK_NAME, jmask); + return true; +} + +/** + * @brief Record the current value of the the user-specified filter mask into + * a Configuration document. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. If NULL, a new Adv. Filter + * Configuration document will be created. + * + * @returns True on success, otherwise False. + */ +bool kshark_export_user_mask(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf) +{ + if (!*conf) + *conf = kshark_filter_config_new(KS_CONFIG_JSON); + + if (!*conf) + return false; + + switch ((*conf)->format) { + case KS_CONFIG_JSON: + return kshark_user_mask_to_json(kshark_ctx, + (*conf)->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + (*conf)->format); + return false; + } +} + +static bool kshark_user_mask_from_json(struct kshark_context *kshark_ctx, + struct json_object *jobj) +{ + json_object *jmask; + uint8_t mask; + + if (!kshark_json_type_check(jobj, "kshark.config.filter")) + return false; + /* + * Use the name of the filter to find the value of the filter maks. + * Notice that the filter config document may contain no data for + * the mask. + */ + if (!json_object_object_get_ex(jobj, KS_USER_FILTER_MASK_NAME, + &jmask)) + return false; + + mask = json_object_get_int(jmask); + kshark_ctx->filter_mask = mask; + + return true; +} + +/** + * @brief Load from Configuration document the value of the user-specified + * filter mask. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a mask has been loaded. If the filter configuration + * document contains no data for the mask or in a case of an error, + * the function returns False. + */ +bool kshark_import_user_mask(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_user_mask_from_json(kshark_ctx, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + static bool filter_is_set(struct tracecmd_filter_id *filter) { return filter && filter->count; @@ -1430,6 +1527,7 @@ kshark_export_all_filters(struct kshark_context *kshark_ctx, !kshark_export_all_event_filters(kshark_ctx, &conf) || !kshark_export_all_task_filters(kshark_ctx, &conf) || !kshark_export_all_cpu_filters(kshark_ctx, &conf) || + !kshark_export_user_mask(kshark_ctx, &conf) || !kshark_export_adv_filters(kshark_ctx, &conf)) { kshark_free_config_doc(conf); return NULL; @@ -1456,6 +1554,7 @@ bool kshark_import_all_filters(struct kshark_context *kshark_ctx, ret = kshark_import_all_task_filters(kshark_ctx, conf); ret |= kshark_import_all_cpu_filters(kshark_ctx, conf); ret |= kshark_import_all_event_filters(kshark_ctx, conf); + ret |= kshark_import_user_mask(kshark_ctx, conf); ret |= kshark_import_adv_filters(kshark_ctx, conf); return ret; diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h index 6a3eba6..b3bd646 100644 --- a/kernel-shark-qt/src/libkshark.h +++ b/kernel-shark-qt/src/libkshark.h @@ -504,6 +504,11 @@ enum kshark_config_formats { */ #define KS_ADV_EVENT_FILTER_NAME "adv event filter" +/** + * Field name for the Configuration document describing user-specified filter + * mask. + */ +#define KS_USER_FILTER_MASK_NAME "filter mask" /** * Field name for the Configuration document describing the state of the Vis. * model. @@ -575,6 +580,12 @@ bool kshark_import_event_filter(struct tep_handle *pevent, const char *filter_name, struct kshark_config_doc *conf); +bool kshark_export_user_mask(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf); + +bool kshark_import_user_mask(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + bool kshark_export_filter_array(struct tracecmd_filter_id *filter, const char *filter_name, struct kshark_config_doc *conf);