155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdio.h>
255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <unistd.h>
355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdlib.h>
455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <inttypes.h>
555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <string.h>
655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h"
755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options.h"
855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef TraceReader<> TraceReaderType;
1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options-inl.h"
1255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project// This function is called from quicksort to compare the cpu time
1455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project// of processes and sort into decreasing order.
1555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint cmp_dec_cpu_time(const void *a, const void *b) {
1655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  ProcessState *proc1, *proc2;
1755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  proc1 = (ProcessState*)a;
1955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  proc2 = (ProcessState*)b;
2055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (proc1 == NULL) {
2155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (proc2 == NULL)
2255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      return 0;
2355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    return 1;
2455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
2555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (proc2 == NULL)
2655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    return -1;
2755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (proc1->cpu_time < proc2->cpu_time)
2855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    return 1;
2955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (proc1->cpu_time > proc2->cpu_time)
3055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    return -1;
3155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // If the cpu_time times are the same, then sort into increasing
3255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // order of pid.
3355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  return proc1->pid - proc2->pid;
3455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
3555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
3655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectvoid Usage(const char *program)
3755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{
3855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  fprintf(stderr, "Usage: %s [options] trace_file\n", program);
3955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  OptionsUsage();
4055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
4155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
4255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) {
4355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Parse the options
4455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  ParseOptions(argc, argv);
4555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (argc - optind != 1) {
4655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    Usage(argv[0]);
4755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    exit(1);
4855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
4955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
5055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  char *trace_filename = argv[optind];
5155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  TraceReader<> *trace = new TraceReader<>;
5255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Open(trace_filename);
5355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->SetRoot(root);
5455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
5555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  while (1) {
5655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    BBEvent event, ignored;
5755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    symbol_type *dummy_sym;
5855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
5955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (GetNextValidEvent(trace, &event, &ignored, &dummy_sym))
6055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      break;
6155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
6255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
6355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  int num_procs;
6455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  ProcessState *processes = trace->GetProcesses(&num_procs);
6555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  qsort(processes, num_procs, sizeof(ProcessState), cmp_dec_cpu_time);
6655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
6755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t total_time = 0;
6855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  for (int ii = 0; ii < num_procs; ++ii) {
6955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    total_time += processes[ii].cpu_time;
7055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
7155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t sum_time = 0;
7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  printf("  pid parent   cpu_time      %%      %% flags argv\n");
7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  ProcessState *pstate = &processes[0];
7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  for (int ii = 0; ii < num_procs; ++ii, ++pstate) {
7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    sum_time += pstate->cpu_time;
7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    double per = 100.0 * pstate->cpu_time / total_time;
7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    double sum_per = 100.0 * sum_time / total_time;
79d4d5b4f63a5760b2212166f539f906edda0bc4deJack Veenstra    const char *print_flags = "";
8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if ((pstate->flags & ProcessState::kCalledExec) == 0)
8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      print_flags = "T";
8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (pstate->name == NULL)
8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      pstate->name = "";
8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    printf("%5d  %5d %10llu %6.2f %6.2f %5s %s",
8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project           pstate->pid, pstate->parent_pid, pstate->cpu_time,
8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project           per, sum_per, print_flags, pstate->name);
87c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra    for (int jj = 1; jj < pstate->argc; ++jj) {
88c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra      printf(" %s", pstate->argv[jj]);
8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    printf("\n");
9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
92c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra  delete trace;
9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  return 0;
9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
95