diff mbox

[6/6] intel_gpu_top: support profiling user-specified commands

Message ID 1315253973-18950-7-git-send-email-eugeni@dodonov.net (mailing list archive)
State New, archived
Headers show

Commit Message

Eugeni Dodonov Sept. 5, 2011, 8:19 p.m. UTC
From: Eugeni Dodonov <eugeni.dodonov@intel.com>

This patch adds support for running intel_gpu_top to profile specific
commands. The required command will be carried out in separate process,
and main intel_gpu_top will leave when the child process will exit.

Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
---
 man/intel_gpu_top.1   |   10 ++++++++
 tools/intel_gpu_top.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 65 insertions(+), 1 deletions(-)
diff mbox

Patch

diff --git a/man/intel_gpu_top.1 b/man/intel_gpu_top.1
index bca83f0..db2f362 100644
--- a/man/intel_gpu_top.1
+++ b/man/intel_gpu_top.1
@@ -19,8 +19,18 @@  number of samples to acquire per second
 .B -o [output file]
 run non-interactively and collect usage statistics to [file]
 .TP
+.B -e ["command to profile"]
+execute a command, and leave when it is finished. Note that the entire command
+with all parameters should be included as one parameter.
+.TP
 .B -h
 show usage notes
+.SH EXAMPLES
+.TP
+intel_gpu_top -o "cairo-trace-gvim.log" -s 100 -e "cairo-perf-trace /tmp/gvim"
+will run cairo-perf-trace with /tmp/gvim trace, non-interactively, saving the
+statistics into cairo-trace-gvim.log file, and collecting 100 samples per
+second.
 .PP
 Note that idle units are not
 displayed, so an entirely idle GPU will only display the ring status and
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 88f7157..3619d1b 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -33,6 +33,8 @@ 
 #include <err.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <sys/wait.h>
+#include <string.h>
 #include "intel_gpu_tools.h"
 #include "instdone.h"
 
@@ -447,12 +449,17 @@  int main(int argc, char **argv)
 	FILE *output = stdout;
 	double elapsed_time=0;
 	int print_headers=1;
+	pid_t child_pid=-1;
+	int child_stat;
+	char *cmd=NULL;
 
 	/* Parse options? */
-	while ((ch = getopt(argc, argv, "s:o:h")) != -1)
+	while ((ch = getopt(argc, argv, "s:o:e:h")) != -1)
 	{
 		switch (ch)
 		{
+			case 'e': cmd = strdup(optarg);
+					  break;
 			case 's': samples_per_sec = atoi(optarg);
 					  if (samples_per_sec < 100) {
 						  fprintf(stderr, "Error: samples per second must be >= 100\n");
@@ -481,6 +488,37 @@  int main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
+	/* Do we have a command to run? */
+	if (cmd != NULL)
+	{
+		if (output != stdout) {
+			fprintf(output, "# Profiling: %s\n", cmd);
+			fflush(output);
+		}
+		child_pid = fork();
+		if (child_pid < 0)
+		{
+			perror("fork");
+			exit(1);
+		}
+		else if (child_pid == 0) {
+			int res;
+			res = system(cmd);
+            free(cmd);
+			if (res < 0)
+				perror("running command");
+			if (output != stdout) {
+				fflush(output);
+				fprintf(output, "# %s exited with status %d\n", cmd, res);
+				fflush(output);
+			}
+			exit(0);
+		}
+        else {
+            free(cmd);
+        }
+	}
+
 	pci_dev = intel_get_pci_device();
 	devid = pci_dev->device_id;
 	intel_get_mmio(pci_dev);
@@ -673,7 +711,23 @@  int main(int argc, char **argv)
 			if (i < STATS_COUNT)
 				last_stats[i] = stats[i];
 		}
+
+		/* Check if child has gone */
+		if (child_pid > 0)
+		{
+			int res;
+			if ((res = waitpid(child_pid, &child_stat, WNOHANG)) == -1) {
+				perror("waitpid");
+				exit(1);
+			}
+			if (res == 0)
+				continue;
+			if (WIFEXITED(child_stat))
+				break;
+		}
 	}
 
+	fclose(output);
+
 	return 0;
 }