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