intel_gpu_top: support profiling user-specified commands

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>
This commit is contained in:
Eugeni Dodonov 2011-09-05 19:41:24 -03:00
parent c2983f24e3
commit a483c97d91
2 changed files with 65 additions and 1 deletions

View File

@ -19,8 +19,18 @@ number of samples to acquire per second
.B -o [output file] .B -o [output file]
run non-interactively and collect usage statistics to [file] run non-interactively and collect usage statistics to [file]
.TP .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 .B -h
show usage notes 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 .PP
Note that idle units are not Note that idle units are not
displayed, so an entirely idle GPU will only display the ring status and displayed, so an entirely idle GPU will only display the ring status and

View File

@ -33,6 +33,8 @@
#include <err.h> #include <err.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <string.h>
#include "intel_gpu_tools.h" #include "intel_gpu_tools.h"
#include "instdone.h" #include "instdone.h"
@ -447,11 +449,16 @@ int main(int argc, char **argv)
FILE *output = stdout; FILE *output = stdout;
double elapsed_time=0; double elapsed_time=0;
int print_headers=1; int print_headers=1;
pid_t child_pid=-1;
int child_stat;
char *cmd=NULL;
/* Parse options? */ /* Parse options? */
while ((ch = getopt(argc, argv, "s:o:h")) != -1) while ((ch = getopt(argc, argv, "s:o:e:h")) != -1)
{ {
switch (ch) { switch (ch) {
case 'e': cmd = strdup(optarg);
break;
case 's': samples_per_sec = atoi(optarg); case 's': samples_per_sec = atoi(optarg);
if (samples_per_sec < 100) { if (samples_per_sec < 100) {
fprintf(stderr, "Error: samples per second must be >= 100\n"); fprintf(stderr, "Error: samples per second must be >= 100\n");
@ -479,6 +486,37 @@ int main(int argc, char **argv)
argc -= optind; argc -= optind;
argv += 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(); pci_dev = intel_get_pci_device();
devid = pci_dev->device_id; devid = pci_dev->device_id;
intel_get_mmio(pci_dev); intel_get_mmio(pci_dev);
@ -671,7 +709,23 @@ int main(int argc, char **argv)
if (i < STATS_COUNT) if (i < STATS_COUNT)
last_stats[i] = stats[i]; 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; return 0;
} }