This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [google] Remove deprecated pfmon-specific functions/structs from pmu-profile.c (was: Changed strucs to structs) (issue6442086)


OK for google branches.

Thanks,

-Rong

On Mon, Aug 6, 2012 at 9:40 AM, Teresa Johnson <tejohnson@google.com> wrote:
> The upload script asks for a subject, even when updating a previous
> issue number. Usually I just re-enter the original patch subject line,
> and describe the changes from the original in the patch description
> that I am uploading.
>
> You don't need to reload it again, it should all be tracked properly
> using Rietveld under the issue number.
>
> Thanks,
> Teresa
>
> On Mon, Aug 6, 2012 at 9:37 AM, Chris Manghane <cmang@google.com> wrote:
>> Sorry, I'm confused. I didn't think updating the issue would change the
>> subject. Do I need to upload the updated patch again with the correct
>> subject using the upload-gcc-patch.py script or is there something I'm
>> missing?
>>
>> Thanks,
>> Chris
>>
>>
>> On Mon, Aug 6, 2012 at 9:13 AM, Teresa Johnson <tejohnson@google.com> wrote:
>>>
>>>
>>> Revised the subject to add [google] tag and add original patch
>>> description.
>>>
>>> Chris, you can use the same subject as the original patch and just
>>> describe the revisions to the patch in the email body.
>>>
>>> Thanks,
>>> Teresa
>>>
>>> On Mon, Aug 6, 2012 at 8:51 AM, Chris Manghane <cmang@google.com> wrote:
>>> > This patch removes functions and structs necessary for gathering pmu
>>> > info with
>>> > pfmon, which is now a deprecated tool.
>>> >
>>> > For google/main. Tested with bootstrap.
>>> >
>>> > 2012-08-03  Chris Manghane  <cmang@google.com>
>>> >
>>> >         * libgcc/pmu-profile.c
>>> >         (enum pmu_tool_type): Remove pfmon-specific functions/structs.
>>> >         (enum pmu_event_type): Ditto.
>>> >         (enum pmu_state): Ditto.
>>> >         (enum cpu_vendor_signature): Ditto.
>>> >         (struct pmu_tool_info): Ditto.
>>> >         (void gcov_write_branch_mispredict_infos): Ditto.
>>> >         (get_x86cpu_vendor): Ditto.
>>> >         (parse_pmu_profile_options): Ditto.
>>> >         (start_addr2line_symbolizer): Ditto.
>>> >         (reset_symbolizer_parent_pipes): Ditto.
>>> >         (reset_symbolizer_child_pipes): Ditto.
>>> >         (end_addr2line_symbolizer): Ditto.
>>> >         (symbolize_addr2line): Ditto.
>>> >         (start_pfmon_module): Ditto.
>>> >         (convert_pct_to_unsigned): Ditto.
>>> >         (parse_load_latency_line): Ditto.
>>> >         (parse_branch_mispredict_line): Ditto.
>>> >         (parse_pfmon_load_latency): Ditto.
>>> >         (parse_pfmon_tool_header): Ditto.
>>> >         (parse_pfmon_branch_mispredicts): Ditto.
>>> >         (pmu_start): Ditto.
>>> >         (init_pmu_branch_mispredict): Ditto.
>>> >         (init_pmu_tool): Ditto.
>>> >         (__gcov_init_pmu_profiler): Ditto.
>>> >         (__gcov_start_pmu_profiler): Ditto.
>>> >         (__gcov_stop_pmu_profiler): Ditto.
>>> >         (gcov_write_branch_mispredict_line): Ditto.
>>> >         (gcov_write_load_latency_infos): Ditto.
>>> >         (gcov_write_branch_mispredict_infos): Ditto.
>>> >         (gcov_write_tool_header): Ditto.
>>> >         (__gcov_end_pmu_profiler): Ditto.
>>> >
>>> > Index: libgcc/pmu-profile.c
>>> > ===================================================================
>>> > --- libgcc/pmu-profile.c        (revision 190103)
>>> > +++ libgcc/pmu-profile.c        (working copy)
>>> > @@ -67,169 +67,11 @@ see the files COPYING3 and COPYING.RUNTIME respect
>>> >  #define XDELETEVEC(p) free(p)
>>> >  #define XDELETE(p) free(p)
>>> >
>>> > -#define PFMON_CMD "/usr/bin/pfmon"
>>> > -#define ADDR2LINE_CMD "/usr/bin/addr2line"
>>> > -#define PMU_TOOL_MAX_ARGS (20)
>>> > -static char default_addr2line[] = "??:0";
>>> > -static const char pfmon_ll_header[] = "#     counts   %self    %cum
>>> > "
>>> > -    "<10     <32     <64    <256   <1024  >=1024  %wself          "
>>> > -    "code addr symbol\n";
>>> > -static const char pfmon_bm_header[] =
>>> > -    "#     counts   %self    %cum          code addr symbol\n";
>>> > -
>>> > -const char *pfmon_intel_ll_args[PMU_TOOL_MAX_ARGS] = {
>>> > -  PFMON_CMD,
>>> > -  "--aggregate-results",
>>> > -  "--follow-all",
>>> > -  "--with-header",
>>> > -  "--smpl-module=pebs-ll",
>>> > -  "--ld-lat-threshold=4",
>>> > -  "--pebs-ll-dcmiss-code",
>>> > -  "--resolve-addresses",
>>> > -  "-emem_inst_retired:LATENCY_ABOVE_THRESHOLD",
>>> > -  "--long-smpl-periods=10000",
>>> > -  0  /* terminating NULL must be present */
>>> > -};
>>> > -
>>> > -const char *pfmon_amd_ll_args[PMU_TOOL_MAX_ARGS] = {
>>> > -  PFMON_CMD,
>>> > -  "--aggregate-results",
>>> > -  "--follow-all",
>>> > -  "-uk",
>>> > -  "--with-header",
>>> > -  "--smpl-module=ibs",
>>> > -  "--resolve-addresses",
>>> > -  "-eibsop_event:uops",
>>> > -  "--ibs-dcmiss-code",
>>> > -  "--long-smpl-periods=0xffff0",
>>> > -  0  /* terminating NULL must be present */
>>> > -};
>>> > -
>>> > -const char *pfmon_intel_brm_args[PMU_TOOL_MAX_ARGS] = {
>>> > -  PFMON_CMD,
>>> > -  "--aggregate-results",
>>> > -  "--follow-all",
>>> > -  "--with-header",
>>> > -  "--resolve-addresses",
>>> > -  "-eMISPREDICTED_BRANCH_RETIRED",
>>> > -  "--long-smpl-periods=10000",
>>> > -  0  /* terminating NULL must be present */
>>> > -};
>>> > -
>>> > -const char *pfmon_amd_brm_args[PMU_TOOL_MAX_ARGS] = {
>>> > -  PFMON_CMD,
>>> > -  "--aggregate-results",
>>> > -  "--follow-all",
>>> > -  "--with-header",
>>> > -  "--resolve-addresses",
>>> > -  "-eRETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS",
>>> > -  "--long-smpl-periods=10000",
>>> > -  0  /* terminating NULL must be present */
>>> > -};
>>> > -
>>> > -const char *addr2line_args[PMU_TOOL_MAX_ARGS] = {
>>> > -  ADDR2LINE_CMD,
>>> > -  "-e",
>>> > -  0  /* terminating NULL must be present */
>>> > -};
>>> > -
>>> > -
>>> > -enum pmu_tool_type
>>> > -{
>>> > -  PTT_PFMON,
>>> > -  PTT_LAST
>>> > -};
>>> > -
>>> > -enum pmu_event_type
>>> > -{
>>> > -  PET_INTEL_LOAD_LATENCY,
>>> > -  PET_AMD_LOAD_LATENCY,
>>> > -  PET_INTEL_BRANCH_MISPREDICT,
>>> > -  PET_AMD_BRANCH_MISPREDICT,
>>> > -  PET_LAST
>>> > -};
>>> > -
>>> > -typedef struct pmu_tool_fns {
>>> > -  const char *name;     /* name of the pmu tool */
>>> > -  /* pmu tool commandline argument.  */
>>> > -  const char **arg_array;
>>> > -  /* Initialize pmu module.  */
>>> > -  void *(*init_pmu_module) (void);
>>> > -  /* Start profililing.  */
>>> > -  void (*start_pmu_module) (pid_t ppid, char *tmpfile, const char
>>> > **args);
>>> > -  /* Stop profililing.  */
>>> > -  void (*stop_pmu_module) (void);
>>> > -  /* How to parse the output generated by the PMU tool.  */
>>> > -  int (*parse_pmu_output) (char *filename, void *pmu_data);
>>> > -  /* How to write parsed pmu data into gcda file.  */
>>> > -  void (*gcov_write_pmu_data) (void *data);
>>> > -  /* How to cleanup any data structure created during parsing.  */
>>> > -  void (*cleanup_pmu_data) (void *data);
>>> > -  /* How to initialize symbolizer for the PPID.  */
>>> > -  int (*start_symbolizer) (pid_t ppid);
>>> > -  void (*end_symbolizer) (void);
>>> > -  char *(*symbolize) (void *addr);
>>> > -} pmu_tool_fns;
>>> > -
>>> > -enum pmu_state
>>> > -{
>>> > -  PMU_NONE,             /* Not configurated at all.  */
>>> > -  PMU_INITIALIZED,      /* Configured and initialized.  */
>>> > -  PMU_ERROR,            /* Configuration error. Cannot recover.  */
>>> > -  PMU_ON,               /* Currently profiling.  */
>>> > -  PMU_OFF               /* Currently stopped, but can be restarted.  */
>>> > -};
>>> > -
>>> > -enum cpu_vendor_signature
>>> > -{
>>> > -  CPU_VENDOR_UKNOWN = 0,
>>> > -  CPU_VENDOR_INTEL  = 0x756e6547, /* Genu */
>>> > -  CPU_VENDOR_AMD    = 0x68747541 /* Auth */
>>> > -};
>>> > -
>>> > -/* Info about pmu tool during the run time.  */
>>> > -struct pmu_tool_info
>>> > -{
>>> > -  /* Current pmu tool.  */
>>> > -  enum pmu_tool_type tool;
>>> > -  /* Current event.  */
>>> > -  enum pmu_event_type event;
>>> > -  /* filename for storing the pmu profile.  */
>>> > -  char *pmu_profile_filename;
>>> > -  /* Intermediate file where the tool stores the PMU data.  */
>>> > -  char *raw_pmu_profile_filename;
>>> > -  /* Where PMU tool's stderr should be stored.  */
>>> > -  char *tool_stderr_filename;
>>> > -  enum pmu_state pmu_profiling_state;
>>> > -  enum cpu_vendor_signature cpu_vendor; /* as discovered by cpuid */
>>> > -  pid_t pmu_tool_pid;   /* process id of the pmu tool */
>>> > -  pid_t symbolizer_pid; /* process id of the symbolizer */
>>> > -  int symbolizer_to_pipefd[2]; /* pipe for writing to the symbolizer */
>>> > -  int symbolizer_from_pipefd[2];  /* pipe for reading from the
>>> > symbolizer */
>>> > -  void *pmu_data;       /* an opaque pointer for the tool to store pmu
>>> > data */
>>> > -  int verbose;          /* turn on additional debugging */
>>> > -  unsigned top_n_address;  /* how many addresses to symbolize */
>>> > -  pmu_tool_fns *tool_details;  /* list of functions how to
>>> > start/stop/parse */
>>> > -};
>>> > -
>>> > -/* Global struct for recordkeeping.  */
>>> > -static struct pmu_tool_info *the_pmu_tool_info;
>>> > -
>>> > -/* Additional info is printed if these are non-zero.  */
>>> > -static int tool_debug = 0;
>>> > -static int sym_debug = 0;
>>> > -
>>> > -static int parse_load_latency_line (char *line, gcov_pmu_ll_info_t
>>> > *ll_info);
>>> > -static int parse_branch_mispredict_line (char *line,
>>> > -                                         gcov_pmu_brm_info_t
>>> > *brm_info);
>>> >  static unsigned convert_pct_to_unsigned (float pct);
>>> > -static void start_pfmon_module (pid_t ppid, char *tmpfile, const char
>>> > **pfmon_args);
>>> >  static void *init_pmu_load_latency (void);
>>> >  static void *init_pmu_branch_mispredict (void);
>>> >  static void destroy_load_latency_infos (void *info);
>>> >  static void destroy_branch_mispredict_infos (void *info);
>>> > -static int parse_pfmon_load_latency (char *filename, void *pmu_data);
>>> > -static int parse_pfmon_branch_mispredicts (char *filename, void
>>> > *pmu_data);
>>> >  static gcov_unsigned_t gcov_tag_pmu_tool_header_length
>>> > (gcov_pmu_tool_header_t
>>> >                                                          *header);
>>> >  static void gcov_write_tool_header (gcov_pmu_tool_header_t *header);
>>> > @@ -238,456 +80,7 @@ static void gcov_write_branch_mispredict_infos (vo
>>> >  static void gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info);
>>> >  static void gcov_write_branch_mispredict_line (const
>>> > gcov_pmu_brm_info_t
>>> >                                                 *brm_info);
>>> > -static int start_addr2line_symbolizer (pid_t pid);
>>> > -static void end_addr2line_symbolizer (void);
>>> > -static char *symbolize_addr2line (void *p);
>>> > -static void reset_symbolizer_parent_pipes (void);
>>> > -static void reset_symbolizer_child_pipes (void);
>>> > -/* parse and cache relevant tool info.  */
>>> > -static int parse_pmu_profile_options (const char *options);
>>> > -static gcov_pmu_tool_header_t *parse_pfmon_tool_header (FILE *fp,
>>> > -                                                        const char
>>> > *end_header);
>>> >
>>> > -
>>> > -/* How to access the necessary functions for the PMU tools.  */
>>> > -pmu_tool_fns all_pmu_tool_fns[PTT_LAST][PET_LAST] = {
>>> > -  {
>>> > -    {
>>> > -      "intel-load-latency",             /* name */
>>> > -      pfmon_intel_ll_args,              /* tool args */
>>> > -      init_pmu_load_latency,            /* initialization */
>>> > -      start_pfmon_module,               /* start */
>>> > -      0,                                /* stop */
>>> > -      parse_pfmon_load_latency,         /* parse */
>>> > -      gcov_write_load_latency_infos,    /* write */
>>> > -      destroy_load_latency_infos,       /* cleanup */
>>> > -      start_addr2line_symbolizer,       /* start symbolizer */
>>> > -      end_addr2line_symbolizer,         /* end symbolizer */
>>> > -      symbolize_addr2line,              /* symbolize */
>>> > -    },
>>> > -    {
>>> > -      "amd-load-latency",               /* name */
>>> > -      pfmon_amd_ll_args,                /* tool args */
>>> > -      init_pmu_load_latency,            /* initialization */
>>> > -      start_pfmon_module,               /* start */
>>> > -      0,                                /* stop */
>>> > -      parse_pfmon_load_latency,         /* parse */
>>> > -      gcov_write_load_latency_infos,    /* write */
>>> > -      destroy_load_latency_infos,       /* cleanup */
>>> > -      start_addr2line_symbolizer,       /* start symbolizer */
>>> > -      end_addr2line_symbolizer,         /* end symbolizer */
>>> > -      symbolize_addr2line,              /* symbolize */
>>> > -    },
>>> > -    {
>>> > -      "intel-branch-mispredict",        /* name */
>>> > -      pfmon_intel_brm_args,             /* tool args */
>>> > -      init_pmu_branch_mispredict,       /* initialization */
>>> > -      start_pfmon_module,               /* start */
>>> > -      0,                                /* stop */
>>> > -      parse_pfmon_branch_mispredicts,   /* parse */
>>> > -      gcov_write_branch_mispredict_infos,/* write */
>>> > -      destroy_branch_mispredict_infos,  /* cleanup */
>>> > -      start_addr2line_symbolizer,       /* start symbolizer */
>>> > -      end_addr2line_symbolizer,         /* end symbolizer */
>>> > -      symbolize_addr2line,              /* symbolize */
>>> > -    },
>>> > -    {
>>> > -      "amd-branch-mispredict",          /* name */
>>> > -      pfmon_amd_brm_args,               /* tool args */
>>> > -      init_pmu_branch_mispredict,       /* initialization */
>>> > -      start_pfmon_module,               /* start */
>>> > -      0,                                /* stop */
>>> > -      parse_pfmon_branch_mispredicts,   /* parse */
>>> > -      gcov_write_branch_mispredict_infos,/* write */
>>> > -      destroy_branch_mispredict_infos,  /* cleanup */
>>> > -      start_addr2line_symbolizer,       /* start symbolizer */
>>> > -      end_addr2line_symbolizer,         /* end symbolizer */
>>> > -      symbolize_addr2line,              /* symbolize */
>>> > -    }
>>> > -  }
>>> > -};
>>> > -
>>> > -/* Determine the CPU vendor.  Currently only distinguishes x86 based
>>> > -   cpus where the vendor is either Intel or AMD.  Returns one of the
>>> > -   enum cpu_vendor_signatures.  */
>>> > -
>>> > -static unsigned int
>>> > -get_x86cpu_vendor (void)
>>> > -{
>>> > -  unsigned int vendor = CPU_VENDOR_UKNOWN;
>>> > -
>>> > -#if (defined (__x86_64__) || defined (__i386__))
>>> > -  if (__get_cpuid_max (0, &vendor) < 1)
>>> > -    return CPU_VENDOR_UKNOWN;      /* Cannot determine cpu type.  */
>>> > -#endif
>>> > -
>>> > -  if (vendor == CPU_VENDOR_INTEL || vendor == CPU_VENDOR_AMD)
>>> > -    return vendor;
>>> > -  else
>>> > -    return CPU_VENDOR_UKNOWN;
>>> > -}
>>> > -
>>> > -
>>> > -/* Parse PMU tool option string provided on the command line and store
>>> > -   information in global structure.  Return 0 on success, otherwise
>>> > -   return 1.  Any changes to this should be synced with
>>> > -   check_pmu_profile_options() which does compile time check.  */
>>> > -
>>> > -static int
>>> > -parse_pmu_profile_options (const char *options)
>>> > -{
>>> > -  enum pmu_tool_type ptt = the_pmu_tool_info->tool;
>>> > -  enum pmu_event_type pet = PET_LAST;
>>> > -  const char *pmutool_path;
>>> > -  the_pmu_tool_info->cpu_vendor =  get_x86cpu_vendor ();
>>> > -  /* Determine the platform we are running on.  */
>>> > -  if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_UKNOWN)
>>> > -    {
>>> > -      /* Cpuid failed or uknown vendor.  */
>>> > -      the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  /* Validate the options.  */
>>> > -  if (strcmp(options, "load-latency") &&
>>> > -      strcmp(options, "load-latency-verbose") &&
>>> > -      strcmp(options, "branch-mispredict") &&
>>> > -      strcmp(options, "branch-mispredict-verbose"))
>>> > -    return 1;
>>> > -
>>> > -  /* Check if are aksed to collect load latency PMU data.  */
>>> > -  if (!strcmp(options, "load-latency") ||
>>> > -      !strcmp(options, "load-latency-verbose"))
>>> > -    {
>>> > -      if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL)
>>> > -        pet = PET_INTEL_LOAD_LATENCY;
>>> > -      else
>>> > -        pet = PET_AMD_LOAD_LATENCY;
>>> > -      if (!strcmp(options, "load-latency-verbose"))
>>> > -        the_pmu_tool_info->verbose = 1;
>>> > -    }
>>> > -
>>> > -  /* Check if are aksed to collect branch mispredict PMU data.  */
>>> > -  if (!strcmp(options, "branch-mispredict") ||
>>> > -      !strcmp(options, "branch-mispredict-verbose"))
>>> > -    {
>>> > -      if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL)
>>> > -        pet = PET_INTEL_BRANCH_MISPREDICT;
>>> > -      else
>>> > -        pet = PET_AMD_BRANCH_MISPREDICT;
>>> > -      if (!strcmp(options, "branch-mispredict-verbose"))
>>> > -        the_pmu_tool_info->verbose = 1;
>>> > -    }
>>> > -
>>> > -  the_pmu_tool_info->tool_details = &all_pmu_tool_fns[ptt][pet];
>>> > -  the_pmu_tool_info->event = pet;
>>> > -
>>> > -  /* Allow users to override the default tool path.  */
>>> > -  pmutool_path = getenv ("GCOV_PMUTOOL_PATH");
>>> > -  if (pmutool_path && strlen (pmutool_path))
>>> > -    the_pmu_tool_info->tool_details->arg_array[0] = pmutool_path;
>>> > -
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Do the initialization of addr2line symbolizer for the process id
>>> > -   given by TASK_PID.  It forks an addr2line process and creates two
>>> > -   pipes where addresses can be written and source_filename:line_num
>>> > -   entries can be read.  Returns 0 on success, non-zero otherwise.  */
>>> > -
>>> > -static int
>>> > -start_addr2line_symbolizer (pid_t task_pid)
>>> > -{
>>> > -  pid_t pid;
>>> > -  char *addr2line_path;
>>> > -
>>> > -  /* Allow users to override the default addr2line path.  */
>>> > -  addr2line_path = getenv ("GCOV_ADDR2LINE_PATH");
>>> > -  if (addr2line_path && strlen (addr2line_path))
>>> > -    addr2line_args[0] = addr2line_path;
>>> > -
>>> > -  if (pipe (the_pmu_tool_info->symbolizer_from_pipefd) == -1)
>>> > -    {
>>> > -      fprintf (stderr, "Cannot create symbolizer write pipe.\n");
>>> > -      return 1;
>>> > -    }
>>> > -  if (pipe (the_pmu_tool_info->symbolizer_to_pipefd) == -1)
>>> > -    {
>>> > -      fprintf (stderr, "Cannot create symbolizer read pipe.\n");
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  pid = fork ();
>>> > -  if (pid == -1)
>>> > -    {
>>> > -      /* error condition */
>>> > -      fprintf (stderr, "Cannot create symbolizer process.\n");
>>> > -      reset_symbolizer_parent_pipes ();
>>> > -      reset_symbolizer_child_pipes ();
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  if (pid == 0)
>>> > -    {
>>> > -      /* child does an exec and then connects to/from the pipe */
>>> > -      unsigned n_args = 0;
>>> > -      char proc_exe_buf[128];
>>> > -      int new_write_fd, new_read_fd;
>>> > -      int i;
>>> > -
>>> > -      /* Go over the current addr2line args.  */
>>> > -      for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i)
>>> > -        n_args++;
>>> > -
>>> > -      /* We are going to add one more arg for the /proc/pid/exe */
>>> > -      if (n_args >= (PMU_TOOL_MAX_ARGS - 1))
>>> > -        {
>>> > -          fprintf (stderr, "too many addr2line args: %d\n", n_args);
>>> > -          _exit (0);
>>> > -        }
>>> > -      snprintf (proc_exe_buf, sizeof (proc_exe_buf), "/proc/%d/exe",
>>> > -                task_pid);
>>> > -
>>> > -      /* Add the extra arg for the process id.  */
>>> > -      addr2line_args[n_args] = proc_exe_buf;
>>> > -      n_args++;
>>> > -
>>> > -      addr2line_args[n_args] = (const char *)NULL;  /* terminating NULL
>>> > */
>>> > -
>>> > -      if (sym_debug)
>>> > -        {
>>> > -          fprintf (stderr, "addr2line args:");
>>> > -          for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i)
>>> > -            fprintf (stderr, " %s", addr2line_args[i]);
>>> > -          fprintf (stderr, "\n");
>>> > -        }
>>> > -
>>> > -      /* Close unused ends of the two pipes.  */
>>> > -      reset_symbolizer_child_pipes ();
>>> > -
>>> > -      /* Connect the pipes to stdin/stdout of the child process.  */
>>> > -      new_read_fd = dup2 (the_pmu_tool_info->symbolizer_to_pipefd[0],
>>> > 0);
>>> > -      new_write_fd = dup2
>>> > (the_pmu_tool_info->symbolizer_from_pipefd[1], 1);
>>> > -      if (new_read_fd == -1 || new_write_fd == -1)
>>> > -        {
>>> > -          fprintf (stderr, "could not dup symbolizer fds\n");
>>> > -          reset_symbolizer_parent_pipes ();
>>> > -          reset_symbolizer_child_pipes ();
>>> > -          _exit (0);
>>> > -        }
>>> > -      the_pmu_tool_info->symbolizer_to_pipefd[0] = new_read_fd;
>>> > -      the_pmu_tool_info->symbolizer_from_pipefd[1] = new_write_fd;
>>> > -
>>> > -      /* Do execve with NULL env. */
>>> > -      execve (addr2line_args[0], (char * const*)addr2line_args,
>>> > -              (char * const*)NULL);
>>> > -      /* exec returned, an error condition.  */
>>> > -      fprintf (stderr, "could not create symbolizer process: %s\n",
>>> > -               addr2line_args[0]);
>>> > -      reset_symbolizer_parent_pipes ();
>>> > -      reset_symbolizer_child_pipes ();
>>> > -      _exit (0);
>>> > -    }
>>> > -  else
>>> > -    {
>>> > -      /* parent */
>>> > -      the_pmu_tool_info->symbolizer_pid = pid;
>>> > -      /* Close unused ends of the two pipes.  */
>>> > -      reset_symbolizer_parent_pipes ();
>>> > -      return 0;
>>> > -    }
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Close unused write end of the from-pipe and read end of the
>>> > -   to-pipe.  */
>>> > -
>>> > -static void
>>> > -reset_symbolizer_parent_pipes (void)
>>> > -{
>>> > -  if (the_pmu_tool_info->symbolizer_from_pipefd[1] != -1)
>>> > -    {
>>> > -      close (the_pmu_tool_info->symbolizer_from_pipefd[1]);
>>> > -      the_pmu_tool_info->symbolizer_from_pipefd[1] = -1;
>>> > -    }
>>> > -  if (the_pmu_tool_info->symbolizer_to_pipefd[0] != -1)
>>> > -    {
>>> > -      close (the_pmu_tool_info->symbolizer_to_pipefd[0]);
>>> > -      the_pmu_tool_info->symbolizer_to_pipefd[0] = -1;
>>> > -    }
>>> > -}
>>> > -
>>> > -/* Close unused write end of the to-pipe and read end of the
>>> > -   from-pipe.  */
>>> > -
>>> > -static void
>>> > -reset_symbolizer_child_pipes (void)
>>> > -{
>>> > -  if (the_pmu_tool_info->symbolizer_to_pipefd[1] != -1)
>>> > -    {
>>> > -      close (the_pmu_tool_info->symbolizer_to_pipefd[1]);
>>> > -      the_pmu_tool_info->symbolizer_to_pipefd[1] = -1;
>>> > -    }
>>> > -  if (the_pmu_tool_info->symbolizer_from_pipefd[0] != -1)
>>> > -    {
>>> > -      close (the_pmu_tool_info->symbolizer_from_pipefd[0]);
>>> > -      the_pmu_tool_info->symbolizer_from_pipefd[0] = -1;
>>> > -    }
>>> > -}
>>> > -
>>> > -
>>> > -/* Perform cleanup for the symbolizer process.  */
>>> > -
>>> > -static void
>>> > -end_addr2line_symbolizer (void)
>>> > -{
>>> > -  int pid_status;
>>> > -  int wait_status;
>>> > -  pid_t pid = the_pmu_tool_info->symbolizer_pid;
>>> > -
>>> > -  /* Symbolizer was not running.  */
>>> > -  if (!pid)
>>> > -    return;
>>> > -
>>> > -  reset_symbolizer_parent_pipes ();
>>> > -  reset_symbolizer_child_pipes ();
>>> > -  kill (pid, SIGTERM);
>>> > -  wait_status = waitpid (pid, &pid_status, 0);
>>> > -  if (sym_debug)
>>> > -  {
>>> > -    if (wait_status == pid)
>>> > -      fprintf (stderr, "Normal exit. symbolizer terminated.\n");
>>> > -    else
>>> > -      fprintf (stderr, "Abnormal exit. symbolizer status, %d.\n",
>>> > pid_status);
>>> > -  }
>>> > -  the_pmu_tool_info->symbolizer_pid = 0;  /* Symoblizer no longer
>>> > running.  */
>>> > -}
>>> > -
>>> > -
>>> > -/* Given an address ADDR, return a string containing
>>> > -   source_filename:line_num entries.  */
>>> > -
>>> > -static char *
>>> > -symbolize_addr2line (void *addr)
>>> > -{
>>> > -  char buf[32];  /* holds the ascii version of address */
>>> > -  int write_count;
>>> > -  int read_count;
>>> > -  char *srcfile_linenum;
>>> > -  size_t max_length = 1024;
>>> > -
>>> > -  if (!the_pmu_tool_info->symbolizer_pid)
>>> > -    return default_addr2line;    /* symbolizer is not running */
>>> > -
>>> > -  write_count = snprintf (buf, sizeof (buf), "%p\n", addr);
>>> > -
>>> > -  /* Write the address into the pipe.  */
>>> > -  if (write (the_pmu_tool_info->symbolizer_to_pipefd[1], buf,
>>> > write_count)
>>> > -      < write_count)
>>> > -    {
>>> > -      if (sym_debug)
>>> > -        fprintf (stderr, "Cannot write symbolizer pipe.\n");
>>> > -      return default_addr2line;
>>> > -    }
>>> > -
>>> > -  srcfile_linenum = XNEWVEC (char, max_length);
>>> > -  read_count = read (the_pmu_tool_info->symbolizer_from_pipefd[0],
>>> > -                     srcfile_linenum, max_length);
>>> > -  if (read_count == -1)
>>> > -    {
>>> > -      if (sym_debug)
>>> > -        fprintf (stderr, "Cannot read symbolizer pipe.\n");
>>> > -      XDELETEVEC (srcfile_linenum);
>>> > -      return default_addr2line;
>>> > -    }
>>> > -
>>> > -  srcfile_linenum[read_count] = 0;
>>> > -  if (sym_debug)
>>> > -    fprintf (stderr, "symbolizer: for address %p, read_count %d, got
>>> > %s\n",
>>> > -             addr, read_count, srcfile_linenum);
>>> > -  return srcfile_linenum;
>>> > -}
>>> > -
>>> > -/* Start monitoring PPID process via pfmon tool using TMPFILE as a
>>> > -   file to store the raw data and using PFMON_ARGS as the command line
>>> > -   arguments.  */
>>> > -
>>> > -static void
>>> > -start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args)
>>> > -{
>>> > -  int i;
>>> > -  unsigned int n_args = 0;
>>> > -  unsigned n_chars;
>>> > -  char pid_buf[64];
>>> > -  char filename_buf[1024];
>>> > -  char top_n_buf[24];
>>> > -  unsigned extra_args;
>>> > -
>>> > -  /* Go over the current pfmon args */
>>> > -  for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i)
>>> > -    n_args++;
>>> > -
>>> > -  if (the_pmu_tool_info->verbose)
>>> > -    extra_args = 4; /* account for additional --verbose */
>>> > -  else
>>> > -    extra_args = 3;
>>> > -
>>> > -  /* We are going to add args.  */
>>> > -  if (n_args >= (PMU_TOOL_MAX_ARGS - extra_args))
>>> > -    {
>>> > -      fprintf (stderr, "too many pfmon args: %d\n", n_args);
>>> > -      _exit (0);
>>> > -    }
>>> > -
>>> > -  n_chars = snprintf (pid_buf, sizeof (pid_buf), "--attach-task=%ld",
>>> > -                      (long)ppid);
>>> > -  if (n_chars >= sizeof (pid_buf))
>>> > -    {
>>> > -      fprintf (stderr, "pfmon task id too long: %s\n", pid_buf);
>>> > -      return;
>>> > -    }
>>> > -  pfmon_args[n_args] = pid_buf;
>>> > -  n_args++;
>>> > -
>>> > -  n_chars = snprintf (filename_buf, sizeof (filename_buf),
>>> > "--smpl-outfile=%s",
>>> > -                      tmpfile);
>>> > -  if (n_chars >= sizeof (filename_buf))
>>> > -    {
>>> > -      fprintf (stderr, "pfmon filename too long: %s\n", filename_buf);
>>> > -      return;
>>> > -    }
>>> > -  pfmon_args[n_args] = filename_buf;
>>> > -  n_args++;
>>> > -
>>> > -  n_chars = snprintf (top_n_buf, sizeof (top_n_buf),
>>> > "--smpl-show-top=%d",
>>> > -                      the_pmu_tool_info->top_n_address);
>>> > -  if (n_chars >= sizeof (top_n_buf))
>>> > -    {
>>> > -      fprintf (stderr, "pfmon option too long: %s\n", top_n_buf);
>>> > -      return;
>>> > -    }
>>> > -  pfmon_args[n_args] = top_n_buf;
>>> > -  n_args++;
>>> > -
>>> > -  if (the_pmu_tool_info->verbose) {
>>> > -    /* Add --verbose as well.  */
>>> > -    pfmon_args[n_args] = "--verbose";
>>> > -    n_args++;
>>> > -  }
>>> > -  pfmon_args[n_args] = (char *)NULL;
>>> > -
>>> > -  if (tool_debug)
>>> > -    {
>>> > -      fprintf (stderr, "pfmon args:");
>>> > -      for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i)
>>> > -        fprintf (stderr, " %s", pfmon_args[i]);
>>> > -      fprintf (stderr, "\n");
>>> > -    }
>>> > -  /* Do execve with NULL env.  */
>>> > -  execve (pfmon_args[0], (char *const *)pfmon_args, (char *
>>> > const*)NULL);
>>> > -  /* does not return */
>>> > -}
>>> > -
>>> >  /* Convert a fractional PCT to an unsigned integer after
>>> >     muliplying by 100.  */
>>> >
>>> > @@ -697,147 +90,6 @@ convert_pct_to_unsigned (float pct)
>>> >    return (unsigned)(pct * 100.0f);
>>> >  }
>>> >
>>> > -/* Parse the load latency info pointed by LINE and save it into
>>> > -   LL_INFO. Returns 0 if the line was parsed successfully, non-zero
>>> > -   otherwise.
>>> > -
>>> > -   An example header+line look like these:
>>> > -   "counts   %self    %cum     <10     <32     <64    <256   <1024
>>> > >=1024
>>> > -   %wself          code addr symbol"
>>> > -   "218  24.06%  24.06% 100.00%   0.00%   0.00%   0.00%   0.00%   0.00%
>>> > 22.70%
>>> > -   0x0000000000413e75 CalcSSIM(...)+965</tmp/psnr>"
>>> > -*/
>>> > -
>>> > -static int
>>> > -parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info)
>>> > -{
>>> > -  unsigned counts;
>>> > -  /* These are percentages parsed as floats, but then converted to
>>> > -     integers after multiplying by 100.  */
>>> > -  float self, cum, lt_10, lt_32, lt_64, lt_256, lt_1024, gt_1024,
>>> > wself;
>>> > -  long unsigned int p;
>>> > -  int n_values;
>>> > -  pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details;
>>> > -
>>> > -  n_values = sscanf (line, "%u%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%lx",
>>> > -                     &counts, &self, &cum, &lt_10, &lt_32, &lt_64,
>>> > &lt_256,
>>> > -                     &lt_1024, &gt_1024, &wself, &p);
>>> > -  if (n_values != 11)
>>> > -    return 1;
>>> > -
>>> > -  /* Values read successfully. Do the assignment after converting
>>> > -   * percentages into ints.  */
>>> > -  ll_info->counts = counts;
>>> > -  ll_info->self = convert_pct_to_unsigned (self);
>>> > -  ll_info->cum = convert_pct_to_unsigned (cum);
>>> > -  ll_info->lt_10 = convert_pct_to_unsigned (lt_10);
>>> > -  ll_info->lt_32 = convert_pct_to_unsigned (lt_32);
>>> > -  ll_info->lt_64 = convert_pct_to_unsigned (lt_64);
>>> > -  ll_info->lt_256 = convert_pct_to_unsigned (lt_256);
>>> > -  ll_info->lt_1024 = convert_pct_to_unsigned (lt_1024);
>>> > -  ll_info->gt_1024 = convert_pct_to_unsigned (gt_1024);
>>> > -  ll_info->wself = convert_pct_to_unsigned (wself);
>>> > -  ll_info->code_addr = p;
>>> > -
>>> > -  /* Run the raw address through the symbolizer.  */
>>> > -  if (tool_details->symbolize)
>>> > -    {
>>> > -      char *sym_info = tool_details->symbolize ((void *)p);
>>> > -      /* sym_info is of the form src_filename:linenum.  Descriminator
>>> > is
>>> > -         currently not supported by addr2line.  */
>>> > -      char *sep = strchr (sym_info, ':');
>>> > -      if (!sep)
>>> > -        {
>>> > -          /* Assume entire string is srcfile.  */
>>> > -          ll_info->filename = (char *)sym_info;
>>> > -          ll_info->line = 0;
>>> > -        }
>>> > -      else
>>> > -        {
>>> > -          /* Terminate the filename string at the separator.  */
>>> > -          *sep = 0;
>>> > -          ll_info->filename = (char *)sym_info;
>>> > -          /* Convert rest of the sym info to a line number.  */
>>> > -          ll_info->line = atol (sep+1);
>>> > -        }
>>> > -      ll_info->discriminator = 0;
>>> > -    }
>>> > -  else
>>> > -    {
>>> > -      /* No symbolizer available.  */
>>> > -      ll_info->filename = NULL;
>>> > -      ll_info->line = 0;
>>> > -      ll_info->discriminator = 0;
>>> > -    }
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Parse the branch mispredict info pointed by LINE and save it into
>>> > -   BRM_INFO. Returns 0 if the line was parsed successfully, non-zero
>>> > -   otherwise.
>>> > -
>>> > -   An example header+line look like these:
>>> > -   "counts   %self    %cum          code addr symbol"
>>> > -   "6869  37.67%  37.67% 0x00000000004007e5 sum(std::vector<int*,
>>> > -    std::allocator<int*> > const&)+51</root/tmp/array>"
>>> > -*/
>>> > -
>>> > -static int
>>> > -parse_branch_mispredict_line (char *line, gcov_pmu_brm_info_t
>>> > *brm_info)
>>> > -{
>>> > -  unsigned counts;
>>> > -  /* These are percentages parsed as floats, but then converted to
>>> > -     ints after multiplying by 100.  */
>>> > -  float self, cum;
>>> > -  long unsigned int p;
>>> > -  int n_values;
>>> > -  pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details;
>>> > -
>>> > -  n_values = sscanf (line, "%u%f%%%f%%%lx",
>>> > -                     &counts, &self, &cum, &p);
>>> > -  if (n_values != 4)
>>> > -    return 1;
>>> > -
>>> > -  /* Values read successfully. Do the assignment after converting
>>> > -   * percentages into ints.  */
>>> > -  brm_info->counts = counts;
>>> > -  brm_info->self = convert_pct_to_unsigned (self);
>>> > -  brm_info->cum = convert_pct_to_unsigned (cum);
>>> > -  brm_info->code_addr = p;
>>> > -
>>> > -  /* Run the raw address through the symbolizer.  */
>>> > -  if (tool_details->symbolize)
>>> > -    {
>>> > -      char *sym_info = tool_details->symbolize ((void *)p);
>>> > -      /* sym_info is of the form src_filename:linenum.  Descriminator
>>> > is
>>> > -         currently not supported by addr2line.  */
>>> > -      char *sep = strchr (sym_info, ':');
>>> > -      if (!sep)
>>> > -        {
>>> > -          /* Assume entire string is srcfile.  */
>>> > -          brm_info->filename = sym_info;
>>> > -          brm_info->line = 0;
>>> > -        }
>>> > -      else
>>> > -        {
>>> > -          /* Terminate the filename string at the separator.  */
>>> > -          *sep = 0;
>>> > -          brm_info->filename = sym_info;
>>> > -          /* Convert rest of the sym info to a line number.  */
>>> > -          brm_info->line = atol (sep+1);
>>> > -        }
>>> > -      brm_info->discriminator = 0;
>>> > -    }
>>> > -  else
>>> > -    {
>>> > -      /* No symbolizer available.  */
>>> > -      brm_info->filename = NULL;
>>> > -      brm_info->line = 0;
>>> > -      brm_info->discriminator = 0;
>>> > -    }
>>> > -  return 0;
>>> > -}
>>> > -
>>> >  /* Delete load latency info structures INFO.  */
>>> >
>>> >  static void
>>> > @@ -876,309 +128,6 @@ destroy_branch_mispredict_infos (void *info)
>>> >    brm_infos->brm_count = 0;
>>> >  }
>>> >
>>> > -/* Parse FILENAME for load latency lines into a structure
>>> > -   PMU_DATA. Returns 0 on on success.  Returns non-zero on
>>> > -   failure.  */
>>> > -
>>> > -static int
>>> > -parse_pfmon_load_latency (char *filename, void *pmu_data)
>>> > -{
>>> > -  FILE *fp;
>>> > -  size_t buflen = 2*1024;
>>> > -  char *buf;
>>> > -  ll_infos_t *load_latency_infos = (ll_infos_t *)pmu_data;
>>> > -  gcov_pmu_tool_header_t *tool_header = 0;
>>> > -
>>> > -  if ((fp = fopen (filename, "r")) == NULL)
>>> > -    {
>>> > -      fprintf (stderr, "cannot open pmu data file: %s\n", filename);
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_ll_header)))
>>> > -    {
>>> > -      fprintf (stderr, "cannot parse pmu data file header: %s\n",
>>> > filename);
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  buf = XNEWVEC (char, buflen);
>>> > -  while (fgets (buf, buflen, fp))
>>> > -    {
>>> > -      gcov_pmu_ll_info_t *ll_info = XNEW (gcov_pmu_ll_info_t);
>>> > -      if (!parse_load_latency_line (buf, ll_info))
>>> > -        {
>>> > -          /* valid line, add to the array */
>>> > -          load_latency_infos->ll_count++;
>>> > -          if (load_latency_infos->ll_count >=
>>> > -              load_latency_infos->alloc_ll_count)
>>> > -            {
>>> > -              /* need to realloc */
>>> > -              load_latency_infos->ll_array =
>>> > -                realloc (load_latency_infos->ll_array,
>>> > -                         2 * load_latency_infos->alloc_ll_count);
>>> > -              if (load_latency_infos->ll_array == NULL)
>>> > -                {
>>> > -                  fprintf (stderr, "Cannot allocate load latency
>>> > memory.\n");
>>> > -                  __destroy_pmu_tool_header (tool_header);
>>> > -                  free (buf);
>>> > -                  fclose (fp);
>>> > -                  return 1;
>>> > -                }
>>> > -            }
>>> > -          load_latency_infos->ll_array[load_latency_infos->ll_count -
>>> > 1] =
>>> > -            ll_info;
>>> > -        }
>>> > -      else
>>> > -        /* Delete invalid line.  */
>>> > -        XDELETE (ll_info);
>>> > -    }
>>> > -  free (buf);
>>> > -  fclose (fp);
>>> > -  load_latency_infos->pmu_tool_header = tool_header;
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Parse open file FP until END_HEADER is seen. The data matching
>>> > -   gcov_pmu_tool_header_t fields is saved and returned in a new
>>> > -   struct. In case of failure, it returns NULL.  */
>>> > -
>>> > -static gcov_pmu_tool_header_t *
>>> > -parse_pfmon_tool_header (FILE *fp, const char *end_header)
>>> > -{
>>> > -  static const char tag_hostname[] = "# hostname: ";
>>> > -  static const char tag_kversion[] = "# kernel version: ";
>>> > -  static const char tag_hostcpu[] = "# host CPUs:  ";
>>> > -  static const char tag_column_desc_start[] = "# description of
>>> > columns:";
>>> > -  static const char tag_column_desc_end[] =
>>> > -      "#       other columns are self-explanatory";
>>> > -  size_t buflen = 4*1024;
>>> > -  char *buf, *buf_start, *buf_end;
>>> > -  gcov_pmu_tool_header_t *tool_header = XNEWVEC
>>> > (gcov_pmu_tool_header_t, 1);
>>> > -  char *hostname = 0;
>>> > -  char *kversion = 0;
>>> > -  char *hostcpu = 0;
>>> > -  char *column_description = 0;
>>> > -  char *column_desc_start = 0;
>>> > -  char *column_desc_end = 0;
>>> > -  const char *column_header = 0;
>>> > -  int got_hostname = 0;
>>> > -  int got_kversion = 0 ;
>>> > -  int got_hostcpu = 0;
>>> > -  int got_end_header = 0;
>>> > -  int got_column_description = 0;
>>> > -
>>> > -  buf = XNEWVEC (char, buflen);
>>> > -  buf_start = buf;
>>> > -  buf_end = buf + buflen;
>>> > -  while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp))
>>> > -    {
>>> > -      if (strncmp (end_header, buf, buf_end - buf) == 0)
>>> > -      {
>>> > -        got_end_header = 1;
>>> > -        break;
>>> > -      }
>>> > -      if (!got_hostname &&
>>> > -          strncmp (buf, tag_hostname, strlen (tag_hostname)) == 0)
>>> > -        {
>>> > -          size_t len = strlen (buf) - strlen (tag_hostname);
>>> > -          hostname = XNEWVEC (char, len);
>>> > -          memcpy (hostname, buf + strlen (tag_hostname), len);
>>> > -          hostname[len - 1] = 0;
>>> > -          tool_header->hostname = hostname;
>>> > -          got_hostname = 1;
>>> > -        }
>>> > -
>>> > -      if (!got_kversion &&
>>> > -          strncmp (buf, tag_kversion, strlen (tag_kversion)) == 0)
>>> > -        {
>>> > -          size_t len = strlen (buf) - strlen (tag_kversion);
>>> > -          kversion = XNEWVEC (char, len);
>>> > -          memcpy (kversion, buf + strlen (tag_kversion), len);
>>> > -          kversion[len - 1] = 0;
>>> > -          tool_header->kernel_version = kversion;
>>> > -          got_kversion = 1;
>>> > -        }
>>> > -
>>> > -      if (!got_hostcpu &&
>>> > -          strncmp (buf, tag_hostcpu, strlen (tag_hostcpu)) == 0)
>>> > -        {
>>> > -          size_t len = strlen (buf) - strlen (tag_hostcpu);
>>> > -          hostcpu = XNEWVEC (char, len);
>>> > -          memcpy (hostcpu, buf + strlen (tag_hostcpu), len);
>>> > -          hostcpu[len - 1] = 0;
>>> > -          tool_header->host_cpu = hostcpu;
>>> > -          got_hostcpu = 1;
>>> > -        }
>>> > -      if (!got_column_description &&
>>> > -          strncmp (buf, tag_column_desc_start, strlen
>>> > (tag_column_desc_start))
>>> > -          == 0)
>>> > -        {
>>> > -          column_desc_start = buf;
>>> > -          column_desc_end = 0;
>>> > -          /* Continue reading until end of the column descriptor.  */
>>> > -          while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp))
>>> > -            {
>>> > -              if (strncmp (buf, tag_column_desc_end,
>>> > -                           strlen (tag_column_desc_end)) == 0)
>>> > -                {
>>> > -                  column_desc_end = buf + strlen (tag_column_desc_end);
>>> > -                  break;
>>> > -                }
>>> > -              buf += strlen (buf);
>>> > -            }
>>> > -          if (column_desc_end)
>>> > -            {
>>> > -              /* Found the end, copy it into a new string.  */
>>> > -              column_description = XNEWVEC (char, column_desc_end -
>>> > -                                            column_desc_start + 1);
>>> > -              got_column_description = 1;
>>> > -              strcpy (column_description, column_desc_start);
>>> > -              tool_header->column_description = column_description;
>>> > -            }
>>> > -        }
>>> > -      buf += strlen (buf);
>>> > -    }
>>> > -
>>> > -  /* If we are missing any of the fields, return NULL.  */
>>> > -  if (!got_end_header || !got_hostname || !got_kversion || !got_hostcpu
>>> > -      || !got_column_description)
>>> > -    {
>>> > -      free (hostname);
>>> > -      free (kversion);
>>> > -      free (hostcpu);
>>> > -      free (column_description);
>>> > -      free (buf_start);
>>> > -      free (tool_header);
>>> > -      return NULL;
>>> > -    }
>>> > -
>>> > -  switch (the_pmu_tool_info->event)
>>> > -    {
>>> > -    case PET_INTEL_LOAD_LATENCY:
>>> > -    case PET_AMD_LOAD_LATENCY:
>>> > -      column_header = pfmon_ll_header;
>>> > -      break;
>>> > -    case PET_INTEL_BRANCH_MISPREDICT:
>>> > -    case PET_AMD_BRANCH_MISPREDICT:
>>> > -      column_header = pfmon_bm_header;
>>> > -      break;
>>> > -    default:
>>> > -      break;
>>> > -    }
>>> > -  tool_header->column_header = strdup (column_header);
>>> > -  tool_header->full_header = buf_start;
>>> > -  return tool_header;
>>> > -}
>>> > -
>>> > -
>>> > -/* Parse FILENAME for branch mispredict lines into a structure
>>> > -   PMU_DATA. Returns 0 on on success.  Returns non-zero on
>>> > -   failure.  */
>>> > -
>>> > -static int
>>> > -parse_pfmon_branch_mispredicts (char *filename, void *pmu_data)
>>> > -{
>>> > -  FILE *fp;
>>> > -  size_t buflen = 2*1024;
>>> > -  char *buf;
>>> > -  brm_infos_t *brm_infos = (brm_infos_t *)pmu_data;
>>> > -  gcov_pmu_tool_header_t *tool_header = 0;
>>> > -
>>> > -  if ((fp = fopen (filename, "r")) == NULL)
>>> > -    {
>>> > -      fprintf (stderr, "cannot open pmu data file: %s\n", filename);
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_bm_header)))
>>> > -    {
>>> > -      fprintf (stderr, "cannot parse pmu data file header: %s\n",
>>> > filename);
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  buf = XNEWVEC (char, buflen);
>>> > -  while (fgets (buf, buflen, fp))
>>> > -    {
>>> > -      gcov_pmu_brm_info_t *brm = XNEW (gcov_pmu_brm_info_t);
>>> > -      if (!parse_branch_mispredict_line (buf, brm))
>>> > -        {
>>> > -          /* Valid line, add to the array.  */
>>> > -          brm_infos->brm_count++;
>>> > -          if (brm_infos->brm_count >= brm_infos->alloc_brm_count)
>>> > -            {
>>> > -              /* Do we need to realloc? */
>>> > -              brm_infos->brm_array =
>>> > -                realloc (brm_infos->brm_array,
>>> > -                         2 * brm_infos->alloc_brm_count);
>>> > -              if (brm_infos->brm_array == NULL) {
>>> > -                fprintf (stderr,
>>> > -                         "Cannot allocate memory for br
>>> > mispredicts.\n");
>>> > -                __destroy_pmu_tool_header (tool_header);
>>> > -                free (buf);
>>> > -                fclose (fp);
>>> > -                return 1;
>>> > -              }
>>> > -            }
>>> > -          brm_infos->brm_array[brm_infos->brm_count - 1] = brm;
>>> > -        }
>>> > -      else
>>> > -        /* Delete invalid line.  */
>>> > -        XDELETE (brm);
>>> > -    }
>>> > -  free (buf);
>>> > -  fclose (fp);
>>> > -  brm_infos->pmu_tool_header = tool_header;
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Start the monitoring process using pmu tool. Return 0 on success,
>>> > -   non-zero otherwise.  */
>>> > -
>>> > -static int
>>> > -pmu_start (void)
>>> > -{
>>> > -  pid_t pid;
>>> > -
>>> > -  /* no start function */
>>> > -  if (!the_pmu_tool_info->tool_details->start_pmu_module)
>>> > -    return 1;
>>> > -
>>> > -  pid = fork ();
>>> > -  if (pid == -1)
>>> > -    {
>>> > -      /* error condition */
>>> > -      fprintf (stderr, "Cannot create PMU profiling process,
>>> > exiting.\n");
>>> > -      return 1;
>>> > -    }
>>> > -  else if (pid == 0)
>>> > -    {
>>> > -      /* child */
>>> > -      pid_t ppid = getppid();
>>> > -      char *tmpfile = the_pmu_tool_info->raw_pmu_profile_filename;
>>> > -      const char **pfmon_args =
>>> > the_pmu_tool_info->tool_details->arg_array;
>>> > -      int new_stderr_fd;
>>> > -
>>> > -      /* Redirect stderr from the child process into a separate file.
>>> > */
>>> > -      new_stderr_fd = creat (the_pmu_tool_info->tool_stderr_filename,
>>> > -                             S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>>> > -      if (new_stderr_fd != -1)
>>> > -          dup2 (new_stderr_fd, 2);
>>> > -      /* The following does an exec and thus is not expected to return.
>>> > */
>>> > -      the_pmu_tool_info->tool_details->start_pmu_module(ppid, tmpfile,
>>> > -                                                        pfmon_args);
>>> > -      /* exec returned, an error condition.  */
>>> > -      fprintf (stderr, "could not create profiling process: %s\n",
>>> > -               the_pmu_tool_info->tool_details->arg_array[0]);
>>> > -      _exit (0);
>>> > -    }
>>> > -  else
>>> > -    {
>>> > -      /* parent */
>>> > -      the_pmu_tool_info->pmu_tool_pid = pid;
>>> > -      return 0;
>>> > -    }
>>> > -}
>>> > -
>>> >  /* Allocate and initialize pmu load latency structure.  */
>>> >
>>> >  static void *
>>> > @@ -1205,160 +154,6 @@ init_pmu_branch_mispredict (void)
>>> >    return (void *)brm_info;
>>> >  }
>>> >
>>> > -/* Initialize pmu tool based upon PMU_INFO. Sets the appropriate tool
>>> > -   type in the global the_pmu_tool_info.  */
>>> > -
>>> > -static int
>>> > -init_pmu_tool (struct gcov_pmu_info *pmu_info)
>>> > -{
>>> > -  the_pmu_tool_info->pmu_profiling_state = PMU_NONE;
>>> > -  the_pmu_tool_info->verbose = 0;
>>> > -  the_pmu_tool_info->tool = PTT_PFMON;  /* we support only pfmon */
>>> > -  the_pmu_tool_info->pmu_tool_pid = 0;
>>> > -  the_pmu_tool_info->top_n_address = pmu_info->pmu_top_n_address;
>>> > -  the_pmu_tool_info->symbolizer_pid = 0;
>>> > -  the_pmu_tool_info->symbolizer_to_pipefd[0] = -1;
>>> > -  the_pmu_tool_info->symbolizer_to_pipefd[1] = -1;
>>> > -  the_pmu_tool_info->symbolizer_from_pipefd[0] = -1;
>>> > -  the_pmu_tool_info->symbolizer_from_pipefd[1] = -1;
>>> > -
>>> > -  if (parse_pmu_profile_options (pmu_info->pmu_tool))
>>> > -    return 1;
>>> > -
>>> > -  if (the_pmu_tool_info->pmu_profiling_state == PMU_ERROR)
>>> > -    {
>>> > -      fprintf (stderr, "Unsupported PMU module: %s, disabling PMU
>>> > profiling.\n",
>>> > -               pmu_info->pmu_tool);
>>> > -      return 1;
>>> > -    }
>>> > -
>>> > -  if (the_pmu_tool_info->tool_details->init_pmu_module)
>>> > -    /* initialize module */
>>> > -    the_pmu_tool_info->pmu_data =
>>> > -      the_pmu_tool_info->tool_details->init_pmu_module();
>>> > -  return 0;
>>> > -}
>>> > -
>>> > -/* Initialize PMU profiling based upon the information passed in
>>> > -   PMU_INFO and use pmu_profile_filename as the file to store the PMU
>>> > -   profile.  This is called multiple times from libgcov, once per
>>> > -   object file.  We need to make sure to do the necessary
>>> > -   initialization only the first time.  For subsequent invocations it
>>> > -   behaves as a NOOP.  */
>>> > -
>>> > -void
>>> > -__gcov_init_pmu_profiler (struct gcov_pmu_info *pmu_info)
>>> > -{
>>> > -  char *raw_pmu_profile_filename;
>>> > -  char *tool_stderr_filename;
>>> > -  if (!pmu_info || !pmu_info->pmu_profile_filename ||
>>> > !pmu_info->pmu_tool)
>>> > -    return;
>>> > -
>>> > -  /* Allocate the global structure on first invocation.  */
>>> > -  if (!the_pmu_tool_info)
>>> > -    {
>>> > -      the_pmu_tool_info = XNEWVEC (struct pmu_tool_info, 1);
>>> > -      if (!the_pmu_tool_info)
>>> > -        {
>>> > -          fprintf (stderr, "Error allocating memory for PMU tool\n");
>>> > -          return;
>>> > -        }
>>> > -      if (init_pmu_tool (pmu_info))
>>> > -        {
>>> > -          /* Initialization error.  */
>>> > -          XDELETE (the_pmu_tool_info);
>>> > -          the_pmu_tool_info = 0;
>>> > -          return;
>>> > -        }
>>> > -    }
>>> > -
>>> > -  switch (the_pmu_tool_info->pmu_profiling_state)
>>> > -    {
>>> > -    case PMU_NONE:
>>> > -      the_pmu_tool_info->pmu_profile_filename =
>>> > -        strdup (pmu_info->pmu_profile_filename);
>>> > -      /* Construct an intermediate filename by substituting trailing
>>> > -         '.gcda' with '.pmud'.  */
>>> > -      raw_pmu_profile_filename = strdup
>>> > (pmu_info->pmu_profile_filename);
>>> > -      if (raw_pmu_profile_filename == NULL)
>>> > -        {
>>> > -          fprintf (stderr, "Cannot allocate memory\n");
>>> > -          exit (1);
>>> > -        }
>>> > -      strcpy (raw_pmu_profile_filename + strlen
>>> > (raw_pmu_profile_filename) - 4,
>>> > -              "pmud");
>>> > -
>>> > -      /* Construct a filename for collecting PMU tool's stderr by
>>> > -         substituting trailing '.gcda' with '.stderr'.  */
>>> > -      tool_stderr_filename =
>>> > -        XNEWVEC (char, strlen (pmu_info->pmu_profile_filename) + 1 +
>>> > 2);
>>> > -      strcpy (tool_stderr_filename, pmu_info->pmu_profile_filename);
>>> > -      strcpy (tool_stderr_filename + strlen (tool_stderr_filename) - 4,
>>> > -              "stderr");
>>> > -      the_pmu_tool_info->raw_pmu_profile_filename =
>>> > raw_pmu_profile_filename;
>>> > -      the_pmu_tool_info->tool_stderr_filename = tool_stderr_filename;
>>> > -      the_pmu_tool_info->pmu_profiling_state = PMU_INITIALIZED;
>>> > -      break;
>>> > -
>>> > -    case PMU_INITIALIZED:
>>> > -    case PMU_OFF:
>>> > -    case PMU_ON:
>>> > -    case PMU_ERROR:
>>> > -      break;
>>> > -    default:
>>> > -      break;
>>> > -    }
>>> > -}
>>> > -
>>> > -/* Start PMU profiling.  It updates the current state.  */
>>> > -
>>> > -void
>>> > -__gcov_start_pmu_profiler (void)
>>> > -{
>>> > -  if (!the_pmu_tool_info)
>>> > -    return;
>>> > -
>>> > -  switch (the_pmu_tool_info->pmu_profiling_state)
>>> > -    {
>>> > -    case PMU_INITIALIZED:
>>> > -      if (!pmu_start ())
>>> > -        the_pmu_tool_info->pmu_profiling_state = PMU_ON;
>>> > -      else
>>> > -        the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
>>> > -      break;
>>> > -
>>> > -    case PMU_NONE:
>>> > -      /* PMU was not properly initialized, don't attempt start it.  */
>>> > -      the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
>>> > -      break;
>>> > -
>>> > -    case PMU_OFF:
>>> > -      /* Restarting PMU is not yet supported.  */
>>> > -    case PMU_ON:
>>> > -      /* Do nothing.  */
>>> > -    case PMU_ERROR:
>>> > -      break;
>>> > -
>>> > -    default:
>>> > -      break;
>>> > -    }
>>> > -}
>>> > -
>>> > -/* Stop PMU profiling.  Currently it doesn't do anything except
>>> > -   bookkeeping.  */
>>> > -
>>> > -void
>>> > -__gcov_stop_pmu_profiler (void)
>>> > -{
>>> > -  if (!the_pmu_tool_info)
>>> > -    return;
>>> > -
>>> > -  if (the_pmu_tool_info->tool_details->stop_pmu_module)
>>> > -    the_pmu_tool_info->tool_details->stop_pmu_module();
>>> > -  if (the_pmu_tool_info->pmu_profiling_state == PMU_ON)
>>> > -    the_pmu_tool_info->pmu_profiling_state = PMU_OFF;
>>> > -}
>>> > -
>>> >  /* Write the load latency information LL_INFO into the gcda file.  */
>>> >
>>> >  static void
>>> > @@ -1400,55 +195,6 @@ gcov_write_branch_mispredict_line (const gcov_pmu_
>>> >    gcov_write_string (brm_info->filename);
>>> >  }
>>> >
>>> > -/* Write load latency information INFO into the gcda file.  The gcda
>>> > -   file has already been opened and is available for writing.  */
>>> > -
>>> > -static void
>>> > -gcov_write_load_latency_infos (void *info)
>>> > -{
>>> > -  unsigned i;
>>> > -  const ll_infos_t *ll_infos = (const ll_infos_t *)info;
>>> > -  gcov_unsigned_t stamp = 0;  /* Don't use stamp as we don't support
>>> > merge.  */
>>> > -  /* We don't support merge, and instead always rewrite the file.  But
>>> > -     to rewrite a gcov file we must first read it, however the read
>>> > -     value is ignored.  */
>>> > -  gcov_read_unsigned ();
>>> > -  gcov_rewrite ();
>>> > -  gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
>>> > -  gcov_write_unsigned (stamp);
>>> > -  if (ll_infos->pmu_tool_header)
>>> > -    gcov_write_tool_header (ll_infos->pmu_tool_header);
>>> > -  for (i = 0; i < ll_infos->ll_count; ++i)
>>> > -    {
>>> > -      /* Write each line.  */
>>> > -      gcov_write_ll_line (ll_infos->ll_array[i]);
>>> > -    }
>>> > -  gcov_truncate ();
>>> > -}
>>> > -
>>> > -/* Write branch mispredict information INFO into the gcda file.  The
>>> > -   gcda file has already been opened and is available for writing.  */
>>> > -
>>> > -static void
>>> > -gcov_write_branch_mispredict_infos (void *info)
>>> > -{
>>> > -  unsigned i;
>>> > -  const brm_infos_t *brm_infos = (const brm_infos_t *)info;
>>> > -  gcov_unsigned_t stamp = 0;  /* Don't use stamp as we don't support
>>> > merge. */
>>> > -  /* We don't support merge, and instead always rewrite the file.  */
>>> > -  gcov_rewrite ();
>>> > -  gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
>>> > -  gcov_write_unsigned (stamp);
>>> > -  if (brm_infos->pmu_tool_header)
>>> > -    gcov_write_tool_header (brm_infos->pmu_tool_header);
>>> > -  for (i = 0; i < brm_infos->brm_count; ++i)
>>> > -    {
>>> > -      /* Write each line.  */
>>> > -      gcov_write_branch_mispredict_line (brm_infos->brm_array[i]);
>>> > -    }
>>> > -  gcov_truncate ();
>>> > -}
>>> > -
>>> >  /* Compute TOOL_HEADER length for writing into the gcov file.  */
>>> >
>>> >  static gcov_unsigned_t
>>> > @@ -1483,70 +229,4 @@ gcov_write_tool_header (gcov_pmu_tool_header_t *he
>>> >    gcov_write_string (header->full_header);
>>> >  }
>>> >
>>> > -
>>> > -/* End PMU profiling. If GCDA_ERROR is non-zero then write profiling
>>> > data into
>>> > -   already open gcda file */
>>> > -
>>> > -void
>>> > -__gcov_end_pmu_profiler (int gcda_error)
>>> > -{
>>> > -  int pid_status;
>>> > -  int wait_status;
>>> > -  pid_t pid;
>>> > -  pmu_tool_fns *tool_details;
>>> > -
>>> > -  if (!the_pmu_tool_info)
>>> > -    return;
>>> > -
>>> > -  tool_details = the_pmu_tool_info->tool_details;
>>> > -  pid = the_pmu_tool_info->pmu_tool_pid;
>>> > -  if (pid)
>>> > -    {
>>> > -      if (tool_debug)
>>> > -        fprintf (stderr, "terminating PMU profiling process %ld\n",
>>> > (long)pid);
>>> > -      kill (pid, SIGTERM);
>>> > -      if (tool_debug)
>>> > -        fprintf (stderr, "parent: waiting for pmu process to end\n");
>>> > -      wait_status = waitpid (pid, &pid_status, 0);
>>> > -      if (tool_debug) {
>>> > -        if (wait_status == pid)
>>> > -          fprintf (stderr, "Normal exit. Child terminated.\n");
>>> > -        else
>>> > -          fprintf (stderr, "Abnormal exit. child status, %d.\n",
>>> > pid_status);
>>> > -      }
>>> > -    }
>>> > -
>>> > -  if (the_pmu_tool_info->pmu_profiling_state != PMU_OFF)
>>> > -    {
>>> > -      /* nothing to do */
>>> > -      fprintf (stderr,
>>> > -               "__gcov_dump_pmu_profile: incorrect pmu state: %d, pid:
>>> > %ld\n",
>>> > -               the_pmu_tool_info->pmu_profiling_state,
>>> > -               (unsigned long)pid);
>>> > -      return;
>>> > -    }
>>> > -
>>> > -  if (!tool_details->parse_pmu_output)
>>> > -    return;
>>> > -
>>> > -  /* Since we are going to parse the output, we also need symbolizer.
>>> > */
>>> > -  if (tool_details->start_symbolizer)
>>> > -    tool_details->start_symbolizer (getpid ());
>>> > -
>>> > -  if (!tool_details->parse_pmu_output
>>> > -      (the_pmu_tool_info->raw_pmu_profile_filename,
>>> > -       the_pmu_tool_info->pmu_data))
>>> > -    {
>>> > -      if (!gcda_error && tool_details->gcov_write_pmu_data)
>>> > -        /* Write tool output into the gcda file.  */
>>> > -        tool_details->gcov_write_pmu_data
>>> > (the_pmu_tool_info->pmu_data);
>>> > -    }
>>> > -
>>> > -  if (tool_details->end_symbolizer)
>>> > -    tool_details->end_symbolizer ();
>>> > -
>>> > -  if (tool_details->cleanup_pmu_data)
>>> > -    tool_details->cleanup_pmu_data (the_pmu_tool_info->pmu_data);
>>> > -}
>>> > -
>>> >  #endif
>>> >
>>> > --
>>> > This patch is available for review at
>>> > http://codereview.appspot.com/6442086
>>>
>>>
>>>
>>> --
>>> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
>>
>>
>
>
>
> --
> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]