/* Copyright (C) 2021-2026 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h"#include <unistd.h>#include <strings.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/statvfs.h>#include <sys/param.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#include <ctype.h>#include <dirent.h>#include <libgen.h>#include <assert.h>#include <regex.h> /* regcomp() */ #include "util.h"#include "libiberty.h"#include "collctrl.h"#include "hwcdrv.h"#include "StringBuilder.h" #define SP_GROUP_HEADER "#analyzer experiment group" /* If the system doesn't provide strsignal, we get it defined in libiberty but no declaration is supplied. */#if !defined (HAVE_STRSIGNAL) && !defined (strsignal)extern const char *strsignal (int);#endif static const char *get_fstype (char *);static cpu_info_t cpu_info; static voidread_str (char *from, char **to){ if (*to != NULL) return; for (char *s = from; *s; s++) if (*s != ':' && *s != '\t' && *s != ' ') { for (int i = ((int) strlen (s)) - 1; i >= 0; i--) { if (s[i] != '\n' && s[i] != ' ' && s[i] != '\t') { *to = xstrndup (s, i + 1); return; } } return; // string is empty }} static intread_int (char *from){ char *val = strchr (from, ':'); if (val) return (int) strtol (val + 1, NULL, 0); return 0;} cpu_info_t *read_cpuinfo (){ static int inited = 0; if (inited) return &cpu_info; inited = 1; #if defined(__aarch64__) asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_info.cpu_clk_freq));#elif defined(__riscv) // Set 1000 MHz for minimal support RISC-V, will fix with a better method to get cpu clock frequency. cpu_info.cpu_clk_freq = 1000;#endif // Read /proc/cpuinfo to get CPU info and clock rate FILE *procf = fopen ("/proc/cpuinfo", "r"); if (procf != NULL) { char temp[1024]; while (fgets (temp, (int) sizeof (temp), procf) != NULL) { if (strncmp (temp, "processor", 9) == 0) cpu_info.cpu_cnt++; else if (strncmp (temp, "cpu MHz", 7) == 0) cpu_info.cpu_clk_freq = read_int (temp + 9); else if (strncmp (temp, "cpu family", 10) == 0) cpu_info.cpu_family = read_int (temp + 10); else if (strncmp (temp, "vendor_id", 9) == 0 || strncmp (temp, "mvendorid", 9) == 0) { if (cpu_info.cpu_vendorstr == NULL) read_str (temp + 9, &cpu_info.cpu_vendorstr); } else if (strncmp (temp, "model name", 10) == 0) { if (cpu_info.cpu_modelstr == NULL) read_str (temp + 10, &cpu_info.cpu_modelstr); } else if (strncmp (temp, "model", 5) == 0) cpu_info.cpu_model = read_int (temp + 5); else if (strncmp (temp, "CPU implementer", 15) == 0) cpu_info.cpu_family = read_int (temp + 15); else if (strncmp (temp, "CPU architecture", 16) == 0) cpu_info.cpu_model = read_int (temp + 16); } fclose (procf); } if (cpu_info.cpu_vendorstr == NULL)#if defined(__aarch64__) cpu_info.cpu_vendorstr = xstrdup (AARCH64_VENDORSTR_ARM);#else cpu_info.cpu_vendorstr = GTXT ("Unknown processor");#endif if (cpu_info.cpu_modelstr == NULL) cpu_info.cpu_modelstr = GTXT ("Unknown cpu model"); return &cpu_info;} Coll_Ctrl::Coll_Ctrl (int _interactive, bool _defHWC, bool _kernelHWC){ char hostname[MAXPATHLEN]; interactive = _interactive; defHWC = _defHWC; kernelHWC = _kernelHWC; /* set this host's parameters */ gethostname (hostname, 1023); node_name = xstrdup (hostname); char *p = strchr (node_name, (int) '.'); if (p != NULL) *p = 0; default_stem = xstrdup ("test"); cpu_info_t *cpu_p = read_cpuinfo (); ncpus = cpu_p->cpu_cnt; cpu_clk_freq = cpu_p->cpu_clk_freq; /* check resolution of system clock */ sys_resolution = sysconf (_SC_CLK_TCK); /* determine memory page size and number of pages */ npages = sysconf (_SC_PHYS_PAGES); page_size = sysconf (_SC_PAGE_SIZE); /* set default clock parameters */ hwcprof_enabled_cnt = 0; // must be set before calling determine_profile_params(); determine_profile_params (); // inits clk_params which is used by clock profiling AND HWCs /* set default control values */ debug_mode = 0;#if defined(GPROFNG_JAVA_PROFILING) java_mode = 1;#else java_mode = 0;#endif java_default = 1; java_path = NULL; java_args = NULL; njava_args = 0; follow_mode = FOLLOW_ON; follow_default = 1; follow_spec_usr = NULL; follow_spec_cmp = NULL; prof_idle = 1; archive_mode = xstrdup ("on"); pauseresume_sig = 0; sample_sig = 0; uinterrupt = 0; attach_pid = 0; time_run = 0; start_delay = 0; /* clear the string pointers */ uexpt_name = NULL; expt_name = NULL; expt_dir = NULL; base_name = NULL; udir_name = NULL; store_dir = NULL; prev_store_dir = xstrdup (""); store_ptr = NULL; expt_group = NULL; target_name = NULL; data_desc = NULL; lockname = NULL; hwc_string = NULL; project_home = NULL; lockfd = -1; /* set default data collection values */ enabled = 0; opened = 0; clkprof_enabled = 1; clkprof_default = 1; for (unsigned ii = 0; ii < MAX_PICS; ii++) { memset (&hwctr[ii], 0, sizeof (Hwcentry)); hwctr[ii].reg_num = -1; } hwcprof_default = 0; if (defHWC == true) { setup_hwc (); hwcprof_default = 1; } else // disable the default, and reset the counters hwcprof_enabled_cnt = 0; synctrace_enabled = 0; synctrace_thresh = -1; synctrace_scope = 0; heaptrace_mode = NULL; iotrace_enabled = 0; count_enabled = 0; Iflag = 0; Nflag = 0; sample_period = 1; sample_default = 1; size_limit = 0; nofswarn = 0; expno = 1; // ensure that the default name is updated // but don't print any message (void) preprocess_names (); (void) update_expt_name (false, false);} /* Copy constructor */Coll_Ctrl::Coll_Ctrl (Coll_Ctrl * cc){ uinterrupt = 0; interactive = cc->interactive; defHWC = cc->defHWC; kernelHWC = cc->kernelHWC; node_name = xstrdup (cc->node_name); default_stem = xstrdup (cc->default_stem); ncpus = cc->ncpus; cpu_clk_freq = cc->cpu_clk_freq; npages = cc->npages; page_size = cc->page_size; debug_mode = cc->debug_mode; java_mode = cc->java_mode; java_default = cc->java_default; java_path = NULL; java_args = NULL; njava_args = 0; follow_mode = cc->follow_mode; follow_default = cc->follow_default; if (cc->follow_spec_usr) { follow_spec_usr = xstrdup (cc->follow_spec_usr); follow_spec_cmp = xstrdup (cc->follow_spec_cmp); } else { follow_spec_usr = NULL; follow_spec_cmp = NULL; } archive_mode = xstrdup (cc->archive_mode); pauseresume_sig = cc->pauseresume_sig; sample_sig = cc->sample_sig; time_run = cc->time_run; start_delay = cc->start_delay; clk_params = cc->clk_params; clkprof_enabled = cc->clkprof_enabled; clkprof_default = cc->clkprof_default; clkprof_timer = cc->clkprof_timer; clkprof_timer_target = cc->clkprof_timer_target; // copy HW counter information hwcprof_default = cc->hwcprof_default; hwcprof_enabled_cnt = cc->hwcprof_enabled_cnt; if (cc->hwc_string != NULL) hwc_string = xstrdup (cc->hwc_string); else hwc_string = NULL; for (int i = 0; i < hwcprof_enabled_cnt; i++) hwcentry_dup (&hwctr[i], &(cc->hwctr[i])); project_home = cc->project_home ? xstrdup (cc->project_home) : NULL; synctrace_enabled = cc->synctrace_enabled; synctrace_thresh = cc->synctrace_thresh; synctrace_scope = cc->synctrace_scope; heaptrace_mode = dbe_strdup(cc->heaptrace_mode); iotrace_enabled = cc->iotrace_enabled; count_enabled = cc->count_enabled; Iflag = cc->Iflag; Nflag = cc->Nflag; sample_period = cc->sample_period; sample_default = cc->sample_default; size_limit = cc->size_limit; nofswarn = cc->nofswarn; // these will get reset during preprocess_names() expt_name = NULL; expt_dir = NULL; store_dir = NULL; base_name = NULL; expno = 1; // these represent user settings expt_group = NULL; if (cc->expt_group != NULL) expt_group = xstrdup (cc->expt_group); uexpt_name = NULL; if (cc->uexpt_name != NULL) uexpt_name = xstrdup (cc->uexpt_name); udir_name = NULL; if (cc->udir_name != NULL) udir_name = xstrdup (cc->udir_name); /* clear the string pointers */ prev_store_dir = xstrdup (""); store_ptr = NULL; target_name = NULL; data_desc = NULL; lockname = NULL; lockfd = -1; /* set default data collection values */ enabled = cc->enabled; opened = 0; nofswarn = cc->nofswarn; sys_resolution = cc->sys_resolution; // ensure that the default name is updated (void) preprocess_names (); (void) update_expt_name (false, false); build_data_desc ();} Coll_Ctrl::~Coll_Ctrl (){ free (node_name); free (expt_name); free (expt_dir); free (base_name); free (udir_name); free (store_dir); free (store_ptr); free (expt_group); free (target_name); free (data_desc); free (lockname); free (hwc_string); free (project_home); free (java_path); free (heaptrace_mode); hwcprof_enabled_cnt = 0;} /* set up the experiment */char *Coll_Ctrl::setup_experiment (){ char *ret; if (enabled == 0) return NULL; build_data_desc (); /* create the experiment directory */ ret = create_exp_dir (); if (ret != NULL) return ret; /* if an experiment-group, join it */ ret = join_group (); if (ret != NULL) { remove_exp_dir (); return ret; } /* all is OK, return 0 */ opened = 1; return NULL;} voidColl_Ctrl::interrupt (){ uinterrupt = 1;} char *Coll_Ctrl::enable_expt (){ if (opened == 1) return xstrdup (GTXT ("Experiment is active; command ignored.\n")); if (cpu_clk_freq == 0) return xstrdup (GTXT ("Can not determine CPU clock frequency.\n")); if (sys_resolution == 0) return xstrdup (GTXT ("System clock profile resolution can not be determined.\n")); enabled = 1; return NULL;} /* close the experiment */voidColl_Ctrl::close_expt (){ opened = 0; (void) update_expt_name (false, false);} /* close and delete the experiment */voidColl_Ctrl::delete_expt (){ if (opened == 0) return; remove_exp_dir (); /* The order of removing the directory and closing * the experiment may seem unnatural, but it's not. * We do need to update names when we close the experiment * (actually Coll_Ctrl object) and we can't remove anything * after that. */ close_expt ();} // Check the experiment settings for consistency. Returns NULL if OK,// or an error message if there are invalid combinations of settings char *Coll_Ctrl::check_consistency (){ /* check for Java arguments, but not Java profiling */ if (java_args != NULL && java_mode == 0) return xstrdup (GTXT ("Java arguments can not be set if Java profiling is not enabled.\n")); /* if count data, no other data is allowed */ if (count_enabled != 0 && ((clkprof_default != 1 && clkprof_enabled != 0) || hwcprof_enabled_cnt != 0 || synctrace_enabled != 0 || heaptrace_mode != NULL || iotrace_enabled != 0)) return xstrdup (GTXT ("Count data cannot be collected along with any other data.\n")); /* if count data, various other options are not allowed */ if (count_enabled != 0 && ((java_mode != 0 && java_default != 1) || java_args != NULL || debug_mode != 0 || (follow_mode != 0 && follow_default != 1) || pauseresume_sig != 0 || sample_sig != 0 || (sample_default != 1 && sample_period != 0) || time_run != 0)) return xstrdup (GTXT ("Count data cannot be collected with any of -F -S -y -l -j -J -x -t .\n")); /* if not count data, I and N options are not allowed */ if (count_enabled == 0 && (Iflag != 0 || Nflag != 0)) return xstrdup (GTXT ("-I or -N can only be specified with count data.\n")); return NULL;} char *Coll_Ctrl::check_expt (char **warn){ char *ret; *warn = NULL; ret = check_consistency (); if (ret != NULL) /* something is wrong, return the error */ return ret; /* check for heaptrace and java -- warn that it covers native allocations only */ if (heaptrace_mode != NULL && java_mode == 1 && java_default == 0) *warn = xstrdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n")); /* if no profiling data selected, warn the user */ if (clkprof_enabled == 0 && hwcprof_enabled_cnt == 0 && synctrace_enabled == 0 && heaptrace_mode == NULL && iotrace_enabled == 0 && count_enabled == 0) *warn = xstrdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n")); build_data_desc (); /* verify that the directory exists */ struct stat statbuf; if (stat (store_dir, &statbuf) != 0) return dbe_sprintf (GTXT ("Store directory %s is not accessible: %s\n"), store_dir, strerror (errno)); if (access (store_dir, W_OK) != 0) return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),Lines 1–500 of 3031. Load more
/* Copyright (C) 2021-2026 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include <unistd.h> #include <strings.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <sys/param.h> #include <signal.h> #include <fcntl.h> #include <errno.h> #include <ctype.h> #include <dirent.h> #include <libgen.h> #include <assert.h> #include <regex.h> /* regcomp() */ #include "util.h" #include "libiberty.h" #include "collctrl.h" #include "hwcdrv.h" #include "StringBuilder.h" #define SP_GROUP_HEADER "#analyzer experiment group" /* If the system doesn't provide strsignal, we get it defined in libiberty but no declaration is supplied. */ #if !defined (HAVE_STRSIGNAL) && !defined (strsignal) extern const char *strsignal (int); #endif static const char *get_fstype (char *); static cpu_info_t cpu_info; static void read_str (char *from, char **to) { if (*to != NULL) return; for (char *s = from; *s; s++) if (*s != ':' && *s != '\t' && *s != ' ') { for (int i = ((int) strlen (s)) - 1; i >= 0; i--) { if (s[i] != '\n' && s[i] != ' ' && s[i] != '\t') { *to = xstrndup (s, i + 1); return; } } return; // string is empty } } static int read_int (char *from) { char *val = strchr (from, ':'); if (val) return (int) strtol (val + 1, NULL, 0); return 0; } cpu_info_t * read_cpuinfo () { static int inited = 0; if (inited) return &cpu_info; inited = 1; #if defined(__aarch64__) asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_info.cpu_clk_freq)); #elif defined(__riscv) // Set 1000 MHz for minimal support RISC-V, will fix with a better method to get cpu clock frequency. cpu_info.cpu_clk_freq = 1000; #endif // Read /proc/cpuinfo to get CPU info and clock rate FILE *procf = fopen ("/proc/cpuinfo", "r"); if (procf != NULL) { char temp[1024]; while (fgets (temp, (int) sizeof (temp), procf) != NULL) { if (strncmp (temp, "processor", 9) == 0) cpu_info.cpu_cnt++; else if (strncmp (temp, "cpu MHz", 7) == 0) cpu_info.cpu_clk_freq = read_int (temp + 9); else if (strncmp (temp, "cpu family", 10) == 0) cpu_info.cpu_family = read_int (temp + 10); else if (strncmp (temp, "vendor_id", 9) == 0 || strncmp (temp, "mvendorid", 9) == 0) { if (cpu_info.cpu_vendorstr == NULL) read_str (temp + 9, &cpu_info.cpu_vendorstr); } else if (strncmp (temp, "model name", 10) == 0) { if (cpu_info.cpu_modelstr == NULL) read_str (temp + 10, &cpu_info.cpu_modelstr); } else if (strncmp (temp, "model", 5) == 0) cpu_info.cpu_model = read_int (temp + 5); else if (strncmp (temp, "CPU implementer", 15) == 0) cpu_info.cpu_family = read_int (temp + 15); else if (strncmp (temp, "CPU architecture", 16) == 0) cpu_info.cpu_model = read_int (temp + 16); } fclose (procf); } if (cpu_info.cpu_vendorstr == NULL) #if defined(__aarch64__) cpu_info.cpu_vendorstr = xstrdup (AARCH64_VENDORSTR_ARM); #else cpu_info.cpu_vendorstr = GTXT ("Unknown processor"); #endif if (cpu_info.cpu_modelstr == NULL) cpu_info.cpu_modelstr = GTXT ("Unknown cpu model"); return &cpu_info; } Coll_Ctrl::Coll_Ctrl (int _interactive, bool _defHWC, bool _kernelHWC) { char hostname[MAXPATHLEN]; interactive = _interactive; defHWC = _defHWC; kernelHWC = _kernelHWC; /* set this host's parameters */ gethostname (hostname, 1023); node_name = xstrdup (hostname); char *p = strchr (node_name, (int) '.'); if (p != NULL) *p = 0; default_stem = xstrdup ("test"); cpu_info_t *cpu_p = read_cpuinfo (); ncpus = cpu_p->cpu_cnt; cpu_clk_freq = cpu_p->cpu_clk_freq; /* check resolution of system clock */ sys_resolution = sysconf (_SC_CLK_TCK); /* determine memory page size and number of pages */ npages = sysconf (_SC_PHYS_PAGES); page_size = sysconf (_SC_PAGE_SIZE); /* set default clock parameters */ hwcprof_enabled_cnt = 0; // must be set before calling determine_profile_params(); determine_profile_params (); // inits clk_params which is used by clock profiling AND HWCs /* set default control values */ debug_mode = 0; #if defined(GPROFNG_JAVA_PROFILING) java_mode = 1; #else java_mode = 0; #endif java_default = 1; java_path = NULL; java_args = NULL; njava_args = 0; follow_mode = FOLLOW_ON; follow_default = 1; follow_spec_usr = NULL; follow_spec_cmp = NULL; prof_idle = 1; archive_mode = xstrdup ("on"); pauseresume_sig = 0; sample_sig = 0; uinterrupt = 0; attach_pid = 0; time_run = 0; start_delay = 0; /* clear the string pointers */ uexpt_name = NULL; expt_name = NULL; expt_dir = NULL; base_name = NULL; udir_name = NULL; store_dir = NULL; prev_store_dir = xstrdup (""); store_ptr = NULL; expt_group = NULL; target_name = NULL; data_desc = NULL; lockname = NULL; hwc_string = NULL; project_home = NULL; lockfd = -1; /* set default data collection values */ enabled = 0; opened = 0; clkprof_enabled = 1; clkprof_default = 1; for (unsigned ii = 0; ii < MAX_PICS; ii++) { memset (&hwctr[ii], 0, sizeof (Hwcentry)); hwctr[ii].reg_num = -1; } hwcprof_default = 0; if (defHWC == true) { setup_hwc (); hwcprof_default = 1; } else // disable the default, and reset the counters hwcprof_enabled_cnt = 0; synctrace_enabled = 0; synctrace_thresh = -1; synctrace_scope = 0; heaptrace_mode = NULL; iotrace_enabled = 0; count_enabled = 0; Iflag = 0; Nflag = 0; sample_period = 1; sample_default = 1; size_limit = 0; nofswarn = 0; expno = 1; // ensure that the default name is updated // but don't print any message (void) preprocess_names (); (void) update_expt_name (false, false); } /* Copy constructor */ Coll_Ctrl::Coll_Ctrl (Coll_Ctrl * cc) { uinterrupt = 0; interactive = cc->interactive; defHWC = cc->defHWC; kernelHWC = cc->kernelHWC; node_name = xstrdup (cc->node_name); default_stem = xstrdup (cc->default_stem); ncpus = cc->ncpus; cpu_clk_freq = cc->cpu_clk_freq; npages = cc->npages; page_size = cc->page_size; debug_mode = cc->debug_mode; java_mode = cc->java_mode; java_default = cc->java_default; java_path = NULL; java_args = NULL; njava_args = 0; follow_mode = cc->follow_mode; follow_default = cc->follow_default; if (cc->follow_spec_usr) { follow_spec_usr = xstrdup (cc->follow_spec_usr); follow_spec_cmp = xstrdup (cc->follow_spec_cmp); } else { follow_spec_usr = NULL; follow_spec_cmp = NULL; } archive_mode = xstrdup (cc->archive_mode); pauseresume_sig = cc->pauseresume_sig; sample_sig = cc->sample_sig; time_run = cc->time_run; start_delay = cc->start_delay; clk_params = cc->clk_params; clkprof_enabled = cc->clkprof_enabled; clkprof_default = cc->clkprof_default; clkprof_timer = cc->clkprof_timer; clkprof_timer_target = cc->clkprof_timer_target; // copy HW counter information hwcprof_default = cc->hwcprof_default; hwcprof_enabled_cnt = cc->hwcprof_enabled_cnt; if (cc->hwc_string != NULL) hwc_string = xstrdup (cc->hwc_string); else hwc_string = NULL; for (int i = 0; i < hwcprof_enabled_cnt; i++) hwcentry_dup (&hwctr[i], &(cc->hwctr[i])); project_home = cc->project_home ? xstrdup (cc->project_home) : NULL; synctrace_enabled = cc->synctrace_enabled; synctrace_thresh = cc->synctrace_thresh; synctrace_scope = cc->synctrace_scope; heaptrace_mode = dbe_strdup(cc->heaptrace_mode); iotrace_enabled = cc->iotrace_enabled; count_enabled = cc->count_enabled; Iflag = cc->Iflag; Nflag = cc->Nflag; sample_period = cc->sample_period; sample_default = cc->sample_default; size_limit = cc->size_limit; nofswarn = cc->nofswarn; // these will get reset during preprocess_names() expt_name = NULL; expt_dir = NULL; store_dir = NULL; base_name = NULL; expno = 1; // these represent user settings expt_group = NULL; if (cc->expt_group != NULL) expt_group = xstrdup (cc->expt_group); uexpt_name = NULL; if (cc->uexpt_name != NULL) uexpt_name = xstrdup (cc->uexpt_name); udir_name = NULL; if (cc->udir_name != NULL) udir_name = xstrdup (cc->udir_name); /* clear the string pointers */ prev_store_dir = xstrdup (""); store_ptr = NULL; target_name = NULL; data_desc = NULL; lockname = NULL; lockfd = -1; /* set default data collection values */ enabled = cc->enabled; opened = 0; nofswarn = cc->nofswarn; sys_resolution = cc->sys_resolution; // ensure that the default name is updated (void) preprocess_names (); (void) update_expt_name (false, false); build_data_desc (); } Coll_Ctrl::~Coll_Ctrl () { free (node_name); free (expt_name); free (expt_dir); free (base_name); free (udir_name); free (store_dir); free (store_ptr); free (expt_group); free (target_name); free (data_desc); free (lockname); free (hwc_string); free (project_home); free (java_path); free (heaptrace_mode); hwcprof_enabled_cnt = 0; } /* set up the experiment */ char * Coll_Ctrl::setup_experiment () { char *ret; if (enabled == 0) return NULL; build_data_desc (); /* create the experiment directory */ ret = create_exp_dir (); if (ret != NULL) return ret; /* if an experiment-group, join it */ ret = join_group (); if (ret != NULL) { remove_exp_dir (); return ret; } /* all is OK, return 0 */ opened = 1; return NULL; } void Coll_Ctrl::interrupt () { uinterrupt = 1; } char * Coll_Ctrl::enable_expt () { if (opened == 1) return xstrdup (GTXT ("Experiment is active; command ignored.\n")); if (cpu_clk_freq == 0) return xstrdup (GTXT ("Can not determine CPU clock frequency.\n")); if (sys_resolution == 0) return xstrdup (GTXT ("System clock profile resolution can not be determined.\n")); enabled = 1; return NULL; } /* close the experiment */ void Coll_Ctrl::close_expt () { opened = 0; (void) update_expt_name (false, false); } /* close and delete the experiment */ void Coll_Ctrl::delete_expt () { if (opened == 0) return; remove_exp_dir (); /* The order of removing the directory and closing * the experiment may seem unnatural, but it's not. * We do need to update names when we close the experiment * (actually Coll_Ctrl object) and we can't remove anything * after that. */ close_expt (); } // Check the experiment settings for consistency. Returns NULL if OK, // or an error message if there are invalid combinations of settings char * Coll_Ctrl::check_consistency () { /* check for Java arguments, but not Java profiling */ if (java_args != NULL && java_mode == 0) return xstrdup (GTXT ("Java arguments can not be set if Java profiling is not enabled.\n")); /* if count data, no other data is allowed */ if (count_enabled != 0 && ((clkprof_default != 1 && clkprof_enabled != 0) || hwcprof_enabled_cnt != 0 || synctrace_enabled != 0 || heaptrace_mode != NULL || iotrace_enabled != 0)) return xstrdup (GTXT ("Count data cannot be collected along with any other data.\n")); /* if count data, various other options are not allowed */ if (count_enabled != 0 && ((java_mode != 0 && java_default != 1) || java_args != NULL || debug_mode != 0 || (follow_mode != 0 && follow_default != 1) || pauseresume_sig != 0 || sample_sig != 0 || (sample_default != 1 && sample_period != 0) || time_run != 0)) return xstrdup (GTXT ("Count data cannot be collected with any of -F -S -y -l -j -J -x -t .\n")); /* if not count data, I and N options are not allowed */ if (count_enabled == 0 && (Iflag != 0 || Nflag != 0)) return xstrdup (GTXT ("-I or -N can only be specified with count data.\n")); return NULL; } char * Coll_Ctrl::check_expt (char **warn) { char *ret; *warn = NULL; ret = check_consistency (); if (ret != NULL) /* something is wrong, return the error */ return ret; /* check for heaptrace and java -- warn that it covers native allocations only */ if (heaptrace_mode != NULL && java_mode == 1 && java_default == 0) *warn = xstrdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n")); /* if no profiling data selected, warn the user */ if (clkprof_enabled == 0 && hwcprof_enabled_cnt == 0 && synctrace_enabled == 0 && heaptrace_mode == NULL && iotrace_enabled == 0 && count_enabled == 0) *warn = xstrdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n")); build_data_desc (); /* verify that the directory exists */ struct stat statbuf; if (stat (store_dir, &statbuf) != 0) return dbe_sprintf (GTXT ("Store directory %s is not accessible: %s\n"), store_dir, strerror (errno)); if (access (store_dir, W_OK) != 0) return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),