1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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)
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.
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. */
25 #include <sys/types.h>
27 #include <sys/statvfs.h>
28 #include <sys/param.h>
36 #include <regex.h> /* regcomp() */
39 #include "libiberty.h"
42 //#include "hwcfuncs.h"
44 #define SP_GROUP_HEADER "#analyzer experiment group"
45 #define DD_MAXPATHLEN (MAXPATHLEN * 4) /* large, to build up data descriptor */
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)
50 extern const char *strsignal (int);
53 // _SC_CPUID_MAX is not available on 2.6/2.7
55 #define _SC_CPUID_MAX 517
58 const char *get_fstype (char *);
60 Coll_Ctrl::Coll_Ctrl (int _interactive
, bool _defHWC
, bool _kernelHWC
)
62 char hostname
[MAXPATHLEN
];
64 interactive
= _interactive
;
66 kernelHWC
= _kernelHWC
;
68 /* set this host's parameters */
69 gethostname (hostname
, 1023);
70 node_name
= strdup (hostname
);
71 char *p
= strchr (node_name
, (int) '.');
74 default_stem
= strdup ("test");
76 /* get CPU count and processor clock rate */
77 ncpumax
= sysconf (_SC_CPUID_MAX
);
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;
87 // On Linux, read /proc/cpuinfo to get CPU count and clock rate
88 // Note that parsing is different on SPARC and x86
90 FILE *procf
= fopen ("/proc/cpuinfo", "r");
94 while (fgets (temp
, (int) sizeof (temp
), procf
) != NULL
)
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)
101 char *val
= strchr (temp
, ':');
104 unsigned long long freq
;
105 sscanf (val
+ 2, "%llx", &freq
);
106 cpu_clk_freq
= (unsigned int) (((double) freq
) / 1000000.0 + 0.5);
115 #elif defined(__aarch64__)
116 asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_clk_freq
));
119 FILE *procf
= fopen ("/proc/cpuinfo", "r");
123 while (fgets (temp
, (int) sizeof (temp
), procf
) != NULL
)
126 if (strncmp (temp
, "processor", 9) == 0)
128 else if (strncmp (temp
, "cpu MHz", 7) == 0)
130 char *val
= strchr (temp
, ':');
131 cpu_clk_freq
= val
? atoi (val
+ 1) : 0;
138 /* check resolution of system clock */
139 sys_resolution
= sysconf (_SC_CLK_TCK
);
140 if (sys_resolution
== 0)
143 sys_period
= MICROSEC
/ (int) sys_resolution
;
145 /* determine memory page size and number of pages */
146 npages
= sysconf (_SC_PHYS_PAGES
);
147 page_size
= sysconf (_SC_PAGE_SIZE
);
149 /* set default clock parameters */
150 hwcprof_enabled_cnt
= 0; // must be set before calling determine_profile_params();
151 determine_profile_params (); // inits clk_params which is used by clock profiling AND HWCs
152 cpc_cpuver
= CPUVER_UNDEFINED
;
154 /* set default control values */
156 #if defined(GPROFNG_JAVA_PROFILING)
165 follow_mode
= FOLLOW_ON
;
167 follow_spec_usr
= NULL
;
168 follow_spec_cmp
= NULL
;
170 archive_mode
= strdup ("on");
178 /* clear the string pointers */
185 prev_store_dir
= strdup ("");
195 /* set default data collection values */
200 for (unsigned ii
= 0; ii
< MAX_PICS
; ii
++)
202 memset (&hwctr
[ii
], 0, sizeof (Hwcentry
));
203 hwctr
[ii
].reg_num
= -1;
211 else // disable the default, and reset the counters
212 hwcprof_enabled_cnt
= 0;
213 synctrace_enabled
= 0;
214 synctrace_thresh
= -1;
216 heaptrace_enabled
= 0;
217 heaptrace_checkenabled
= 0;
228 // ensure that the default name is updated
229 // but don't print any message
230 (void) preprocess_names ();
231 (void) update_expt_name (false, false);
234 /* Copy constructor */
235 Coll_Ctrl::Coll_Ctrl (Coll_Ctrl
* cc
)
238 interactive
= cc
->interactive
;
240 kernelHWC
= cc
->kernelHWC
;
241 node_name
= strdup (cc
->node_name
);
242 default_stem
= strdup (cc
->default_stem
);
244 cpu_clk_freq
= cc
->cpu_clk_freq
;
246 page_size
= cc
->page_size
;
247 cpc_cpuver
= cc
->cpc_cpuver
;
248 debug_mode
= cc
->debug_mode
;
249 java_mode
= cc
->java_mode
;
250 java_default
= cc
->java_default
;
254 follow_mode
= cc
->follow_mode
;
255 follow_default
= cc
->follow_default
;
256 if (cc
->follow_spec_usr
)
258 follow_spec_usr
= strdup (cc
->follow_spec_usr
);
259 follow_spec_cmp
= strdup (cc
->follow_spec_cmp
);
263 follow_spec_usr
= NULL
;
264 follow_spec_cmp
= NULL
;
266 archive_mode
= strdup (cc
->archive_mode
);
267 pauseresume_sig
= cc
->pauseresume_sig
;
268 sample_sig
= cc
->sample_sig
;
269 time_run
= cc
->time_run
;
270 start_delay
= cc
->start_delay
;
271 clk_params
= cc
->clk_params
;
272 clkprof_enabled
= cc
->clkprof_enabled
;
273 clkprof_default
= cc
->clkprof_default
;
274 clkprof_timer
= cc
->clkprof_timer
;
275 clkprof_timer_target
= cc
->clkprof_timer_target
;
277 // copy HW counter information
278 hwcprof_default
= cc
->hwcprof_default
;
279 hwcprof_enabled_cnt
= cc
->hwcprof_enabled_cnt
;
280 if (cc
->hwc_string
!= NULL
)
281 hwc_string
= strdup (cc
->hwc_string
);
284 for (int i
= 0; i
< hwcprof_enabled_cnt
; i
++)
285 hwcentry_dup (&hwctr
[i
], &(cc
->hwctr
[i
]));
286 project_home
= cc
->project_home
? strdup (cc
->project_home
) : NULL
;
287 synctrace_enabled
= cc
->synctrace_enabled
;
288 synctrace_thresh
= cc
->synctrace_thresh
;
289 synctrace_scope
= cc
->synctrace_scope
;
290 heaptrace_enabled
= cc
->heaptrace_enabled
;
291 heaptrace_checkenabled
= cc
->heaptrace_checkenabled
;
292 iotrace_enabled
= cc
->iotrace_enabled
;
293 count_enabled
= cc
->count_enabled
;
296 sample_period
= cc
->sample_period
;
297 sample_default
= cc
->sample_default
;
298 size_limit
= cc
->size_limit
;
299 nofswarn
= cc
->nofswarn
;
301 // these will get reset during preprocess_names()
308 // these represent user settings
310 if (cc
->expt_group
!= NULL
)
311 expt_group
= strdup (cc
->expt_group
);
313 if (cc
->uexpt_name
!= NULL
)
314 uexpt_name
= strdup (cc
->uexpt_name
);
316 if (cc
->udir_name
!= NULL
)
317 udir_name
= strdup (cc
->udir_name
);
319 /* clear the string pointers */
320 prev_store_dir
= strdup ("");
327 /* set default data collection values */
328 enabled
= cc
->enabled
;
330 nofswarn
= cc
->nofswarn
;
331 sys_resolution
= cc
->sys_resolution
;
332 sys_period
= cc
->sys_period
;
334 // ensure that the default name is updated
335 (void) preprocess_names ();
336 (void) update_expt_name (false, false);
340 Coll_Ctrl::~Coll_Ctrl ()
356 hwcprof_enabled_cnt
= 0;
359 /* set up the experiment */
361 Coll_Ctrl::setup_experiment ()
368 /* create the experiment directory */
369 ret
= create_exp_dir ();
373 /* if an experiment-group, join it */
380 /* all is OK, return 0 */
386 Coll_Ctrl::interrupt ()
392 Coll_Ctrl::enable_expt ()
395 return strdup (GTXT ("Experiment is active; command ignored.\n"));
396 if (cpu_clk_freq
== 0)
397 return strdup (GTXT ("Can not determine CPU clock frequency.\n"));
398 if (sys_resolution
== 0)
399 return strdup (GTXT ("System clock profile resolution can not be determined.\n"));
404 /* close the experiment */
406 Coll_Ctrl::close_expt ()
409 (void) update_expt_name (false, false);
412 /* close and delete the experiment */
414 Coll_Ctrl::delete_expt ()
420 /* The order of removing the directory and closing
421 * the experiment may seem unnatural, but it's not.
422 * We do need to update names when we close the experiment
423 * (actually Coll_Ctrl object) and we can't remove anything
429 // Check the experiment settings for consistency. Returns NULL if OK,
430 // or an error message if there are invalid combinations of settings
432 Coll_Ctrl::check_consistency ()
434 /* check for Java arguments, but not Java profiling */
435 if (java_args
!= NULL
&& java_mode
== 0)
436 return strdup (GTXT ("Java arguments can not be set if Java profiling is not enabled.\n"));
438 /* if count data, no other data is allowed */
439 if (count_enabled
!= 0
440 && ((clkprof_default
!= 1 && clkprof_enabled
!= 0)
441 || hwcprof_enabled_cnt
!= 0 || synctrace_enabled
!= 0
442 || heaptrace_enabled
!= 0 || iotrace_enabled
!= 0))
443 return strdup (GTXT ("Count data cannot be collected along with any other data.\n"));
445 /* if count data, various other options are not allowed */
446 if (count_enabled
!= 0
447 && ((java_mode
!= 0 && java_default
!= 1)
448 || java_args
!= NULL
|| debug_mode
!= 0
449 || (follow_mode
!= 0 && follow_default
!= 1)
450 || pauseresume_sig
!= 0 || sample_sig
!= 0
451 || (sample_default
!= 1 && sample_period
!= 0) || time_run
!= 0))
452 return strdup (GTXT ("Count data cannot be collected with any of -F -S -y -l -j -J -x -t .\n"));
453 /* if not count data, I and N options are not allowed */
454 if (count_enabled
== 0 && (Iflag
!= 0 || Nflag
!= 0))
455 return strdup (GTXT ("-I or -N can only be specified with count data.\n"));
460 Coll_Ctrl::check_expt (char **warn
)
464 ret
= check_consistency ();
465 if (ret
!= NULL
) /* something is wrong, return the error */
467 /* check for heaptrace and java -- warn that it covers native allocations only */
468 if (heaptrace_enabled
== 1 && java_mode
== 1 && java_default
== 0)
469 *warn
= strdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n"));
471 /* if no profiling data selected, warn the user */
472 if (clkprof_enabled
== 0 && hwcprof_enabled_cnt
== 0 && synctrace_enabled
== 0
473 && heaptrace_enabled
== 0 && iotrace_enabled
== 0 && count_enabled
== 0)
474 *warn
= strdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n"));
477 /* verify that the directory exists */
479 if (stat (store_dir
, &statbuf
) != 0)
480 return dbe_sprintf (GTXT ("Store directory %s is not accessible: %s\n"),
481 store_dir
, strerror (errno
));
482 if (access (store_dir
, W_OK
) != 0)
483 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),
484 store_dir
, strerror (errno
));
486 /* if an experiment-group, verify that it can be written */
487 ret
= check_group ();
494 Coll_Ctrl::show (int i
)
500 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
501 GTXT ("Collection parameters:\n"));
502 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
503 GTXT (" experiment enabled\n"));
505 if (target_name
!= NULL
)
506 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
507 GTXT ("\ttarget = %s\n"), target_name
);
508 if (uexpt_name
!= NULL
)
509 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
510 GTXT ("\tuser_expt_name = %s\n"), uexpt_name
);
511 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
512 GTXT ("\texpt_name = %s\n"),
513 ((expt_name
!= NULL
) ? expt_name
: NTXT ("<NULL>")));
514 if (udir_name
!= NULL
)
515 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
516 GTXT ("\tdir_name = %s\n"), udir_name
);
517 if (expt_group
!= NULL
)
518 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
519 GTXT ("\texpt_group = %s\n"), expt_group
);
521 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
522 GTXT ("\tdebug_mode enabled\n"));
523 if (clkprof_enabled
!= 0)
524 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
525 GTXT ("\tclock profiling enabled, %.3f millisec.\n"),
526 (double) (clkprof_timer
) / 1000.);
527 if (synctrace_enabled
!= 0)
529 if (synctrace_thresh
< 0)
530 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
531 GTXT ("\tsynchronization tracing enabled, threshold: calibrate; "));
532 else if (synctrace_thresh
== 0)
533 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
534 GTXT ("\tsynchronization tracing enabled, threshold: all; "));
536 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
537 GTXT ("\tsynchronization tracing enabled, threshold: %d micros.; "), synctrace_thresh
);
538 switch (synctrace_scope
)
540 case SYNCSCOPE_NATIVE
:
541 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
542 GTXT ("Native-APIs\n"));
545 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
546 GTXT ("Java-APIs\n"));
548 case SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
:
549 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
550 GTXT ("Native- and Java-APIs\n"));
553 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
554 GTXT ("ERR -- unexpected synctrace_scope %d\n"), synctrace_scope
);
558 if (hwcprof_enabled_cnt
!= 0)
560 char ctrbuf
[MAXPATHLEN
];
561 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
562 GTXT ("\thardware counter profiling%s enabled:\n"),
563 (hwcprof_default
== 1 ? GTXT (" (default)") : ""));
564 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
565 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
566 GTXT ("\t %u. %s\n"), ii
+ 1,
567 hwc_hwcentry_specd_string (ctrbuf
, MAXPATHLEN
, &hwctr
[ii
]));
569 if (heaptrace_enabled
!= 0)
570 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
571 GTXT ("\theap tracing enabled, %s\n"),
572 (heaptrace_checkenabled
== 0 ? GTXT ("no checking") :
573 (heaptrace_checkenabled
== 1 ? GTXT ("over/underrun checking") :
574 GTXT ("over/underrun checking and pattern storing"))));
575 if (iotrace_enabled
!= 0)
576 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
577 GTXT ("\tI/O tracing enabled\n"));
578 switch (count_enabled
)
583 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
584 GTXT ("\tcount data enabled\n"));
587 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
588 GTXT ("\tstatic count data will be generated (for a.out only)\n"));
594 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
595 GTXT ("\tdescendant processes will be followed\n"));
598 if (follow_spec_usr
&& follow_spec_cmp
)
599 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
600 GTXT ("\texperiments will be recorded for descendant processes that match pattern '%s'\n"),
603 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
604 GTXT ("\tdescendant processes will all be followed\n"));
607 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
608 GTXT ("\tdescendant processes will not be followed\n"));
611 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
612 GTXT ("\tfollowing descendant processes: <UNKNOWN>\n"));
616 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
617 GTXT ("\tjava profiling disabled\n"));
618 if (pauseresume_sig
!= 0)
620 const char *buf
= strsignal (pauseresume_sig
);
623 if (pauseresume_pause
== 1)
624 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
625 GTXT ("\tpause-resume (delayed initialization) signal %s (%d) -- paused\n"), buf
, pauseresume_sig
);
627 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
628 GTXT ("\tpause-resume (delayed initialization) signal %s (%d)\n"), buf
, pauseresume_sig
);
632 if (pauseresume_pause
== 1)
633 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
634 GTXT ("\tpause-resume (delayed initialization) signal %d -- paused\n"), pauseresume_sig
);
636 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
637 GTXT ("\tpause-resume (delayed initialization) signal %d\n"), pauseresume_sig
);
642 const char *buf
= strsignal (sample_sig
);
644 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
645 GTXT ("\tsample signal %s (%d)\n"), buf
, sample_sig
);
647 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
648 GTXT ("\tsample signal %d\n"), sample_sig
);
650 if (time_run
!= 0 || start_delay
!= 0)
652 if (start_delay
!= 0)
655 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
656 GTXT ("\tdata-collection duration, %d-%d secs.\n"), start_delay
, time_run
);
658 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
659 GTXT ("\tdata-collection duration, %d- secs.\n"), start_delay
);
662 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
663 GTXT ("\tdata-collection duration, %d secs.\n"), time_run
);
665 if (sample_period
!= 0)
666 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
667 GTXT ("\tperiodic sampling, %d secs.\n"), sample_period
);
669 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
670 GTXT ("\tno periodic sampling\n"));
672 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
673 GTXT ("\texperiment size limit %d MB.\n"), size_limit
);
675 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
676 GTXT ("\tno experiment size limit set\n"));
677 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
678 GTXT ("\texperiment archiving: -a %s\n"), archive_mode
);
679 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
680 GTXT ("\tdata descriptor: \"%s\"\n"),
681 ((data_desc
!= NULL
) ? data_desc
: NTXT ("<NULL>")));
683 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
684 GTXT ("\t expt_dir: %s\n"),
685 ((expt_dir
!= NULL
) ? expt_dir
: NTXT ("<NULL>")));
686 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
687 GTXT ("\t base_name: %s\n"),
688 ((base_name
!= NULL
) ? base_name
: NTXT ("<NULL>")));
689 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
690 GTXT ("\t store_dir: %s\n"),
691 ((store_dir
!= NULL
) ? store_dir
: NTXT ("<NULL>")));
692 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
693 GTXT ("\t store_ptr: %s\n"),
694 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")));
696 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
697 GTXT ("\t\thost: `%s', ncpus = %d, clock frequency %d MHz.\n"),
698 ((node_name
!= NULL
) ? node_name
: NTXT ("<NULL>")),
699 (int) ncpus
, (int) cpu_clk_freq
);
702 long long memsize
= ((long long) npages
* (long long) page_size
) / (1024 * 1024);
703 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
704 GTXT ("\t\tmemory: %ld pages @ %ld bytes = %lld MB.\n"),
705 npages
, page_size
, memsize
);
707 return strdup (UEbuf
);
710 #define MAX_COLLECT_ARGS 100
713 Coll_Ctrl::get_collect_args ()
715 char buf
[DD_MAXPATHLEN
];
717 char **argv
= (char **) calloc (MAX_COLLECT_ARGS
, sizeof (char *));
718 if (argv
== NULL
) // poor way of dealing with calloc failure
721 *p
++ = strdup ("collect");
723 *p
++ = strdup ("-x");
724 if (clkprof_enabled
!= 0)
726 *p
++ = strdup ("-p");
727 snprintf (buf
, sizeof (buf
), "%du", clkprof_timer
);
730 if (hwcprof_enabled_cnt
> 0)
733 *p
++ = strdup ("-h");
734 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
736 char*rateString
= hwc_rate_string (&hwctr
[ii
], 1); //"1" is for temporary goldfile compatibility. TBR YXXX!!
737 snprintf (buf
+ strlen (buf
), sizeof (buf
) - strlen (buf
),
738 "%s%s,%s%s", ii
? "," : "", hwctr
[ii
].name
,
739 rateString
? rateString
: "",
740 (ii
+ 1 < hwcprof_enabled_cnt
) ? "," : "");
743 if (strlen (buf
) + 1 >= sizeof (buf
))
747 if (heaptrace_enabled
!= 0)
749 *p
++ = strdup ("-H");
750 *p
++ = strdup ("on");
752 if (iotrace_enabled
!= 0)
754 *p
++ = strdup ("-i");
755 *p
++ = strdup ("on");
757 if (synctrace_enabled
!= 0)
759 *p
++ = strdup ("-s");
760 if (synctrace_thresh
< 0)
761 *p
++ = strdup ("calibrate");
762 else if (synctrace_thresh
== 0)
763 *p
++ = strdup ("all");
765 *p
++ = dbe_sprintf ("%d", synctrace_thresh
);
766 *p
++ = dbe_sprintf (",%d", synctrace_scope
);
768 if (follow_mode
!= 0)
770 *p
++ = strdup ("-F");
771 char * fs
= get_follow_usr_spec ();
776 switch (get_follow_mode ())
779 *p
++ = strdup ("on");
782 *p
++ = strdup ("all");
786 *p
++ = strdup ("off");
791 *p
++ = strdup ("-a");
792 *p
++ = strdup (get_archive_mode ());
795 *p
++ = strdup ("-j");
796 *p
++ = strdup ("on");
798 if (pauseresume_sig
!= 0)
800 *p
++ = strdup ("-y");
801 *p
++ = dbe_sprintf ("%d%s", pauseresume_sig
,
802 (pauseresume_pause
== 0 ? ",r" : ""));
806 *p
++ = strdup ("-l");
807 *p
++ = dbe_sprintf ("%d", sample_sig
);
809 if (sample_period
!= 0)
811 *p
++ = strdup ("-S");
812 *p
++ = dbe_sprintf ("%d", sample_period
);
816 *p
++ = strdup ("-L");
817 *p
++ = dbe_sprintf ("%d", size_limit
);
819 if (expt_group
!= NULL
)
821 *p
++ = strdup ("-g");
822 *p
++ = strdup (expt_group
);
826 *p
++ = strdup ("-d");
827 *p
++ = strdup (udir_name
);
831 *p
++ = strdup ("-o");
832 *p
++ = strdup (expt_name
);
834 if (p
- argv
>= MAX_COLLECT_ARGS
) // argument list too small -- fatal error
840 Coll_Ctrl::show_expt ()
846 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
847 GTXT ("Creating experiment directory %s (Process ID: %ld) ...\n"),
848 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")), (long) getpid ());
849 char *caller
= getenv ("SP_COLLECTOR_FROM_GUI"); // Collector from GUI
850 if (caller
!= NULL
) // Print non-localized message
851 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
852 NTXT ("\nCreating experiment directory %s (Process ID: %ld) ...\n"),
853 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")), (long) getpid ());
855 char *fstype
= get_fstype (store_dir
);
856 if ((fstype
!= NULL
) && (nofswarn
== 0))
858 // only warn if clock or hwc profiling is turned on
859 if (clkprof_enabled
|| hwcprof_enabled_cnt
!= 0)
860 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
861 GTXT ("this experiment is being recorded to a file system \nof type \"%s\", which may distort the measured performance."),
865 return strdup (UEbuf
);
869 Coll_Ctrl::set_clk_params (int min
, int res
, int max
, int hi
, int norm
, int lo
)
871 clk_params
.min
= min
;
872 clk_params
.res
= res
;
873 clk_params
.max
= max
;
874 clk_params
.hival
= hi
;
875 clk_params
.normval
= norm
;
876 clk_params
.lowval
= lo
;
877 set_clkprof_timer_target (clk_params
.normval
); // note: requires clk_params to be initialized!
881 Coll_Ctrl::reset_clkprof (int val
)
883 if (val
!= clkprof_timer
)
885 // profiler has had to reset to a different value; warn user
886 char *msg
= dbe_sprintf (
887 GTXT ("Warning: Clock profiling timer reset from %.3f millisec. to %.3f millisec. as required by profiling driver\n\n"),
888 (double) (clkprof_timer
) / 1000., (double) (val
) / 1000.);
889 adjust_clkprof_timer (val
);
896 Coll_Ctrl::set_clkprof (const char *string
, char** warn
)
900 int prevclkprof_enabled
;
901 int prevclkprof_default
;
904 return strdup (GTXT ("Experiment is active; command ignored.\n"));
905 /* if the first character is a +, warn user that it is no longer supported */
906 if (string
[0] == '+')
907 return strdup (GTXT ("Warning: clock-based memoryspace and dataspace profiling is no longer supported\n"));
908 if (strcmp (string
, "off") == 0)
914 else if (string
== NULL
|| strcmp (string
, "on") == 0)
915 nclkprof_timer
= clk_params
.normval
;
916 else if (strcmp (string
, "lo") == 0 || strcmp (string
, "low") == 0)
917 nclkprof_timer
= clk_params
.lowval
;
918 else if (strcmp (string
, "hi") == 0 || strcmp (string
, "high") == 0
919 || strcmp (string
, "h") == 0)
920 nclkprof_timer
= clk_params
.hival
;
923 /* the remaining string should be a number > 0 */
924 char *endchar
= NULL
;
925 double dval
= strtod (string
, &endchar
);
926 if (*endchar
== 'm' || *endchar
== 0) /* user specified milliseconds */
928 else if (*endchar
== 'u') /* user specified microseconds */
931 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string
);
932 nclkprof_timer
= (int) (dval
+ 0.5);
934 // we now have the proposed value; ensure it's within limits
935 if (nclkprof_timer
<= 0)
936 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string
);
938 // Check consistency with experiment
939 prevclkprof_enabled
= clkprof_enabled
;
940 prevclkprof_default
= clkprof_default
;
943 char *ret
= check_consistency ();
946 clkprof_default
= prevclkprof_default
;
947 clkprof_enabled
= prevclkprof_enabled
;
950 int ref_nclkprof_timer
= nclkprof_timer
;
952 // check for minimum value
953 if (nclkprof_timer
< clk_params
.min
)
955 /* value too small, use minimum value, with warning */
956 *warn
= dbe_sprintf (
957 GTXT ("Warning: Clock profiling at %.3f millisec. interval is not supported on this system; minimum %.3f millisec. used\n"),
958 (double) (nclkprof_timer
) / 1000., (double) (clk_params
.min
) / 1000.);
959 nclkprof_timer
= clk_params
.min
;
962 // check for maximum value
963 if (nclkprof_timer
> clk_params
.max
)
965 *warn
= dbe_sprintf (
966 GTXT ("Clock profiling at %.3f millisec. interval is not supported on this system; maximum %.3f millisec. used\n"),
967 (double) (nclkprof_timer
) / 1000., (double) (clk_params
.max
) / 1000.);
968 nclkprof_timer
= clk_params
.max
;
971 /* see if setting is a multiple of the period */
972 if (nclkprof_timer
> clk_params
.res
)
974 ticks
= ((nclkprof_timer
/ clk_params
.res
) * clk_params
.res
);
975 if (ticks
!= nclkprof_timer
)
977 /* no, we need to reset to a multiple */
978 *warn
= dbe_sprintf (
979 GTXT ("Clock profile interval rounded from %.3f to %.3f (system resolution = %.3f) millisec."),
980 (double) (nclkprof_timer
) / 1000., (double) (ticks
) / 1000.,
981 (double) (clk_params
.res
) / 1000.);
982 nclkprof_timer
= ticks
;
986 // limit reference "target" rate. Target rate is also used for HWCS.
987 if (ref_nclkprof_timer
> PROFINT_MAX
)
988 ref_nclkprof_timer
= PROFINT_MAX
;
989 if (ref_nclkprof_timer
< PROFINT_MIN
)
990 ref_nclkprof_timer
= PROFINT_MIN
;
991 set_clkprof_timer_target (ref_nclkprof_timer
);
992 adjust_clkprof_timer (nclkprof_timer
);
997 Coll_Ctrl::set_synctrace (const char *string
)
1000 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1001 char *comma_p
= NULL
;
1004 /* no argument provided, use default: calibrate and native */
1005 synctrace_enabled
= 1;
1006 synctrace_thresh
= -1;
1007 synctrace_scope
= SYNCSCOPE_NATIVE
;
1008 char *ret
= check_consistency ();
1011 synctrace_enabled
= 0;
1016 char *val
= strdup (string
);
1017 /* see if there's a comma in the string */
1018 char *next
= strchr (val
, (int) ',');
1021 /* remember where the comma was */
1024 /* set the scope based on the characters following the comma */
1025 synctrace_scope
= 0;
1030 synctrace_scope
|= SYNCSCOPE_NATIVE
;
1031 else if (*next
== 'j')
1032 synctrace_scope
|= SYNCSCOPE_JAVA
;
1034 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string
);
1037 if (synctrace_scope
== 0)
1038 synctrace_scope
= SYNCSCOPE_NATIVE
;
1039 /* clear the comma for the threshold determination */
1042 else /* no ",<scope>" -- default to native and Java */
1043 synctrace_scope
= SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
;
1044 if (!strlen (val
) || !strcmp (val
, "calibrate") || !strcmp (val
, "on"))
1046 /* use default: calibrate and native */
1047 synctrace_enabled
= 1;
1048 synctrace_thresh
= -1;
1050 char *ret
= check_consistency ();
1053 synctrace_enabled
= 0;
1058 if (strcmp (val
, "off") == 0)
1060 synctrace_enabled
= 0;
1064 if (strcmp (val
, "all") == 0)
1066 /* set to record all events */
1067 synctrace_thresh
= 0;
1068 synctrace_enabled
= 1;
1069 char *ret
= check_consistency ();
1073 synctrace_enabled
= 0;
1078 /* the remaining string should be a number >= 0 */
1079 char *endchar
= NULL
;
1080 int tval
= (int) strtol (val
, &endchar
, 0);
1081 if (*endchar
!= 0 || tval
< 0)
1084 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string
);
1087 synctrace_thresh
= tval
;
1088 synctrace_enabled
= 1;
1093 Coll_Ctrl::set_heaptrace (const char *string
)
1096 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1097 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
1099 heaptrace_enabled
= 1;
1100 char *ret
= check_consistency ();
1103 heaptrace_enabled
= 0;
1108 if (strcmp (string
, "off") == 0)
1110 heaptrace_enabled
= 0;
1114 if (strcmp (string
, "check") == 0)
1116 /* set to check for over/underruns */
1117 heaptrace_checkenabled
= 1;
1118 heaptrace_enabled
= 1;
1121 if (strcmp (string
, "clear") == 0)
1123 /* set to check for over/underruns, and store patterns */
1124 heaptrace_checkenabled
= 2;
1125 heaptrace_enabled
= 1;
1129 return dbe_sprintf (GTXT ("Unrecognized heap tracing parameter `%s'\n"), string
);
1133 Coll_Ctrl::set_iotrace (const char *string
)
1136 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1137 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
1139 iotrace_enabled
= 1;
1140 char *ret
= check_consistency ();
1143 iotrace_enabled
= 0;
1148 if (strcmp (string
, "off") == 0)
1150 iotrace_enabled
= 0;
1153 return dbe_sprintf (GTXT ("Unrecognized I/O tracing parameter `%s'\n"), string
);
1157 Coll_Ctrl::set_count (const char *string
)
1161 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1162 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "off") == 0)
1167 if (strcmp (string
, "on") == 0)
1170 char *cret
= check_consistency ();
1178 if (strcmp (string
, "static") == 0)
1181 char *cret
= check_consistency ();
1191 if (count_enabled
!= 0)
1193 /* ensure that sample period is 0, if set by default */
1194 if (sample_default
== 1)
1196 /* ensure that clock profiling is off, if set by default */
1197 if (clkprof_default
== 1)
1199 clkprof_default
= 0;
1200 clkprof_enabled
= 0;
1202 if (hwcprof_default
== 1)
1203 hwcprof_default
= 0;
1207 return dbe_sprintf (GTXT ("Unrecognized count parameter `%s'\n"), string
);
1211 Coll_Ctrl::set_time_run (const char *valarg
)
1214 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1215 if (valarg
== NULL
) /* invalid setting */
1216 return strdup (GTXT ("time parameter can not be NULL\n"));
1217 /* the string should be a number >= 0 */
1218 int prev_start_delay
= start_delay
;
1219 int prev_time_run
= time_run
;
1220 const char *endchar
= valarg
;
1221 char *newchar
= NULL
;
1223 if (*endchar
!= '-')
1225 val
= (int) strtol (endchar
, &newchar
, 0);
1228 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1229 if (*endchar
== 'm')
1231 val
= val
* 60; /* convert to seconds */
1234 else if (*endchar
== 's') /* no conversion needed */
1241 else if (*endchar
!= '-')
1242 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1244 /* a second number is provided */
1247 val
= (int) strtol (endchar
, &newchar
, 0);
1251 start_delay
= prev_start_delay
;
1252 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1254 if (*endchar
== 'm')
1256 val
= val
* 60; /* convert to seconds */
1259 else if (*endchar
== 's') /* no conversion needed */
1263 start_delay
= prev_start_delay
;
1264 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1267 if (time_run
!= 0 && start_delay
>= time_run
)
1269 start_delay
= prev_start_delay
;
1270 return dbe_sprintf (GTXT ("Invalid time parameter `%s': start time must be earlier than end time\n"), valarg
);
1272 char *ret
= check_consistency ();
1275 start_delay
= prev_start_delay
;
1276 time_run
= prev_time_run
;
1283 Coll_Ctrl::set_attach_pid (char *valarg
)
1286 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1288 return strdup (GTXT ("Specified PID can not be NULL\n"));
1290 /* the string should be a number corresponding to an active process' pid */
1291 char *endchar
= NULL
;
1292 int val
= (int) strtol (valarg
, &endchar
, 0);
1293 if (*endchar
!= 0 || val
< 0)
1294 return dbe_sprintf (GTXT ("Invalid process pid `%s'\n"), valarg
);
1295 int prev_attach_pid
= attach_pid
;
1297 char *ret
= check_consistency ();
1300 attach_pid
= prev_attach_pid
;
1307 Coll_Ctrl::free_hwc_fields (Hwcentry
* tmpctr
)
1309 if (tmpctr
->name
!= NULL
)
1310 free (tmpctr
->name
);
1311 if (tmpctr
->int_name
!= NULL
)
1312 free (tmpctr
->int_name
);
1313 memset (tmpctr
, 0, sizeof (Hwcentry
));
1314 tmpctr
->reg_num
= -1;
1318 Coll_Ctrl::hwcentry_dup (Hwcentry
*hnew
, Hwcentry
*_hwc
)
1321 if (_hwc
->name
!= NULL
)
1322 hnew
->name
= strdup (_hwc
->name
);
1325 if (_hwc
->int_name
!= NULL
)
1326 hnew
->int_name
= strdup (_hwc
->int_name
);
1328 hnew
->int_name
= NULL
;
1329 if (_hwc
->metric
!= NULL
)
1330 hnew
->metric
= strdup (_hwc
->metric
);
1332 hnew
->metric
= NULL
;
1333 if (_hwc
->short_desc
!= NULL
)
1334 hnew
->short_desc
= strdup (_hwc
->short_desc
);
1336 hnew
->short_desc
= NULL
;
1337 if (_hwc
->reg_list
!= NULL
)
1339 hnew
->reg_list
= (regno_t
*) malloc (sizeof (regno_t
*) * MAX_PICS
);
1340 // poor way of dealing with malloc failure
1343 for (int i
= 0; i
< MAX_PICS
; i
++)
1345 hnew
->reg_list
[i
] = _hwc
->reg_list
[i
];
1346 if (hnew
->reg_list
[i
] == REGNO_ANY
)
1353 // Routine to initialize the HWC tables, set up the default experiment, etc.
1355 Coll_Ctrl::setup_hwc ()
1357 static bool is_hwc_setup
= false;
1358 if (is_hwc_setup
== true)
1360 // try to set the default counters
1361 is_hwc_setup
= true;
1366 Coll_Ctrl::clkprof_timer_2_hwcentry_min_time (int target_clkprof_usec
)
1368 hrtime_t hwc_nanosec
;
1369 if (target_clkprof_usec
== clk_params
.normval
)
1370 hwc_nanosec
= HWCTIME_ON
;
1371 else if (target_clkprof_usec
== clk_params
.lowval
)
1372 hwc_nanosec
= HWCTIME_LO
;
1373 else if (target_clkprof_usec
== clk_params
.hival
)
1374 hwc_nanosec
= HWCTIME_HI
;
1376 hwc_nanosec
= 1000LL * target_clkprof_usec
; // nanoseconds
1381 Coll_Ctrl::set_clkprof_timer_target (int microseconds
)
1383 clkprof_timer
= microseconds
;
1384 clkprof_timer_target
= microseconds
;
1385 hrtime_t hwc_min_time_nanosec
= clkprof_timer_2_hwcentry_min_time (microseconds
);
1386 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1388 hwctr
[ii
].min_time_default
= hwc_min_time_nanosec
;
1389 hwc_update_val (&hwctr
[ii
]);
1394 Coll_Ctrl::adjust_clkprof_timer (int use
)
1396 clkprof_timer
= use
;
1399 /* set HWC counter set from a string */
1400 char * /* return an error string */
1401 Coll_Ctrl::set_hwcstring (const char *string
, char **warnmsg
)
1404 if (string
== NULL
|| strcmp (string
, "off") == 0)
1406 hwcprof_enabled_cnt
= 0;
1410 int old_cnt
= hwcprof_enabled_cnt
;
1411 int old_hwcprof_default
= hwcprof_default
;
1413 /* reset any previous count to zero */
1414 hwcprof_enabled_cnt
= 0;
1415 char *ret
= add_hwcstring (string
, warnmsg
);
1418 // restore previous setting
1419 hwcprof_enabled_cnt
= old_cnt
;
1420 hwcprof_default
= old_hwcprof_default
;
1425 /* add additional HWC counters to counter set from string */
1426 char * /* return an error string */
1427 Coll_Ctrl::add_hwcstring (const char *string
, char **warnmsg
)
1430 if (string
== NULL
|| strcmp (string
, "off") == 0)
1432 hwcprof_enabled_cnt
= 0;
1437 int old_cnt
= hwcprof_enabled_cnt
;
1438 int prev_cnt
= hwcprof_enabled_cnt
;
1439 // int old_hwcprof_default = hwcprof_default;
1440 char UEbuf
[MAXPATHLEN
* 5];
1442 Hwcentry tmpctr
[MAX_PICS
];
1443 Hwcentry
* ctrtable
[MAX_PICS
];
1447 UEsz
= sizeof (UEbuf
);
1449 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1450 if (hwcprof_default
== 0)
1452 /* Copy the counters already defined */
1453 for (int ii
= 0; ii
< prev_cnt
; ii
++)
1454 tmpctr
[ii
] = hwctr
[ii
];
1456 else /* the previously-defined counters were defaulted; don't copy them */
1459 /* look up the CPU version */
1460 cpc_cpuver
= hwc_get_cpc_cpuver ();
1461 if (string
&& *string
)
1463 /* lookup counters */
1464 /* set up a pointer array */
1465 for (unsigned ii
= 0; ii
< MAX_PICS
; ii
++)
1466 ctrtable
[ii
] = &tmpctr
[ii
];
1467 hrtime_t global_min_time
= clkprof_timer_2_hwcentry_min_time (clkprof_timer_target
);
1468 rc
= hwc_lookup (kernelHWC
, global_min_time
, string
, &ctrtable
[prev_cnt
], MAX_PICS
- prev_cnt
, &emsg
, &wmsg
);
1473 /* set count for sum of old and new counters */
1477 /* even though the actual hwctr[] array is not updated, we can check consistency */
1478 char *ret
= check_consistency ();
1481 hwcprof_enabled_cnt
= old_cnt
;
1485 /* finally, validate the full counter set */
1486 emsg
= hwc_validate_ctrs (kernelHWC
, ctrtable
, rc
);
1489 hwcprof_enabled_cnt
= old_cnt
;
1493 /* success, update real counters and the string for them */
1494 /* turn off the default */
1495 hwcprof_default
= 0;
1496 hwcprof_enabled_cnt
= rc
;
1498 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1500 /* shallow copy of new counters */
1501 hwctr
[ii
] = tmpctr
[ii
];
1502 char *rateString
= hwc_rate_string (&hwctr
[ii
], 0);
1503 snprintf (UEbuf
+ strlen (UEbuf
), UEsz
- strlen (UEbuf
),
1504 NTXT (",%s,%s"), hwctr
[ii
].name
,
1505 rateString
? rateString
: "");
1508 /* now duplicate that string, skipping the leading comma */
1509 hwc_string
= strdup (&UEbuf
[1]);
1513 /* add default HWC counters to counter set with resolution (on, hi, or lo) */
1514 /* Note that the resultion will also be used to set the clock-profiling default */
1515 char * /* return an error string */
1516 Coll_Ctrl::add_default_hwcstring (const char *resolution
, char **warnmsg
, bool add
, bool forKernel
)
1520 char *def_string
= hwc_get_default_cntrs2 (forKernel
, 1);
1521 if (def_string
== NULL
)
1523 /* no string defined, format and return an error message */
1525 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1526 return dbe_sprintf (GTXT ("No default HW counter set is defined for %s\n"), cpuname
);
1528 int len
= strlen (def_string
);
1531 /* string zero-length, meaning default counters can't be used */
1533 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1534 return dbe_sprintf (GTXT ("HW counter set for %s cannot be loaded on this system\n"), cpuname
);
1536 /* allocate return string */
1537 int retsize
= 2 * len
+ 10;
1538 char *ret
= (char *) malloc (retsize
);
1540 return strdup (GTXT ("internal error formating HW counter set; malloc failed\n"));
1543 char *stringp
= def_string
;
1545 char *hwc_defaultx
= strdup (def_string
);
1547 /* now massage the string in order to insert resolution for each counter */
1550 /* find the next comma */
1556 nextp
= stringp
+ 1;
1558 if ((next
= strchr (nextp
, (int) ',')) != NULL
)
1562 /* next counter is zero-length -- invalid string */
1564 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1566 ret
= dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname
, hwc_defaultx
);
1567 free (hwc_defaultx
);
1570 /* another field found */
1572 char nextc
= *(next
+ 1);
1573 if ((nextc
== 0) || (nextc
== ','))
1575 /* either ,, between fields, or string ends in comma */
1576 /* append the string */
1577 strncat (retp
, stringp
, (retsize
- strlen (retp
) - 1));
1578 strncat (retp
, ",", (retsize
- strlen (retp
) - 1));
1579 strncat (retp
, resolution
, (retsize
- strlen (retp
) - 1));
1580 if (nextc
== 0) /* string ended in comma; we're done */
1585 /* string had only one comma between counter names; that's not valid */
1587 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1589 ret
= dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname
, hwc_defaultx
);
1590 free (hwc_defaultx
);
1593 /* string had ,, between fields; move to next field */
1595 if (* (stringp
+ 1) == 0) /* name ended in ,, -- we're done */
1601 /* no comma found, add the last counter and the comma and resolution */
1602 strncat (retp
, stringp
, (retsize
- strlen (retp
) - 1));
1603 strncat (retp
, ",", (retsize
- strlen (retp
) - 1));
1604 strncat (retp
, resolution
, (retsize
- strlen (retp
) - 1));
1609 /* we have now formatted the new string, with resolution inserted */
1612 ccret
= add_hwcstring (ret
, warnmsg
);
1614 ccret
= set_hwcstring (ret
, warnmsg
);
1615 free (hwc_defaultx
);
1618 /* now set the clock-profiling timer, if on by default */
1619 if (clkprof_default
== 1)
1621 if (strcmp (resolution
, NTXT ("on")) == 0)
1622 set_clkprof_timer_target (clk_params
.normval
);
1623 else if (strcmp (resolution
, NTXT ("lo")) == 0)
1624 set_clkprof_timer_target (clk_params
.lowval
);
1625 else if (strcmp (resolution
, NTXT ("hi")) == 0)
1626 set_clkprof_timer_target (clk_params
.hival
);
1632 Coll_Ctrl::set_hwcdefault ()
1634 char *string
= hwc_get_default_cntrs2 (kernelHWC
, 1);
1637 if (strlen (string
) == 0)
1638 hwcprof_default
= 0;
1641 char * warnmsg
= NULL
;
1642 char *ccret
= add_hwcstring (string
, &warnmsg
);
1646 /* set string to zero-length so that it won't be used again */
1647 hwc_set_default_cntrs (kernelHWC
, NTXT (""));
1649 hwcprof_default
= 0;
1652 hwcprof_default
= 1;
1657 hwcprof_default
= 0;
1661 Coll_Ctrl::disable_hwc ()
1663 hwcprof_enabled_cnt
= 0;
1664 hwcprof_default
= 0;
1670 Coll_Ctrl::set_sample_period (const char *string
)
1674 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1675 if (string
== NULL
|| strcmp (string
, "on") == 0)
1677 else if (strcmp (string
, "off") == 0)
1681 /* string should be a number > 0 */
1682 char *endchar
= NULL
;
1683 val
= (int) strtol (string
, &endchar
, 0);
1684 if (*endchar
!= 0 || val
<= 0)
1685 return dbe_sprintf (GTXT ("Unrecognized sample period `%s'\n"), string
);
1687 /* set that value */
1688 int prev_sample_period
= sample_period
;
1689 sample_period
= val
;
1690 char *ret
= check_consistency ();
1693 sample_period
= prev_sample_period
;
1701 Coll_Ctrl::set_size_limit (const char *string
)
1704 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1705 if (string
== NULL
|| strlen (string
) == 0
1706 || strcmp (string
, "unlimited") == 0 || strcmp (string
, "none") == 0)
1711 /* string should be a number >0; 0 is an error */
1712 char *endchar
= NULL
;
1713 int val
= (int) strtol (string
, &endchar
, 0);
1714 if (*endchar
!= 0 || val
<= 0)
1715 return dbe_sprintf (GTXT ("Unrecognized size limit `%s'\n"), string
);
1721 Coll_Ctrl::build_data_desc ()
1723 char spec
[DD_MAXPATHLEN
];
1726 // Put sample sig before clock profiling. Dbx uses PROF
1727 // for that purpose and we want it to be processed first.
1729 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "P:%s;", project_home
);
1730 if (sample_sig
!= 0)
1731 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "g:%d;", sample_sig
);
1732 if (pauseresume_sig
!= 0)
1733 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "d:%d%s;", pauseresume_sig
,
1734 (pauseresume_pause
== 1 ? "p" : ""));
1735 if (clkprof_enabled
== 1)
1736 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "p:%d;", clkprof_timer
);
1737 if (synctrace_enabled
== 1)
1738 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "s:%d,%d;", synctrace_thresh
, synctrace_scope
);
1739 if (heaptrace_enabled
== 1)
1740 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "H:%d;", heaptrace_checkenabled
);
1741 if (iotrace_enabled
== 1)
1742 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "i:;");
1743 if (hwcprof_enabled_cnt
> 0)
1745 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "h:%s",
1746 (hwcprof_default
== true) ? "*" : "");
1747 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1749 /* min_time is a "new" field.
1751 * To help process_data_descriptor() in hwcfuncs.c parse
1752 * the HWC portion of this string -- specifically, to
1753 * recognize min_time when it's present and skip over
1754 * when it's not -- we prepend 'm' to the min_time value.
1756 * When we no longer worry about, say, an old dbx
1757 * writing this string and a new libcollector looking for
1758 * the min_time field, the 'm' character can be
1759 * removed and process_data_descriptor() simplified.
1761 hrtime_t min_time
= hwctr
[ii
].min_time
;
1762 if (min_time
== HWCTIME_TBD
)
1763 // user did not specify any value for overflow rate
1764 min_time
= hwctr
[ii
].min_time_default
;
1765 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
),
1766 "%s%s:%s:%d:%d:m%lld:%d:%d:0x%x", ii
? "," : "",
1767 strcmp (hwctr
[ii
].name
, hwctr
[ii
].int_name
) ? hwctr
[ii
].name
: "",
1768 hwctr
[ii
].int_name
, hwctr
[ii
].reg_num
, hwctr
[ii
].val
,
1769 min_time
, ii
, /*tag*/ hwctr
[ii
].timecvt
, hwctr
[ii
].memop
);
1771 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), ";");
1773 if ((time_run
!= 0) || (start_delay
!= 0))
1775 if (start_delay
!= 0)
1776 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "t:%d:%d;", start_delay
, time_run
);
1778 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "t:%d;", time_run
);
1780 if (sample_period
!= 0)
1781 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "S:%d;",
1783 if (size_limit
!= 0)
1784 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "L:%d;",
1787 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "j:%d;", (int) java_mode
);
1788 if (follow_mode
!= FOLLOW_NONE
)
1789 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "F:%d;", (int) follow_mode
);
1790 snprintf (spec
+ strlen (spec
), sizeof (spec
) - strlen (spec
), "a:%s;", archive_mode
);
1791 if (strlen (spec
) + 1 >= sizeof (spec
))
1794 data_desc
= strdup (spec
);
1798 Coll_Ctrl::check_group ()
1800 char group_file
[MAXPATHLEN
];
1801 if (expt_group
== NULL
)
1803 // Is the group an relative path, with a store directory set?
1804 if ((expt_group
[0] == '/') || ((udir_name
== NULL
) || (udir_name
[0] == '0')))
1805 snprintf (group_file
, sizeof (group_file
), "%s", expt_group
);
1806 else // relative path, store directory; make group_file in that directory
1807 snprintf (group_file
, sizeof (group_file
), "%s/%s", udir_name
, expt_group
);
1808 // See if we can write the group file
1809 int ret
= access (group_file
, W_OK
);
1812 if (errno
== ENOENT
)
1814 char *stmp
= group_file
;
1815 char *dir
= dirname (stmp
);
1816 ret
= access (dir
, W_OK
);
1817 if (ret
!= 0) // group file does not exist;
1818 return dbe_sprintf (GTXT ("Directory (%s) for group file %s is not writeable: %s\n"),
1819 dir
, group_file
, strerror (errno
));
1822 return dbe_sprintf (GTXT ("Group file %s is not writeable: %s\n"),
1823 group_file
, strerror (errno
));
1829 Coll_Ctrl::join_group ()
1834 char group_file
[MAXPATHLEN
];
1835 struct stat statbuf
;
1836 struct flock flockbuf
;
1837 flockbuf
.l_type
= F_WRLCK
;
1838 flockbuf
.l_whence
= SEEK_SET
;
1839 flockbuf
.l_start
= 0;
1841 if (expt_group
== NULL
)
1843 // Is the group an relative path, with a store directory set?
1844 if (expt_group
[0] == '/' || udir_name
== NULL
|| udir_name
[0] == '0')
1845 snprintf (group_file
, sizeof (group_file
), "%s", expt_group
);
1846 else // relative path, store directory; make group_file in that directory
1847 snprintf (group_file
, sizeof (group_file
), "%s/%s", udir_name
, expt_group
);
1851 // try to open the group file
1852 while ((groupfd
= open (group_file
, O_RDWR
)) >= 0)
1854 if (uinterrupt
== 1)
1857 return strdup (GTXT ("user interrupt\n"));
1859 // it's opened, now lock it
1860 if (fcntl (groupfd
, F_SETLK
, &flockbuf
) != -1)
1862 // we got the lock; check the file size
1863 if (fstat (groupfd
, &statbuf
) != 0)
1865 // can't stat the file -- give up
1867 return dbe_sprintf (GTXT ("Can't fstat group file %s\n"), group_file
);
1869 if (statbuf
.st_size
== 0)
1871 // size is zero: we got the lock just as someone
1872 // else created the group file
1873 // close the file and release the lock; try again
1879 // size is non-zero, add our record
1880 file
= fdopen (groupfd
, "a");
1884 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file
);
1886 if (fprintf (file
, "%s\n", store_ptr
) <= 0)
1889 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file
);
1891 // close the file, releasing our lock
1898 // can't get the lock, close the file and try again
1900 if (uinterrupt
== 1)
1901 return strdup (GTXT ("user interrupt\n"));
1903 return dbe_sprintf (GTXT ("Timed out: waiting for group file %s\n"), group_file
);
1905 if (tries
% 500 == 0)
1906 USR_WARN (GTXT ("Waiting for group file %s . . ."), group_file
);
1912 // If the error was not that the file did not exist, report it
1913 if (errno
!= ENOENT
)
1914 return dbe_sprintf (GTXT ("Can't open group file %s: %s\n"),
1915 group_file
, strerror (errno
));
1916 // the file did not exist, try to create it
1917 groupfd
= open (group_file
, O_CREAT
| O_EXCL
| O_RDWR
, 0666);
1920 // we could not create the file
1921 if (errno
== EEXIST
)
1923 return dbe_sprintf (GTXT ("Can't create group file %s: %s\n"),
1924 group_file
, strerror (errno
));
1926 // we created the group file, now lock it, waiting for the lock
1927 while (fcntl (groupfd
, F_SETLKW
, &flockbuf
) == -1)
1929 // we created the file, but couldn't lock it
1931 return dbe_sprintf (GTXT ("Unable to lock group file %s\n"), group_file
);
1933 // we created and locked the file, write to it
1934 file
= fdopen (groupfd
, "a");
1938 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file
);
1940 // write the header line
1941 if (fprintf (file
, "%s\n", SP_GROUP_HEADER
) <= 0)
1944 return dbe_sprintf (GTXT ("Can't initialize group file %s\n"), group_file
);
1946 if (fprintf (file
, "%s\n", store_ptr
) <= 0)
1949 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file
);
1951 // finally, close the file, releasing the lock
1959 Coll_Ctrl::set_directory (char *dir
, char **warn
)
1961 struct stat statbuf
;
1964 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1965 if (stat (dir
, &statbuf
) != 0)
1966 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"),
1967 dir
, strerror (errno
));
1968 if (!S_ISDIR (statbuf
.st_mode
))
1969 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"),
1970 dir
, strerror (ENOTDIR
));
1972 udir_name
= strdup (dir
);
1974 // Process new setting
1975 *warn
= preprocess_names ();
1976 if ((uexpt_name
!= NULL
) || (interactive
!= 0))
1978 char *ret
= update_expt_name (true, true);
1983 char *msg
= dbe_sprintf ("%s%s", *warn
, ret
);
1993 (void) update_expt_name (false, false);
1994 return NULL
; // All is OK
1998 Coll_Ctrl::set_target (char* targetname
)
2002 if (targetname
!= NULL
)
2003 target_name
= strdup (targetname
);
2008 Coll_Ctrl::set_default_stem (const char* stem
)
2010 default_stem
= strdup (stem
);
2011 preprocess_names ();
2012 (void) update_expt_name (false, false); // no warnings
2016 Coll_Ctrl::set_expt (const char *ename
, char **warn
, bool overwriteExp
)
2025 char *exptname
= canonical_path(strdup(ename
));
2026 size_t i
= strlen (exptname
);
2027 if (i
< 4 || strcmp (&exptname
[i
- 3], ".er") != 0)
2030 return dbe_sprintf (GTXT ("Experiment name `%s' must end in `.er'\n"),
2035 uexpt_name
= exptname
;
2036 preprocess_names ();
2037 char *err
= update_expt_name (true, true, overwriteExp
);
2042 char *nm
= dbe_sprintf ("%s/%s", store_dir
, base_name
);
2043 struct stat statbuf
;
2044 char *cmd
= dbe_sprintf ("/bin/rm -rf %s >/dev/null 2>&1", nm
);
2047 if (stat (nm
, &statbuf
) == 0)
2048 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm
);
2049 if (errno
!= ENOENT
)
2050 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm
);
2053 *warn
= update_expt_name (true, false);
2058 Coll_Ctrl::set_group (char *groupname
)
2061 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2062 if (expt_group
!= NULL
)
2067 if (groupname
== NULL
)
2070 preprocess_names ();
2071 (void) update_expt_name (true, false);
2074 int i
= (int) strlen (groupname
);
2075 if (i
< 5 || strcmp (&groupname
[i
- 4], ".erg") != 0)
2076 return dbe_sprintf (GTXT ("Experiment group name `%s'must end in `.erg'\n"), groupname
);
2077 expt_group
= strdup (groupname
);
2078 preprocess_names ();
2079 (void) update_expt_name (true, false);
2084 Coll_Ctrl::set_java_mode (const char *string
)
2086 struct stat statbuf
;
2088 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2089 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
2091 #if defined(GPROFNG_JAVA_PROFILING)
2092 int prev_java_mode
= java_mode
;
2093 int prev_java_default
= java_default
;
2096 char *ret
= check_consistency ();
2099 java_mode
= prev_java_mode
;
2100 java_default
= prev_java_default
;
2105 return strdup (GTXT ("gprofng was built without support for profiling Java applications\n"));
2108 if (strcmp (string
, "off") == 0)
2110 int prev_java_mode
= java_mode
;
2111 int prev_java_default
= java_default
;
2114 char *ret
= check_consistency ();
2117 java_mode
= prev_java_mode
;
2118 java_default
= prev_java_default
;
2125 /* any other value should be a path to Java installation directory */
2126 if (stat (string
, &statbuf
) == 0)
2128 if ((statbuf
.st_mode
& S_IFMT
) == S_IFDIR
)
2130 // it's a directory -- set the Java path to it
2131 int prev_java_mode
= java_mode
;
2132 int prev_java_default
= java_default
;
2135 char *ret
= check_consistency ();
2138 java_mode
= prev_java_mode
;
2139 java_default
= prev_java_default
;
2142 return set_java_path (string
);
2145 return dbe_sprintf (GTXT ("Java-profiling parameter is neither \"on\", nor \"off\", nor is it a directory: `%s'\n"), string
);
2149 Coll_Ctrl::set_java_path (const char *string
)
2152 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2154 java_path
= strdup (string
);
2159 Coll_Ctrl::set_java_args (char *string
)
2163 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2164 char *prev_java_args
= java_args
;
2165 if (string
== NULL
|| strlen (string
) == 0)
2166 java_args
= strdup ("");
2168 java_args
= strdup (string
);
2169 // now count the number of Java arguments
2170 for (next
= java_args
; *next
; next
++)
2172 if (*next
== ' ' || *next
== '\t')
2175 for (++next
; *next
; next
++)
2176 if (*next
== ' ' || *next
== '\t')
2181 if (njava_args
== 0)
2183 char *ret
= check_consistency ();
2186 java_args
= prev_java_args
;
2189 free (prev_java_args
);
2194 Coll_Ctrl::set_follow_mode (const char *string
)
2197 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2198 free (follow_spec_usr
);
2199 free (follow_spec_cmp
);
2200 follow_spec_usr
= NULL
;
2201 follow_spec_cmp
= NULL
;
2202 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "all") == 0
2203 || strcmp (string
, "on") == 0)
2205 follow_mode
= FOLLOW_ON
;
2209 if (strcmp (string
, "off") == 0)
2211 follow_mode
= FOLLOW_NONE
;
2216 /* compile regular expression if string starts with "=" */
2217 if (string
[0] == '=' && string
[1] != 0)
2219 // user has specified a string matching specification
2222 const char *userspec
= &string
[1];
2223 size_t newstrlen
= strlen (userspec
) + 3;
2224 char * str
= (char *) malloc (newstrlen
);
2227 snprintf (str
, newstrlen
, "^%s$", userspec
);
2228 assert (strlen (str
) == newstrlen
- 1);
2229 ercode
= regcomp (®ex_desc
, str
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
);
2235 follow_spec_usr
= strdup (string
);
2236 /* Ideally, follow_spec_cmp = [serialized regex_desc], */
2237 /* so that libcollector wouldn't have to recompile it. */
2238 /* For now, just copy the regular expression into follow_spec_cmp */
2239 follow_spec_cmp
= str
;
2240 follow_mode
= FOLLOW_ALL
;
2244 // syntax error in parsing string
2247 regerror (ercode
, ®ex_desc
, errbuf
, sizeof (errbuf
));
2248 fprintf (stderr
, "Coll_Ctrl::set_follow_mode: regerror()=%s\n", errbuf
);
2252 return dbe_sprintf (GTXT ("Unrecognized follow-mode parameter `%s'\n"), string
);
2256 Coll_Ctrl::set_prof_idle (const char *string
)
2259 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2260 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
2265 if (strcmp (string
, "off") == 0)
2270 return dbe_sprintf (GTXT ("Unrecognized profiling idle cpus parameter `%s'\n"), string
);
2274 Coll_Ctrl::set_archive_mode (const char *string
)
2277 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2278 if (string
== NULL
|| strlen (string
) == 0)
2280 if (strcasecmp (string
, "on") == 0 || strcasecmp (string
, "off") == 0
2281 || strcasecmp (string
, "ldobjects") == 0
2282 || strcasecmp (string
, "usedldobjects") == 0
2283 || strcasecmp (string
, "src") == 0 || strcasecmp (string
, "usedsrc") == 0
2284 || strcasecmp (string
, "all") == 0)
2286 free (archive_mode
);
2287 archive_mode
= strdup (string
);
2290 return dbe_sprintf (GTXT ("Unrecognized archive-mode parameter `%s'\n"), string
);
2294 Coll_Ctrl::set_sample_signal (int value
)
2298 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2304 if (value
== pauseresume_sig
)
2305 return report_signal_conflict (value
);
2306 if ((buf
= strsignal (value
)) != NULL
)
2309 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), value
);
2313 /* find a signal by name */
2315 Coll_Ctrl::find_sig (const char *string
)
2318 char *signame_alloc
= NULL
;
2319 const char *signame
;
2321 if (strcmp (string
, "off") == 0)
2323 // see if the name begins with SIG
2324 if (strncmp (string
, "SIG", 3) != 0)
2327 signame_alloc
= (char *) malloc (strlen (string
) + 3 + 1);
2328 if (signame_alloc
== NULL
)
2330 strcpy (signame_alloc
, "SIG");
2331 strcpy (&signame_alloc
[3], string
);
2332 signame
= signame_alloc
;
2337 /* see if the string is a number */
2338 char *endchar
= NULL
;
2339 val
= (int) strtol (signame
, &endchar
, 0);
2341 val
= strtosigno (signame
);
2342 free (signame_alloc
);
2349 Coll_Ctrl::set_pauseresume_signal (int value
, int resume
)
2352 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2355 pauseresume_sig
= 0;
2358 if (value
== sample_sig
)
2359 return report_signal_conflict (value
);
2360 if (strsignal (value
) != NULL
)
2362 pauseresume_sig
= value
;
2363 pauseresume_pause
= resume
;
2366 return dbe_sprintf (GTXT ("Invalid pause-resume (delayed initialization) signal %d\n"), value
);
2371 Coll_Ctrl::report_signal_conflict (int value
)
2373 const char *xbuf
= strsignal (value
);
2375 return dbe_sprintf (GTXT ("Signal %s (%d) can not be used for both sample and pause-resume (delayed initialization)\n"),
2377 return dbe_sprintf (GTXT ("Signal %d can not be used for both sample and pause-resume (delayed initialization)\n"),
2382 Coll_Ctrl::set_debug_mode (int value
)
2385 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2391 Coll_Ctrl::create_exp_dir ()
2393 int max
= 4095; // 0xFFF - can be increased if it seems too low
2394 for (int i
= 0; i
< max
; i
++)
2396 if (mkdir (store_ptr
,
2397 S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
) != 0)
2401 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),
2402 store_dir
, strerror (err
));
2403 if (i
+ 1 >= max
) // no more attempts
2404 return dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n%s: %d\n"),
2405 store_ptr
, strerror (err
),
2406 GTXT ("collect: Internal error: loop count achieved"),
2408 char *ermsg
= update_expt_name (false, false, true);
2411 char *msg
= dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n"),
2418 return NULL
; // All is OK
2420 return dbe_sprintf (GTXT ("Unable to create directory `%s'\n"), store_ptr
);
2424 Coll_Ctrl::get_exp_name (const char *stembase
)
2427 return dbe_sprintf ("%s.%d.er", stembase
, expno
);
2431 Coll_Ctrl::preprocess_names ()
2433 char buf
[MAXPATHLEN
];
2434 char msgbuf
[MAXPATHLEN
];
2437 /* convert the experiment name and directory into store name/dir */
2438 /* free the old strings */
2439 if (store_dir
!= NULL
)
2444 if (expt_dir
!= NULL
)
2449 if (base_name
!= NULL
)
2454 if (expt_name
!= NULL
)
2460 if (uexpt_name
!= NULL
)
2461 expt_name
= strdup (uexpt_name
);
2464 // no user name -- pick a default
2468 if (expt_group
== NULL
)
2470 stem
= strdup (default_stem
);
2475 stem
= strdup (expt_group
);
2476 stem
[strlen (stem
) - 4] = 0;
2478 // now remove any leading directory
2479 for (int i
= 0;; i
++)
2484 stembase
= &stem
[i
+ 1];
2486 if (strlen (stembase
) == 0)
2489 stem
= strdup (default_stem
);
2493 c
= get_exp_name (stembase
);
2497 snprintf (buf
, sizeof (buf
), NTXT ("%s"), expt_name
);
2500 // it's a full path name
2501 if (udir_name
!= NULL
)
2503 snprintf (msgbuf
, sizeof (msgbuf
),
2504 GTXT ("Warning: Experiment name is an absolute path; directory name %s ignored.\n"),
2506 ret
= strdup (msgbuf
);
2510 // now extract the directory and basename
2512 for (int i
= 0;; i
++)
2519 expt_dir
= strdup (buf
);
2521 base_name
= strdup (&buf
[lastslash
+ 1]);
2523 base_name
= strdup (buf
);
2524 expt_dir
[lastslash
] = 0;
2525 if (expt_dir
[0] == '/')
2526 store_dir
= strdup (expt_dir
);
2527 else if ((udir_name
== NULL
) || (udir_name
[0] == 0))
2529 if (expt_dir
[0] == 0)
2530 store_dir
= strdup (".");
2532 store_dir
= strdup (expt_dir
);
2536 /* udir_name is a non-empty string */
2537 if (expt_dir
[0] == 0)
2538 store_dir
= strdup (udir_name
);
2541 snprintf (buf
, sizeof (buf
), "%s/%s", udir_name
, expt_dir
);
2542 store_dir
= strdup (buf
);
2546 if (strcmp (store_dir
, ".") == 0)
2547 store_ptr
= strdup (base_name
);
2550 snprintf (buf
, sizeof (buf
), "%s/%s", store_dir
, base_name
);
2551 store_ptr
= strdup (buf
);
2554 // determine the file system type
2555 if (strcmp (store_dir
, prev_store_dir
) != 0)
2557 free (prev_store_dir
);
2558 prev_store_dir
= strdup (store_dir
);
2559 const char *fstype
= get_fstype (store_dir
);
2560 if (interactive
&& enabled
&& (fstype
!= NULL
) && (nofswarn
== 0))
2562 snprintf (msgbuf
, sizeof (msgbuf
),
2563 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"),
2564 (ret
== NULL
? "" : ret
), fstype
);
2566 ret
= strdup (msgbuf
);
2573 Coll_Ctrl::update_expt_name (bool chgmsg
, bool chkonly
, bool newname
)
2576 struct stat statbuf
;
2577 // make sure the name ends in .er
2578 // set count to the length of the name
2579 int count
= (int) strlen (base_name
);
2581 // this should have been checked already, so we can abort
2582 if (count
< 4 || strcmp (&base_name
[count
- 3], ".er") != 0)
2584 int pcount
= count
- 4;
2586 { // check if old name can be used
2587 char fullname
[MAXPATHLEN
];
2588 snprintf (fullname
, sizeof (fullname
), "%s/%s", store_dir
, base_name
);
2589 if (stat (fullname
, &statbuf
) != 0)
2590 if (errno
== ENOENT
) // name does not exist, we can use it
2596 // current name will not work, update the name
2598 struct dirent
*dir_entry
;
2600 // see if there's a numeric field in front of the .er of the name
2602 while (isdigit ((int) (base_name
[pcount
])) != 0)
2605 if (pcount
== 0) // name is of the form 12345.er; don't update it
2606 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2610 if (digits
== 0) // name is of form xyz.er (or xyz..er); don't update it
2611 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2613 if (base_name
[pcount
] != '.') // name is of form xyz123.er; don't update it
2614 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2619 // save the name for a changed message
2620 char *oldbase
= strdup (base_name
);
2622 // the name is of the from prefix.nnn.er; extract the value of nnn
2623 int version
= atoi (&base_name
[pcount
+ 1]);
2624 if (newname
) // do not try to use old name
2626 int max_version
= version
- 1;
2628 // terminate the base_name string after that . yielding "prefix."
2629 base_name
[pcount
+ 1] = 0;
2630 if ((dir
= opendir (store_dir
)) == NULL
)
2632 // ignore error -- we'll hit it again later
2637 // find the maximum version in the directory
2638 // count is the number of characters before the number
2640 while ((dir_entry
= readdir (dir
)) != NULL
)
2642 count
= (int) strlen (dir_entry
->d_name
);
2643 if ((count
< 4) || (strcmp (&dir_entry
->d_name
[count
- 3], ".er") != 0))
2645 // check that the name is of the form prefix.nnn.er; if not, skip it
2646 if (strncmp (base_name
, dir_entry
->d_name
, pcount
+ 1) == 0)
2648 // the "prefix." part matches, terminate the entry name before the .er
2649 dir_entry
->d_name
[count
- 3] = 0;
2651 int dversion
= (int) strtol (&dir_entry
->d_name
[pcount
+ 1], &lastchar
, 10);
2653 // if it did not end where the .er was, skip it
2656 if (dversion
> max_version
)
2657 max_version
= dversion
;
2661 // we now have the maximum version determined
2662 char newbase
[MAXPATHLEN
];
2663 base_name
[pcount
+ 1] = 0;
2664 version
= max_version
+ 1;
2665 snprintf (newbase
, sizeof (newbase
), "%s%d.er", base_name
, version
);
2666 if ((strcmp (oldbase
, newbase
) != 0) && chgmsg
)
2668 ret
= dbe_sprintf (GTXT ("name %s is in use; changed to %s\n"),
2675 base_name
= strdup (newbase
);
2677 // now, reset expt_name to reflect new setting
2679 if (expt_dir
[0] == 0)
2680 expt_name
= strdup (base_name
);
2682 expt_name
= dbe_sprintf ("%s/%s", expt_dir
, base_name
);
2684 if (strcmp (store_dir
, ".") == 0)
2685 store_ptr
= strdup (base_name
);
2687 store_ptr
= dbe_sprintf ("%s/%s", store_dir
, base_name
);
2693 Coll_Ctrl::remove_exp_dir ()
2695 if (store_ptr
== NULL
)
2704 Coll_Ctrl::determine_profile_params ()
2706 struct itimerval itimer
;
2707 struct itimerval otimer
;
2710 struct sigaction act
;
2711 struct sigaction old_handler
;
2712 memset (&act
, 0, sizeof (struct sigaction
));
2715 // set SIGPROF handler to SIG_IGN
2716 sigemptyset (&act
.sa_mask
);
2717 act
.sa_handler
= SIG_IGN
;
2718 act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
2719 if (sigaction (SIGPROF
, &act
, &old_handler
) == -1)
2721 /* couldn't set signal */
2722 fprintf (stderr
, GTXT ("Can't set SIGPROF: %s\n"), strerror (errno
));
2726 // set the timer to arbitrary resolution
2727 itimer
.it_interval
.tv_sec
= period
/ MICROSEC
;
2728 itimer
.it_interval
.tv_usec
= period
% MICROSEC
;
2729 itimer
.it_value
= itimer
.it_interval
;
2730 setitimer (ITIMER_REALPROF
, &itimer
, &otimer
);
2732 // now reset the timer to turn it off
2733 itimer
.it_value
.tv_sec
= 0;
2734 itimer
.it_value
.tv_usec
= 0;
2735 if (setitimer (ITIMER_REALPROF
, &itimer
, &otimer
) == -1) // call failed
2738 nperiod
= otimer
.it_interval
.tv_sec
* MICROSEC
+ otimer
.it_interval
.tv_usec
;
2740 // check the returned value: is the what we asked for?
2741 if (period
== nperiod
) // arbitrary precision is OK
2742 set_clk_params (PROFINT_MIN
, 1, PROFINT_MAX
, PROFINT_HIGH
, PROFINT_NORM
, PROFINT_LOW
);
2743 else if (nperiod
< 10000) // hi resolution allowed, but not arbitrary precision
2744 set_clk_params ((int) nperiod
, 1000, PROFINT_MAX
, 1000, 10000, 100000);
2745 else // low resolution only allowed
2746 set_clk_params (10000, 10000, PROFINT_MAX
, 1000, 10000, 100000);
2748 // If old handler was default, ignore it; otherwise restore it
2749 if (old_handler
.sa_handler
!= SIG_DFL
)
2751 act
.sa_handler
= old_handler
.sa_handler
;
2752 if (sigaction (SIGPROF
, &act
, &old_handler
) == -1)
2754 /* couldn't reset signal */
2755 fprintf (stderr
, GTXT ("Can't reset SIGPROF: %s\n"), strerror (errno
));
2764 /* On Linux, statvfs() doesn't return any information that seems to indicate
2765 the filetype. The structure statvfs does not have any field/flag that
2766 gives this information. Comparing the fields from
2767 /usr/include/bits/statvfs.h:
2768 unsigned long int f_fsid;
2770 ^^^^ On Solaris, this is where f_basetype is
2771 unsigned long int f_flag;
2772 unsigned long int f_namemax;
2773 XXX Need to revisit this XXX
2775 return NULL
; // no NFS warning on Linux for now
2778 //========== Special functions to communicate with the Collector GUI ==========//
2780 /* Interface strings GUI <-> CLI */
2781 const char *ipc_str_exp_limit
= "exp_limit";
2782 const char *ipc_str_time_limit
= "time_limit";
2783 const char *ipc_str_arch_exp
= "arch_exp";
2784 const char *ipc_str_descendant
= "descendant";
2785 const char *ipc_str_clkprof
= "clkprof";
2786 const char *ipc_str_hwcprof
= "hwcprof";
2787 const char *ipc_str_hwc2_prof
= "hwc2_prof";
2788 const char *ipc_str_javaprof
= "javaprof";
2789 const char *ipc_str_sample
= "sample";
2790 const char *ipc_str_sample_sig
= "sample_sig";
2791 const char *ipc_str_pause_resume_sig
= "pause_resume_sig";
2792 const char *ipc_str_synctrace
= "synctrace";
2793 const char *ipc_str_heaptrace
= "heaptrace";
2794 const char *ipc_str_iotrace
= "iotrace";
2795 const char *ipc_str_count
= "count";
2796 const char *ipc_str_prof_idle
= "prof_idle"; // -x option
2798 const char *ipc_str_empty
= "";
2799 const char *ipc_str_on
= "on";
2800 const char *ipc_str_off
= "off";
2801 const char *ipc_str_src
= "src";
2802 const char *ipc_str_usedsrc
= "usedsrc";
2803 const char *ipc_str_usedldobjects
= "usedldobjects";
2804 const char *ipc_str_unlimited
= "unlimited";
2805 const char *ipc_str_unknown_control
= "Unknown control";
2806 const char *ipc_str_internal_error
= "Internal error";
2811 * @return NULL or signal name (pointer to allocated memory)
2814 Coll_Ctrl::find_signal_name (int signal
)
2816 char *str_signal
= NULL
;
2817 const char *buf
= strsignal (signal
);
2819 str_signal
= strdup (buf
);
2824 * Gets control's value
2829 Coll_Ctrl::get (char * control
)
2831 int len
= strlen (control
);
2832 if (!strncmp (control
, ipc_str_exp_limit
, len
))
2834 if ((size_limit
> 0))
2835 return dbe_sprintf ("%d", size_limit
);
2836 return strdup (ipc_str_unlimited
);
2838 if (!strncmp (control
, ipc_str_time_limit
, len
))
2840 if ((time_run
!= 0) || (start_delay
!= 0))
2842 if (start_delay
!= 0)
2845 return dbe_sprintf ("%ds-%ds", start_delay
, start_delay
+ time_run
);
2846 return dbe_sprintf ("%ds-0s", start_delay
);
2848 return dbe_sprintf ("0s-%ds", time_run
);
2850 return strdup (ipc_str_unlimited
);
2852 if (strncmp (control
, ipc_str_arch_exp
, len
) == 0)
2853 return strdup (get_archive_mode ());
2854 if (!strncmp (control
, ipc_str_descendant
, len
))
2856 switch (get_follow_mode ())
2859 return strdup (ipc_str_on
);
2861 return strdup (ipc_str_on
);
2864 return strdup (ipc_str_off
);
2867 if (!strncmp (control
, ipc_str_prof_idle
, len
))
2870 return strdup (ipc_str_off
);
2871 return strdup (ipc_str_on
);
2873 if (!strncmp (control
, ipc_str_clkprof
, len
))
2875 if (clkprof_default
== 1 && clkprof_enabled
== 1) // Default value
2876 return strdup (ipc_str_empty
);
2877 if (clkprof_enabled
== 0)
2878 return strdup (ipc_str_off
);
2879 if ((clkprof_timer
> 0))
2880 return dbe_sprintf ("%d", clkprof_timer
/ 1000);
2881 return strdup (ipc_str_internal_error
);
2883 if (!strncmp (control
, ipc_str_hwcprof
, len
))
2885 if (hwcprof_enabled_cnt
== 0)
2886 return strdup (ipc_str_off
);
2887 if (hwc_string
!= NULL
)
2888 return dbe_sprintf ("on\n%s", hwc_string
);
2889 return strdup (ipc_str_on
); // XXX need more details?
2891 if (!strncmp (control
, ipc_str_javaprof
, len
))
2893 if ((java_mode
== 0))
2894 return strdup (ipc_str_off
);
2895 return strdup (ipc_str_on
);
2897 if (!strncmp (control
, ipc_str_sample
, len
))
2899 if (sample_default
== 1 && sample_period
== 1) // Default value
2900 return strdup (ipc_str_empty
);
2901 if (sample_period
== 0)
2902 return strdup (ipc_str_off
);
2903 if (sample_period
> 0)
2904 return dbe_sprintf ("%d", sample_period
);
2905 return strdup (ipc_str_internal_error
);
2907 if (!strncmp (control
, ipc_str_sample_sig
, len
))
2909 if ((sample_sig
== 0))
2910 return strdup (ipc_str_off
);
2911 char *str_signal
= find_signal_name (sample_sig
);
2912 if (str_signal
!= NULL
)
2914 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), sample_sig
);
2916 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
2918 if (pauseresume_sig
== 0)
2919 return strdup (ipc_str_off
);
2920 char *str_signal
= find_signal_name (pauseresume_sig
);
2921 if (str_signal
!= NULL
)
2923 return dbe_sprintf (GTXT ("Invalid pause/resume signal %d\n"), pauseresume_sig
);
2925 if (!strncmp (control
, ipc_str_synctrace
, len
))
2927 if (synctrace_enabled
== 0)
2928 return strdup (ipc_str_off
);
2929 if (synctrace_thresh
< 0)
2930 return strdup ("on\nthreshold: calibrate");
2931 if (synctrace_thresh
== 0)
2932 return strdup ("on\nthreshold: all");
2933 return dbe_sprintf ("on\nthreshold: %d", synctrace_thresh
);
2935 if (!strncmp (control
, ipc_str_heaptrace
, len
))
2937 if ((heaptrace_enabled
== 0))
2938 return strdup (ipc_str_off
);
2939 return strdup (ipc_str_on
);
2941 if (!strncmp (control
, ipc_str_iotrace
, len
))
2943 if ((iotrace_enabled
== 0))
2944 return strdup (ipc_str_off
);
2945 return strdup (ipc_str_on
);
2947 if (!strncmp (control
, ipc_str_count
, len
))
2949 if ((count_enabled
== 0))
2950 return strdup (ipc_str_off
);
2951 if ((count_enabled
< 0))
2952 return strdup ("on\nstatic");
2953 return strdup (ipc_str_on
);
2955 return strdup (ipc_str_unknown_control
);
2959 * Resets control's value (restores the default value)
2962 * @return error or warning or NULL (done)
2965 Coll_Ctrl::set (char * control
, const char * value
)
2969 int len
= strlen (control
);
2970 if (!strncmp (control
, ipc_str_exp_limit
, len
))
2971 return set_size_limit (value
);
2972 if (!strncmp (control
, ipc_str_time_limit
, len
))
2973 return set_time_run (value
);
2974 if (!strncmp (control
, ipc_str_arch_exp
, len
))
2975 return set_archive_mode (value
);
2976 if (!strncmp (control
, ipc_str_descendant
, len
))
2977 return set_follow_mode (value
);
2978 if (!strncmp (control
, ipc_str_prof_idle
, len
))
2979 return set_prof_idle (value
);
2980 if (!strncmp (control
, ipc_str_clkprof
, len
))
2982 ret
= set_clkprof (value
, &warn
);
2986 return warn
; // Warning
2987 return NULL
; // Done
2989 return ret
; // Error
2991 if (!strncmp (control
, ipc_str_hwcprof
, len
))
2993 ret
= set_hwcstring (value
, &warn
);
2997 return warn
; // Warning
2998 return NULL
; // Done
3000 return ret
; // Error
3002 if (!strncmp (control
, ipc_str_hwc2_prof
, len
))
3004 ret
= set_hwcstring (value
, &warn
);
3008 return warn
; // Warning
3009 return NULL
; // Done
3011 return ret
; // Error
3013 if (!strncmp (control
, ipc_str_javaprof
, len
))
3014 return set_java_mode (value
);
3015 if (!strncmp (control
, ipc_str_sample
, len
))
3016 return set_sample_period (value
);
3017 if (!strncmp (control
, ipc_str_sample_sig
, len
))
3018 return set_sample_signal (find_sig (value
));
3019 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
3021 char *str_signal
= strdup (value
);
3022 char *str_state
= strchr (str_signal
, (int) '\n');
3023 if (str_state
!= NULL
)
3028 int signal
= atoi (str_signal
);
3030 if (str_state
!= NULL
)
3031 state
= atoi (str_state
);
3033 return set_pauseresume_signal (signal
, state
);
3035 if (!strncmp (control
, ipc_str_synctrace
, len
))
3036 return set_synctrace (value
);
3037 if (!strncmp (control
, ipc_str_heaptrace
, len
))
3038 return set_heaptrace (value
);
3039 if (!strncmp (control
, ipc_str_iotrace
, len
))
3040 return set_iotrace (value
);
3041 if (!strncmp (control
, ipc_str_count
, len
))
3042 return set_count (value
);
3043 return strdup (ipc_str_unknown_control
);
3047 * Resets control's value (restores the default value)
3049 * @return error or NULL (done)
3052 Coll_Ctrl::unset (char * control
)
3054 int len
= strlen (control
);
3055 if (!strncmp (control
, ipc_str_exp_limit
, len
))
3057 if (!strncmp (control
, ipc_str_time_limit
, len
))
3062 if (!strncmp (control
, ipc_str_arch_exp
, len
))
3064 archive_mode
= strdup ("on");
3067 if (!strncmp (control
, ipc_str_descendant
, len
))
3069 follow_mode
= FOLLOW_NONE
;
3072 if (!strncmp (control
, ipc_str_prof_idle
, len
))
3077 if (!strncmp (control
, ipc_str_clkprof
, len
))
3079 clkprof_default
= 1;
3080 clkprof_enabled
= 1;
3083 if (!strncmp (control
, ipc_str_hwcprof
, len
))
3089 if (!strncmp (control
, ipc_str_javaprof
, len
))
3098 if (!strncmp (control
, ipc_str_sample
, len
))
3104 if (!strncmp (control
, ipc_str_sample_sig
, len
))
3109 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
3111 pauseresume_sig
= 0;
3114 if (!strncmp (control
, ipc_str_synctrace
, len
))
3116 synctrace_enabled
= 0;
3117 synctrace_thresh
= -1;
3120 if (!strncmp (control
, ipc_str_heaptrace
, len
))
3122 heaptrace_enabled
= 0;
3125 if (!strncmp (control
, ipc_str_iotrace
, len
))
3127 iotrace_enabled
= 0;
3130 if (!strncmp (control
, ipc_str_count
, len
))
3137 return strdup (ipc_str_unknown_control
);
3141 Coll_Ctrl::set_project_home (char *s
)
3144 project_home
= strdup (s
);