1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <unistd.h> 23#include <strings.h> 24#include <string.h> 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <sys/statvfs.h> 28#include <sys/param.h> 29#include <signal.h> 30#include <fcntl.h> 31#include <errno.h> 32#include <ctype.h> 33#include <dirent.h> 34#include <libgen.h> 35#include <assert.h> 36#include <regex.h> /* regcomp() */ 37 38#include "util.h" 39#include "libiberty.h" 40#include "collctrl.h" 41#include "hwcdrv.h" 42//#include "hwcfuncs.h" 43 44#define SP_GROUP_HEADER "#analyzer experiment group" 45#define DD_MAXPATHLEN (MAXPATHLEN * 4) /* large, to build up data descriptor */ 46 47/* If the system doesn't provide strsignal, we get it defined in 48 libiberty but no declaration is supplied. */ 49#if !defined (HAVE_STRSIGNAL) && !defined (strsignal) 50extern const char *strsignal (int); 51#endif 52 53// _SC_CPUID_MAX is not available on 2.6/2.7 54#ifndef _SC_CPUID_MAX 55#define _SC_CPUID_MAX 517 56#endif 57 58const char *get_fstype (char *); 59 60Coll_Ctrl::Coll_Ctrl (int _interactive, bool _defHWC, bool _kernelHWC) 61{ 62 char hostname[MAXPATHLEN]; 63 long ncpumax; 64 interactive = _interactive; 65 defHWC = _defHWC; 66 kernelHWC = _kernelHWC; 67 68 /* set this host's parameters */ 69 gethostname (hostname, 1023); 70 node_name = strdup (hostname); 71 char *p = strchr (node_name, (int) '.'); 72 if (p != NULL) 73 *p = 0; 74 default_stem = strdup ("test"); 75 76 /* get CPU count and processor clock rate */ 77 ncpumax = sysconf (_SC_CPUID_MAX); 78 if (ncpumax == -1) 79 { 80 ncpus = sysconf (_SC_NPROCESSORS_CONF); 81 /* add 2048 to count, since on some systems CPUID does not start at zero */ 82 ncpumax = ncpus + 2048; 83 } 84 ncpus = 0; 85 cpu_clk_freq = 0; 86 87 // On Linux, read /proc/cpuinfo to get CPU count and clock rate 88 // Note that parsing is different on SPARC and x86 89#if defined(sparc) 90 FILE *procf = fopen ("/proc/cpuinfo", "r"); 91 if (procf != NULL) 92 { 93 char temp[1024]; 94 while (fgets (temp, (int) sizeof (temp), procf) != NULL) 95 { 96 if (strncmp (temp, "Cpu", 3) == 0 && temp[3] != '\0' 97 && strncmp ((strchr (temp + 1, 'C')) ? strchr (temp + 1, 'C') 98 : (temp + 4), "ClkTck", 6) == 0) 99 { 100 ncpus++; 101 char *val = strchr (temp, ':'); 102 if (val) 103 { 104 unsigned long long freq; 105 sscanf (val + 2, "%llx", &freq); 106 cpu_clk_freq = (unsigned int) (((double) freq) / 1000000.0 + 0.5); 107 } 108 else 109 cpu_clk_freq = 0; 110 } 111 } 112 fclose (procf); 113 } 114 115#elif defined(__aarch64__) 116 asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_clk_freq)); 117 dbe_write (2, GTXT ("CPU clock frequency: %d\n"), cpu_clk_freq); 118 119#else 120 FILE *procf = fopen ("/proc/cpuinfo", "r"); 121 if (procf != NULL) 122 { 123 char temp[1024]; 124 while (fgets (temp, (int) sizeof (temp), procf) != NULL) 125 { 126 // x86 Linux 127 if (strncmp (temp, "processor", 9) == 0) 128 ncpus++; 129 else if (strncmp (temp, "cpu MHz", 7) == 0) 130 { 131 char *val = strchr (temp, ':'); 132 cpu_clk_freq = val ? atoi (val + 1) : 0; 133 } 134 } 135 fclose (procf); 136 } 137#endif 138 139 /* check resolution of system clock */ 140 sys_resolution = sysconf (_SC_CLK_TCK); 141 if (sys_resolution == 0) 142 sys_period = 10000; 143 else 144 sys_period = MICROSEC / (int) sys_resolution; 145 146 /* determine memory page size and number of pages */ 147 npages = sysconf (_SC_PHYS_PAGES); 148 page_size = sysconf (_SC_PAGE_SIZE); 149 150 /* set default clock parameters */ 151 hwcprof_enabled_cnt = 0; // must be set before calling determine_profile_params(); 152 determine_profile_params (); // inits clk_params which is used by clock profiling AND HWCs 153 cpc_cpuver = CPUVER_UNDEFINED; 154 155 /* set default control values */ 156 debug_mode = 0; 157#if defined(GPROFNG_JAVA_PROFILING) 158 java_mode = 1; 159#else 160 java_mode = 0; 161#endif 162 java_default = 1; 163 java_path = NULL; 164 java_args = NULL; 165 njava_args = 0; 166 follow_mode = FOLLOW_ON; 167 follow_default = 1; 168 follow_spec_usr = NULL; 169 follow_spec_cmp = NULL; 170 prof_idle = 1; 171 archive_mode = strdup ("on"); 172 pauseresume_sig = 0; 173 sample_sig = 0; 174 uinterrupt = 0; 175 attach_pid = 0; 176 time_run = 0; 177 start_delay = 0; 178 179 /* clear the string pointers */ 180 uexpt_name = NULL; 181 expt_name = NULL; 182 expt_dir = NULL; 183 base_name = NULL; 184 udir_name = NULL; 185 store_dir = NULL; 186 prev_store_dir = strdup (""); 187 store_ptr = NULL; 188 expt_group = NULL; 189 target_name = NULL; 190 data_desc = NULL; 191 lockname = NULL; 192 hwc_string = NULL; 193 project_home = NULL; 194 lockfd = -1; 195 196 /* set default data collection values */ 197 enabled = 0; 198 opened = 0; 199 clkprof_enabled = 1; 200 clkprof_default = 1; 201 for (unsigned ii = 0; ii < MAX_PICS; ii++) 202 { 203 memset (&hwctr[ii], 0, sizeof (Hwcentry)); 204 hwctr[ii].reg_num = -1; 205 } 206 hwcprof_default = 0; 207 if (defHWC == true) 208 { 209 setup_hwc (); 210 hwcprof_default = 1; 211 } 212 else // disable the default, and reset the counters 213 hwcprof_enabled_cnt = 0; 214 synctrace_enabled = 0; 215 synctrace_thresh = -1; 216 synctrace_scope = 0; 217 heaptrace_enabled = 0; 218 heaptrace_checkenabled = 0; 219 iotrace_enabled = 0; 220 count_enabled = 0; 221 Iflag = 0; 222 Nflag = 0; 223 sample_period = 1; 224 sample_default = 1; 225 size_limit = 0; 226 nofswarn = 0; 227 expno = 1; 228 229 // ensure that the default name is updated 230 // but don't print any message 231 (void) preprocess_names (); 232 (void) update_expt_name (false, false); 233} 234 235/* Copy constructor */ 236Coll_Ctrl::Coll_Ctrl (Coll_Ctrl * cc) 237{ 238 uinterrupt = 0; 239 interactive = cc->interactive; 240 defHWC = cc->defHWC; 241 kernelHWC = cc->kernelHWC; 242 node_name = strdup (cc->node_name); 243 default_stem = strdup (cc->default_stem); 244 ncpus = cc->ncpus; 245 cpu_clk_freq = cc->cpu_clk_freq; 246 npages = cc->npages; 247 page_size = cc->page_size; 248 cpc_cpuver = cc->cpc_cpuver; 249 debug_mode = cc->debug_mode; 250 java_mode = cc->java_mode; 251 java_default = cc->java_default; 252 java_path = NULL; 253 java_args = NULL; 254 njava_args = 0; 255 follow_mode = cc->follow_mode; 256 follow_default = cc->follow_default; 257 if (cc->follow_spec_usr) 258 { 259 follow_spec_usr = strdup (cc->follow_spec_usr); 260 follow_spec_cmp = strdup (cc->follow_spec_cmp); 261 } 262 else 263 { 264 follow_spec_usr = NULL; 265 follow_spec_cmp = NULL; 266 } 267 archive_mode = strdup (cc->archive_mode); 268 pauseresume_sig = cc->pauseresume_sig; 269 sample_sig = cc->sample_sig; 270 time_run = cc->time_run; 271 start_delay = cc->start_delay; 272 clk_params = cc->clk_params; 273 clkprof_enabled = cc->clkprof_enabled; 274 clkprof_default = cc->clkprof_default; 275 clkprof_timer = cc->clkprof_timer; 276 clkprof_timer_target = cc->clkprof_timer_target; 277 278 // copy HW counter information 279 hwcprof_default = cc->hwcprof_default; 280 hwcprof_enabled_cnt = cc->hwcprof_enabled_cnt; 281 if (cc->hwc_string != NULL) 282 hwc_string = strdup (cc->hwc_string); 283 else 284 hwc_string = NULL; 285 for (int i = 0; i < hwcprof_enabled_cnt; i++) 286 hwcentry_dup (&hwctr[i], &(cc->hwctr[i])); 287 project_home = cc->project_home ? strdup (cc->project_home) : NULL; 288 synctrace_enabled = cc->synctrace_enabled; 289 synctrace_thresh = cc->synctrace_thresh; 290 synctrace_scope = cc->synctrace_scope; 291 heaptrace_enabled = cc->heaptrace_enabled; 292 heaptrace_checkenabled = cc->heaptrace_checkenabled; 293 iotrace_enabled = cc->iotrace_enabled; 294 count_enabled = cc->count_enabled; 295 Iflag = cc->Iflag; 296 Nflag = cc->Nflag; 297 sample_period = cc->sample_period; 298 sample_default = cc->sample_default; 299 size_limit = cc->size_limit; 300 nofswarn = cc->nofswarn; 301 302 // these will get reset during preprocess_names() 303 expt_name = NULL; 304 expt_dir = NULL; 305 store_dir = NULL; 306 base_name = NULL; 307 expno = 1; 308 309 // these represent user settings 310 expt_group = NULL; 311 if (cc->expt_group != NULL) 312 expt_group = strdup (cc->expt_group); 313 uexpt_name = NULL; 314 if (cc->uexpt_name != NULL) 315 uexpt_name = strdup (cc->uexpt_name); 316 udir_name = NULL; 317 if (cc->udir_name != NULL) 318 udir_name = strdup (cc->udir_name); 319 320 /* clear the string pointers */ 321 prev_store_dir = strdup (""); 322 store_ptr = NULL; 323 target_name = NULL; 324 data_desc = NULL; 325 lockname = NULL; 326 lockfd = -1; 327 328 /* set default data collection values */ 329 enabled = cc->enabled; 330 opened = 0; 331 nofswarn = cc->nofswarn; 332 sys_resolution = cc->sys_resolution; 333 sys_period = cc->sys_period; 334 335 // ensure that the default name is updated 336 (void) preprocess_names (); 337 (void) update_expt_name (false, false); 338 build_data_desc (); 339} 340 341Coll_Ctrl::~Coll_Ctrl () 342{ 343 free (node_name); 344 free (expt_name); 345 free (expt_dir); 346 free (base_name); 347 free (udir_name); 348 free (store_dir); 349 free (store_ptr); 350 free (expt_group); 351 free (target_name); 352 free (data_desc); 353 free (lockname); 354 free (hwc_string); 355 free (project_home); 356 free (java_path); 357 hwcprof_enabled_cnt = 0; 358} 359 360/* set up the experiment */ 361char * 362Coll_Ctrl::setup_experiment () 363{ 364 char *ret; 365 if (enabled == 0) 366 return NULL; 367 build_data_desc (); 368 369 /* create the experiment directory */ 370 ret = create_exp_dir (); 371 if (ret != NULL) 372 return ret; 373 374 /* if an experiment-group, join it */ 375 ret = join_group (); 376 if (ret != NULL) 377 { 378 remove_exp_dir (); 379 return ret; 380 } 381 /* all is OK, return 0 */ 382 opened = 1; 383 return NULL; 384} 385 386void 387Coll_Ctrl::interrupt () 388{ 389 uinterrupt = 1; 390} 391 392char * 393Coll_Ctrl::enable_expt () 394{ 395 if (opened == 1) 396 return strdup (GTXT ("Experiment is active; command ignored.\n")); 397 if (cpu_clk_freq == 0) 398 return strdup (GTXT ("Can not determine CPU clock frequency.\n")); 399 if (sys_resolution == 0) 400 return strdup (GTXT ("System clock profile resolution can not be determined.\n")); 401 enabled = 1; 402 return NULL; 403} 404 405/* close the experiment */ 406void 407Coll_Ctrl::close_expt () 408{ 409 opened = 0; 410 (void) update_expt_name (false, false); 411} 412 413/* close and delete the experiment */ 414void 415Coll_Ctrl::delete_expt () 416{ 417 if (opened == 0) 418 return; 419 remove_exp_dir (); 420 421 /* The order of removing the directory and closing 422 * the experiment may seem unnatural, but it's not. 423 * We do need to update names when we close the experiment 424 * (actually Coll_Ctrl object) and we can't remove anything 425 * after that. 426 */ 427 close_expt (); 428} 429 430// Check the experiment settings for consistency. Returns NULL if OK, 431// or an error message if there are invalid combinations of settings 432char * 433Coll_Ctrl::check_consistency () 434{ 435 /* check for Java arguments, but not Java profiling */ 436 if (java_args != NULL && java_mode == 0) 437 return strdup (GTXT ("Java arguments can not be set if Java profiling is not enabled.\n")); 438 439 /* if count data, no other data is allowed */ 440 if (count_enabled != 0 441 && ((clkprof_default != 1 && clkprof_enabled != 0) 442 || hwcprof_enabled_cnt != 0 || synctrace_enabled != 0 443 || heaptrace_enabled != 0 || iotrace_enabled != 0)) 444 return strdup (GTXT ("Count data cannot be collected along with any other data.\n")); 445 446 /* if count data, various other options are not allowed */ 447 if (count_enabled != 0 448 && ((java_mode != 0 && java_default != 1) 449 || java_args != NULL || debug_mode != 0 450 || (follow_mode != 0 && follow_default != 1) 451 || pauseresume_sig != 0 || sample_sig != 0 452 || (sample_default != 1 && sample_period != 0) || time_run != 0)) 453 return strdup (GTXT ("Count data cannot be collected with any of -F -S -y -l -j -J -x -t .\n")); 454 /* if not count data, I and N options are not allowed */ 455 if (count_enabled == 0 && (Iflag != 0 || Nflag != 0)) 456 return strdup (GTXT ("-I or -N can only be specified with count data.\n")); 457 return NULL; 458} 459 460char * 461Coll_Ctrl::check_expt (char **warn) 462{ 463 char *ret; 464 *warn = NULL; 465 ret = check_consistency (); 466 if (ret != NULL) /* something is wrong, return the error */ 467 return ret; 468 /* check for heaptrace and java -- warn that it covers native allocations only */ 469 if (heaptrace_enabled == 1 && java_mode == 1 && java_default == 0) 470 *warn = strdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n")); 471 472 /* if no profiling data selected, warn the user */ 473 if (clkprof_enabled == 0 && hwcprof_enabled_cnt == 0 && synctrace_enabled == 0 474 && heaptrace_enabled == 0 && iotrace_enabled == 0 && count_enabled == 0) 475 *warn = strdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n")); 476 build_data_desc (); 477 478 /* verify that the directory exists */ 479 struct stat statbuf; 480 if (stat (store_dir, &statbuf) != 0) 481 return dbe_sprintf (GTXT ("Store directory %s is not accessible: %s\n"), 482 store_dir, strerror (errno)); 483 if (access (store_dir, W_OK) != 0) 484 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"), 485 store_dir, strerror (errno)); 486 487 /* if an experiment-group, verify that it can be written */ 488 ret = check_group (); 489 if (ret != NULL) 490 return ret; 491 return NULL; 492} 493 494char * 495Coll_Ctrl::show (int i) 496{ 497 char UEbuf[4096]; 498 UEbuf[0] = 0; 499 if (i == 0) 500 { 501 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 502 GTXT ("Collection parameters:\n")); 503 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 504 GTXT (" experiment enabled\n")); 505 } 506 if (target_name != NULL) 507 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 508 GTXT ("\ttarget = %s\n"), target_name); 509 if (uexpt_name != NULL) 510 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 511 GTXT ("\tuser_expt_name = %s\n"), uexpt_name); 512 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 513 GTXT ("\texpt_name = %s\n"), 514 ((expt_name != NULL) ? expt_name : NTXT ("<NULL>"))); 515 if (udir_name != NULL) 516 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 517 GTXT ("\tdir_name = %s\n"), udir_name); 518 if (expt_group != NULL) 519 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 520 GTXT ("\texpt_group = %s\n"), expt_group); 521 if (debug_mode == 1) 522 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 523 GTXT ("\tdebug_mode enabled\n")); 524 if (clkprof_enabled != 0) 525 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 526 GTXT ("\tclock profiling enabled, %.3f millisec.\n"), 527 (double) (clkprof_timer) / 1000.); 528 if (synctrace_enabled != 0) 529 { 530 if (synctrace_thresh < 0) 531 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 532 GTXT ("\tsynchronization tracing enabled, threshold: calibrate; ")); 533 else if (synctrace_thresh == 0) 534 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 535 GTXT ("\tsynchronization tracing enabled, threshold: all; ")); 536 else 537 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 538 GTXT ("\tsynchronization tracing enabled, threshold: %d micros.; "), synctrace_thresh); 539 switch (synctrace_scope) 540 { 541 case SYNCSCOPE_NATIVE: 542 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 543 GTXT ("Native-APIs\n")); 544 break; 545 case SYNCSCOPE_JAVA: 546 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 547 GTXT ("Java-APIs\n")); 548 break; 549 case SYNCSCOPE_NATIVE | SYNCSCOPE_JAVA: 550 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 551 GTXT ("Native- and Java-APIs\n")); 552 break; 553 default: 554 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 555 GTXT ("ERR -- unexpected synctrace_scope %d\n"), synctrace_scope); 556 break; 557 } 558 } 559 if (hwcprof_enabled_cnt != 0) 560 { 561 char ctrbuf[MAXPATHLEN]; 562 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 563 GTXT ("\thardware counter profiling%s enabled:\n"), 564 (hwcprof_default == 1 ? GTXT (" (default)") : "")); 565 for (int ii = 0; ii < hwcprof_enabled_cnt; ii++) 566 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 567 GTXT ("\t %u. %s\n"), ii + 1, 568 hwc_hwcentry_specd_string (ctrbuf, MAXPATHLEN, &hwctr[ii])); 569 } 570 if (heaptrace_enabled != 0) 571 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 572 GTXT ("\theap tracing enabled, %s\n"), 573 (heaptrace_checkenabled == 0 ? GTXT ("no checking") : 574 (heaptrace_checkenabled == 1 ? GTXT ("over/underrun checking") : 575 GTXT ("over/underrun checking and pattern storing")))); 576 if (iotrace_enabled != 0) 577 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 578 GTXT ("\tI/O tracing enabled\n")); 579 switch (count_enabled) 580 { 581 case 0: 582 break; 583 case 1: 584 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 585 GTXT ("\tcount data enabled\n")); 586 break; 587 case -1: 588 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 589 GTXT ("\tstatic count data will be generated (for a.out only)\n")); 590 break; 591 } 592 switch (follow_mode) 593 { 594 case FOLLOW_ON: 595 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 596 GTXT ("\tdescendant processes will be followed\n")); 597 break; 598 case FOLLOW_ALL: 599 if (follow_spec_usr && follow_spec_cmp) 600 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 601 GTXT ("\texperiments will be recorded for descendant processes that match pattern '%s'\n"), 602 follow_spec_usr); 603 else 604 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 605 GTXT ("\tdescendant processes will all be followed\n")); 606 break; 607 case FOLLOW_NONE: 608 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 609 GTXT ("\tdescendant processes will not be followed\n")); 610 break; 611 default: 612 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 613 GTXT ("\tfollowing descendant processes: <UNKNOWN>\n")); 614 break; 615 } 616 if (java_mode == 0) 617 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 618 GTXT ("\tjava profiling disabled\n")); 619 if (pauseresume_sig != 0) 620 { 621 const char *buf = strsignal (pauseresume_sig); 622 if (buf != NULL) 623 { 624 if (pauseresume_pause == 1) 625 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 626 GTXT ("\tpause-resume (delayed initialization) signal %s (%d) -- paused\n"), buf, pauseresume_sig); 627 else 628 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 629 GTXT ("\tpause-resume (delayed initialization) signal %s (%d)\n"), buf, pauseresume_sig); 630 } 631 else 632 { 633 if (pauseresume_pause == 1) 634 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 635 GTXT ("\tpause-resume (delayed initialization) signal %d -- paused\n"), pauseresume_sig); 636 else 637 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 638 GTXT ("\tpause-resume (delayed initialization) signal %d\n"), pauseresume_sig); 639 } 640 } 641 if (sample_sig != 0) 642 { 643 const char *buf = strsignal (sample_sig); 644 if (buf != NULL) 645 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 646 GTXT ("\tsample signal %s (%d)\n"), buf, sample_sig); 647 else 648 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 649 GTXT ("\tsample signal %d\n"), sample_sig); 650 } 651 if (time_run != 0 || start_delay != 0) 652 { 653 if (start_delay != 0) 654 { 655 if (time_run != 0) 656 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 657 GTXT ("\tdata-collection duration, %d-%d secs.\n"), start_delay, time_run); 658 else 659 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 660 GTXT ("\tdata-collection duration, %d- secs.\n"), start_delay); 661 } 662 else 663 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 664 GTXT ("\tdata-collection duration, %d secs.\n"), time_run); 665 } 666 if (sample_period != 0) 667 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 668 GTXT ("\tperiodic sampling, %d secs.\n"), sample_period); 669 else 670 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 671 GTXT ("\tno periodic sampling\n")); 672 if (size_limit != 0) 673 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 674 GTXT ("\texperiment size limit %d MB.\n"), size_limit); 675 else 676 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 677 GTXT ("\tno experiment size limit set\n")); 678 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 679 GTXT ("\texperiment archiving: -a %s\n"), archive_mode); 680 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 681 GTXT ("\tdata descriptor: \"%s\"\n"), 682 ((data_desc != NULL) ? data_desc : NTXT ("<NULL>"))); 683#if 0 684 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 685 GTXT ("\t expt_dir: %s\n"), 686 ((expt_dir != NULL) ? expt_dir : NTXT ("<NULL>"))); 687 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 688 GTXT ("\t base_name: %s\n"), 689 ((base_name != NULL) ? base_name : NTXT ("<NULL>"))); 690 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 691 GTXT ("\t store_dir: %s\n"), 692 ((store_dir != NULL) ? store_dir : NTXT ("<NULL>"))); 693 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 694 GTXT ("\t store_ptr: %s\n"), 695 ((store_ptr != NULL) ? store_ptr : NTXT ("<NULL>"))); 696#endif 697 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 698 GTXT ("\t\thost: `%s', ncpus = %d, clock frequency %d MHz.\n"), 699 ((node_name != NULL) ? node_name : NTXT ("<NULL>")), 700 (int) ncpus, (int) cpu_clk_freq); 701 if (npages > 0) 702 { 703 long long memsize = ((long long) npages * (long long) page_size) / (1024 * 1024); 704 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 705 GTXT ("\t\tmemory: %ld pages @ %ld bytes = %lld MB.\n"), 706 npages, page_size, memsize); 707 } 708 return strdup (UEbuf); 709} 710 711#define MAX_COLLECT_ARGS 100 712 713char ** 714Coll_Ctrl::get_collect_args () 715{ 716 char buf[DD_MAXPATHLEN]; 717 char **p; 718 char **argv = (char **) calloc (MAX_COLLECT_ARGS, sizeof (char *)); 719 if (argv == NULL) // poor way of dealing with calloc failure 720 abort (); 721 p = argv; 722 *p++ = strdup ("collect"); 723 if (debug_mode == 1) 724 *p++ = strdup ("-x"); 725 if (clkprof_enabled != 0) 726 { 727 *p++ = strdup ("-p"); 728 snprintf (buf, sizeof (buf), "%du", clkprof_timer); 729 *p++ = strdup (buf); 730 } 731 if (hwcprof_enabled_cnt > 0) 732 { 733 *buf = 0; 734 *p++ = strdup ("-h"); 735 for (int ii = 0; ii < hwcprof_enabled_cnt; ii++) 736 { 737 char*rateString = hwc_rate_string (&hwctr[ii], 1); //"1" is for temporary goldfile compatibility. TBR YXXX!! 738 snprintf (buf + strlen (buf), sizeof (buf) - strlen (buf), 739 "%s%s,%s%s", ii ? "," : "", hwctr[ii].name, 740 rateString ? rateString : "", 741 (ii + 1 < hwcprof_enabled_cnt) ? "," : ""); 742 free (rateString); 743 } 744 if (strlen (buf) + 1 >= sizeof (buf)) 745 abort (); 746 *p++ = strdup (buf); 747 } 748 if (heaptrace_enabled != 0) 749 { 750 *p++ = strdup ("-H"); 751 *p++ = strdup ("on"); 752 } 753 if (iotrace_enabled != 0) 754 { 755 *p++ = strdup ("-i"); 756 *p++ = strdup ("on"); 757 } 758 if (synctrace_enabled != 0) 759 { 760 *p++ = strdup ("-s"); 761 if (synctrace_thresh < 0) 762 *p++ = strdup ("calibrate"); 763 else if (synctrace_thresh < 0) 764 *p++ = strdup ("all"); 765 else 766 *p++ = dbe_sprintf ("%d", synctrace_thresh); 767 *p++ = dbe_sprintf (",%d", synctrace_scope); 768 } 769 if (follow_mode != 0) 770 { 771 *p++ = strdup ("-F"); 772 char * fs = get_follow_usr_spec (); 773 if (fs) 774 *p++ = strdup (fs); 775 else 776 { 777 switch (get_follow_mode ()) 778 { 779 case FOLLOW_ON: 780 *p++ = strdup ("on"); 781 break; 782 case FOLLOW_ALL: 783 *p++ = strdup ("all"); 784 break; 785 case FOLLOW_NONE: 786 default: 787 *p++ = strdup ("off"); 788 break; 789 } 790 } 791 } 792 *p++ = strdup ("-a"); 793 *p++ = strdup (get_archive_mode ()); 794 if (java_mode != 0) 795 { 796 *p++ = strdup ("-j"); 797 *p++ = strdup ("on"); 798 } 799 if (pauseresume_sig != 0) 800 { 801 *p++ = strdup ("-y"); 802 *p++ = dbe_sprintf ("%d%s", pauseresume_sig, 803 (pauseresume_pause == 0 ? ",r" : "")); 804 } 805 if (sample_sig != 0) 806 { 807 *p++ = strdup ("-l"); 808 *p++ = dbe_sprintf ("%d", sample_sig); 809 } 810 if (sample_period != 0) 811 { 812 *p++ = strdup ("-S"); 813 *p++ = dbe_sprintf ("%d", sample_period); 814 } 815 if (size_limit != 0) 816 { 817 *p++ = strdup ("-L"); 818 *p++ = dbe_sprintf ("%d", size_limit); 819 } 820 if (expt_group != NULL) 821 { 822 *p++ = strdup ("-g"); 823 *p++ = strdup (expt_group); 824 } 825 if (udir_name != 0) 826 { 827 *p++ = strdup ("-d"); 828 *p++ = strdup (udir_name); 829 } 830 if (expt_name != 0) 831 { 832 *p++ = strdup ("-o"); 833 *p++ = strdup (expt_name); 834 } 835 if (p - argv >= MAX_COLLECT_ARGS) // argument list too small -- fatal error 836 abort (); 837 return argv; 838} 839 840char * 841Coll_Ctrl::show_expt () 842{ 843 if (enabled == 0) 844 return NULL; 845 char UEbuf[4096]; 846 UEbuf[0] = 0; 847 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 848 GTXT ("Creating experiment directory %s (Process ID: %ld) ...\n"), 849 ((store_ptr != NULL) ? store_ptr : NTXT ("<NULL>")), (long) getpid ()); 850 char *caller = getenv ("SP_COLLECTOR_FROM_GUI"); // Collector from GUI 851 if (caller != NULL) // Print non-localized message 852 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 853 NTXT ("\nCreating experiment directory %s (Process ID: %ld) ...\n"), 854 ((store_ptr != NULL) ? store_ptr : NTXT ("<NULL>")), (long) getpid ()); 855#if 0 856 char *fstype = get_fstype (store_dir); 857 if ((fstype != NULL) && (nofswarn == 0)) 858 { 859 // only warn if clock or hwc profiling is turned on 860 if (clkprof_enabled || hwcprof_enabled_cnt != 0) 861 snprintf (UEbuf + strlen (UEbuf), sizeof (UEbuf) - strlen (UEbuf), 862 GTXT ("this experiment is being recorded to a file system \nof type \"%s\", which may distort the measured performance."), 863 fstype); 864 } 865#endif 866 return strdup (UEbuf); 867} 868 869void 870Coll_Ctrl::set_clk_params (int min, int res, int max, int hi, int norm, int lo) 871{ 872 clk_params.min = min; 873 clk_params.res = res; 874 clk_params.max = max; 875 clk_params.hival = hi; 876 clk_params.normval = norm; 877 clk_params.lowval = lo; 878 set_clkprof_timer_target (clk_params.normval); // note: requires clk_params to be initialized! 879} 880 881char * 882Coll_Ctrl::reset_clkprof (int val) 883{ 884 if (val != clkprof_timer) 885 { 886 // profiler has had to reset to a different value; warn user 887 char *msg = dbe_sprintf ( 888 GTXT ("Warning: Clock profiling timer reset from %.3f millisec. to %.3f millisec. as required by profiling driver\n\n"), 889 (double) (clkprof_timer) / 1000., (double) (val) / 1000.); 890 adjust_clkprof_timer (val); 891 return msg; 892 } 893 return NULL; 894} 895 896char * 897Coll_Ctrl::set_clkprof (const char *string, char** warn) 898{ 899 int ticks; 900 int nclkprof_timer; 901 int prevclkprof_enabled; 902 int prevclkprof_default; 903 *warn = NULL; 904 if (opened == 1) 905 return strdup (GTXT ("Experiment is active; command ignored.\n")); 906 /* if the first character is a +, warn user that it is no longer supported */ 907 if (string[0] == '+') 908 return strdup (GTXT ("Warning: clock-based memoryspace and dataspace profiling is no longer supported\n")); 909 if (strcmp (string, "off") == 0) 910 { 911 clkprof_enabled = 0; 912 clkprof_default = 0; 913 return NULL; 914 } 915 else if (string == NULL || strcmp (string, "on") == 0) 916 nclkprof_timer = clk_params.normval; 917 else if (strcmp (string, "lo") == 0 || strcmp (string, "low") == 0) 918 nclkprof_timer = clk_params.lowval; 919 else if (strcmp (string, "hi") == 0 || strcmp (string, "high") == 0 920 || strcmp (string, "h") == 0) 921 nclkprof_timer = clk_params.hival; 922 else 923 { 924 /* the remaining string should be a number > 0 */ 925 char *endchar = NULL; 926 double dval = strtod (string, &endchar); 927 if (*endchar == 'm' || *endchar == 0) /* user specified milliseconds */ 928 dval = dval * 1000.; 929 else if (*endchar == 'u') /* user specified microseconds */ 930 dval = dval; 931 else 932 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string); 933 nclkprof_timer = (int) (dval + 0.5); 934 } 935 // we now have the proposed value; ensure it's within limits 936 if (nclkprof_timer <= 0) 937 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string); 938 939 // Check consistency with experiment 940 prevclkprof_enabled = clkprof_enabled; 941 prevclkprof_default = clkprof_default; 942 clkprof_enabled = 1; 943 clkprof_default = 0; 944 char *ret = check_consistency (); 945 if (ret != NULL) 946 { 947 clkprof_default = prevclkprof_default; 948 clkprof_enabled = prevclkprof_enabled; 949 return ret; 950 } 951 int ref_nclkprof_timer = nclkprof_timer; 952 953 // check for minimum value 954 if (nclkprof_timer < clk_params.min) 955 { 956 /* value too small, use minimum value, with warning */ 957 *warn = dbe_sprintf ( 958 GTXT ("Warning: Clock profiling at %.3f millisec. interval is not supported on this system; minimum %.3f millisec. used\n"), 959 (double) (nclkprof_timer) / 1000., (double) (clk_params.min) / 1000.); 960 nclkprof_timer = clk_params.min; 961 } 962 963 // check for maximum value 964 if (nclkprof_timer > clk_params.max) 965 { 966 *warn = dbe_sprintf ( 967 GTXT ("Clock profiling at %.3f millisec. interval is not supported on this system; maximum %.3f millisec. used\n"), 968 (double) (nclkprof_timer) / 1000., (double) (clk_params.max) / 1000.); 969 nclkprof_timer = clk_params.max; 970 } 971 972 /* see if setting is a multiple of the period */ 973 if (nclkprof_timer > clk_params.res) 974 { 975 ticks = ((nclkprof_timer / clk_params.res) * clk_params.res); 976 if (ticks != nclkprof_timer) 977 { 978 /* no, we need to reset to a multiple */ 979 *warn = dbe_sprintf ( 980 GTXT ("Clock profile interval rounded from %.3f to %.3f (system resolution = %.3f) millisec."), 981 (double) (nclkprof_timer) / 1000., (double) (ticks) / 1000., 982 (double) (clk_params.res) / 1000.); 983 nclkprof_timer = ticks; 984 } 985 } 986 987 // limit reference "target" rate. Target rate is also used for HWCS. 988 if (ref_nclkprof_timer > PROFINT_MAX) 989 ref_nclkprof_timer = PROFINT_MAX; 990 if (ref_nclkprof_timer < PROFINT_MIN) 991 ref_nclkprof_timer = PROFINT_MIN; 992 set_clkprof_timer_target (ref_nclkprof_timer); 993 adjust_clkprof_timer (nclkprof_timer); 994 return NULL; 995} 996 997char * 998Coll_Ctrl::set_synctrace (const char *string) 999{ 1000 if (opened == 1) 1001 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1002 char *comma_p = NULL; 1003 if (string == NULL) 1004 { 1005 /* no argument provided, use default: calibrate and native */ 1006 synctrace_enabled = 1; 1007 synctrace_thresh = -1; 1008 synctrace_scope = SYNCSCOPE_NATIVE; 1009 char *ret = check_consistency (); 1010 if (ret != NULL) 1011 { 1012 synctrace_enabled = 0; 1013 return ret; 1014 } 1015 return NULL; 1016 } 1017 char *val = strdup (string); 1018 /* see if there's a comma in the string */ 1019 char *next = strchr (val, (int) ','); 1020 if (next != NULL) 1021 { 1022 /* remember where the comma was */ 1023 comma_p = next; 1024 1025 /* set the scope based on the characters following the comma */ 1026 synctrace_scope = 0; 1027 next++; 1028 while (*next != 0) 1029 { 1030 if (*next == 'n') 1031 synctrace_scope |= SYNCSCOPE_NATIVE; 1032 else if (*next == 'j') 1033 synctrace_scope |= SYNCSCOPE_JAVA; 1034 else 1035 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string); 1036 next++; 1037 } 1038 if (synctrace_scope == 0) 1039 synctrace_scope = SYNCSCOPE_NATIVE; 1040 /* clear the comma for the threshold determination */ 1041 *comma_p = 0; 1042 } 1043 else /* no ",<scope>" -- default to native and Java */ 1044 synctrace_scope = SYNCSCOPE_NATIVE | SYNCSCOPE_JAVA; 1045 if (!strlen (val) || !strcmp (val, "calibrate") || !strcmp (val, "on")) 1046 { 1047 /* use default: calibrate and native */ 1048 synctrace_enabled = 1; 1049 synctrace_thresh = -1; 1050 free (val); 1051 char *ret = check_consistency (); 1052 if (ret != NULL) 1053 { 1054 synctrace_enabled = 0; 1055 return ret; 1056 } 1057 return NULL; 1058 } 1059 if (strcmp (val, "off") == 0) 1060 { 1061 synctrace_enabled = 0; 1062 free (val); 1063 return NULL; 1064 } 1065 if (strcmp (val, "all") == 0) 1066 { 1067 /* set to record all events */ 1068 synctrace_thresh = 0; 1069 synctrace_enabled = 1; 1070 char *ret = check_consistency (); 1071 free (val); 1072 if (ret != NULL) 1073 { 1074 synctrace_enabled = 0; 1075 return ret; 1076 } 1077 return NULL; 1078 } 1079 /* the remaining string should be a number >= 0 */ 1080 char *endchar = NULL; 1081 int tval = (int) strtol (val, &endchar, 0); 1082 free (val); 1083 if (*endchar != 0 || tval < 0) 1084 { 1085 /* invalid setting */ 1086 /* restore the comma, if it was zeroed out */ 1087 if (comma_p != NULL) 1088 *comma_p = ','; 1089 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string); 1090 } 1091 synctrace_thresh = tval; 1092 synctrace_enabled = 1; 1093 return NULL; 1094} 1095 1096char * 1097Coll_Ctrl::set_heaptrace (const char *string) 1098{ 1099 if (opened == 1) 1100 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1101 if (string == NULL || strlen (string) == 0 || strcmp (string, "on") == 0) 1102 { 1103 heaptrace_enabled = 1; 1104 char *ret = check_consistency (); 1105 if (ret != NULL) 1106 { 1107 heaptrace_enabled = 0; 1108 return ret; 1109 } 1110 return NULL; 1111 } 1112 if (strcmp (string, "off") == 0) 1113 { 1114 heaptrace_enabled = 0; 1115 return NULL; 1116 } 1117#if 0 1118 if (strcmp (string, "check") == 0) 1119 { 1120 /* set to check for over/underruns */ 1121 heaptrace_checkenabled = 1; 1122 heaptrace_enabled = 1; 1123 return NULL; 1124 } 1125 if (strcmp (string, "clear") == 0) 1126 { 1127 /* set to check for over/underruns, and store patterns */ 1128 heaptrace_checkenabled = 2; 1129 heaptrace_enabled = 1; 1130 return NULL; 1131 } 1132#endif 1133 return dbe_sprintf (GTXT ("Unrecognized heap tracing parameter `%s'\n"), string); 1134} 1135 1136char * 1137Coll_Ctrl::set_iotrace (const char *string) 1138{ 1139 if (opened == 1) 1140 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1141 if (string == NULL || strlen (string) == 0 || strcmp (string, "on") == 0) 1142 { 1143 iotrace_enabled = 1; 1144 char *ret = check_consistency (); 1145 if (ret != NULL) 1146 { 1147 iotrace_enabled = 0; 1148 return ret; 1149 } 1150 return NULL; 1151 } 1152 if (strcmp (string, "off") == 0) 1153 { 1154 iotrace_enabled = 0; 1155 return NULL; 1156 } 1157 return dbe_sprintf (GTXT ("Unrecognized I/O tracing parameter `%s'\n"), string); 1158} 1159 1160char * 1161Coll_Ctrl::set_count (const char *string) 1162{ 1163 int ret = -1; 1164 if (opened == 1) 1165 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1166 if (string == NULL || strlen (string) == 0 || strcmp (string, "off") == 0) 1167 { 1168 count_enabled = 0; 1169 ret = 0; 1170 } 1171 if (strcmp (string, "on") == 0) 1172 { 1173 count_enabled = 1; 1174 char *cret = check_consistency (); 1175 if (cret != NULL) 1176 { 1177 count_enabled = 0; 1178 return cret; 1179 } 1180 ret = 0; 1181 } 1182 if (strcmp (string, "static") == 0) 1183 { 1184 count_enabled = -1; 1185 char *cret = check_consistency (); 1186 if (cret != NULL) 1187 { 1188 count_enabled = 0; 1189 return cret; 1190 } 1191 ret = 0; 1192 } 1193 if (ret == 0) 1194 { 1195 if (count_enabled != 0) 1196 { 1197 /* ensure that sample period is 0, if set by default */ 1198 if (sample_default == 1) 1199 sample_period = 0; 1200 /* ensure that clock profiling is off, if set by default */ 1201 if (clkprof_default == 1) 1202 { 1203 clkprof_default = 0; 1204 clkprof_enabled = 0; 1205 } 1206 if (hwcprof_default == 1) 1207 hwcprof_default = 0; 1208 } 1209 return NULL; 1210 } 1211 return dbe_sprintf (GTXT ("Unrecognized count parameter `%s'\n"), string); 1212} 1213 1214char * 1215Coll_Ctrl::set_time_run (const char *valarg) 1216{ 1217 if (opened == 1) 1218 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1219 if (valarg == NULL) /* invalid setting */ 1220 return strdup (GTXT ("time parameter can not be NULL\n")); 1221 /* the string should be a number >= 0 */ 1222 int prev_start_delay = start_delay; 1223 int prev_time_run = time_run; 1224 const char *endchar = valarg; 1225 char *newchar = NULL; 1226 int val = 0; 1227 if (*endchar != '-') 1228 { 1229 val = (int) strtol (endchar, &newchar, 0); 1230 endchar = newchar; 1231 if (val < 0) 1232 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg); 1233 if (*endchar == 'm') 1234 { 1235 val = val * 60; /* convert to seconds */ 1236 endchar++; 1237 } 1238 else if (*endchar == 's') /* no conversion needed */ 1239 endchar++; 1240 if (*endchar == 0) 1241 { 1242 time_run = val; 1243 return NULL; 1244 } 1245 else if (*endchar != '-') 1246 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg); 1247 } 1248 /* a second number is provided */ 1249 start_delay = val; 1250 endchar++; 1251 val = (int) strtol (endchar, &newchar, 0); 1252 endchar = newchar; 1253 if (val < 0) 1254 { 1255 start_delay = prev_start_delay; 1256 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg); 1257 } 1258 if (*endchar == 'm') 1259 { 1260 val = val * 60; /* convert to seconds */ 1261 endchar++; 1262 } 1263 else if (*endchar == 's') /* no conversion needed */ 1264 endchar++; 1265 if (*endchar != 0) 1266 { 1267 start_delay = prev_start_delay; 1268 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg); 1269 } 1270 time_run = val; 1271 if (time_run != 0 && start_delay >= time_run) 1272 { 1273 start_delay = prev_start_delay; 1274 return dbe_sprintf (GTXT ("Invalid time parameter `%s': start time must be earlier than end time\n"), valarg); 1275 } 1276 char *ret = check_consistency (); 1277 if (ret != NULL) 1278 { 1279 start_delay = prev_start_delay; 1280 time_run = prev_time_run; 1281 return ret; 1282 } 1283 return NULL; 1284} 1285 1286char * 1287Coll_Ctrl::set_attach_pid (char *valarg) 1288{ 1289 if (opened == 1) 1290 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1291 if (valarg == NULL) 1292 return strdup (GTXT ("Specified PID can not be NULL\n")); 1293 1294 /* the string should be a number corresponding to an active process' pid */ 1295 char *endchar = NULL; 1296 int val = (int) strtol (valarg, &endchar, 0); 1297 if (*endchar != 0 || val < 0) 1298 return dbe_sprintf (GTXT ("Invalid process pid `%s'\n"), valarg); 1299 int prev_attach_pid = attach_pid; 1300 attach_pid = val; 1301 char *ret = check_consistency (); 1302 if (ret != NULL) 1303 { 1304 attach_pid = prev_attach_pid; 1305 return ret; 1306 } 1307 return NULL; 1308} 1309 1310void 1311Coll_Ctrl::free_hwc_fields (Hwcentry * tmpctr) 1312{ 1313 if (tmpctr->name != NULL) 1314 free (tmpctr->name); 1315 if (tmpctr->int_name != NULL) 1316 free (tmpctr->int_name); 1317 memset (tmpctr, 0, sizeof (Hwcentry)); 1318 tmpctr->reg_num = -1; 1319} 1320 1321void 1322Coll_Ctrl::hwcentry_dup (Hwcentry *hnew, Hwcentry *_hwc) 1323{ 1324 *hnew = *_hwc; 1325 if (_hwc->name != NULL) 1326 hnew->name = strdup (_hwc->name); 1327 else 1328 hnew->name = NULL; 1329 if (_hwc->int_name != NULL) 1330 hnew->int_name = strdup (_hwc->int_name); 1331 else 1332 hnew->int_name = NULL; 1333 if (_hwc->metric != NULL) 1334 hnew->metric = strdup (_hwc->metric); 1335 else 1336 hnew->metric = NULL; 1337 if (_hwc->short_desc != NULL) 1338 hnew->short_desc = strdup (_hwc->short_desc); 1339 else 1340 hnew->short_desc = NULL; 1341 if (_hwc->reg_list != NULL) 1342 { 1343 hnew->reg_list = (regno_t*) malloc (sizeof (regno_t*) * MAX_PICS); 1344 // poor way of dealing with malloc failure 1345 if (hnew->reg_list) 1346 { 1347 for (int i = 0; i < MAX_PICS; i++) 1348 { 1349 hnew->reg_list[i] = _hwc->reg_list[i]; 1350 if (hnew->reg_list[i] == REGNO_ANY) 1351 break; 1352 } 1353 } 1354 } 1355} 1356 1357// Routine to initialize the HWC tables, set up the default experiment, etc. 1358void 1359Coll_Ctrl::setup_hwc () 1360{ 1361 static bool is_hwc_setup = false; 1362 if (is_hwc_setup == true) 1363 return; 1364 // try to set the default counters 1365 is_hwc_setup = true; 1366 set_hwcdefault (); 1367} 1368 1369hrtime_t 1370Coll_Ctrl::clkprof_timer_2_hwcentry_min_time (int target_clkprof_usec) 1371{ 1372 hrtime_t hwc_nanosec; 1373 if (target_clkprof_usec == clk_params.normval) 1374 hwc_nanosec = HWCTIME_ON; 1375 else if (target_clkprof_usec == clk_params.lowval) 1376 hwc_nanosec = HWCTIME_LO; 1377 else if (target_clkprof_usec == clk_params.hival) 1378 hwc_nanosec = HWCTIME_HI; 1379 else 1380 hwc_nanosec = 1000LL * target_clkprof_usec; // nanoseconds 1381 return hwc_nanosec; 1382} 1383 1384void 1385Coll_Ctrl::set_clkprof_timer_target (int microseconds) 1386{ 1387 clkprof_timer = microseconds; 1388 clkprof_timer_target = microseconds; 1389 hrtime_t hwc_min_time_nanosec = clkprof_timer_2_hwcentry_min_time (microseconds); 1390 for (int ii = 0; ii < hwcprof_enabled_cnt; ii++) 1391 { 1392 hwctr[ii].min_time_default = hwc_min_time_nanosec; 1393 hwc_update_val (&hwctr[ii]); 1394 } 1395} 1396 1397void 1398Coll_Ctrl::adjust_clkprof_timer (int use) 1399{ 1400 clkprof_timer = use; 1401} 1402 1403/* set HWC counter set from a string */ 1404char * /* return an error string */ 1405Coll_Ctrl::set_hwcstring (const char *string, char **warnmsg) 1406{ 1407 *warnmsg = NULL; 1408 if (string == NULL || strcmp (string, "off") == 0) 1409 { 1410 hwcprof_enabled_cnt = 0; 1411 return NULL; 1412 } 1413 setup_hwc (); 1414 int old_cnt = hwcprof_enabled_cnt; 1415 int old_hwcprof_default = hwcprof_default; 1416 1417 /* reset any previous count to zero */ 1418 hwcprof_enabled_cnt = 0; 1419 char *ret = add_hwcstring (string, warnmsg); 1420 if (ret != NULL) 1421 { 1422 // restore previous setting 1423 hwcprof_enabled_cnt = old_cnt; 1424 hwcprof_default = old_hwcprof_default; 1425 } 1426 return ret; 1427} 1428 1429/* add additional HWC counters to counter set from string */ 1430char * /* return an error string */ 1431Coll_Ctrl::add_hwcstring (const char *string, char **warnmsg) 1432{ 1433 *warnmsg = NULL; 1434 if (string == NULL || strcmp (string, "off") == 0) 1435 { 1436 hwcprof_enabled_cnt = 0; 1437 return NULL; 1438 } 1439 setup_hwc (); 1440 int rc = 0; 1441 int old_cnt = hwcprof_enabled_cnt; 1442 int prev_cnt = hwcprof_enabled_cnt; 1443 // int old_hwcprof_default = hwcprof_default; 1444 char UEbuf[MAXPATHLEN * 5]; 1445 int UEsz; 1446 Hwcentry tmpctr[MAX_PICS]; 1447 Hwcentry * ctrtable[MAX_PICS]; 1448 char *emsg; 1449 char *wmsg; 1450 UEbuf[0] = 0; 1451 UEsz = sizeof (UEbuf); 1452 if (opened == 1) 1453 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1454 if (hwcprof_default == 0) 1455 { 1456 /* Copy the counters already defined */ 1457 for (int ii = 0; ii < prev_cnt; ii++) 1458 tmpctr[ii] = hwctr[ii]; 1459 } 1460 else /* the previously-defined counters were defaulted; don't copy them */ 1461 prev_cnt = 0; 1462 1463 /* look up the CPU version */ 1464 cpc_cpuver = hwc_get_cpc_cpuver (); 1465 if (string && *string) 1466 { 1467 /* lookup counters */ 1468 /* set up a pointer array */ 1469 for (unsigned ii = 0; ii < MAX_PICS; ii++) 1470 ctrtable[ii] = &tmpctr[ii]; 1471 hrtime_t global_min_time = clkprof_timer_2_hwcentry_min_time (clkprof_timer_target); 1472 rc = hwc_lookup (kernelHWC, global_min_time, string, &ctrtable[prev_cnt], MAX_PICS - prev_cnt, &emsg, &wmsg); 1473 if (wmsg != NULL) 1474 *warnmsg = wmsg; 1475 if (rc < 0) 1476 return emsg; 1477 /* set count for sum of old and new counters */ 1478 rc = rc + prev_cnt; 1479 } 1480 1481 /* even though the actual hwctr[] array is not updated, we can check consistency */ 1482 char *ret = check_consistency (); 1483 if (ret != NULL) 1484 { 1485 hwcprof_enabled_cnt = old_cnt; 1486 return ret; 1487 } 1488 1489 /* finally, validate the full counter set */ 1490 emsg = hwc_validate_ctrs (kernelHWC, ctrtable, rc); 1491 if (emsg != NULL) 1492 { 1493 hwcprof_enabled_cnt = old_cnt; 1494 return emsg; 1495 } 1496 1497 /* success, update real counters and the string for them */ 1498 /* turn off the default */ 1499 hwcprof_default = 0; 1500 hwcprof_enabled_cnt = rc; 1501 free (hwc_string); 1502 for (int ii = 0; ii < hwcprof_enabled_cnt; ii++) 1503 { 1504 /* shallow copy of new counters */ 1505 hwctr[ii] = tmpctr[ii]; 1506 char *rateString = hwc_rate_string (&hwctr[ii], 0); 1507 snprintf (UEbuf + strlen (UEbuf), UEsz - strlen (UEbuf), 1508 NTXT (",%s,%s"), hwctr[ii].name, 1509 rateString ? rateString : ""); 1510 free (rateString); 1511 } 1512 /* now duplicate that string, skipping the leading comma */ 1513 hwc_string = strdup (&UEbuf[1]); 1514 return NULL; 1515} 1516 1517/* add default HWC counters to counter set with resolution (on, hi, or lo) */ 1518/* Note that the resultion will also be used to set the clock-profiling default */ 1519char * /* return an error string */ 1520Coll_Ctrl::add_default_hwcstring (const char *resolution, char **warnmsg, bool add, bool forKernel) 1521{ 1522 setup_hwc (); 1523 *warnmsg = NULL; 1524 char *def_string = hwc_get_default_cntrs2 (forKernel, 1); 1525 if (def_string == NULL) 1526 { 1527 /* no string defined, format and return an error message */ 1528 char cpuname[128]; 1529 hwc_get_cpuname (cpuname, sizeof (cpuname)); 1530 return dbe_sprintf (GTXT ("No default HW counter set is defined for %s\n"), cpuname); 1531 } 1532 int len = strlen (def_string); 1533 if (len == 0) 1534 { 1535 /* string zero-length, meaning default counters can't be used */ 1536 char cpuname[128]; 1537 hwc_get_cpuname (cpuname, sizeof (cpuname)); 1538 return dbe_sprintf (GTXT ("HW counter set for %s cannot be loaded on this system\n"), cpuname); 1539 } 1540 /* allocate return string */ 1541 int retsize = 2 * len + 10; 1542 char *ret = (char *) malloc (retsize); 1543 if (ret == NULL) 1544 return strdup (GTXT ("internal error formating HW counter set; malloc failed\n")); 1545 *ret = 0; 1546 char *retp = ret; 1547 char *stringp = def_string; 1548 int first = 1; 1549 char *hwc_defaultx = strdup (def_string); 1550 1551 /* now massage the string in order to insert resolution for each counter */ 1552 for (;;) 1553 { 1554 /* find the next comma */ 1555 char * next; 1556 char *nextp; 1557 if (first == 1) 1558 nextp = stringp; 1559 else 1560 nextp = stringp + 1; 1561 first = 0; 1562 if ((next = strchr (nextp, (int) ',')) != NULL) 1563 { 1564 if (next == nextp) 1565 { 1566 /* next counter is zero-length -- invalid string */ 1567 char cpuname[128]; 1568 hwc_get_cpuname (cpuname, sizeof (cpuname)); 1569 free (ret); 1570 ret = dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname, hwc_defaultx); 1571 free (hwc_defaultx); 1572 return ret; 1573 } 1574 /* another field found */ 1575 *next = 0; 1576 char nextc = *(next + 1); 1577 if ((nextc == 0) || (nextc == ',')) 1578 { 1579 /* either ,, between fields, or string ends in comma */ 1580 /* append the string */ 1581 strncat (retp, stringp, (retsize - strlen (retp) - 1)); 1582 strncat (retp, ",", (retsize - strlen (retp) - 1)); 1583 strncat (retp, resolution, (retsize - strlen (retp) - 1)); 1584 if (nextc == 0) /* string ended in comma; we're done */ 1585 break; 1586 } 1587 else 1588 { 1589 /* string had only one comma between counter names; that's not valid */ 1590 char cpuname[128]; 1591 hwc_get_cpuname (cpuname, sizeof (cpuname)); 1592 free (ret); 1593 ret = dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname, hwc_defaultx); 1594 free (hwc_defaultx); 1595 return ret; 1596 } 1597 /* string had ,, between fields; move to next field */ 1598 stringp = next + 1; 1599 if (* (stringp + 1) == 0) /* name ended in ,, -- we're done */ 1600 break; 1601 continue; 1602 } 1603 else 1604 { 1605 /* no comma found, add the last counter and the comma and resolution */ 1606 strncat (retp, stringp, (retsize - strlen (retp) - 1)); 1607 strncat (retp, ",", (retsize - strlen (retp) - 1)); 1608 strncat (retp, resolution, (retsize - strlen (retp) - 1)); 1609 break; 1610 } 1611 } 1612 1613 /* we have now formatted the new string, with resolution inserted */ 1614 char *ccret; 1615 if (add == true) 1616 ccret = add_hwcstring (ret, warnmsg); 1617 else 1618 ccret = set_hwcstring (ret, warnmsg); 1619 free (hwc_defaultx); 1620 free (ret); 1621 1622 /* now set the clock-profiling timer, if on by default */ 1623 if (clkprof_default == 1) 1624 { 1625 if (strcmp (resolution, NTXT ("on")) == 0) 1626 set_clkprof_timer_target (clk_params.normval); 1627 else if (strcmp (resolution, NTXT ("lo")) == 0) 1628 set_clkprof_timer_target (clk_params.lowval); 1629 else if (strcmp (resolution, NTXT ("hi")) == 0) 1630 set_clkprof_timer_target (clk_params.hival); 1631 } 1632 return ccret; 1633} 1634 1635void 1636Coll_Ctrl::set_hwcdefault () 1637{ 1638 char *string = hwc_get_default_cntrs2 (kernelHWC, 1); 1639 if (string != NULL) 1640 { 1641 if (strlen (string) == 0) 1642 hwcprof_default = 0; 1643 else 1644 { 1645 char * warnmsg = NULL; 1646 char *ccret = add_hwcstring (string, &warnmsg); 1647 if (ccret != NULL) 1648 { 1649#if 0 1650 /* set string to zero-length so that it won't be used again */ 1651 hwc_set_default_cntrs (kernelHWC, NTXT ("")); 1652#endif 1653 hwcprof_default = 0; 1654 } 1655 else 1656 hwcprof_default = 1; 1657 } 1658 free (string); 1659 } 1660 else 1661 hwcprof_default = 0; 1662} 1663 1664void 1665Coll_Ctrl::disable_hwc () 1666{ 1667 hwcprof_enabled_cnt = 0; 1668 hwcprof_default = 0; 1669 free (hwc_string); 1670 hwc_string = NULL; 1671} 1672 1673char * 1674Coll_Ctrl::set_sample_period (const char *string) 1675{ 1676 int val; 1677 if (opened == 1) 1678 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1679 if (string == NULL || strcmp (string, "on") == 0) 1680 val = 1; 1681 else if (strcmp (string, "off") == 0) 1682 val = 0; 1683 else 1684 { 1685 /* string should be a number > 0 */ 1686 char *endchar = NULL; 1687 val = (int) strtol (string, &endchar, 0); 1688 if (*endchar != 0 || val <= 0) 1689 return dbe_sprintf (GTXT ("Unrecognized sample period `%s'\n"), string); 1690 } 1691 /* set that value */ 1692 int prev_sample_period = sample_period; 1693 sample_period = val; 1694 char *ret = check_consistency (); 1695 if (ret != NULL) 1696 { 1697 sample_period = prev_sample_period; 1698 return ret; 1699 } 1700 sample_default = 0; 1701 return NULL; 1702} 1703 1704char * 1705Coll_Ctrl::set_size_limit (const char *string) 1706{ 1707 if (opened == 1) 1708 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1709 if (string == NULL || strlen (string) == 0 1710 || strcmp (string, "unlimited") == 0 || strcmp (string, "none") == 0) 1711 { 1712 size_limit = 0; 1713 return NULL; 1714 } 1715 /* string should be a number >0; 0 is an error */ 1716 char *endchar = NULL; 1717 int val = (int) strtol (string, &endchar, 0); 1718 if (*endchar != 0 || val <= 0) 1719 return dbe_sprintf (GTXT ("Unrecognized size limit `%s'\n"), string); 1720 size_limit = val; 1721 return 0; 1722} 1723 1724void 1725Coll_Ctrl::build_data_desc () 1726{ 1727 char spec[DD_MAXPATHLEN]; 1728 spec[0] = 0; 1729 1730 // Put sample sig before clock profiling. Dbx uses PROF 1731 // for that purpose and we want it to be processed first. 1732 if (project_home) 1733 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "P:%s;", project_home); 1734 if (sample_sig != 0) 1735 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "g:%d;", sample_sig); 1736 if (pauseresume_sig != 0) 1737 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "d:%d%s;", pauseresume_sig, 1738 (pauseresume_pause == 1 ? "p" : "")); 1739 if (clkprof_enabled == 1) 1740 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "p:%d;", clkprof_timer); 1741 if (synctrace_enabled == 1) 1742 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "s:%d,%d;", synctrace_thresh, synctrace_scope); 1743 if (heaptrace_enabled == 1) 1744 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "H:%d;", heaptrace_checkenabled); 1745 if (iotrace_enabled == 1) 1746 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "i:;"); 1747 if (hwcprof_enabled_cnt > 0) 1748 { 1749 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "h:%s", 1750 (hwcprof_default == true) ? "*" : ""); 1751 for (int ii = 0; ii < hwcprof_enabled_cnt; ii++) 1752 { 1753 /* min_time is a "new" field. 1754 * 1755 * To help process_data_descriptor() in hwcfuncs.c parse 1756 * the HWC portion of this string -- specifically, to 1757 * recognize min_time when it's present and skip over 1758 * when it's not -- we prepend 'm' to the min_time value. 1759 * 1760 * When we no longer worry about, say, an old dbx 1761 * writing this string and a new libcollector looking for 1762 * the min_time field, the 'm' character can be 1763 * removed and process_data_descriptor() simplified. 1764 */ 1765 hrtime_t min_time = hwctr[ii].min_time; 1766 if (min_time == HWCTIME_TBD) 1767 // user did not specify any value for overflow rate 1768 min_time = hwctr[ii].min_time_default; 1769 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), 1770 "%s%s:%s:%d:%d:m%lld:%d:%d:0x%x", ii ? "," : "", 1771 strcmp (hwctr[ii].name, hwctr[ii].int_name) ? hwctr[ii].name : "", 1772 hwctr[ii].int_name, hwctr[ii].reg_num, hwctr[ii].val, 1773 min_time, ii, /*tag*/ hwctr[ii].timecvt, hwctr[ii].memop); 1774 } 1775 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), ";"); 1776 } 1777 if ((time_run != 0) || (start_delay != 0)) 1778 { 1779 if (start_delay != 0) 1780 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "t:%d:%d;", start_delay, time_run); 1781 else 1782 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "t:%d;", time_run); 1783 } 1784 if (sample_period != 0) 1785 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "S:%d;", 1786 sample_period); 1787 if (size_limit != 0) 1788 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "L:%d;", 1789 size_limit); 1790 if (java_mode != 0) 1791 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "j:%d;", (int) java_mode); 1792 if (follow_mode != FOLLOW_NONE) 1793 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "F:%d;", (int) follow_mode); 1794 snprintf (spec + strlen (spec), sizeof (spec) - strlen (spec), "a:%s;", archive_mode); 1795 if (strlen (spec) + 1 >= sizeof (spec)) 1796 abort (); 1797 free (data_desc); 1798 data_desc = strdup (spec); 1799} 1800 1801char * 1802Coll_Ctrl::check_group () 1803{ 1804 char group_file[MAXPATHLEN]; 1805 if (expt_group == NULL) 1806 return NULL; 1807 // Is the group an relative path, with a store directory set? 1808 if ((expt_group[0] == '/') || ((udir_name == NULL) || (udir_name[0] == '0'))) 1809 snprintf (group_file, sizeof (group_file), "%s", expt_group); 1810 else // relative path, store directory; make group_file in that directory 1811 snprintf (group_file, sizeof (group_file), "%s/%s", udir_name, expt_group); 1812 // See if we can write the group file 1813 int ret = access (group_file, W_OK); 1814 if (ret != 0) 1815 { 1816 if (errno == ENOENT) 1817 { 1818 char *stmp = group_file; 1819 char *dir = dirname (stmp); 1820 ret = access (dir, W_OK); 1821 if (ret != 0) // group file does not exist; 1822 return dbe_sprintf (GTXT ("Directory (%s) for group file %s is not writeable: %s\n"), 1823 dir, group_file, strerror (errno)); 1824 } 1825 else 1826 return dbe_sprintf (GTXT ("Group file %s is not writeable: %s\n"), 1827 group_file, strerror (errno)); 1828 } 1829 return NULL; 1830} 1831 1832char * 1833Coll_Ctrl::join_group () 1834{ 1835 int tries = 0; 1836 int groupfd; 1837 FILE *file; 1838 char group_file[MAXPATHLEN]; 1839 struct stat statbuf; 1840 struct flock flockbuf; 1841 flockbuf.l_type = F_WRLCK; 1842 flockbuf.l_whence = SEEK_SET; 1843 flockbuf.l_start = 0; 1844 flockbuf.l_len = 0; 1845 if (expt_group == NULL) 1846 return NULL; 1847 // Is the group an relative path, with a store directory set? 1848 if (expt_group[0] == '/' || udir_name == NULL || udir_name[0] == '0') 1849 snprintf (group_file, sizeof (group_file), "%s", expt_group); 1850 else // relative path, store directory; make group_file in that directory 1851 snprintf (group_file, sizeof (group_file), "%s/%s", udir_name, expt_group); 1852 for (;;) 1853 { 1854 tries++; 1855 // try to open the group file 1856 while ((groupfd = open (group_file, O_RDWR)) >= 0) 1857 { 1858 if (uinterrupt == 1) 1859 { 1860 close (groupfd); 1861 return strdup (GTXT ("user interrupt\n")); 1862 } 1863 // it's opened, now lock it 1864 if (fcntl (groupfd, F_SETLK, &flockbuf) != -1) 1865 { 1866 // we got the lock; check the file size 1867 if (fstat (groupfd, &statbuf) != 0) 1868 { 1869 // can't stat the file -- give up 1870 close (groupfd); 1871 return dbe_sprintf (GTXT ("Can't fstat group file %s\n"), group_file); 1872 } 1873 if (statbuf.st_size == 0) 1874 { 1875 // size is zero: we got the lock just as someone 1876 // else created the group file 1877 // close the file and release the lock; try again 1878 close (groupfd); 1879 continue; 1880 } 1881 else 1882 { 1883 // size is non-zero, add our record 1884 file = fdopen (groupfd, "a"); 1885 if (file == NULL) 1886 { 1887 close (groupfd); 1888 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file); 1889 } 1890 if (fprintf (file, "%s\n", store_ptr) <= 0) 1891 { 1892 fclose (file); 1893 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file); 1894 } 1895 // close the file, releasing our lock 1896 fclose (file); 1897 return NULL; 1898 } 1899 } 1900 else 1901 { 1902 // can't get the lock, close the file and try again 1903 close (groupfd); 1904 if (uinterrupt == 1) 1905 return strdup (GTXT ("user interrupt\n")); 1906 if (tries == 11900) 1907 return dbe_sprintf (GTXT ("Timed out: waiting for group file %s\n"), group_file); 1908#if 0 1909 if (tries % 500 == 0) 1910 USR_WARN (GTXT ("Waiting for group file %s . . ."), group_file); 1911#endif 1912 usleep (10000U); 1913 continue; 1914 } 1915 } 1916 // If the error was not that the file did not exist, report it 1917 if (errno != ENOENT) 1918 return dbe_sprintf (GTXT ("Can't open group file %s: %s\n"), 1919 group_file, strerror (errno)); 1920 // the file did not exist, try to create it 1921 groupfd = open (group_file, O_CREAT | O_EXCL | O_RDWR, 0666); 1922 if (groupfd < 0) 1923 { 1924 // we could not create the file 1925 if (errno == EEXIST) 1926 continue; 1927 return dbe_sprintf (GTXT ("Can't create group file %s: %s\n"), 1928 group_file, strerror (errno)); 1929 } 1930 // we created the group file, now lock it, waiting for the lock 1931 while (fcntl (groupfd, F_SETLKW, &flockbuf) == -1) 1932 { 1933 // we created the file, but couldn't lock it 1934 if (errno != EINTR) 1935 return dbe_sprintf (GTXT ("Unable to lock group file %s\n"), group_file); 1936 } 1937 // we created and locked the file, write to it 1938 file = fdopen (groupfd, "a"); 1939 if (file == NULL) 1940 { 1941 close (groupfd); 1942 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file); 1943 } 1944 // write the header line 1945 if (fprintf (file, "%s\n", SP_GROUP_HEADER) <= 0) 1946 { 1947 fclose (file); 1948 return dbe_sprintf (GTXT ("Can't initialize group file %s\n"), group_file); 1949 } 1950 if (fprintf (file, "%s\n", store_ptr) <= 0) 1951 { 1952 fclose (file); 1953 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file); 1954 } 1955 // finally, close the file, releasing the lock 1956 fclose (file); 1957 return NULL; 1958 } 1959 // never reached 1960} 1961 1962char * 1963Coll_Ctrl::set_directory (char *dir, char **warn) 1964{ 1965 struct stat statbuf; 1966 *warn = NULL; 1967 if (opened == 1) 1968 return strdup (GTXT ("Experiment is active; command ignored.\n")); 1969 if (stat (dir, &statbuf) != 0) 1970 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"), 1971 dir, strerror (errno)); 1972 if (!S_ISDIR (statbuf.st_mode)) 1973 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"), 1974 dir, strerror (ENOTDIR)); 1975 free (udir_name); 1976 udir_name = strdup (dir); 1977 1978 // Process new setting 1979 *warn = preprocess_names (); 1980 if ((uexpt_name != NULL) || (interactive != 0)) 1981 { 1982 char *ret = update_expt_name (true, true); 1983 if (ret != NULL) 1984 { 1985 if (*warn != NULL) 1986 { 1987 char *msg = dbe_sprintf ("%s%s", *warn, ret); 1988 free (*warn); 1989 free (ret); 1990 *warn = msg; 1991 } 1992 else 1993 *warn = ret; 1994 } 1995 } 1996 else 1997 (void) update_expt_name (false, false); 1998 return NULL; // All is OK 1999} 2000 2001int 2002Coll_Ctrl::set_target (char* targetname) 2003{ 2004 free (target_name); 2005 target_name = NULL; 2006 if (targetname != NULL) 2007 target_name = strdup (targetname); 2008 return 0; 2009} 2010 2011void 2012Coll_Ctrl::set_default_stem (const char* stem) 2013{ 2014 default_stem = strdup (stem); 2015 preprocess_names (); 2016 (void) update_expt_name (false, false); // no warnings 2017} 2018 2019char * 2020Coll_Ctrl::set_expt (const char *ename, char **warn, bool overwriteExp) 2021{ 2022 *warn = NULL; 2023 if (ename == NULL) 2024 { 2025 free (uexpt_name); 2026 uexpt_name = NULL; 2027 return NULL; 2028 } 2029 char *exptname = canonical_path(strdup(ename)); 2030 size_t i = strlen (exptname); 2031 if (i < 4 || strcmp (&exptname[i - 3], ".er") != 0) 2032 { 2033 free (exptname); 2034 return dbe_sprintf (GTXT ("Experiment name `%s' must end in `.er'\n"), 2035 ename); 2036 } 2037 // Name is OK 2038 free (uexpt_name); 2039 uexpt_name = exptname; 2040 preprocess_names (); 2041 char *err = update_expt_name (true, true, overwriteExp); 2042 if (err != NULL) 2043 return err; 2044 if (overwriteExp) 2045 { 2046 char *nm = dbe_sprintf ("%s/%s", store_dir, base_name); 2047 struct stat statbuf; 2048 char *cmd = dbe_sprintf ("/bin/rm -rf %s >/dev/null 2>&1", nm); 2049 system (cmd); 2050 free (cmd); 2051 if (stat (nm, &statbuf) == 0) 2052 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm); 2053 if (errno != ENOENT) 2054 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm); 2055 free (nm); 2056 } 2057 *warn = update_expt_name (true, false); 2058 return NULL; 2059} 2060 2061char * 2062Coll_Ctrl::set_group (char *groupname) 2063{ 2064 if (opened == 1) 2065 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2066 if (expt_group != NULL) 2067 { 2068 free (expt_group); 2069 expt_group = NULL; 2070 } 2071 if (groupname == NULL) 2072 { 2073 // reset the name 2074 preprocess_names (); 2075 (void) update_expt_name (true, false); 2076 return NULL; 2077 } 2078 int i = (int) strlen (groupname); 2079 if (i < 5 || strcmp (&groupname[i - 4], ".erg") != 0) 2080 return dbe_sprintf (GTXT ("Experiment group name `%s'must end in `.erg'\n"), groupname); 2081 expt_group = strdup (groupname); 2082 preprocess_names (); 2083 (void) update_expt_name (true, false); 2084 return NULL; 2085} 2086 2087char * 2088Coll_Ctrl::set_java_mode (const char *string) 2089{ 2090 struct stat statbuf; 2091 if (opened == 1) 2092 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2093 if (string == NULL || strlen (string) == 0 || strcmp (string, "on") == 0) 2094 { 2095#if defined(GPROFNG_JAVA_PROFILING) 2096 int prev_java_mode = java_mode; 2097 int prev_java_default = java_default; 2098 java_mode = 1; 2099 java_default = 0; 2100 char *ret = check_consistency (); 2101 if (ret != NULL) 2102 { 2103 java_mode = prev_java_mode; 2104 java_default = prev_java_default; 2105 return ret; 2106 } 2107 return NULL; 2108#else 2109 return strdup (GTXT ("gprofng was built without support for profiling Java applications\n")); 2110#endif 2111 } 2112 if (strcmp (string, "off") == 0) 2113 { 2114 int prev_java_mode = java_mode; 2115 int prev_java_default = java_default; 2116 java_mode = 0; 2117 java_default = 0; 2118 char *ret = check_consistency (); 2119 if (ret != NULL) 2120 { 2121 java_mode = prev_java_mode; 2122 java_default = prev_java_default; 2123 return ret; 2124 } 2125 free (java_path); 2126 java_path = NULL; 2127 return NULL; 2128 } 2129 /* any other value should be a path to Java installation directory */ 2130 if (stat (string, &statbuf) == 0) 2131 { 2132 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) 2133 { 2134 // it's a directory -- set the Java path to it 2135 int prev_java_mode = java_mode; 2136 int prev_java_default = java_default; 2137 java_mode = 1; 2138 java_default = 0; 2139 char *ret = check_consistency (); 2140 if (ret != NULL) 2141 { 2142 java_mode = prev_java_mode; 2143 java_default = prev_java_default; 2144 return ret; 2145 } 2146 return set_java_path (string); 2147 } 2148 } 2149 return dbe_sprintf (GTXT ("Java-profiling parameter is neither \"on\", nor \"off\", nor is it a directory: `%s'\n"), string); 2150} 2151 2152char * 2153Coll_Ctrl::set_java_path (const char *string) 2154{ 2155 if (opened == 1) 2156 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2157 free (java_path); 2158 java_path = strdup (string); 2159 return NULL; 2160} 2161 2162char * 2163Coll_Ctrl::set_java_args (char *string) 2164{ 2165 char *next; 2166 if (opened == 1) 2167 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2168 char *prev_java_args = java_args; 2169 if (string == NULL || strlen (string) == 0) 2170 java_args = strdup (""); 2171 else 2172 java_args = strdup (string); 2173 // now count the number of Java arguments 2174 for (next = java_args; *next; next++) 2175 { 2176 if (*next == ' ' || *next == '\t') 2177 continue; 2178 njava_args++; 2179 for (++next; *next; next++) 2180 if (*next == ' ' || *next == '\t') 2181 break; 2182 if (!*next) 2183 break; 2184 } 2185 if (njava_args == 0) 2186 java_args = NULL; 2187 char *ret = check_consistency (); 2188 if (ret != NULL) 2189 { 2190 java_args = prev_java_args; 2191 return ret; 2192 } 2193 free (prev_java_args); 2194 return NULL; 2195} 2196 2197char * 2198Coll_Ctrl::set_follow_mode (const char *string) 2199{ 2200 if (opened == 1) 2201 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2202 free (follow_spec_usr); 2203 free (follow_spec_cmp); 2204 follow_spec_usr = NULL; 2205 follow_spec_cmp = NULL; 2206 if (string == NULL || strlen (string) == 0 || strcmp (string, "all") == 0 2207 || strcmp (string, "on") == 0) 2208 { 2209 follow_mode = FOLLOW_ON; 2210 follow_default = 0; 2211 return NULL; 2212 } 2213 if (strcmp (string, "off") == 0) 2214 { 2215 follow_mode = FOLLOW_NONE; 2216 follow_default = 0; 2217 return NULL; 2218 } 2219 2220 /* compile regular expression if string starts with "=" */ 2221 if (string[0] == '=' && string[1] != 0) 2222 { 2223 // user has specified a string matching specification 2224 regex_t regex_desc; 2225 int ercode; 2226 const char *userspec = &string[1]; 2227 size_t newstrlen = strlen (userspec) + 3; 2228 char * str = (char *) malloc (newstrlen); 2229 if (str) 2230 { 2231 snprintf (str, newstrlen, "^%s$", userspec); 2232 assert (strlen (str) == newstrlen - 1); 2233 ercode = regcomp (®ex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); 2234 } 2235 else 2236 ercode = 1; 2237 if (!ercode) 2238 { 2239 follow_spec_usr = strdup (string); 2240 /* Ideally, follow_spec_cmp = [serialized regex_desc], */ 2241 /* so that libcollector wouldn't have to recompile it. */ 2242 /* For now, just copy the regular expression into follow_spec_cmp */ 2243 follow_spec_cmp = str; 2244 follow_mode = FOLLOW_ALL; 2245 follow_default = 0; 2246 return NULL; 2247 } 2248 // syntax error in parsing string 2249#if 0 2250 char errbuf[256]; 2251 regerror (ercode, ®ex_desc, errbuf, sizeof (errbuf)); 2252 fprintf (stderr, "Coll_Ctrl::set_follow_mode: regerror()=%s\n", errbuf); 2253#endif 2254 free (str); 2255 } 2256 return dbe_sprintf (GTXT ("Unrecognized follow-mode parameter `%s'\n"), string); 2257} 2258 2259char * 2260Coll_Ctrl::set_prof_idle (const char *string) 2261{ 2262 if (opened == 1) 2263 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2264 if (string == NULL || strlen (string) == 0 || strcmp (string, "on") == 0) 2265 { 2266 prof_idle = 1; 2267 return NULL; 2268 } 2269 if (strcmp (string, "off") == 0) 2270 { 2271 prof_idle = 0; 2272 return NULL; 2273 } 2274 return dbe_sprintf (GTXT ("Unrecognized profiling idle cpus parameter `%s'\n"), string); 2275} 2276 2277char * 2278Coll_Ctrl::set_archive_mode (const char *string) 2279{ 2280 if (opened == 1) 2281 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2282 if (string == NULL || strlen (string) == 0) 2283 string = "on"; 2284 if (strcasecmp (string, "on") == 0 || strcasecmp (string, "off") == 0 2285 || strcasecmp (string, "ldobjects") == 0 2286 || strcasecmp (string, "usedldobjects") == 0 2287 || strcasecmp (string, "src") == 0 || strcasecmp (string, "usedsrc") == 0 2288 || strcasecmp (string, "all") == 0) 2289 { 2290 free (archive_mode); 2291 archive_mode = strdup (string); 2292 return NULL; 2293 } 2294 return dbe_sprintf (GTXT ("Unrecognized archive-mode parameter `%s'\n"), string); 2295} 2296 2297char * 2298Coll_Ctrl::set_sample_signal (int value) 2299{ 2300 const char *buf; 2301 if (opened == 1) 2302 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2303 if (value == 0) 2304 { 2305 sample_sig = 0; 2306 return NULL; 2307 } 2308 if (value == pauseresume_sig) 2309 return report_signal_conflict (value); 2310 if ((buf = strsignal (value)) != NULL) 2311 sample_sig = value; 2312 else 2313 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), value); 2314 return NULL; 2315} 2316 2317/* find a signal by name */ 2318int 2319Coll_Ctrl::find_sig (const char *string) 2320{ 2321 int val; 2322 char *signame_alloc = NULL; 2323 const char *signame; 2324 val = -1; 2325 if (strcmp (string, "off") == 0) 2326 return 0; 2327 // see if the name begins with SIG 2328 if (strncmp (string, "SIG", 3) != 0) 2329 { 2330 // no: add it 2331 signame_alloc = (char *) malloc (strlen (string) + 3 + 1); 2332 if (signame_alloc == NULL) 2333 return -1; 2334 strcpy (signame_alloc, "SIG"); 2335 strcpy (&signame_alloc[3], string); 2336 signame = signame_alloc; 2337 } 2338 else 2339 signame = string; 2340 2341 /* see if the string is a number */ 2342 char *endchar = NULL; 2343 val = (int) strtol (signame, &endchar, 0); 2344 if (*endchar != 0) 2345 val = strtosigno (signame); 2346 free (signame_alloc); 2347 if (val == SIGKILL) 2348 return -1; 2349 return val; 2350} 2351 2352char * 2353Coll_Ctrl::set_pauseresume_signal (int value, int resume) 2354{ 2355 if (opened == 1) 2356 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2357 if (value == 0) 2358 { 2359 pauseresume_sig = 0; 2360 return NULL; 2361 } 2362 if (value == sample_sig) 2363 return report_signal_conflict (value); 2364 if (strsignal (value) != NULL) 2365 { 2366 pauseresume_sig = value; 2367 pauseresume_pause = resume; 2368 } 2369 else 2370 return dbe_sprintf (GTXT ("Invalid pause-resume (delayed initialization) signal %d\n"), value); 2371 return NULL; 2372} 2373 2374char * 2375Coll_Ctrl::report_signal_conflict (int value) 2376{ 2377 const char *xbuf = strsignal (value); 2378 if (xbuf != NULL) 2379 return dbe_sprintf (GTXT ("Signal %s (%d) can not be used for both sample and pause-resume (delayed initialization)\n"), 2380 xbuf, value); 2381 return dbe_sprintf (GTXT ("Signal %d can not be used for both sample and pause-resume (delayed initialization)\n"), 2382 value); 2383} 2384 2385char * 2386Coll_Ctrl::set_debug_mode (int value) 2387{ 2388 if (opened == 1) 2389 return strdup (GTXT ("Experiment is active; command ignored.\n")); 2390 debug_mode = value; 2391 return NULL; 2392} 2393 2394char * 2395Coll_Ctrl::create_exp_dir () 2396{ 2397 int max = 4095; // 0xFFF - can be increased if it seems too low 2398 for (int i = 0; i < max; i++) 2399 { 2400 if (mkdir (store_ptr, 2401 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) 2402 { 2403 int err = errno; 2404 if (err == EACCES) 2405 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"), 2406 store_dir, strerror (err)); 2407 if (i + 1 >= max) // no more attempts 2408 return dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n%s: %d\n"), 2409 store_ptr, strerror (err), 2410 GTXT ("collect: Internal error: loop count achieved"), 2411 max); 2412 char *ermsg = update_expt_name (false, false, true); 2413 if (ermsg != NULL) 2414 { 2415 char *msg = dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n"), 2416 store_ptr, ermsg); 2417 free (ermsg); 2418 return msg; 2419 } 2420 continue; 2421 } 2422 return NULL; // All is OK 2423 } 2424 return dbe_sprintf (GTXT ("Unable to create directory `%s'\n"), store_ptr); 2425} 2426 2427char * 2428Coll_Ctrl::get_exp_name (const char *stembase) 2429{ 2430 expno = 1; 2431 return dbe_sprintf ("%s.%d.er", stembase, expno); 2432} 2433 2434char * 2435Coll_Ctrl::preprocess_names () 2436{ 2437 char buf[MAXPATHLEN]; 2438 char msgbuf[MAXPATHLEN]; 2439 char *ret = NULL; 2440 2441 /* convert the experiment name and directory into store name/dir */ 2442 /* free the old strings */ 2443 if (store_dir != NULL) 2444 { 2445 free (store_dir); 2446 store_dir = NULL; 2447 } 2448 if (expt_dir != NULL) 2449 { 2450 free (expt_dir); 2451 expt_dir = NULL; 2452 } 2453 if (base_name != NULL) 2454 { 2455 free (base_name); 2456 base_name = NULL; 2457 } 2458 if (expt_name != NULL) 2459 { 2460 free (expt_name); 2461 expt_name = NULL; 2462 } 2463 expno = 1; 2464 if (uexpt_name != NULL) 2465 expt_name = strdup (uexpt_name); 2466 else 2467 { 2468 // no user name -- pick a default 2469 char *c; 2470 char *stem; 2471 char *stembase; 2472 if (expt_group == NULL) 2473 { 2474 stem = strdup (default_stem); 2475 stembase = stem; 2476 } 2477 else 2478 { 2479 stem = strdup (expt_group); 2480 stem[strlen (stem) - 4] = 0; 2481 stembase = stem; 2482 // now remove any leading directory 2483 for (int i = 0;; i++) 2484 { 2485 if (stem[i] == 0) 2486 break; 2487 if (stem[i] == '/') 2488 stembase = &stem[i + 1]; 2489 } 2490 if (strlen (stembase) == 0) 2491 { 2492 free (stem); 2493 stem = strdup (default_stem); 2494 stembase = stem; 2495 } 2496 } 2497 c = get_exp_name (stembase); 2498 expt_name = c; 2499 free (stem); 2500 } 2501 snprintf (buf, sizeof (buf), NTXT ("%s"), expt_name); 2502 if (buf[0] == '/') 2503 { 2504 // it's a full path name 2505 if (udir_name != NULL) 2506 { 2507 snprintf (msgbuf, sizeof (msgbuf), 2508 GTXT ("Warning: Experiment name is an absolute path; directory name %s ignored.\n"), 2509 udir_name); 2510 ret = strdup (msgbuf); 2511 } 2512 } 2513 2514 // now extract the directory and basename 2515 int lastslash = 0; 2516 for (int i = 0;; i++) 2517 { 2518 if (buf[i] == 0) 2519 break; 2520 if (buf[i] == '/') 2521 lastslash = i; 2522 } 2523 expt_dir = strdup (buf); 2524 if (lastslash != 0) 2525 base_name = strdup (&buf[lastslash + 1]); 2526 else 2527 base_name = strdup (buf); 2528 expt_dir[lastslash] = 0; 2529 if (expt_dir[0] == '/') 2530 store_dir = strdup (expt_dir); 2531 else if ((udir_name == NULL) || (udir_name[0] == 0)) 2532 { 2533 if (expt_dir[0] == 0) 2534 store_dir = strdup ("."); 2535 else 2536 store_dir = strdup (expt_dir); 2537 } 2538 else 2539 { 2540 /* udir_name is a non-empty string */ 2541 if (expt_dir[0] == 0) 2542 store_dir = strdup (udir_name); 2543 else 2544 { 2545 snprintf (buf, sizeof (buf), "%s/%s", udir_name, expt_dir); 2546 store_dir = strdup (buf); 2547 } 2548 } 2549 free (store_ptr); 2550 if (strcmp (store_dir, ".") == 0) 2551 store_ptr = strdup (base_name); 2552 else 2553 { 2554 snprintf (buf, sizeof (buf), "%s/%s", store_dir, base_name); 2555 store_ptr = strdup (buf); 2556 } 2557 2558 // determine the file system type 2559 if (strcmp (store_dir, prev_store_dir) != 0) 2560 { 2561 free (prev_store_dir); 2562 prev_store_dir = strdup (store_dir); 2563 const char *fstype = get_fstype (store_dir); 2564 if (interactive && enabled && (fstype != NULL) && (nofswarn == 0)) 2565 { 2566 snprintf (msgbuf, sizeof (msgbuf), 2567 GTXT ("%sExperiment directory is set to a file system of type \"%s\",\n which may distort the measured performance;\n it is preferable to record to a local disk.\n"), 2568 (ret == NULL ? "" : ret), fstype); 2569 free (ret); 2570 ret = strdup (msgbuf); 2571 } 2572 } 2573 return ret; 2574} 2575 2576char * 2577Coll_Ctrl::update_expt_name (bool chgmsg, bool chkonly, bool newname) 2578{ 2579 char *ret = NULL; 2580 struct stat statbuf; 2581 // make sure the name ends in .er 2582 // set count to the length of the name 2583 int count = (int) strlen (base_name); 2584 2585 // this should have been checked already, so we can abort 2586 if (count < 4 || strcmp (&base_name[count - 3], ".er") != 0) 2587 abort (); 2588 int pcount = count - 4; 2589 if (!newname) 2590 { // check if old name can be used 2591 char fullname[MAXPATHLEN]; 2592 snprintf (fullname, sizeof (fullname), "%s/%s", store_dir, base_name); 2593 if (stat (fullname, &statbuf) != 0) 2594 if (errno == ENOENT) // name does not exist, we can use it 2595 return NULL; 2596 } 2597 else if (chkonly) 2598 return NULL; 2599 2600 // current name will not work, update the name 2601 DIR *dir; 2602 struct dirent *dir_entry; 2603 2604 // see if there's a numeric field in front of the .er of the name 2605 int digits = 0; 2606 while (isdigit ((int) (base_name[pcount])) != 0) 2607 { 2608 pcount--; 2609 if (pcount == 0) // name is of the form 12345.er; don't update it 2610 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"), 2611 base_name); 2612 digits++; 2613 } 2614 if (digits == 0) // name is of form xyz.er (or xyz..er); don't update it 2615 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"), 2616 base_name); 2617 if (base_name[pcount] != '.') // name is of form xyz123.er; don't update it 2618 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"), 2619 base_name); 2620 if (chkonly) 2621 return NULL; 2622 2623 // save the name for a changed message 2624 char *oldbase = strdup (base_name); 2625 2626 // the name is of the from prefix.nnn.er; extract the value of nnn 2627 int version = atoi (&base_name[pcount + 1]); 2628 if (newname) // do not try to use old name 2629 version++; 2630 int max_version = version - 1; 2631 2632 // terminate the base_name string after that . yielding "prefix." 2633 base_name[pcount + 1] = 0; 2634 if ((dir = opendir (store_dir)) == NULL) 2635 { 2636 // ignore error -- we'll hit it again later 2637 free (oldbase); 2638 return NULL; 2639 } 2640 2641 // find the maximum version in the directory 2642 // count is the number of characters before the number 2643 // 2644 while ((dir_entry = readdir (dir)) != NULL) 2645 { 2646 count = (int) strlen (dir_entry->d_name); 2647 if ((count < 4) || (strcmp (&dir_entry->d_name[count - 3], ".er") != 0)) 2648 continue; 2649 // check that the name is of the form prefix.nnn.er; if not, skip it 2650 if (strncmp (base_name, dir_entry->d_name, pcount + 1) == 0) 2651 { 2652 // the "prefix." part matches, terminate the entry name before the .er 2653 dir_entry->d_name[count - 3] = 0; 2654 char *lastchar; 2655 int dversion = (int) strtol (&dir_entry->d_name[pcount + 1], &lastchar, 10); 2656 2657 // if it did not end where the .er was, skip it 2658 if (*lastchar != 0) 2659 continue; 2660 if (dversion > max_version) 2661 max_version = dversion; 2662 } 2663 } 2664 2665 // we now have the maximum version determined 2666 char newbase[MAXPATHLEN]; 2667 base_name[pcount + 1] = 0; 2668 version = max_version + 1; 2669 snprintf (newbase, sizeof (newbase), "%s%d.er", base_name, version); 2670 if ((strcmp (oldbase, newbase) != 0) && chgmsg) 2671 { 2672 ret = dbe_sprintf (GTXT ("name %s is in use; changed to %s\n"), 2673 oldbase, newbase); 2674 free (oldbase); 2675 } 2676 else 2677 free (oldbase); 2678 free (base_name); 2679 base_name = strdup (newbase); 2680 2681 // now, reset expt_name to reflect new setting 2682 free (expt_name); 2683 if (expt_dir[0] == 0) 2684 expt_name = strdup (base_name); 2685 else 2686 expt_name = dbe_sprintf ("%s/%s", expt_dir, base_name); 2687 free (store_ptr); 2688 if (strcmp (store_dir, ".") == 0) 2689 store_ptr = strdup (base_name); 2690 else 2691 store_ptr = dbe_sprintf ("%s/%s", store_dir, base_name); 2692 closedir (dir); 2693 return ret; 2694} 2695 2696void 2697Coll_Ctrl::remove_exp_dir () 2698{ 2699 if (store_ptr == NULL) 2700 return; 2701 rmdir (store_ptr); 2702 free (store_ptr); 2703 store_ptr = NULL; 2704 return; 2705} 2706 2707void 2708Coll_Ctrl::determine_profile_params () 2709{ 2710 struct itimerval itimer; 2711 struct itimerval otimer; 2712 int period; 2713 long nperiod; 2714 struct sigaction act; 2715 struct sigaction old_handler; 2716 memset (&act, 0, sizeof (struct sigaction)); 2717 period = 997; 2718 2719 // set SIGPROF handler to SIG_IGN 2720 sigemptyset (&act.sa_mask); 2721 act.sa_handler = SIG_IGN; 2722 act.sa_flags = SA_RESTART | SA_SIGINFO; 2723 if (sigaction (SIGPROF, &act, &old_handler) == -1) 2724 { 2725 /* couldn't set signal */ 2726 fprintf (stderr, GTXT ("Can't set SIGPROF: %s\n"), strerror (errno)); 2727 exit (1); 2728 } 2729 2730 // set the timer to arbitrary resolution 2731 itimer.it_interval.tv_sec = period / MICROSEC; 2732 itimer.it_interval.tv_usec = period % MICROSEC; 2733 itimer.it_value = itimer.it_interval; 2734 setitimer (ITIMER_REALPROF, &itimer, &otimer); 2735 2736 // now reset the timer to turn it off 2737 itimer.it_value.tv_sec = 0; 2738 itimer.it_value.tv_usec = 0; 2739 if (setitimer (ITIMER_REALPROF, &itimer, &otimer) == -1) // call failed 2740 nperiod = -1; 2741 else 2742 nperiod = otimer.it_interval.tv_sec * MICROSEC + otimer.it_interval.tv_usec; 2743 2744 // check the returned value: is the what we asked for? 2745 if (period == nperiod) // arbitrary precision is OK 2746 set_clk_params (PROFINT_MIN, 1, PROFINT_MAX, PROFINT_HIGH, PROFINT_NORM, PROFINT_LOW); 2747 else if (nperiod < 10000) // hi resolution allowed, but not arbitrary precision 2748 set_clk_params ((int) nperiod, 1000, PROFINT_MAX, 1000, 10000, 100000); 2749 else // low resolution only allowed 2750 set_clk_params (10000, 10000, PROFINT_MAX, 1000, 10000, 100000); 2751 2752 // If old handler was default, ignore it; otherwise restore it 2753 if (old_handler.sa_handler != SIG_DFL) 2754 { 2755 act.sa_handler = old_handler.sa_handler; 2756 if (sigaction (SIGPROF, &act, &old_handler) == -1) 2757 { 2758 /* couldn't reset signal */ 2759 fprintf (stderr, GTXT ("Can't reset SIGPROF: %s\n"), strerror (errno)); 2760 exit (1); 2761 } 2762 } 2763} 2764 2765const char * 2766get_fstype (char *) 2767{ 2768 /* On Linux, statvfs() doesn't return any information that seems to indicate 2769 the filetype. The structure statvfs does not have any field/flag that 2770 gives this information. Comparing the fields from 2771 /usr/include/bits/statvfs.h: 2772 unsigned long int f_fsid; 2773 int __f_unused; 2774 ^^^^ On Solaris, this is where f_basetype is 2775 unsigned long int f_flag; 2776 unsigned long int f_namemax; 2777 XXX Need to revisit this XXX 2778 */ 2779 return NULL; // no NFS warning on Linux for now 2780} 2781 2782//========== Special functions to communicate with the Collector GUI ==========// 2783 2784/* Interface strings GUI <-> CLI */ 2785const char *ipc_str_exp_limit = "exp_limit"; 2786const char *ipc_str_time_limit = "time_limit"; 2787const char *ipc_str_arch_exp = "arch_exp"; 2788const char *ipc_str_descendant = "descendant"; 2789const char *ipc_str_clkprof = "clkprof"; 2790const char *ipc_str_hwcprof = "hwcprof"; 2791const char *ipc_str_hwc2_prof = "hwc2_prof"; 2792const char *ipc_str_javaprof = "javaprof"; 2793const char *ipc_str_sample = "sample"; 2794const char *ipc_str_sample_sig = "sample_sig"; 2795const char *ipc_str_pause_resume_sig = "pause_resume_sig"; 2796const char *ipc_str_synctrace = "synctrace"; 2797const char *ipc_str_heaptrace = "heaptrace"; 2798const char *ipc_str_iotrace = "iotrace"; 2799const char *ipc_str_count = "count"; 2800const char *ipc_str_prof_idle = "prof_idle"; // -x option 2801// Standard answers 2802const char *ipc_str_empty = ""; 2803const char *ipc_str_on = "on"; 2804const char *ipc_str_off = "off"; 2805const char *ipc_str_src = "src"; 2806const char *ipc_str_usedsrc = "usedsrc"; 2807const char *ipc_str_usedldobjects = "usedldobjects"; 2808const char *ipc_str_unlimited = "unlimited"; 2809const char *ipc_str_unknown_control = "Unknown control"; 2810const char *ipc_str_internal_error = "Internal error"; 2811 2812/** 2813 * Finds signal name 2814 * @param signal 2815 * @return NULL or signal name (pointer to allocated memory) 2816 */ 2817char * 2818Coll_Ctrl::find_signal_name (int signal) 2819{ 2820 char *str_signal = NULL; 2821 const char *buf = strsignal (signal); 2822 if (buf != NULL) 2823 str_signal = strdup (buf); 2824 return str_signal; 2825} 2826 2827/** 2828 * Gets control's value 2829 * @param control 2830 * @return value 2831 */ 2832char * 2833Coll_Ctrl::get (char * control) 2834{ 2835 int len = strlen (control); 2836 if (!strncmp (control, ipc_str_exp_limit, len)) 2837 { 2838 if ((size_limit > 0)) 2839 return dbe_sprintf ("%d", size_limit); 2840 return strdup (ipc_str_unlimited); 2841 } 2842 if (!strncmp (control, ipc_str_time_limit, len)) 2843 { 2844 if ((time_run != 0) || (start_delay != 0)) 2845 { 2846 if (start_delay != 0) 2847 { 2848 if (time_run != 0) 2849 return dbe_sprintf ("%ds-%ds", start_delay, start_delay + time_run); 2850 return dbe_sprintf ("%ds-0s", start_delay); 2851 } 2852 return dbe_sprintf ("0s-%ds", time_run); 2853 } 2854 return strdup (ipc_str_unlimited); 2855 } 2856 if (strncmp (control, ipc_str_arch_exp, len) == 0) 2857 return strdup (get_archive_mode ()); 2858 if (!strncmp (control, ipc_str_descendant, len)) 2859 { 2860 switch (get_follow_mode ()) 2861 { 2862 case FOLLOW_ON: 2863 return strdup (ipc_str_on); 2864 case FOLLOW_ALL: 2865 return strdup (ipc_str_on); 2866 case FOLLOW_NONE: 2867 default: 2868 return strdup (ipc_str_off); 2869 } 2870 } 2871 if (!strncmp (control, ipc_str_prof_idle, len)) 2872 { 2873 if (prof_idle == 0) 2874 return strdup (ipc_str_off); 2875 return strdup (ipc_str_on); 2876 } 2877 if (!strncmp (control, ipc_str_clkprof, len)) 2878 { 2879 if (clkprof_default == 1 && clkprof_enabled == 1) // Default value 2880 return strdup (ipc_str_empty); 2881 if (clkprof_enabled == 0) 2882 return strdup (ipc_str_off); 2883 if ((clkprof_timer > 0)) 2884 return dbe_sprintf ("%d", clkprof_timer / 1000); 2885 return strdup (ipc_str_internal_error); 2886 } 2887 if (!strncmp (control, ipc_str_hwcprof, len)) 2888 { 2889 if (hwcprof_enabled_cnt == 0) 2890 return strdup (ipc_str_off); 2891 if (hwc_string != NULL) 2892 return dbe_sprintf ("on\n%s", hwc_string); 2893 return strdup (ipc_str_on); // XXX need more details? 2894 } 2895 if (!strncmp (control, ipc_str_javaprof, len)) 2896 { 2897 if ((java_mode == 0)) 2898 return strdup (ipc_str_off); 2899 return strdup (ipc_str_on); 2900 } 2901 if (!strncmp (control, ipc_str_sample, len)) 2902 { 2903 if (sample_default == 1 && sample_period == 1) // Default value 2904 return strdup (ipc_str_empty); 2905 if (sample_period == 0) 2906 return strdup (ipc_str_off); 2907 if (sample_period > 0) 2908 return dbe_sprintf ("%d", sample_period); 2909 return strdup (ipc_str_internal_error); 2910 } 2911 if (!strncmp (control, ipc_str_sample_sig, len)) 2912 { 2913 if ((sample_sig == 0)) 2914 return strdup (ipc_str_off); 2915 char *str_signal = find_signal_name (sample_sig); 2916 if (str_signal != NULL) 2917 return str_signal; 2918 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), sample_sig); 2919 } 2920 if (!strncmp (control, ipc_str_pause_resume_sig, len)) 2921 { 2922 if (pauseresume_sig == 0) 2923 return strdup (ipc_str_off); 2924 char *str_signal = find_signal_name (pauseresume_sig); 2925 if (str_signal != NULL) 2926 return str_signal; 2927 return dbe_sprintf (GTXT ("Invalid pause/resume signal %d\n"), pauseresume_sig); 2928 } 2929 if (!strncmp (control, ipc_str_synctrace, len)) 2930 { 2931 if (synctrace_enabled == 0) 2932 return strdup (ipc_str_off); 2933 if (synctrace_thresh < 0) 2934 return strdup ("on\nthreshold: calibrate"); 2935 if (synctrace_thresh == 0) 2936 return strdup ("on\nthreshold: all"); 2937 return dbe_sprintf ("on\nthreshold: %d", synctrace_thresh); 2938 } 2939 if (!strncmp (control, ipc_str_heaptrace, len)) 2940 { 2941 if ((heaptrace_enabled == 0)) 2942 return strdup (ipc_str_off); 2943 return strdup (ipc_str_on); 2944 } 2945 if (!strncmp (control, ipc_str_iotrace, len)) 2946 { 2947 if ((iotrace_enabled == 0)) 2948 return strdup (ipc_str_off); 2949 return strdup (ipc_str_on); 2950 } 2951 if (!strncmp (control, ipc_str_count, len)) 2952 { 2953 if ((count_enabled == 0)) 2954 return strdup (ipc_str_off); 2955 if ((count_enabled < 0)) 2956 return strdup ("on\nstatic"); 2957 return strdup (ipc_str_on); 2958 } 2959 return strdup (ipc_str_unknown_control); 2960} 2961 2962/** 2963 * Resets control's value (restores the default value) 2964 * @param control 2965 * @param value 2966 * @return error or warning or NULL (done) 2967 */ 2968char * 2969Coll_Ctrl::set (char * control, const char * value) 2970{ 2971 char * ret; 2972 char * warn = NULL; 2973 int len = strlen (control); 2974 if (!strncmp (control, ipc_str_exp_limit, len)) 2975 return set_size_limit (value); 2976 if (!strncmp (control, ipc_str_time_limit, len)) 2977 return set_time_run (value); 2978 if (!strncmp (control, ipc_str_arch_exp, len)) 2979 return set_archive_mode (value); 2980 if (!strncmp (control, ipc_str_descendant, len)) 2981 return set_follow_mode (value); 2982 if (!strncmp (control, ipc_str_prof_idle, len)) 2983 return set_prof_idle (value); 2984 if (!strncmp (control, ipc_str_clkprof, len)) 2985 { 2986 ret = set_clkprof (value, &warn); 2987 if (ret == NULL) 2988 { 2989 if (warn != NULL) 2990 return warn; // Warning 2991 return NULL; // Done 2992 } 2993 return ret; // Error 2994 } 2995 if (!strncmp (control, ipc_str_hwcprof, len)) 2996 { 2997 ret = set_hwcstring (value, &warn); 2998 if (ret == NULL) 2999 { 3000 if (warn != NULL) 3001 return warn; // Warning 3002 return NULL; // Done 3003 } 3004 return ret; // Error 3005 } 3006 if (!strncmp (control, ipc_str_hwc2_prof, len)) 3007 { 3008 ret = set_hwcstring (value, &warn); 3009 if (ret == NULL) 3010 { 3011 if (warn != NULL) 3012 return warn; // Warning 3013 return NULL; // Done 3014 } 3015 return ret; // Error 3016 } 3017 if (!strncmp (control, ipc_str_javaprof, len)) 3018 return set_java_mode (value); 3019 if (!strncmp (control, ipc_str_sample, len)) 3020 return set_sample_period (value); 3021 if (!strncmp (control, ipc_str_sample_sig, len)) 3022 return set_sample_signal (find_sig (value)); 3023 if (!strncmp (control, ipc_str_pause_resume_sig, len)) 3024 { 3025 char *str_signal = strdup (value); 3026 char *str_state = strchr (str_signal, (int) '\n'); 3027 if (str_state != NULL) 3028 { 3029 *str_state = 0; 3030 str_state++; 3031 } 3032 int signal = atoi (str_signal); 3033 int state = 0; 3034 if (str_state != NULL) 3035 state = atoi (str_state); 3036 free (str_signal); 3037 return set_pauseresume_signal (signal, state); 3038 } 3039 if (!strncmp (control, ipc_str_synctrace, len)) 3040 return set_synctrace (value); 3041 if (!strncmp (control, ipc_str_heaptrace, len)) 3042 return set_heaptrace (value); 3043 if (!strncmp (control, ipc_str_iotrace, len)) 3044 return set_iotrace (value); 3045 if (!strncmp (control, ipc_str_count, len)) 3046 return set_count (value); 3047 return strdup (ipc_str_unknown_control); 3048} 3049 3050/** 3051 * Resets control's value (restores the default value) 3052 * @param control 3053 * @return error or NULL (done) 3054 */ 3055char * 3056Coll_Ctrl::unset (char * control) 3057{ 3058 int len = strlen (control); 3059 if (!strncmp (control, ipc_str_exp_limit, len)) 3060 size_limit = 0; 3061 if (!strncmp (control, ipc_str_time_limit, len)) 3062 { 3063 time_run = 0; 3064 start_delay = 0; 3065 } 3066 if (!strncmp (control, ipc_str_arch_exp, len)) 3067 { 3068 archive_mode = strdup ("on"); 3069 return NULL; 3070 } 3071 if (!strncmp (control, ipc_str_descendant, len)) 3072 { 3073 follow_mode = FOLLOW_NONE; 3074 return NULL; 3075 } 3076 if (!strncmp (control, ipc_str_prof_idle, len)) 3077 { 3078 prof_idle = 1; 3079 return NULL; 3080 } 3081 if (!strncmp (control, ipc_str_clkprof, len)) 3082 { 3083 clkprof_default = 1; 3084 clkprof_enabled = 1; 3085 return NULL; 3086 } 3087 if (!strncmp (control, ipc_str_hwcprof, len)) 3088 { 3089 setup_hwc (); 3090 set_hwcdefault (); 3091 return NULL; 3092 } 3093 if (!strncmp (control, ipc_str_javaprof, len)) 3094 { 3095 java_mode = 0; 3096 java_default = 0; 3097 free (java_path); 3098 java_path = NULL; 3099 free (java_args); 3100 java_args = NULL; 3101 } 3102 if (!strncmp (control, ipc_str_sample, len)) 3103 { 3104 sample_period = 1; 3105 sample_default = 1; 3106 return NULL; 3107 } 3108 if (!strncmp (control, ipc_str_sample_sig, len)) 3109 { 3110 sample_sig = 0; 3111 return NULL; 3112 } 3113 if (!strncmp (control, ipc_str_pause_resume_sig, len)) 3114 { 3115 pauseresume_sig = 0; 3116 return NULL; 3117 } 3118 if (!strncmp (control, ipc_str_synctrace, len)) 3119 { 3120 synctrace_enabled = 0; 3121 synctrace_thresh = -1; 3122 return NULL; 3123 } 3124 if (!strncmp (control, ipc_str_heaptrace, len)) 3125 { 3126 heaptrace_enabled = 0; 3127 return NULL; 3128 } 3129 if (!strncmp (control, ipc_str_iotrace, len)) 3130 { 3131 iotrace_enabled = 0; 3132 return NULL; 3133 } 3134 if (!strncmp (control, ipc_str_count, len)) 3135 { 3136 count_enabled = 0; 3137 Iflag = 0; 3138 Nflag = 0; 3139 return NULL; 3140 } 3141 return strdup (ipc_str_unknown_control); 3142} 3143 3144void 3145Coll_Ctrl::set_project_home (char *s) 3146{ 3147 if (s) 3148 project_home = strdup (s); 3149} 3150