intel_gpu_top: support profiling user-specified commands
authorEugeni Dodonov <eugeni.dodonov@intel.com>
Mon, 5 Sep 2011 22:41:24 +0000 (19:41 -0300)
committerEugeni Dodonov <eugeni.dodonov@intel.com>
Mon, 5 Sep 2011 22:45:01 +0000 (19:45 -0300)
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
tools/intel_gpu_top.c

index bca83f0..db2f362 100644 (file)
@@ -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
index f7ea6db..2e277fe 100644 (file)
@@ -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,11 +449,16 @@ 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");
@@ -479,6 +486,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);
@@ -671,7 +709,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;
 }