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