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 "StringBuilder.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 static const char *get_fstype (char *);
59 static cpu_info_t cpu_info
;
62 read_str (char *from
, char **to
)
66 for (char *s
= from
; *s
; s
++)
67 if (*s
!= ':' && *s
!= '\t' && *s
!= ' ')
69 for (int i
= ((int) strlen (s
)) - 1; i
>= 0; i
--)
71 if (s
[i
] != '\n' && s
[i
] != ' ' && s
[i
] != '\t')
73 *to
= strndup(s
, i
+ 1);
77 return; // string is empty
84 char *val
= strchr (from
, ':');
86 return atoi (val
+ 1);
93 static int inited
= 0;
98 #if defined(__aarch64__)
99 asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_info
.cpu_clk_freq
));
102 // Read /proc/cpuinfo to get CPU info and clock rate
103 FILE *procf
= fopen ("/proc/cpuinfo", "r");
107 while (fgets (temp
, (int) sizeof (temp
), procf
) != NULL
)
109 if (strncmp (temp
, "processor", 9) == 0)
111 else if (strncmp (temp
, "cpu MHz", 7) == 0)
112 cpu_info
.cpu_clk_freq
= read_int (temp
+ 9);
113 else if (strncmp (temp
, "cpu family", 10) == 0)
114 cpu_info
.cpu_family
= read_int (temp
+ 10);
115 else if (strncmp (temp
, "vendor_id", 9) == 0)
117 if (cpu_info
.cpu_vendorstr
== NULL
)
118 read_str (temp
+ 9, &cpu_info
.cpu_vendorstr
);
120 else if (strncmp (temp
, "model name", 10) == 0)
122 if (cpu_info
.cpu_modelstr
== NULL
)
123 read_str (temp
+ 10, &cpu_info
.cpu_modelstr
);
125 else if (strncmp (temp
, "model", 5) == 0)
126 cpu_info
.cpu_model
= read_int (temp
+ 5);
127 else if (strncmp (temp
, "CPU implementer", 15) == 0)
128 cpu_info
.cpu_family
= read_int (temp
+ 15);
129 else if (strncmp (temp
, "CPU architecture", 16) == 0)
130 cpu_info
.cpu_model
= read_int (temp
+ 16);
137 Coll_Ctrl::Coll_Ctrl (int _interactive
, bool _defHWC
, bool _kernelHWC
)
139 char hostname
[MAXPATHLEN
];
141 interactive
= _interactive
;
143 kernelHWC
= _kernelHWC
;
145 /* set this host's parameters */
146 gethostname (hostname
, 1023);
147 node_name
= strdup (hostname
);
148 char *p
= strchr (node_name
, (int) '.');
151 default_stem
= strdup ("test");
153 /* get CPU count and processor clock rate */
154 ncpumax
= sysconf (_SC_CPUID_MAX
);
157 ncpus
= sysconf (_SC_NPROCESSORS_CONF
);
158 /* add 2048 to count, since on some systems CPUID does not start at zero */
159 ncpumax
= ncpus
+ 2048;
161 cpu_info_t
*cpu_p
= read_cpuinfo();
162 ncpus
= cpu_p
->cpu_cnt
;
163 cpu_clk_freq
= cpu_p
->cpu_clk_freq
;
165 /* check resolution of system clock */
166 sys_resolution
= sysconf (_SC_CLK_TCK
);
167 if (sys_resolution
== 0)
170 sys_period
= MICROSEC
/ (int) sys_resolution
;
172 /* determine memory page size and number of pages */
173 npages
= sysconf (_SC_PHYS_PAGES
);
174 page_size
= sysconf (_SC_PAGE_SIZE
);
176 /* set default clock parameters */
177 hwcprof_enabled_cnt
= 0; // must be set before calling determine_profile_params();
178 determine_profile_params (); // inits clk_params which is used by clock profiling AND HWCs
179 cpc_cpuver
= CPUVER_UNDEFINED
;
181 /* set default control values */
183 #if defined(GPROFNG_JAVA_PROFILING)
192 follow_mode
= FOLLOW_ON
;
194 follow_spec_usr
= NULL
;
195 follow_spec_cmp
= NULL
;
197 archive_mode
= strdup ("on");
205 /* clear the string pointers */
212 prev_store_dir
= strdup ("");
222 /* set default data collection values */
227 for (unsigned ii
= 0; ii
< MAX_PICS
; ii
++)
229 memset (&hwctr
[ii
], 0, sizeof (Hwcentry
));
230 hwctr
[ii
].reg_num
= -1;
238 else // disable the default, and reset the counters
239 hwcprof_enabled_cnt
= 0;
240 synctrace_enabled
= 0;
241 synctrace_thresh
= -1;
243 heaptrace_enabled
= 0;
244 heaptrace_checkenabled
= 0;
255 // ensure that the default name is updated
256 // but don't print any message
257 (void) preprocess_names ();
258 (void) update_expt_name (false, false);
261 /* Copy constructor */
262 Coll_Ctrl::Coll_Ctrl (Coll_Ctrl
* cc
)
265 interactive
= cc
->interactive
;
267 kernelHWC
= cc
->kernelHWC
;
268 node_name
= strdup (cc
->node_name
);
269 default_stem
= strdup (cc
->default_stem
);
271 cpu_clk_freq
= cc
->cpu_clk_freq
;
273 page_size
= cc
->page_size
;
274 cpc_cpuver
= cc
->cpc_cpuver
;
275 debug_mode
= cc
->debug_mode
;
276 java_mode
= cc
->java_mode
;
277 java_default
= cc
->java_default
;
281 follow_mode
= cc
->follow_mode
;
282 follow_default
= cc
->follow_default
;
283 if (cc
->follow_spec_usr
)
285 follow_spec_usr
= strdup (cc
->follow_spec_usr
);
286 follow_spec_cmp
= strdup (cc
->follow_spec_cmp
);
290 follow_spec_usr
= NULL
;
291 follow_spec_cmp
= NULL
;
293 archive_mode
= strdup (cc
->archive_mode
);
294 pauseresume_sig
= cc
->pauseresume_sig
;
295 sample_sig
= cc
->sample_sig
;
296 time_run
= cc
->time_run
;
297 start_delay
= cc
->start_delay
;
298 clk_params
= cc
->clk_params
;
299 clkprof_enabled
= cc
->clkprof_enabled
;
300 clkprof_default
= cc
->clkprof_default
;
301 clkprof_timer
= cc
->clkprof_timer
;
302 clkprof_timer_target
= cc
->clkprof_timer_target
;
304 // copy HW counter information
305 hwcprof_default
= cc
->hwcprof_default
;
306 hwcprof_enabled_cnt
= cc
->hwcprof_enabled_cnt
;
307 if (cc
->hwc_string
!= NULL
)
308 hwc_string
= strdup (cc
->hwc_string
);
311 for (int i
= 0; i
< hwcprof_enabled_cnt
; i
++)
312 hwcentry_dup (&hwctr
[i
], &(cc
->hwctr
[i
]));
313 project_home
= cc
->project_home
? strdup (cc
->project_home
) : NULL
;
314 synctrace_enabled
= cc
->synctrace_enabled
;
315 synctrace_thresh
= cc
->synctrace_thresh
;
316 synctrace_scope
= cc
->synctrace_scope
;
317 heaptrace_enabled
= cc
->heaptrace_enabled
;
318 heaptrace_checkenabled
= cc
->heaptrace_checkenabled
;
319 iotrace_enabled
= cc
->iotrace_enabled
;
320 count_enabled
= cc
->count_enabled
;
323 sample_period
= cc
->sample_period
;
324 sample_default
= cc
->sample_default
;
325 size_limit
= cc
->size_limit
;
326 nofswarn
= cc
->nofswarn
;
328 // these will get reset during preprocess_names()
335 // these represent user settings
337 if (cc
->expt_group
!= NULL
)
338 expt_group
= strdup (cc
->expt_group
);
340 if (cc
->uexpt_name
!= NULL
)
341 uexpt_name
= strdup (cc
->uexpt_name
);
343 if (cc
->udir_name
!= NULL
)
344 udir_name
= strdup (cc
->udir_name
);
346 /* clear the string pointers */
347 prev_store_dir
= strdup ("");
354 /* set default data collection values */
355 enabled
= cc
->enabled
;
357 nofswarn
= cc
->nofswarn
;
358 sys_resolution
= cc
->sys_resolution
;
359 sys_period
= cc
->sys_period
;
361 // ensure that the default name is updated
362 (void) preprocess_names ();
363 (void) update_expt_name (false, false);
367 Coll_Ctrl::~Coll_Ctrl ()
383 hwcprof_enabled_cnt
= 0;
386 /* set up the experiment */
388 Coll_Ctrl::setup_experiment ()
395 /* create the experiment directory */
396 ret
= create_exp_dir ();
400 /* if an experiment-group, join it */
407 /* all is OK, return 0 */
413 Coll_Ctrl::interrupt ()
419 Coll_Ctrl::enable_expt ()
422 return strdup (GTXT ("Experiment is active; command ignored.\n"));
423 if (cpu_clk_freq
== 0)
424 return strdup (GTXT ("Can not determine CPU clock frequency.\n"));
425 if (sys_resolution
== 0)
426 return strdup (GTXT ("System clock profile resolution can not be determined.\n"));
431 /* close the experiment */
433 Coll_Ctrl::close_expt ()
436 (void) update_expt_name (false, false);
439 /* close and delete the experiment */
441 Coll_Ctrl::delete_expt ()
447 /* The order of removing the directory and closing
448 * the experiment may seem unnatural, but it's not.
449 * We do need to update names when we close the experiment
450 * (actually Coll_Ctrl object) and we can't remove anything
456 // Check the experiment settings for consistency. Returns NULL if OK,
457 // or an error message if there are invalid combinations of settings
459 Coll_Ctrl::check_consistency ()
461 /* check for Java arguments, but not Java profiling */
462 if (java_args
!= NULL
&& java_mode
== 0)
463 return strdup (GTXT ("Java arguments can not be set if Java profiling is not enabled.\n"));
465 /* if count data, no other data is allowed */
466 if (count_enabled
!= 0
467 && ((clkprof_default
!= 1 && clkprof_enabled
!= 0)
468 || hwcprof_enabled_cnt
!= 0 || synctrace_enabled
!= 0
469 || heaptrace_enabled
!= 0 || iotrace_enabled
!= 0))
470 return strdup (GTXT ("Count data cannot be collected along with any other data.\n"));
472 /* if count data, various other options are not allowed */
473 if (count_enabled
!= 0
474 && ((java_mode
!= 0 && java_default
!= 1)
475 || java_args
!= NULL
|| debug_mode
!= 0
476 || (follow_mode
!= 0 && follow_default
!= 1)
477 || pauseresume_sig
!= 0 || sample_sig
!= 0
478 || (sample_default
!= 1 && sample_period
!= 0) || time_run
!= 0))
479 return strdup (GTXT ("Count data cannot be collected with any of -F -S -y -l -j -J -x -t .\n"));
480 /* if not count data, I and N options are not allowed */
481 if (count_enabled
== 0 && (Iflag
!= 0 || Nflag
!= 0))
482 return strdup (GTXT ("-I or -N can only be specified with count data.\n"));
487 Coll_Ctrl::check_expt (char **warn
)
491 ret
= check_consistency ();
492 if (ret
!= NULL
) /* something is wrong, return the error */
494 /* check for heaptrace and java -- warn that it covers native allocations only */
495 if (heaptrace_enabled
== 1 && java_mode
== 1 && java_default
== 0)
496 *warn
= strdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n"));
498 /* if no profiling data selected, warn the user */
499 if (clkprof_enabled
== 0 && hwcprof_enabled_cnt
== 0 && synctrace_enabled
== 0
500 && heaptrace_enabled
== 0 && iotrace_enabled
== 0 && count_enabled
== 0)
501 *warn
= strdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n"));
504 /* verify that the directory exists */
506 if (stat (store_dir
, &statbuf
) != 0)
507 return dbe_sprintf (GTXT ("Store directory %s is not accessible: %s\n"),
508 store_dir
, strerror (errno
));
509 if (access (store_dir
, W_OK
) != 0)
510 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),
511 store_dir
, strerror (errno
));
513 /* if an experiment-group, verify that it can be written */
514 ret
= check_group ();
521 Coll_Ctrl::show (int i
)
527 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
528 GTXT ("Collection parameters:\n"));
529 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
530 GTXT (" experiment enabled\n"));
532 if (target_name
!= NULL
)
533 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
534 GTXT ("\ttarget = %s\n"), target_name
);
535 if (uexpt_name
!= NULL
)
536 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
537 GTXT ("\tuser_expt_name = %s\n"), uexpt_name
);
538 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
539 GTXT ("\texpt_name = %s\n"),
540 ((expt_name
!= NULL
) ? expt_name
: NTXT ("<NULL>")));
541 if (udir_name
!= NULL
)
542 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
543 GTXT ("\tdir_name = %s\n"), udir_name
);
544 if (expt_group
!= NULL
)
545 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
546 GTXT ("\texpt_group = %s\n"), expt_group
);
548 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
549 GTXT ("\tdebug_mode enabled\n"));
550 if (clkprof_enabled
!= 0)
551 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
552 GTXT ("\tclock profiling enabled, %.3f millisec.\n"),
553 (double) (clkprof_timer
) / 1000.);
554 if (synctrace_enabled
!= 0)
556 if (synctrace_thresh
< 0)
557 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
558 GTXT ("\tsynchronization tracing enabled, threshold: calibrate; "));
559 else if (synctrace_thresh
== 0)
560 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
561 GTXT ("\tsynchronization tracing enabled, threshold: all; "));
563 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
564 GTXT ("\tsynchronization tracing enabled, threshold: %d micros.; "), synctrace_thresh
);
565 switch (synctrace_scope
)
567 case SYNCSCOPE_NATIVE
:
568 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
569 GTXT ("Native-APIs\n"));
572 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
573 GTXT ("Java-APIs\n"));
575 case SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
:
576 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
577 GTXT ("Native- and Java-APIs\n"));
580 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
581 GTXT ("ERR -- unexpected synctrace_scope %d\n"), synctrace_scope
);
585 if (hwcprof_enabled_cnt
!= 0)
587 char ctrbuf
[MAXPATHLEN
];
588 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
589 GTXT ("\thardware counter profiling%s enabled:\n"),
590 (hwcprof_default
== 1 ? GTXT (" (default)") : ""));
591 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
592 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
593 GTXT ("\t %u. %s\n"), ii
+ 1,
594 hwc_hwcentry_specd_string (ctrbuf
, MAXPATHLEN
, &hwctr
[ii
]));
596 if (heaptrace_enabled
!= 0)
597 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
598 GTXT ("\theap tracing enabled, %s\n"),
599 (heaptrace_checkenabled
== 0 ? GTXT ("no checking") :
600 (heaptrace_checkenabled
== 1 ? GTXT ("over/underrun checking") :
601 GTXT ("over/underrun checking and pattern storing"))));
602 if (iotrace_enabled
!= 0)
603 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
604 GTXT ("\tI/O tracing enabled\n"));
605 switch (count_enabled
)
610 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
611 GTXT ("\tcount data enabled\n"));
614 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
615 GTXT ("\tstatic count data will be generated (for a.out only)\n"));
621 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
622 GTXT ("\tdescendant processes will be followed\n"));
625 if (follow_spec_usr
&& follow_spec_cmp
)
626 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
627 GTXT ("\texperiments will be recorded for descendant processes that match pattern '%s'\n"),
630 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
631 GTXT ("\tdescendant processes will all be followed\n"));
634 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
635 GTXT ("\tdescendant processes will not be followed\n"));
638 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
639 GTXT ("\tfollowing descendant processes: <UNKNOWN>\n"));
643 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
644 GTXT ("\tjava profiling disabled\n"));
645 if (pauseresume_sig
!= 0)
647 const char *buf
= strsignal (pauseresume_sig
);
650 if (pauseresume_pause
== 1)
651 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
652 GTXT ("\tpause-resume (delayed initialization) signal %s (%d) -- paused\n"), buf
, pauseresume_sig
);
654 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
655 GTXT ("\tpause-resume (delayed initialization) signal %s (%d)\n"), buf
, pauseresume_sig
);
659 if (pauseresume_pause
== 1)
660 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
661 GTXT ("\tpause-resume (delayed initialization) signal %d -- paused\n"), pauseresume_sig
);
663 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
664 GTXT ("\tpause-resume (delayed initialization) signal %d\n"), pauseresume_sig
);
669 const char *buf
= strsignal (sample_sig
);
671 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
672 GTXT ("\tsample signal %s (%d)\n"), buf
, sample_sig
);
674 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
675 GTXT ("\tsample signal %d\n"), sample_sig
);
677 if (time_run
!= 0 || start_delay
!= 0)
679 if (start_delay
!= 0)
682 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
683 GTXT ("\tdata-collection duration, %d-%d secs.\n"), start_delay
, time_run
);
685 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
686 GTXT ("\tdata-collection duration, %d- secs.\n"), start_delay
);
689 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
690 GTXT ("\tdata-collection duration, %d secs.\n"), time_run
);
692 if (sample_period
!= 0)
693 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
694 GTXT ("\tperiodic sampling, %d secs.\n"), sample_period
);
696 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
697 GTXT ("\tno periodic sampling\n"));
699 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
700 GTXT ("\texperiment size limit %d MB.\n"), size_limit
);
702 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
703 GTXT ("\tno experiment size limit set\n"));
704 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
705 GTXT ("\texperiment archiving: -a %s\n"), archive_mode
);
706 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
707 GTXT ("\tdata descriptor: \"%s\"\n"),
708 ((data_desc
!= NULL
) ? data_desc
: NTXT ("<NULL>")));
710 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
711 GTXT ("\t expt_dir: %s\n"),
712 ((expt_dir
!= NULL
) ? expt_dir
: NTXT ("<NULL>")));
713 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
714 GTXT ("\t base_name: %s\n"),
715 ((base_name
!= NULL
) ? base_name
: NTXT ("<NULL>")));
716 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
717 GTXT ("\t store_dir: %s\n"),
718 ((store_dir
!= NULL
) ? store_dir
: NTXT ("<NULL>")));
719 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
720 GTXT ("\t store_ptr: %s\n"),
721 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")));
723 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
724 GTXT ("\t\thost: `%s', ncpus = %d, clock frequency %d MHz.\n"),
725 ((node_name
!= NULL
) ? node_name
: NTXT ("<NULL>")),
726 (int) ncpus
, (int) cpu_clk_freq
);
729 long long memsize
= ((long long) npages
* (long long) page_size
) / (1024 * 1024);
730 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
731 GTXT ("\t\tmemory: %ld pages @ %ld bytes = %lld MB.\n"),
732 npages
, page_size
, memsize
);
734 return strdup (UEbuf
);
737 #define MAX_COLLECT_ARGS 100
740 Coll_Ctrl::get_collect_args ()
742 char buf
[DD_MAXPATHLEN
];
744 char **argv
= (char **) calloc (MAX_COLLECT_ARGS
, sizeof (char *));
745 if (argv
== NULL
) // poor way of dealing with calloc failure
748 *p
++ = strdup ("collect");
750 *p
++ = strdup ("-x");
751 if (clkprof_enabled
!= 0)
753 *p
++ = strdup ("-p");
754 snprintf (buf
, sizeof (buf
), "%du", clkprof_timer
);
757 if (hwcprof_enabled_cnt
> 0)
760 *p
++ = strdup ("-h");
761 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
763 char*rateString
= hwc_rate_string (&hwctr
[ii
], 1); //"1" is for temporary goldfile compatibility. TBR YXXX!!
764 snprintf (buf
+ strlen (buf
), sizeof (buf
) - strlen (buf
),
765 "%s%s,%s%s", ii
? "," : "", hwctr
[ii
].name
,
766 rateString
? rateString
: "",
767 (ii
+ 1 < hwcprof_enabled_cnt
) ? "," : "");
770 if (strlen (buf
) + 1 >= sizeof (buf
))
774 if (heaptrace_enabled
!= 0)
776 *p
++ = strdup ("-H");
777 *p
++ = strdup ("on");
779 if (iotrace_enabled
!= 0)
781 *p
++ = strdup ("-i");
782 *p
++ = strdup ("on");
784 if (synctrace_enabled
!= 0)
786 *p
++ = strdup ("-s");
787 if (synctrace_thresh
< 0)
788 *p
++ = strdup ("calibrate");
789 else if (synctrace_thresh
== 0)
790 *p
++ = strdup ("all");
792 *p
++ = dbe_sprintf ("%d", synctrace_thresh
);
793 *p
++ = dbe_sprintf (",%d", synctrace_scope
);
795 if (follow_mode
!= 0)
797 *p
++ = strdup ("-F");
798 char * fs
= get_follow_usr_spec ();
803 switch (get_follow_mode ())
806 *p
++ = strdup ("on");
809 *p
++ = strdup ("all");
813 *p
++ = strdup ("off");
818 *p
++ = strdup ("-a");
819 *p
++ = strdup (get_archive_mode ());
822 *p
++ = strdup ("-j");
823 *p
++ = strdup ("on");
825 if (pauseresume_sig
!= 0)
827 *p
++ = strdup ("-y");
828 *p
++ = dbe_sprintf ("%d%s", pauseresume_sig
,
829 (pauseresume_pause
== 0 ? ",r" : ""));
833 *p
++ = strdup ("-l");
834 *p
++ = dbe_sprintf ("%d", sample_sig
);
836 if (sample_period
!= 0)
838 *p
++ = strdup ("-S");
839 *p
++ = dbe_sprintf ("%d", sample_period
);
843 *p
++ = strdup ("-L");
844 *p
++ = dbe_sprintf ("%d", size_limit
);
846 if (expt_group
!= NULL
)
848 *p
++ = strdup ("-g");
849 *p
++ = strdup (expt_group
);
853 *p
++ = strdup ("-d");
854 *p
++ = strdup (udir_name
);
858 *p
++ = strdup ("-o");
859 *p
++ = strdup (expt_name
);
861 if (p
- argv
>= MAX_COLLECT_ARGS
) // argument list too small -- fatal error
867 Coll_Ctrl::show_expt ()
873 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
874 GTXT ("Creating experiment directory %s (Process ID: %ld) ...\n"),
875 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")), (long) getpid ());
876 char *caller
= getenv ("SP_COLLECTOR_FROM_GUI"); // Collector from GUI
877 if (caller
!= NULL
) // Print non-localized message
878 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
879 NTXT ("\nCreating experiment directory %s (Process ID: %ld) ...\n"),
880 ((store_ptr
!= NULL
) ? store_ptr
: NTXT ("<NULL>")), (long) getpid ());
882 char *fstype
= get_fstype (store_dir
);
883 if ((fstype
!= NULL
) && (nofswarn
== 0))
885 // only warn if clock or hwc profiling is turned on
886 if (clkprof_enabled
|| hwcprof_enabled_cnt
!= 0)
887 snprintf (UEbuf
+ strlen (UEbuf
), sizeof (UEbuf
) - strlen (UEbuf
),
888 GTXT ("this experiment is being recorded to a file system \nof type \"%s\", which may distort the measured performance."),
892 return strdup (UEbuf
);
896 Coll_Ctrl::set_clk_params (int min
, int res
, int max
, int hi
, int norm
, int lo
)
898 clk_params
.min
= min
;
899 clk_params
.res
= res
;
900 clk_params
.max
= max
;
901 clk_params
.hival
= hi
;
902 clk_params
.normval
= norm
;
903 clk_params
.lowval
= lo
;
904 set_clkprof_timer_target (clk_params
.normval
); // note: requires clk_params to be initialized!
908 Coll_Ctrl::reset_clkprof (int val
)
910 if (val
!= clkprof_timer
)
912 // profiler has had to reset to a different value; warn user
913 char *msg
= dbe_sprintf (
914 GTXT ("Warning: Clock profiling timer reset from %.3f millisec. to %.3f millisec. as required by profiling driver\n\n"),
915 (double) (clkprof_timer
) / 1000., (double) (val
) / 1000.);
916 adjust_clkprof_timer (val
);
923 Coll_Ctrl::set_clkprof (const char *string
, char** warn
)
927 int prevclkprof_enabled
;
928 int prevclkprof_default
;
931 return strdup (GTXT ("Experiment is active; command ignored.\n"));
932 /* if the first character is a +, warn user that it is no longer supported */
933 if (string
[0] == '+')
934 return strdup (GTXT ("Warning: clock-based memoryspace and dataspace profiling is no longer supported\n"));
935 if (strcmp (string
, "off") == 0)
941 else if (string
== NULL
|| strcmp (string
, "on") == 0)
942 nclkprof_timer
= clk_params
.normval
;
943 else if (strcmp (string
, "lo") == 0 || strcmp (string
, "low") == 0)
944 nclkprof_timer
= clk_params
.lowval
;
945 else if (strcmp (string
, "hi") == 0 || strcmp (string
, "high") == 0
946 || strcmp (string
, "h") == 0)
947 nclkprof_timer
= clk_params
.hival
;
950 /* the remaining string should be a number > 0 */
951 char *endchar
= NULL
;
952 double dval
= strtod (string
, &endchar
);
953 if (*endchar
== 'm' || *endchar
== 0) /* user specified milliseconds */
955 else if (*endchar
== 'u') /* user specified microseconds */
958 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string
);
959 nclkprof_timer
= (int) (dval
+ 0.5);
961 // we now have the proposed value; ensure it's within limits
962 if (nclkprof_timer
<= 0)
963 return dbe_sprintf (GTXT ("Unrecognized clock-profiling interval `%s'\n"), string
);
965 // Check consistency with experiment
966 prevclkprof_enabled
= clkprof_enabled
;
967 prevclkprof_default
= clkprof_default
;
970 char *ret
= check_consistency ();
973 clkprof_default
= prevclkprof_default
;
974 clkprof_enabled
= prevclkprof_enabled
;
977 int ref_nclkprof_timer
= nclkprof_timer
;
979 // check for minimum value
980 if (nclkprof_timer
< clk_params
.min
)
982 /* value too small, use minimum value, with warning */
983 *warn
= dbe_sprintf (
984 GTXT ("Warning: Clock profiling at %.3f millisec. interval is not supported on this system; minimum %.3f millisec. used\n"),
985 (double) (nclkprof_timer
) / 1000., (double) (clk_params
.min
) / 1000.);
986 nclkprof_timer
= clk_params
.min
;
989 // check for maximum value
990 if (nclkprof_timer
> clk_params
.max
)
992 *warn
= dbe_sprintf (
993 GTXT ("Clock profiling at %.3f millisec. interval is not supported on this system; maximum %.3f millisec. used\n"),
994 (double) (nclkprof_timer
) / 1000., (double) (clk_params
.max
) / 1000.);
995 nclkprof_timer
= clk_params
.max
;
998 /* see if setting is a multiple of the period */
999 if (nclkprof_timer
> clk_params
.res
)
1001 ticks
= ((nclkprof_timer
/ clk_params
.res
) * clk_params
.res
);
1002 if (ticks
!= nclkprof_timer
)
1004 /* no, we need to reset to a multiple */
1005 *warn
= dbe_sprintf (
1006 GTXT ("Clock profile interval rounded from %.3f to %.3f (system resolution = %.3f) millisec."),
1007 (double) (nclkprof_timer
) / 1000., (double) (ticks
) / 1000.,
1008 (double) (clk_params
.res
) / 1000.);
1009 nclkprof_timer
= ticks
;
1013 // limit reference "target" rate. Target rate is also used for HWCS.
1014 if (ref_nclkprof_timer
> PROFINT_MAX
)
1015 ref_nclkprof_timer
= PROFINT_MAX
;
1016 if (ref_nclkprof_timer
< PROFINT_MIN
)
1017 ref_nclkprof_timer
= PROFINT_MIN
;
1018 set_clkprof_timer_target (ref_nclkprof_timer
);
1019 adjust_clkprof_timer (nclkprof_timer
);
1024 Coll_Ctrl::set_synctrace (const char *string
)
1027 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1028 char *comma_p
= NULL
;
1031 /* no argument provided, use default: calibrate and native */
1032 synctrace_enabled
= 1;
1033 synctrace_thresh
= -1;
1034 synctrace_scope
= SYNCSCOPE_NATIVE
;
1035 char *ret
= check_consistency ();
1038 synctrace_enabled
= 0;
1043 char *val
= strdup (string
);
1044 /* see if there's a comma in the string */
1045 char *next
= strchr (val
, (int) ',');
1048 /* remember where the comma was */
1051 /* set the scope based on the characters following the comma */
1052 synctrace_scope
= 0;
1057 synctrace_scope
|= SYNCSCOPE_NATIVE
;
1058 else if (*next
== 'j')
1059 synctrace_scope
|= SYNCSCOPE_JAVA
;
1061 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string
);
1064 if (synctrace_scope
== 0)
1065 synctrace_scope
= SYNCSCOPE_NATIVE
;
1066 /* clear the comma for the threshold determination */
1069 else /* no ",<scope>" -- default to native and Java */
1070 synctrace_scope
= SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
;
1071 if (!strlen (val
) || !strcmp (val
, "calibrate") || !strcmp (val
, "on"))
1073 /* use default: calibrate and native */
1074 synctrace_enabled
= 1;
1075 synctrace_thresh
= -1;
1077 char *ret
= check_consistency ();
1080 synctrace_enabled
= 0;
1085 if (strcmp (val
, "off") == 0)
1087 synctrace_enabled
= 0;
1091 if (strcmp (val
, "all") == 0)
1093 /* set to record all events */
1094 synctrace_thresh
= 0;
1095 synctrace_enabled
= 1;
1096 char *ret
= check_consistency ();
1100 synctrace_enabled
= 0;
1105 /* the remaining string should be a number >= 0 */
1106 char *endchar
= NULL
;
1107 int tval
= (int) strtol (val
, &endchar
, 0);
1108 if (*endchar
!= 0 || tval
< 0)
1111 return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string
);
1114 synctrace_thresh
= tval
;
1115 synctrace_enabled
= 1;
1120 Coll_Ctrl::set_heaptrace (const char *string
)
1123 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1124 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
1126 heaptrace_enabled
= 1;
1127 char *ret
= check_consistency ();
1130 heaptrace_enabled
= 0;
1135 if (strcmp (string
, "off") == 0)
1137 heaptrace_enabled
= 0;
1141 if (strcmp (string
, "check") == 0)
1143 /* set to check for over/underruns */
1144 heaptrace_checkenabled
= 1;
1145 heaptrace_enabled
= 1;
1148 if (strcmp (string
, "clear") == 0)
1150 /* set to check for over/underruns, and store patterns */
1151 heaptrace_checkenabled
= 2;
1152 heaptrace_enabled
= 1;
1156 return dbe_sprintf (GTXT ("Unrecognized heap tracing parameter `%s'\n"), string
);
1160 Coll_Ctrl::set_iotrace (const char *string
)
1163 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1164 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
1166 iotrace_enabled
= 1;
1167 char *ret
= check_consistency ();
1170 iotrace_enabled
= 0;
1175 if (strcmp (string
, "off") == 0)
1177 iotrace_enabled
= 0;
1180 return dbe_sprintf (GTXT ("Unrecognized I/O tracing parameter `%s'\n"), string
);
1184 Coll_Ctrl::set_count (const char *string
)
1188 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1189 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "off") == 0)
1194 if (strcmp (string
, "on") == 0)
1197 char *cret
= check_consistency ();
1205 if (strcmp (string
, "static") == 0)
1208 char *cret
= check_consistency ();
1218 if (count_enabled
!= 0)
1220 /* ensure that sample period is 0, if set by default */
1221 if (sample_default
== 1)
1223 /* ensure that clock profiling is off, if set by default */
1224 if (clkprof_default
== 1)
1226 clkprof_default
= 0;
1227 clkprof_enabled
= 0;
1229 if (hwcprof_default
== 1)
1230 hwcprof_default
= 0;
1234 return dbe_sprintf (GTXT ("Unrecognized count parameter `%s'\n"), string
);
1238 Coll_Ctrl::set_time_run (const char *valarg
)
1241 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1242 if (valarg
== NULL
) /* invalid setting */
1243 return strdup (GTXT ("time parameter can not be NULL\n"));
1244 /* the string should be a number >= 0 */
1245 int prev_start_delay
= start_delay
;
1246 int prev_time_run
= time_run
;
1247 const char *endchar
= valarg
;
1248 char *newchar
= NULL
;
1250 if (*endchar
!= '-')
1252 val
= (int) strtol (endchar
, &newchar
, 0);
1255 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1256 if (*endchar
== 'm')
1258 val
= val
* 60; /* convert to seconds */
1261 else if (*endchar
== 's') /* no conversion needed */
1268 else if (*endchar
!= '-')
1269 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1271 /* a second number is provided */
1274 val
= (int) strtol (endchar
, &newchar
, 0);
1278 start_delay
= prev_start_delay
;
1279 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1281 if (*endchar
== 'm')
1283 val
= val
* 60; /* convert to seconds */
1286 else if (*endchar
== 's') /* no conversion needed */
1290 start_delay
= prev_start_delay
;
1291 return dbe_sprintf (GTXT ("Unrecognized time parameter `%s'\n"), valarg
);
1294 if (time_run
!= 0 && start_delay
>= time_run
)
1296 start_delay
= prev_start_delay
;
1297 return dbe_sprintf (GTXT ("Invalid time parameter `%s': start time must be earlier than end time\n"), valarg
);
1299 char *ret
= check_consistency ();
1302 start_delay
= prev_start_delay
;
1303 time_run
= prev_time_run
;
1310 Coll_Ctrl::set_attach_pid (char *valarg
)
1313 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1315 return strdup (GTXT ("Specified PID can not be NULL\n"));
1317 /* the string should be a number corresponding to an active process' pid */
1318 char *endchar
= NULL
;
1319 int val
= (int) strtol (valarg
, &endchar
, 0);
1320 if (*endchar
!= 0 || val
< 0)
1321 return dbe_sprintf (GTXT ("Invalid process pid `%s'\n"), valarg
);
1322 int prev_attach_pid
= attach_pid
;
1324 char *ret
= check_consistency ();
1327 attach_pid
= prev_attach_pid
;
1334 Coll_Ctrl::free_hwc_fields (Hwcentry
* tmpctr
)
1336 if (tmpctr
->name
!= NULL
)
1337 free (tmpctr
->name
);
1338 if (tmpctr
->int_name
!= NULL
)
1339 free (tmpctr
->int_name
);
1340 memset (tmpctr
, 0, sizeof (Hwcentry
));
1341 tmpctr
->reg_num
= -1;
1345 Coll_Ctrl::hwcentry_dup (Hwcentry
*hnew
, Hwcentry
*_hwc
)
1348 if (_hwc
->name
!= NULL
)
1349 hnew
->name
= strdup (_hwc
->name
);
1352 if (_hwc
->int_name
!= NULL
)
1353 hnew
->int_name
= strdup (_hwc
->int_name
);
1355 hnew
->int_name
= NULL
;
1356 if (_hwc
->metric
!= NULL
)
1357 hnew
->metric
= strdup (_hwc
->metric
);
1359 hnew
->metric
= NULL
;
1360 if (_hwc
->short_desc
!= NULL
)
1361 hnew
->short_desc
= strdup (_hwc
->short_desc
);
1363 hnew
->short_desc
= NULL
;
1364 if (_hwc
->reg_list
!= NULL
)
1366 hnew
->reg_list
= (regno_t
*) malloc (sizeof (regno_t
*) * MAX_PICS
);
1367 // poor way of dealing with malloc failure
1370 for (int i
= 0; i
< MAX_PICS
; i
++)
1372 hnew
->reg_list
[i
] = _hwc
->reg_list
[i
];
1373 if (hnew
->reg_list
[i
] == REGNO_ANY
)
1380 // Routine to initialize the HWC tables, set up the default experiment, etc.
1382 Coll_Ctrl::setup_hwc ()
1384 static bool is_hwc_setup
= false;
1385 if (is_hwc_setup
== true)
1387 // try to set the default counters
1388 is_hwc_setup
= true;
1393 Coll_Ctrl::clkprof_timer_2_hwcentry_min_time (int target_clkprof_usec
)
1395 hrtime_t hwc_nanosec
;
1396 if (target_clkprof_usec
== clk_params
.normval
)
1397 hwc_nanosec
= HWCTIME_ON
;
1398 else if (target_clkprof_usec
== clk_params
.lowval
)
1399 hwc_nanosec
= HWCTIME_LO
;
1400 else if (target_clkprof_usec
== clk_params
.hival
)
1401 hwc_nanosec
= HWCTIME_HI
;
1403 hwc_nanosec
= 1000LL * target_clkprof_usec
; // nanoseconds
1408 Coll_Ctrl::set_clkprof_timer_target (int microseconds
)
1410 clkprof_timer
= microseconds
;
1411 clkprof_timer_target
= microseconds
;
1412 hrtime_t hwc_min_time_nanosec
= clkprof_timer_2_hwcentry_min_time (microseconds
);
1413 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1415 hwctr
[ii
].min_time_default
= hwc_min_time_nanosec
;
1416 hwc_update_val (&hwctr
[ii
]);
1421 Coll_Ctrl::adjust_clkprof_timer (int use
)
1423 clkprof_timer
= use
;
1426 /* set HWC counter set from a string */
1427 char * /* return an error string */
1428 Coll_Ctrl::set_hwcstring (const char *string
, char **warnmsg
)
1431 if (string
== NULL
|| strcmp (string
, "off") == 0)
1433 hwcprof_enabled_cnt
= 0;
1437 int old_cnt
= hwcprof_enabled_cnt
;
1438 int old_hwcprof_default
= hwcprof_default
;
1440 /* reset any previous count to zero */
1441 hwcprof_enabled_cnt
= 0;
1442 char *ret
= add_hwcstring (string
, warnmsg
);
1445 // restore previous setting
1446 hwcprof_enabled_cnt
= old_cnt
;
1447 hwcprof_default
= old_hwcprof_default
;
1452 /* add additional HWC counters to counter set from string */
1453 char * /* return an error string */
1454 Coll_Ctrl::add_hwcstring (const char *string
, char **warnmsg
)
1457 if (string
== NULL
|| strcmp (string
, "off") == 0)
1459 hwcprof_enabled_cnt
= 0;
1464 int old_cnt
= hwcprof_enabled_cnt
;
1465 int prev_cnt
= hwcprof_enabled_cnt
;
1466 // int old_hwcprof_default = hwcprof_default;
1467 char UEbuf
[MAXPATHLEN
* 5];
1469 Hwcentry tmpctr
[MAX_PICS
];
1470 Hwcentry
* ctrtable
[MAX_PICS
];
1474 UEsz
= sizeof (UEbuf
);
1476 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1477 if (hwcprof_default
== 0)
1479 /* Copy the counters already defined */
1480 for (int ii
= 0; ii
< prev_cnt
; ii
++)
1481 tmpctr
[ii
] = hwctr
[ii
];
1483 else /* the previously-defined counters were defaulted; don't copy them */
1486 /* look up the CPU version */
1487 cpc_cpuver
= hwc_get_cpc_cpuver ();
1488 if (string
&& *string
)
1490 /* lookup counters */
1491 /* set up a pointer array */
1492 for (unsigned ii
= 0; ii
< MAX_PICS
; ii
++)
1493 ctrtable
[ii
] = &tmpctr
[ii
];
1494 hrtime_t global_min_time
= clkprof_timer_2_hwcentry_min_time (clkprof_timer_target
);
1495 rc
= hwc_lookup (kernelHWC
, global_min_time
, string
, &ctrtable
[prev_cnt
], MAX_PICS
- prev_cnt
, &emsg
, &wmsg
);
1500 /* set count for sum of old and new counters */
1504 /* even though the actual hwctr[] array is not updated, we can check consistency */
1505 char *ret
= check_consistency ();
1508 hwcprof_enabled_cnt
= old_cnt
;
1512 /* finally, validate the full counter set */
1513 emsg
= hwc_validate_ctrs (kernelHWC
, ctrtable
, rc
);
1516 hwcprof_enabled_cnt
= old_cnt
;
1520 /* success, update real counters and the string for them */
1521 /* turn off the default */
1522 hwcprof_default
= 0;
1523 hwcprof_enabled_cnt
= rc
;
1525 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1527 /* shallow copy of new counters */
1528 hwctr
[ii
] = tmpctr
[ii
];
1529 char *rateString
= hwc_rate_string (&hwctr
[ii
], 0);
1530 snprintf (UEbuf
+ strlen (UEbuf
), UEsz
- strlen (UEbuf
),
1531 NTXT (",%s,%s"), hwctr
[ii
].name
,
1532 rateString
? rateString
: "");
1535 /* now duplicate that string, skipping the leading comma */
1536 hwc_string
= strdup (&UEbuf
[1]);
1540 /* add default HWC counters to counter set with resolution (on, hi, or lo) */
1541 /* Note that the resultion will also be used to set the clock-profiling default */
1542 char * /* return an error string */
1543 Coll_Ctrl::add_default_hwcstring (const char *resolution
, char **warnmsg
, bool add
, bool forKernel
)
1547 char *def_string
= hwc_get_default_cntrs2 (forKernel
, 1);
1548 if (def_string
== NULL
)
1550 /* no string defined, format and return an error message */
1552 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1553 return dbe_sprintf (GTXT ("No default HW counter set is defined for %s\n"), cpuname
);
1555 int len
= strlen (def_string
);
1558 /* string zero-length, meaning default counters can't be used */
1560 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1561 return dbe_sprintf (GTXT ("HW counter set for %s cannot be loaded on this system\n"), cpuname
);
1563 /* allocate return string */
1564 int retsize
= 2 * len
+ 10;
1565 char *ret
= (char *) malloc (retsize
);
1567 return strdup (GTXT ("internal error formating HW counter set; malloc failed\n"));
1570 char *stringp
= def_string
;
1572 char *hwc_defaultx
= strdup (def_string
);
1574 /* now massage the string in order to insert resolution for each counter */
1577 /* find the next comma */
1583 nextp
= stringp
+ 1;
1585 if ((next
= strchr (nextp
, (int) ',')) != NULL
)
1589 /* next counter is zero-length -- invalid string */
1591 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1593 ret
= dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname
, hwc_defaultx
);
1594 free (hwc_defaultx
);
1597 /* another field found */
1599 char nextc
= *(next
+ 1);
1600 if ((nextc
== 0) || (nextc
== ','))
1602 /* either ,, between fields, or string ends in comma */
1603 /* append the string */
1604 strncat (retp
, stringp
, (retsize
- strlen (retp
) - 1));
1605 strncat (retp
, ",", (retsize
- strlen (retp
) - 1));
1606 strncat (retp
, resolution
, (retsize
- strlen (retp
) - 1));
1607 if (nextc
== 0) /* string ended in comma; we're done */
1612 /* string had only one comma between counter names; that's not valid */
1614 hwc_get_cpuname (cpuname
, sizeof (cpuname
));
1616 ret
= dbe_sprintf (GTXT ("HW counter set for %s, \"%s\", format error\n"), cpuname
, hwc_defaultx
);
1617 free (hwc_defaultx
);
1620 /* string had ,, between fields; move to next field */
1622 if (* (stringp
+ 1) == 0) /* name ended in ,, -- we're done */
1628 /* no comma found, add the last counter and the comma and resolution */
1629 strncat (retp
, stringp
, (retsize
- strlen (retp
) - 1));
1630 strncat (retp
, ",", (retsize
- strlen (retp
) - 1));
1631 strncat (retp
, resolution
, (retsize
- strlen (retp
) - 1));
1636 /* we have now formatted the new string, with resolution inserted */
1639 ccret
= add_hwcstring (ret
, warnmsg
);
1641 ccret
= set_hwcstring (ret
, warnmsg
);
1642 free (hwc_defaultx
);
1645 /* now set the clock-profiling timer, if on by default */
1646 if (clkprof_default
== 1)
1648 if (strcmp (resolution
, NTXT ("on")) == 0)
1649 set_clkprof_timer_target (clk_params
.normval
);
1650 else if (strcmp (resolution
, NTXT ("lo")) == 0)
1651 set_clkprof_timer_target (clk_params
.lowval
);
1652 else if (strcmp (resolution
, NTXT ("hi")) == 0)
1653 set_clkprof_timer_target (clk_params
.hival
);
1659 Coll_Ctrl::set_hwcdefault ()
1661 char *string
= hwc_get_default_cntrs2 (kernelHWC
, 1);
1664 if (strlen (string
) == 0)
1665 hwcprof_default
= 0;
1668 char * warnmsg
= NULL
;
1669 char *ccret
= add_hwcstring (string
, &warnmsg
);
1673 /* set string to zero-length so that it won't be used again */
1674 hwc_set_default_cntrs (kernelHWC
, NTXT (""));
1676 hwcprof_default
= 0;
1679 hwcprof_default
= 1;
1684 hwcprof_default
= 0;
1688 Coll_Ctrl::disable_hwc ()
1690 hwcprof_enabled_cnt
= 0;
1691 hwcprof_default
= 0;
1697 Coll_Ctrl::set_sample_period (const char *string
)
1701 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1702 if (string
== NULL
|| strcmp (string
, "on") == 0)
1704 else if (strcmp (string
, "off") == 0)
1708 /* string should be a number > 0 */
1709 char *endchar
= NULL
;
1710 val
= (int) strtol (string
, &endchar
, 0);
1711 if (*endchar
!= 0 || val
<= 0)
1712 return dbe_sprintf (GTXT ("Unrecognized sample period `%s'\n"), string
);
1714 /* set that value */
1715 int prev_sample_period
= sample_period
;
1716 sample_period
= val
;
1717 char *ret
= check_consistency ();
1720 sample_period
= prev_sample_period
;
1728 Coll_Ctrl::set_size_limit (const char *string
)
1731 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1732 if (string
== NULL
|| strlen (string
) == 0
1733 || strcmp (string
, "unlimited") == 0 || strcmp (string
, "none") == 0)
1738 /* string should be a number >0; 0 is an error */
1739 char *endchar
= NULL
;
1740 int val
= (int) strtol (string
, &endchar
, 0);
1741 if (*endchar
!= 0 || val
<= 0)
1742 return dbe_sprintf (GTXT ("Unrecognized size limit `%s'\n"), string
);
1748 Coll_Ctrl::build_data_desc ()
1752 // Put sample sig before clock profiling. Dbx uses PROF
1753 // for that purpose and we want it to be processed first.
1755 sb
.appendf ("P:%s;", project_home
);
1756 if (sample_sig
!= 0)
1757 sb
.appendf ("g:%d;", sample_sig
);
1758 if (pauseresume_sig
!= 0)
1759 sb
.appendf ("d:%d%s;", pauseresume_sig
, pauseresume_pause
== 1 ? "p" : "");
1760 if (clkprof_enabled
== 1)
1761 sb
.appendf ("p:%d;", clkprof_timer
);
1762 if (synctrace_enabled
== 1)
1763 sb
.appendf ("s:%d,%d;", synctrace_thresh
, synctrace_scope
);
1764 if (heaptrace_enabled
== 1)
1765 sb
.appendf ("H:%d;", heaptrace_checkenabled
);
1766 if (iotrace_enabled
== 1)
1768 if (hwcprof_enabled_cnt
> 0)
1770 sb
.appendf ("h:%s", (hwcprof_default
== true) ? "*" : "");
1771 for (int ii
= 0; ii
< hwcprof_enabled_cnt
; ii
++)
1773 Hwcentry
*h
= hwctr
+ ii
;
1774 hrtime_t min_time
= h
->min_time
;
1775 if (min_time
== HWCTIME_TBD
)
1776 // user did not specify any value for overflow rate
1777 min_time
= h
->min_time_default
;
1780 sb
.appendf ("%d:%d:%lld:%s:%s:%lld:%d:m%lld:%d:%d:0x%x",
1781 h
->use_perf_event_type
, h
->type
, (long long) h
->config
,
1782 strcmp (h
->name
, h
->int_name
) ? h
->name
: "",
1783 h
->int_name
, (long long) h
->reg_num
, h
->val
,
1784 (long long) min_time
, ii
, /*tag*/ h
->timecvt
, h
->memop
);
1788 if (time_run
!= 0 || start_delay
!= 0)
1790 if (start_delay
!= 0)
1791 sb
.appendf ("t:%d:%d;", start_delay
, time_run
);
1793 sb
.appendf ("t:%d;", time_run
);
1795 if (sample_period
!= 0)
1796 sb
.appendf ("S:%d;", sample_period
);
1797 if (size_limit
!= 0)
1798 sb
.appendf ("L:%d;", size_limit
);
1800 sb
.appendf ("j:%d;", (int) java_mode
);
1801 if (follow_mode
!= FOLLOW_NONE
)
1802 sb
.appendf ("F:%d;", (int) follow_mode
);
1803 sb
.appendf ("a:%s;", archive_mode
);
1805 data_desc
= sb
.toString ();
1809 Coll_Ctrl::check_group ()
1811 char group_file
[MAXPATHLEN
];
1812 if (expt_group
== NULL
)
1814 // Is the group an relative path, with a store directory set?
1815 if ((expt_group
[0] == '/') || ((udir_name
== NULL
) || (udir_name
[0] == '0')))
1816 snprintf (group_file
, sizeof (group_file
), "%s", expt_group
);
1817 else // relative path, store directory; make group_file in that directory
1818 snprintf (group_file
, sizeof (group_file
), "%s/%s", udir_name
, expt_group
);
1819 // See if we can write the group file
1820 int ret
= access (group_file
, W_OK
);
1823 if (errno
== ENOENT
)
1825 char *stmp
= group_file
;
1826 char *dir
= dirname (stmp
);
1827 ret
= access (dir
, W_OK
);
1828 if (ret
!= 0) // group file does not exist;
1829 return dbe_sprintf (GTXT ("Directory (%s) for group file %s is not writeable: %s\n"),
1830 dir
, group_file
, strerror (errno
));
1833 return dbe_sprintf (GTXT ("Group file %s is not writeable: %s\n"),
1834 group_file
, strerror (errno
));
1840 Coll_Ctrl::join_group ()
1845 char group_file
[MAXPATHLEN
];
1846 struct stat statbuf
;
1847 struct flock flockbuf
;
1848 flockbuf
.l_type
= F_WRLCK
;
1849 flockbuf
.l_whence
= SEEK_SET
;
1850 flockbuf
.l_start
= 0;
1852 if (expt_group
== NULL
)
1854 // Is the group an relative path, with a store directory set?
1855 if (expt_group
[0] == '/' || udir_name
== NULL
|| udir_name
[0] == '0')
1856 snprintf (group_file
, sizeof (group_file
), "%s", expt_group
);
1857 else // relative path, store directory; make group_file in that directory
1858 snprintf (group_file
, sizeof (group_file
), "%s/%s", udir_name
, expt_group
);
1862 // try to open the group file
1863 while ((groupfd
= open (group_file
, O_RDWR
)) >= 0)
1865 if (uinterrupt
== 1)
1868 return strdup (GTXT ("user interrupt\n"));
1870 // it's opened, now lock it
1871 if (fcntl (groupfd
, F_SETLK
, &flockbuf
) != -1)
1873 // we got the lock; check the file size
1874 if (fstat (groupfd
, &statbuf
) != 0)
1876 // can't stat the file -- give up
1878 return dbe_sprintf (GTXT ("Can't fstat group file %s\n"), group_file
);
1880 if (statbuf
.st_size
== 0)
1882 // size is zero: we got the lock just as someone
1883 // else created the group file
1884 // close the file and release the lock; try again
1890 // size is non-zero, add our record
1891 file
= fdopen (groupfd
, "a");
1895 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file
);
1897 if (fprintf (file
, "%s\n", store_ptr
) <= 0)
1900 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file
);
1902 // close the file, releasing our lock
1909 // can't get the lock, close the file and try again
1911 if (uinterrupt
== 1)
1912 return strdup (GTXT ("user interrupt\n"));
1914 return dbe_sprintf (GTXT ("Timed out: waiting for group file %s\n"), group_file
);
1916 if (tries
% 500 == 0)
1917 USR_WARN (GTXT ("Waiting for group file %s . . ."), group_file
);
1923 // If the error was not that the file did not exist, report it
1924 if (errno
!= ENOENT
)
1925 return dbe_sprintf (GTXT ("Can't open group file %s: %s\n"),
1926 group_file
, strerror (errno
));
1927 // the file did not exist, try to create it
1928 groupfd
= open (group_file
, O_CREAT
| O_EXCL
| O_RDWR
, 0666);
1931 // we could not create the file
1932 if (errno
== EEXIST
)
1934 return dbe_sprintf (GTXT ("Can't create group file %s: %s\n"),
1935 group_file
, strerror (errno
));
1937 // we created the group file, now lock it, waiting for the lock
1938 while (fcntl (groupfd
, F_SETLKW
, &flockbuf
) == -1)
1940 // we created the file, but couldn't lock it
1942 return dbe_sprintf (GTXT ("Unable to lock group file %s\n"), group_file
);
1944 // we created and locked the file, write to it
1945 file
= fdopen (groupfd
, "a");
1949 return dbe_sprintf (GTXT ("Can't access group file %s\n"), group_file
);
1951 // write the header line
1952 if (fprintf (file
, "%s\n", SP_GROUP_HEADER
) <= 0)
1955 return dbe_sprintf (GTXT ("Can't initialize group file %s\n"), group_file
);
1957 if (fprintf (file
, "%s\n", store_ptr
) <= 0)
1960 return dbe_sprintf (GTXT ("Can't update group file %s\n"), group_file
);
1962 // finally, close the file, releasing the lock
1970 Coll_Ctrl::set_directory (char *dir
, char **warn
)
1972 struct stat statbuf
;
1975 return strdup (GTXT ("Experiment is active; command ignored.\n"));
1976 if (stat (dir
, &statbuf
) != 0)
1977 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"),
1978 dir
, strerror (errno
));
1979 if (!S_ISDIR (statbuf
.st_mode
))
1980 return dbe_sprintf (GTXT ("Can't set directory `%s': %s\n"),
1981 dir
, strerror (ENOTDIR
));
1983 udir_name
= strdup (dir
);
1985 // Process new setting
1986 *warn
= preprocess_names ();
1987 if ((uexpt_name
!= NULL
) || (interactive
!= 0))
1989 char *ret
= update_expt_name (true, true);
1994 char *msg
= dbe_sprintf ("%s%s", *warn
, ret
);
2004 (void) update_expt_name (false, false);
2005 return NULL
; // All is OK
2009 Coll_Ctrl::set_target (char* targetname
)
2013 if (targetname
!= NULL
)
2014 target_name
= strdup (targetname
);
2019 Coll_Ctrl::set_default_stem (const char* stem
)
2021 default_stem
= strdup (stem
);
2022 preprocess_names ();
2023 (void) update_expt_name (false, false); // no warnings
2027 Coll_Ctrl::set_expt (const char *ename
, char **warn
, bool overwriteExp
)
2036 char *exptname
= canonical_path(strdup(ename
));
2037 size_t i
= strlen (exptname
);
2038 if (i
< 4 || strcmp (&exptname
[i
- 3], ".er") != 0)
2041 return dbe_sprintf (GTXT ("Experiment name `%s' must end in `.er'\n"),
2046 uexpt_name
= exptname
;
2047 preprocess_names ();
2048 char *err
= update_expt_name (true, true, overwriteExp
);
2053 char *nm
= dbe_sprintf ("%s/%s", store_dir
, base_name
);
2054 struct stat statbuf
;
2055 char *cmd
= dbe_sprintf ("/bin/rm -rf %s >/dev/null 2>&1", nm
);
2058 if (stat (nm
, &statbuf
) == 0)
2059 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm
);
2060 if (errno
!= ENOENT
)
2061 return dbe_sprintf (GTXT ("Cannot remove experiment `%s'\n"), nm
);
2064 *warn
= update_expt_name (true, false);
2069 Coll_Ctrl::set_group (char *groupname
)
2072 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2073 if (expt_group
!= NULL
)
2078 if (groupname
== NULL
)
2081 preprocess_names ();
2082 (void) update_expt_name (true, false);
2085 int i
= (int) strlen (groupname
);
2086 if (i
< 5 || strcmp (&groupname
[i
- 4], ".erg") != 0)
2087 return dbe_sprintf (GTXT ("Experiment group name `%s'must end in `.erg'\n"), groupname
);
2088 expt_group
= strdup (groupname
);
2089 preprocess_names ();
2090 (void) update_expt_name (true, false);
2095 Coll_Ctrl::set_java_mode (const char *string
)
2097 struct stat statbuf
;
2099 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2100 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
2102 #if defined(GPROFNG_JAVA_PROFILING)
2103 int prev_java_mode
= java_mode
;
2104 int prev_java_default
= java_default
;
2107 char *ret
= check_consistency ();
2110 java_mode
= prev_java_mode
;
2111 java_default
= prev_java_default
;
2116 return strdup (GTXT ("gprofng was built without support for profiling Java applications\n"));
2119 if (strcmp (string
, "off") == 0)
2121 int prev_java_mode
= java_mode
;
2122 int prev_java_default
= java_default
;
2125 char *ret
= check_consistency ();
2128 java_mode
= prev_java_mode
;
2129 java_default
= prev_java_default
;
2136 /* any other value should be a path to Java installation directory */
2137 if (stat (string
, &statbuf
) == 0)
2139 if ((statbuf
.st_mode
& S_IFMT
) == S_IFDIR
)
2141 // it's a directory -- set the Java path to it
2142 int prev_java_mode
= java_mode
;
2143 int prev_java_default
= java_default
;
2146 char *ret
= check_consistency ();
2149 java_mode
= prev_java_mode
;
2150 java_default
= prev_java_default
;
2153 return set_java_path (string
);
2156 return dbe_sprintf (GTXT ("Java-profiling parameter is neither \"on\", nor \"off\", nor is it a directory: `%s'\n"), string
);
2160 Coll_Ctrl::set_java_path (const char *string
)
2163 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2165 java_path
= strdup (string
);
2170 Coll_Ctrl::set_java_args (char *string
)
2174 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2175 char *prev_java_args
= java_args
;
2176 if (string
== NULL
|| strlen (string
) == 0)
2177 java_args
= strdup ("");
2179 java_args
= strdup (string
);
2180 // now count the number of Java arguments
2181 for (next
= java_args
; *next
; next
++)
2183 if (*next
== ' ' || *next
== '\t')
2186 for (++next
; *next
; next
++)
2187 if (*next
== ' ' || *next
== '\t')
2192 if (njava_args
== 0)
2194 char *ret
= check_consistency ();
2197 java_args
= prev_java_args
;
2200 free (prev_java_args
);
2205 Coll_Ctrl::set_follow_mode (const char *string
)
2208 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2209 free (follow_spec_usr
);
2210 free (follow_spec_cmp
);
2211 follow_spec_usr
= NULL
;
2212 follow_spec_cmp
= NULL
;
2213 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "all") == 0
2214 || strcmp (string
, "on") == 0)
2216 follow_mode
= FOLLOW_ON
;
2220 if (strcmp (string
, "off") == 0)
2222 follow_mode
= FOLLOW_NONE
;
2227 /* compile regular expression if string starts with "=" */
2228 if (string
[0] == '=' && string
[1] != 0)
2230 // user has specified a string matching specification
2233 const char *userspec
= &string
[1];
2234 size_t newstrlen
= strlen (userspec
) + 3;
2235 char * str
= (char *) malloc (newstrlen
);
2238 snprintf (str
, newstrlen
, "^%s$", userspec
);
2239 assert (strlen (str
) == newstrlen
- 1);
2240 ercode
= regcomp (®ex_desc
, str
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
);
2246 follow_spec_usr
= strdup (string
);
2247 /* Ideally, follow_spec_cmp = [serialized regex_desc], */
2248 /* so that libcollector wouldn't have to recompile it. */
2249 /* For now, just copy the regular expression into follow_spec_cmp */
2250 follow_spec_cmp
= str
;
2251 follow_mode
= FOLLOW_ALL
;
2255 // syntax error in parsing string
2258 regerror (ercode
, ®ex_desc
, errbuf
, sizeof (errbuf
));
2259 fprintf (stderr
, "Coll_Ctrl::set_follow_mode: regerror()=%s\n", errbuf
);
2263 return dbe_sprintf (GTXT ("Unrecognized follow-mode parameter `%s'\n"), string
);
2267 Coll_Ctrl::set_prof_idle (const char *string
)
2270 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2271 if (string
== NULL
|| strlen (string
) == 0 || strcmp (string
, "on") == 0)
2276 if (strcmp (string
, "off") == 0)
2281 return dbe_sprintf (GTXT ("Unrecognized profiling idle cpus parameter `%s'\n"), string
);
2285 Coll_Ctrl::set_archive_mode (const char *string
)
2288 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2289 if (string
== NULL
|| strlen (string
) == 0)
2291 if (strcasecmp (string
, "on") == 0 || strcasecmp (string
, "off") == 0
2292 || strcasecmp (string
, "ldobjects") == 0
2293 || strcasecmp (string
, "usedldobjects") == 0
2294 || strcasecmp (string
, "src") == 0 || strcasecmp (string
, "usedsrc") == 0
2295 || strcasecmp (string
, "all") == 0)
2297 free (archive_mode
);
2298 archive_mode
= strdup (string
);
2301 return dbe_sprintf (GTXT ("Unrecognized archive-mode parameter `%s'\n"), string
);
2305 Coll_Ctrl::set_sample_signal (int value
)
2309 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2315 if (value
== pauseresume_sig
)
2316 return report_signal_conflict (value
);
2317 if ((buf
= strsignal (value
)) != NULL
)
2320 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), value
);
2324 /* find a signal by name */
2326 Coll_Ctrl::find_sig (const char *string
)
2329 char *signame_alloc
= NULL
;
2330 const char *signame
;
2332 if (strcmp (string
, "off") == 0)
2334 // see if the name begins with SIG
2335 if (strncmp (string
, "SIG", 3) != 0)
2338 signame_alloc
= (char *) malloc (strlen (string
) + 3 + 1);
2339 if (signame_alloc
== NULL
)
2341 strcpy (signame_alloc
, "SIG");
2342 strcpy (&signame_alloc
[3], string
);
2343 signame
= signame_alloc
;
2348 /* see if the string is a number */
2349 char *endchar
= NULL
;
2350 val
= (int) strtol (signame
, &endchar
, 0);
2352 val
= strtosigno (signame
);
2353 free (signame_alloc
);
2360 Coll_Ctrl::set_pauseresume_signal (int value
, int resume
)
2363 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2366 pauseresume_sig
= 0;
2369 if (value
== sample_sig
)
2370 return report_signal_conflict (value
);
2371 if (strsignal (value
) != NULL
)
2373 pauseresume_sig
= value
;
2374 pauseresume_pause
= resume
;
2377 return dbe_sprintf (GTXT ("Invalid pause-resume (delayed initialization) signal %d\n"), value
);
2382 Coll_Ctrl::report_signal_conflict (int value
)
2384 const char *xbuf
= strsignal (value
);
2386 return dbe_sprintf (GTXT ("Signal %s (%d) can not be used for both sample and pause-resume (delayed initialization)\n"),
2388 return dbe_sprintf (GTXT ("Signal %d can not be used for both sample and pause-resume (delayed initialization)\n"),
2393 Coll_Ctrl::set_debug_mode (int value
)
2396 return strdup (GTXT ("Experiment is active; command ignored.\n"));
2402 Coll_Ctrl::create_exp_dir ()
2404 int max
= 4095; // 0xFFF - can be increased if it seems too low
2405 for (int i
= 0; i
< max
; i
++)
2407 if (mkdir (store_ptr
,
2408 S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
) != 0)
2412 return dbe_sprintf (GTXT ("Store directory %s is not writeable: %s\n"),
2413 store_dir
, strerror (err
));
2414 if (i
+ 1 >= max
) // no more attempts
2415 return dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n%s: %d\n"),
2416 store_ptr
, strerror (err
),
2417 GTXT ("collect: Internal error: loop count achieved"),
2419 char *ermsg
= update_expt_name (false, false, true);
2422 char *msg
= dbe_sprintf (GTXT ("Unable to create directory `%s' -- %s\n"),
2429 return NULL
; // All is OK
2431 return dbe_sprintf (GTXT ("Unable to create directory `%s'\n"), store_ptr
);
2435 Coll_Ctrl::get_exp_name (const char *stembase
)
2438 return dbe_sprintf ("%s.%d.er", stembase
, expno
);
2442 Coll_Ctrl::preprocess_names ()
2444 char buf
[MAXPATHLEN
];
2445 char msgbuf
[MAXPATHLEN
];
2448 /* convert the experiment name and directory into store name/dir */
2449 /* free the old strings */
2450 if (store_dir
!= NULL
)
2455 if (expt_dir
!= NULL
)
2460 if (base_name
!= NULL
)
2465 if (expt_name
!= NULL
)
2471 if (uexpt_name
!= NULL
)
2472 expt_name
= strdup (uexpt_name
);
2475 // no user name -- pick a default
2479 if (expt_group
== NULL
)
2481 stem
= strdup (default_stem
);
2486 stem
= strdup (expt_group
);
2487 stem
[strlen (stem
) - 4] = 0;
2489 // now remove any leading directory
2490 for (int i
= 0;; i
++)
2495 stembase
= &stem
[i
+ 1];
2497 if (strlen (stembase
) == 0)
2500 stem
= strdup (default_stem
);
2504 c
= get_exp_name (stembase
);
2508 snprintf (buf
, sizeof (buf
), NTXT ("%s"), expt_name
);
2511 // it's a full path name
2512 if (udir_name
!= NULL
)
2514 snprintf (msgbuf
, sizeof (msgbuf
),
2515 GTXT ("Warning: Experiment name is an absolute path; directory name %s ignored.\n"),
2517 ret
= strdup (msgbuf
);
2521 // now extract the directory and basename
2523 for (int i
= 0;; i
++)
2530 expt_dir
= strdup (buf
);
2532 base_name
= strdup (&buf
[lastslash
+ 1]);
2534 base_name
= strdup (buf
);
2535 expt_dir
[lastslash
] = 0;
2536 if (expt_dir
[0] == '/')
2537 store_dir
= strdup (expt_dir
);
2538 else if ((udir_name
== NULL
) || (udir_name
[0] == 0))
2540 if (expt_dir
[0] == 0)
2541 store_dir
= strdup (".");
2543 store_dir
= strdup (expt_dir
);
2547 /* udir_name is a non-empty string */
2548 if (expt_dir
[0] == 0)
2549 store_dir
= strdup (udir_name
);
2552 snprintf (buf
, sizeof (buf
), "%s/%s", udir_name
, expt_dir
);
2553 store_dir
= strdup (buf
);
2557 if (strcmp (store_dir
, ".") == 0)
2558 store_ptr
= strdup (base_name
);
2561 snprintf (buf
, sizeof (buf
), "%s/%s", store_dir
, base_name
);
2562 store_ptr
= strdup (buf
);
2565 // determine the file system type
2566 if (strcmp (store_dir
, prev_store_dir
) != 0)
2568 free (prev_store_dir
);
2569 prev_store_dir
= strdup (store_dir
);
2570 const char *fstype
= get_fstype (store_dir
);
2571 if (interactive
&& enabled
&& (fstype
!= NULL
) && (nofswarn
== 0))
2573 snprintf (msgbuf
, sizeof (msgbuf
),
2574 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"),
2575 (ret
== NULL
? "" : ret
), fstype
);
2577 ret
= strdup (msgbuf
);
2584 Coll_Ctrl::update_expt_name (bool chgmsg
, bool chkonly
, bool newname
)
2587 struct stat statbuf
;
2588 // make sure the name ends in .er
2589 // set count to the length of the name
2590 int count
= (int) strlen (base_name
);
2592 // this should have been checked already, so we can abort
2593 if (count
< 4 || strcmp (&base_name
[count
- 3], ".er") != 0)
2595 int pcount
= count
- 4;
2597 { // check if old name can be used
2598 char fullname
[MAXPATHLEN
];
2599 snprintf (fullname
, sizeof (fullname
), "%s/%s", store_dir
, base_name
);
2600 if (stat (fullname
, &statbuf
) != 0)
2601 if (errno
== ENOENT
) // name does not exist, we can use it
2607 // current name will not work, update the name
2609 struct dirent
*dir_entry
;
2611 // see if there's a numeric field in front of the .er of the name
2613 while (isdigit ((int) (base_name
[pcount
])) != 0)
2616 if (pcount
== 0) // name is of the form 12345.er; don't update it
2617 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2621 if (digits
== 0) // name is of form xyz.er (or xyz..er); don't update it
2622 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2624 if (base_name
[pcount
] != '.') // name is of form xyz123.er; don't update it
2625 return dbe_sprintf (GTXT ("name %s is in use and cannot be updated\n"),
2630 // save the name for a changed message
2631 char *oldbase
= strdup (base_name
);
2633 // the name is of the from prefix.nnn.er; extract the value of nnn
2634 int version
= atoi (&base_name
[pcount
+ 1]);
2635 if (newname
) // do not try to use old name
2637 int max_version
= version
- 1;
2639 // terminate the base_name string after that . yielding "prefix."
2640 base_name
[pcount
+ 1] = 0;
2641 if ((dir
= opendir (store_dir
)) == NULL
)
2643 // ignore error -- we'll hit it again later
2648 // find the maximum version in the directory
2649 // count is the number of characters before the number
2651 while ((dir_entry
= readdir (dir
)) != NULL
)
2653 count
= (int) strlen (dir_entry
->d_name
);
2654 if ((count
< 4) || (strcmp (&dir_entry
->d_name
[count
- 3], ".er") != 0))
2656 // check that the name is of the form prefix.nnn.er; if not, skip it
2657 if (strncmp (base_name
, dir_entry
->d_name
, pcount
+ 1) == 0)
2659 // the "prefix." part matches, terminate the entry name before the .er
2660 dir_entry
->d_name
[count
- 3] = 0;
2662 int dversion
= (int) strtol (&dir_entry
->d_name
[pcount
+ 1], &lastchar
, 10);
2664 // if it did not end where the .er was, skip it
2667 if (dversion
> max_version
)
2668 max_version
= dversion
;
2672 // we now have the maximum version determined
2673 char newbase
[MAXPATHLEN
];
2674 base_name
[pcount
+ 1] = 0;
2675 version
= max_version
+ 1;
2676 snprintf (newbase
, sizeof (newbase
), "%s%d.er", base_name
, version
);
2677 if ((strcmp (oldbase
, newbase
) != 0) && chgmsg
)
2679 ret
= dbe_sprintf (GTXT ("name %s is in use; changed to %s\n"),
2686 base_name
= strdup (newbase
);
2688 // now, reset expt_name to reflect new setting
2690 if (expt_dir
[0] == 0)
2691 expt_name
= strdup (base_name
);
2693 expt_name
= dbe_sprintf ("%s/%s", expt_dir
, base_name
);
2695 if (strcmp (store_dir
, ".") == 0)
2696 store_ptr
= strdup (base_name
);
2698 store_ptr
= dbe_sprintf ("%s/%s", store_dir
, base_name
);
2704 Coll_Ctrl::remove_exp_dir ()
2706 if (store_ptr
== NULL
)
2715 Coll_Ctrl::determine_profile_params ()
2717 struct itimerval itimer
;
2718 struct itimerval otimer
;
2721 struct sigaction act
;
2722 struct sigaction old_handler
;
2723 memset (&act
, 0, sizeof (struct sigaction
));
2726 // set SIGPROF handler to SIG_IGN
2727 sigemptyset (&act
.sa_mask
);
2728 act
.sa_handler
= SIG_IGN
;
2729 act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
2730 if (sigaction (SIGPROF
, &act
, &old_handler
) == -1)
2732 /* couldn't set signal */
2733 fprintf (stderr
, GTXT ("Can't set SIGPROF: %s\n"), strerror (errno
));
2737 // set the timer to arbitrary resolution
2738 itimer
.it_interval
.tv_sec
= period
/ MICROSEC
;
2739 itimer
.it_interval
.tv_usec
= period
% MICROSEC
;
2740 itimer
.it_value
= itimer
.it_interval
;
2741 setitimer (ITIMER_REALPROF
, &itimer
, &otimer
);
2743 // now reset the timer to turn it off
2744 itimer
.it_value
.tv_sec
= 0;
2745 itimer
.it_value
.tv_usec
= 0;
2746 if (setitimer (ITIMER_REALPROF
, &itimer
, &otimer
) == -1) // call failed
2749 nperiod
= otimer
.it_interval
.tv_sec
* MICROSEC
+ otimer
.it_interval
.tv_usec
;
2751 // check the returned value: is the what we asked for?
2752 if (period
== nperiod
) // arbitrary precision is OK
2753 set_clk_params (PROFINT_MIN
, 1, PROFINT_MAX
, PROFINT_HIGH
, PROFINT_NORM
, PROFINT_LOW
);
2754 else if (nperiod
< 10000) // hi resolution allowed, but not arbitrary precision
2755 set_clk_params ((int) nperiod
, 1000, PROFINT_MAX
, 1000, 10000, 100000);
2756 else // low resolution only allowed
2757 set_clk_params (10000, 10000, PROFINT_MAX
, 1000, 10000, 100000);
2759 // If old handler was default, ignore it; otherwise restore it
2760 if (old_handler
.sa_handler
!= SIG_DFL
)
2762 act
.sa_handler
= old_handler
.sa_handler
;
2763 if (sigaction (SIGPROF
, &act
, &old_handler
) == -1)
2765 /* couldn't reset signal */
2766 fprintf (stderr
, GTXT ("Can't reset SIGPROF: %s\n"), strerror (errno
));
2775 /* On Linux, statvfs() doesn't return any information that seems to indicate
2776 the filetype. The structure statvfs does not have any field/flag that
2777 gives this information. Comparing the fields from
2778 /usr/include/bits/statvfs.h:
2779 unsigned long int f_fsid;
2781 ^^^^ On Solaris, this is where f_basetype is
2782 unsigned long int f_flag;
2783 unsigned long int f_namemax;
2784 XXX Need to revisit this XXX
2786 return NULL
; // no NFS warning on Linux for now
2789 //========== Special functions to communicate with the Collector GUI ==========//
2791 /* Interface strings GUI <-> CLI */
2792 const char *ipc_str_exp_limit
= "exp_limit";
2793 const char *ipc_str_time_limit
= "time_limit";
2794 const char *ipc_str_arch_exp
= "arch_exp";
2795 const char *ipc_str_descendant
= "descendant";
2796 const char *ipc_str_clkprof
= "clkprof";
2797 const char *ipc_str_hwcprof
= "hwcprof";
2798 const char *ipc_str_hwc2_prof
= "hwc2_prof";
2799 const char *ipc_str_javaprof
= "javaprof";
2800 const char *ipc_str_sample
= "sample";
2801 const char *ipc_str_sample_sig
= "sample_sig";
2802 const char *ipc_str_pause_resume_sig
= "pause_resume_sig";
2803 const char *ipc_str_synctrace
= "synctrace";
2804 const char *ipc_str_heaptrace
= "heaptrace";
2805 const char *ipc_str_iotrace
= "iotrace";
2806 const char *ipc_str_count
= "count";
2807 const char *ipc_str_prof_idle
= "prof_idle"; // -x option
2809 const char *ipc_str_empty
= "";
2810 const char *ipc_str_on
= "on";
2811 const char *ipc_str_off
= "off";
2812 const char *ipc_str_src
= "src";
2813 const char *ipc_str_usedsrc
= "usedsrc";
2814 const char *ipc_str_usedldobjects
= "usedldobjects";
2815 const char *ipc_str_unlimited
= "unlimited";
2816 const char *ipc_str_unknown_control
= "Unknown control";
2817 const char *ipc_str_internal_error
= "Internal error";
2822 * @return NULL or signal name (pointer to allocated memory)
2825 Coll_Ctrl::find_signal_name (int signal
)
2827 char *str_signal
= NULL
;
2828 const char *buf
= strsignal (signal
);
2830 str_signal
= strdup (buf
);
2835 * Gets control's value
2840 Coll_Ctrl::get (char * control
)
2842 int len
= strlen (control
);
2843 if (!strncmp (control
, ipc_str_exp_limit
, len
))
2845 if ((size_limit
> 0))
2846 return dbe_sprintf ("%d", size_limit
);
2847 return strdup (ipc_str_unlimited
);
2849 if (!strncmp (control
, ipc_str_time_limit
, len
))
2851 if ((time_run
!= 0) || (start_delay
!= 0))
2853 if (start_delay
!= 0)
2856 return dbe_sprintf ("%ds-%ds", start_delay
, start_delay
+ time_run
);
2857 return dbe_sprintf ("%ds-0s", start_delay
);
2859 return dbe_sprintf ("0s-%ds", time_run
);
2861 return strdup (ipc_str_unlimited
);
2863 if (strncmp (control
, ipc_str_arch_exp
, len
) == 0)
2864 return strdup (get_archive_mode ());
2865 if (!strncmp (control
, ipc_str_descendant
, len
))
2867 switch (get_follow_mode ())
2870 return strdup (ipc_str_on
);
2872 return strdup (ipc_str_on
);
2875 return strdup (ipc_str_off
);
2878 if (!strncmp (control
, ipc_str_prof_idle
, len
))
2881 return strdup (ipc_str_off
);
2882 return strdup (ipc_str_on
);
2884 if (!strncmp (control
, ipc_str_clkprof
, len
))
2886 if (clkprof_default
== 1 && clkprof_enabled
== 1) // Default value
2887 return strdup (ipc_str_empty
);
2888 if (clkprof_enabled
== 0)
2889 return strdup (ipc_str_off
);
2890 if ((clkprof_timer
> 0))
2891 return dbe_sprintf ("%d", clkprof_timer
/ 1000);
2892 return strdup (ipc_str_internal_error
);
2894 if (!strncmp (control
, ipc_str_hwcprof
, len
))
2896 if (hwcprof_enabled_cnt
== 0)
2897 return strdup (ipc_str_off
);
2898 if (hwc_string
!= NULL
)
2899 return dbe_sprintf ("on\n%s", hwc_string
);
2900 return strdup (ipc_str_on
); // XXX need more details?
2902 if (!strncmp (control
, ipc_str_javaprof
, len
))
2904 if ((java_mode
== 0))
2905 return strdup (ipc_str_off
);
2906 return strdup (ipc_str_on
);
2908 if (!strncmp (control
, ipc_str_sample
, len
))
2910 if (sample_default
== 1 && sample_period
== 1) // Default value
2911 return strdup (ipc_str_empty
);
2912 if (sample_period
== 0)
2913 return strdup (ipc_str_off
);
2914 if (sample_period
> 0)
2915 return dbe_sprintf ("%d", sample_period
);
2916 return strdup (ipc_str_internal_error
);
2918 if (!strncmp (control
, ipc_str_sample_sig
, len
))
2920 if ((sample_sig
== 0))
2921 return strdup (ipc_str_off
);
2922 char *str_signal
= find_signal_name (sample_sig
);
2923 if (str_signal
!= NULL
)
2925 return dbe_sprintf (GTXT ("Invalid sample signal %d\n"), sample_sig
);
2927 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
2929 if (pauseresume_sig
== 0)
2930 return strdup (ipc_str_off
);
2931 char *str_signal
= find_signal_name (pauseresume_sig
);
2932 if (str_signal
!= NULL
)
2934 return dbe_sprintf (GTXT ("Invalid pause/resume signal %d\n"), pauseresume_sig
);
2936 if (!strncmp (control
, ipc_str_synctrace
, len
))
2938 if (synctrace_enabled
== 0)
2939 return strdup (ipc_str_off
);
2940 if (synctrace_thresh
< 0)
2941 return strdup ("on\nthreshold: calibrate");
2942 if (synctrace_thresh
== 0)
2943 return strdup ("on\nthreshold: all");
2944 return dbe_sprintf ("on\nthreshold: %d", synctrace_thresh
);
2946 if (!strncmp (control
, ipc_str_heaptrace
, len
))
2948 if ((heaptrace_enabled
== 0))
2949 return strdup (ipc_str_off
);
2950 return strdup (ipc_str_on
);
2952 if (!strncmp (control
, ipc_str_iotrace
, len
))
2954 if ((iotrace_enabled
== 0))
2955 return strdup (ipc_str_off
);
2956 return strdup (ipc_str_on
);
2958 if (!strncmp (control
, ipc_str_count
, len
))
2960 if ((count_enabled
== 0))
2961 return strdup (ipc_str_off
);
2962 if ((count_enabled
< 0))
2963 return strdup ("on\nstatic");
2964 return strdup (ipc_str_on
);
2966 return strdup (ipc_str_unknown_control
);
2970 * Resets control's value (restores the default value)
2973 * @return error or warning or NULL (done)
2976 Coll_Ctrl::set (char * control
, const char * value
)
2980 int len
= strlen (control
);
2981 if (!strncmp (control
, ipc_str_exp_limit
, len
))
2982 return set_size_limit (value
);
2983 if (!strncmp (control
, ipc_str_time_limit
, len
))
2984 return set_time_run (value
);
2985 if (!strncmp (control
, ipc_str_arch_exp
, len
))
2986 return set_archive_mode (value
);
2987 if (!strncmp (control
, ipc_str_descendant
, len
))
2988 return set_follow_mode (value
);
2989 if (!strncmp (control
, ipc_str_prof_idle
, len
))
2990 return set_prof_idle (value
);
2991 if (!strncmp (control
, ipc_str_clkprof
, len
))
2993 ret
= set_clkprof (value
, &warn
);
2997 return warn
; // Warning
2998 return NULL
; // Done
3000 return ret
; // Error
3002 if (!strncmp (control
, ipc_str_hwcprof
, 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_hwc2_prof
, len
))
3015 ret
= set_hwcstring (value
, &warn
);
3019 return warn
; // Warning
3020 return NULL
; // Done
3022 return ret
; // Error
3024 if (!strncmp (control
, ipc_str_javaprof
, len
))
3025 return set_java_mode (value
);
3026 if (!strncmp (control
, ipc_str_sample
, len
))
3027 return set_sample_period (value
);
3028 if (!strncmp (control
, ipc_str_sample_sig
, len
))
3029 return set_sample_signal (find_sig (value
));
3030 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
3032 char *str_signal
= strdup (value
);
3033 char *str_state
= strchr (str_signal
, (int) '\n');
3034 if (str_state
!= NULL
)
3039 int signal
= atoi (str_signal
);
3041 if (str_state
!= NULL
)
3042 state
= atoi (str_state
);
3044 return set_pauseresume_signal (signal
, state
);
3046 if (!strncmp (control
, ipc_str_synctrace
, len
))
3047 return set_synctrace (value
);
3048 if (!strncmp (control
, ipc_str_heaptrace
, len
))
3049 return set_heaptrace (value
);
3050 if (!strncmp (control
, ipc_str_iotrace
, len
))
3051 return set_iotrace (value
);
3052 if (!strncmp (control
, ipc_str_count
, len
))
3053 return set_count (value
);
3054 return strdup (ipc_str_unknown_control
);
3058 * Resets control's value (restores the default value)
3060 * @return error or NULL (done)
3063 Coll_Ctrl::unset (char * control
)
3065 int len
= strlen (control
);
3066 if (!strncmp (control
, ipc_str_exp_limit
, len
))
3068 if (!strncmp (control
, ipc_str_time_limit
, len
))
3073 if (!strncmp (control
, ipc_str_arch_exp
, len
))
3075 archive_mode
= strdup ("on");
3078 if (!strncmp (control
, ipc_str_descendant
, len
))
3080 follow_mode
= FOLLOW_NONE
;
3083 if (!strncmp (control
, ipc_str_prof_idle
, len
))
3088 if (!strncmp (control
, ipc_str_clkprof
, len
))
3090 clkprof_default
= 1;
3091 clkprof_enabled
= 1;
3094 if (!strncmp (control
, ipc_str_hwcprof
, len
))
3100 if (!strncmp (control
, ipc_str_javaprof
, len
))
3109 if (!strncmp (control
, ipc_str_sample
, len
))
3115 if (!strncmp (control
, ipc_str_sample_sig
, len
))
3120 if (!strncmp (control
, ipc_str_pause_resume_sig
, len
))
3122 pauseresume_sig
= 0;
3125 if (!strncmp (control
, ipc_str_synctrace
, len
))
3127 synctrace_enabled
= 0;
3128 synctrace_thresh
= -1;
3131 if (!strncmp (control
, ipc_str_heaptrace
, len
))
3133 heaptrace_enabled
= 0;
3136 if (!strncmp (control
, ipc_str_iotrace
, len
))
3138 iotrace_enabled
= 0;
3141 if (!strncmp (control
, ipc_str_count
, len
))
3148 return strdup (ipc_str_unknown_control
);
3152 Coll_Ctrl::set_project_home (char *s
)
3155 project_home
= strdup (s
);