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