We add a new command line option for starting KernelShark that allows the user to select Task plots to be shown. The new option is similar to "--pid" but the tasks can be specified by name. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx> --- src/KsUtils.cpp | 32 ++++++++++++++++++++++++++++++++ src/KsUtils.hpp | 2 ++ src/kernelshark.cpp | 17 +++++++++++++---- tests/libkshark-gui-tests.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/KsUtils.cpp b/src/KsUtils.cpp index 27cda55..ec53267 100644 --- a/src/KsUtils.cpp +++ b/src/KsUtils.cpp @@ -548,6 +548,38 @@ QVector<int> parseIdList(QString v_str) return v; } +/** + * @brief Convert a string containing task names into a list of PID numbers. + */ +QMap<int, QVector<int>> parseTaskList(QString v_str) +{ + QStringList taskList = v_str.split(",", QString::SkipEmptyParts); + QVector<int> streamIds, allPids; + kshark_context *kshark_ctx(nullptr); + QMap<int, QVector<int>> ret; + QString name; + + if (!kshark_instance(&kshark_ctx)) + return {}; + + streamIds = getStreamIdList(kshark_ctx); + for (auto const sd: streamIds) { + allPids = getPidList(sd); + for (auto const pid: allPids) { + name = kshark_comm_from_pid(sd, pid); + if (name.isEmpty()) + continue; + + for (auto const task: taskList) { + if(name == task) + ret[sd].append(pid); + } + } + } + + return ret; +} + /** * @brief Split the ststem name from the actual name of the event itself. * diff --git a/src/KsUtils.hpp b/src/KsUtils.hpp index 0d2c9c3..cf209bc 100644 --- a/src/KsUtils.hpp +++ b/src/KsUtils.hpp @@ -161,6 +161,8 @@ QStringList splitArguments(QString cmd); QVector<int> parseIdList(QString v_str); +QMap<int, QVector<int>> parseTaskList(QString v_str); + QStringList getTepEvtName(int sd, int eventId); /** Get a string to be used as a standard name of a CPU graph. */ diff --git a/src/kernelshark.cpp b/src/kernelshark.cpp index 41ffbe7..8ed4948 100644 --- a/src/kernelshark.cpp +++ b/src/kernelshark.cpp @@ -32,7 +32,8 @@ void usage(const char *prog) printf(" -s import a session\n"); printf(" -l import the last session\n"); puts(" --cpu show plots for CPU cores, default is \"show all\""); - puts(" --pid show plots for tasks, default is \"do not show\""); + puts(" --pid show plots for tasks (by PID), default is \"do not show\""); + puts(" --task show plots for tasks (by name), default is \"do not show\""); puts("\n example:"); puts(" kernelshark -i mytrace.dat --cpu 1,4-7 --pid 11 -p path/to/my/plugin/myplugin.so\n"); } @@ -42,6 +43,7 @@ static option longOptions[] = { {"help", no_argument, nullptr, 'h'}, {"pid", required_argument, nullptr, KS_LONG_OPTS}, {"cpu", required_argument, nullptr, KS_LONG_OPTS}, + {"task", required_argument, nullptr, KS_LONG_OPTS}, {nullptr, 0, nullptr, 0} }; @@ -50,6 +52,7 @@ int main(int argc, char **argv) QVector<int> cpuPlots, taskPlots; bool fromSession = false; int optionIndex = 0; + QString taskList; int c; QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); @@ -67,7 +70,8 @@ int main(int argc, char **argv) cpuPlots.append(KsUtils::parseIdList(QString(optarg))); else if (strcmp(longOptions[optionIndex].name, "pid") == 0) taskPlots.append(KsUtils::parseIdList(QString(optarg))); - + else if (strcmp(longOptions[optionIndex].name, "task") == 0) + taskList = QString(optarg); break; case 'h': @@ -136,9 +140,14 @@ int main(int argc, char **argv) return ids; }; - if (cpuPlots.count() || taskPlots.count()) { + if (cpuPlots.count() || taskPlots.count() || taskList.size()) { ks.setCPUPlots(0, lamOrderIds(cpuPlots)); - ks.setTaskPlots(0, lamOrderIds(taskPlots)); + + auto pidMap = KsUtils::parseTaskList(taskList); + pidMap[0].append(taskPlots); + for (auto it = pidMap.begin(); it != pidMap.end(); ++it) { + ks.setTaskPlots(it.key(), lamOrderIds(it.value())); + } } ks.raise(); diff --git a/tests/libkshark-gui-tests.cpp b/tests/libkshark-gui-tests.cpp index 5a0ca01..bc49194 100644 --- a/tests/libkshark-gui-tests.cpp +++ b/tests/libkshark-gui-tests.cpp @@ -286,3 +286,28 @@ BOOST_AUTO_TEST_CASE(GraphModel) model.reset(); BOOST_CHECK_EQUAL(model.rowCount({}), 0); } + +BOOST_AUTO_TEST_CASE(KsUtils_parseTasks) +{ + QVector<int> pids{28121, 28137, 28141, 28199, 28201, 205666, 267481}; + kshark_context *kshark_ctx{nullptr}; + kshark_entry **data{nullptr}; + std::string file(KS_TEST_DIR); + ssize_t n_rows; + int sd; + + kshark_instance(&kshark_ctx); + file += "/trace_test1.dat"; + sd = kshark_open(kshark_ctx, file.c_str()); + n_rows = kshark_load_entries(kshark_ctx, sd, &data); + + auto pids_test = parseTaskList("zoom,sleep"); + BOOST_CHECK(pids == pids_test[0]); + + for (ssize_t r = 0; r < n_rows; ++r) + free(data[r]); + free(data); + + kshark_close(kshark_ctx, sd); + kshark_free(kshark_ctx); +} -- 2.25.1