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 <cm...@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 <tejohn...@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 <cm...@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 <cm...@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, <_10, <_32, <_64, >> > <_256, >> > - <_1024, >_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 | tejohn...@google.com | 408-460-2413 > > -- Teresa Johnson | Software Engineer | tejohn...@google.com | 408-460-2413