GCC Code Coverage Report


Directory: src/
File: src/support/options.c
Date: 2024-11-22 17:07:10
Exec Total Coverage
Lines: 381 467 81.6%
Functions: 14 14 100.0%
Branches: 194 264 73.5%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2024 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB 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 Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include "support/options.h"
25
26 #include "apis/dlb_types.h"
27 #include "apis/dlb_errors.h"
28 #include "support/types.h"
29 #include "support/mask_utils.h"
30 #include "support/debug.h"
31 #include "LB_core/spd.h"
32
33 #include <string.h>
34 #include <stddef.h>
35 #include <ctype.h>
36 #include <stdint.h>
37 #include <limits.h>
38
39 typedef enum OptionFlags {
40 OPT_CLEAR = 0,
41 OPT_READONLY = 1 << 0,
42 OPT_OPTIONAL = 1 << 1,
43 OPT_DEPRECATED = 1 << 2,
44 OPT_ADVANCED = 1 << 3,
45 OPT_HIDDEN = 1 << 4,
46 OPT_UNUSED = 1 << 5
47 } option_flags_t;
48
49 typedef enum OptionTypes {
50 OPT_BOOL_T,
51 OPT_NEG_BOOL_T,
52 OPT_INT_T,
53 OPT_STR_T,
54 OPT_PTR_PATH_T, // pointer to char[PATH_MAX]
55 OPT_VB_T, // verbose_opts_t
56 OPT_VBFMT_T, // verbose_fmt_t
57 OPT_INST_T, // instrument_items_t
58 OPT_DBG_T, // debug_opts_t
59 OPT_LEWI_AFF_T, // lewi_affinity_t
60 OPT_MASK_T, // cpu_set_t
61 OPT_MODE_T, // interaction_mode_t
62 OPT_MPISET_T, // mpi_set_t
63 OPT_OMPTOPTS_T, // omptool_opts_t
64 OPT_TLPSUM_T, // talp_summary_t
65 OPT_TLPMOD_T, // talp_model_t
66 OPT_OMPTM_T // omptm_version_t
67 } option_type_t;
68
69 typedef struct {
70 char var_name[MAX_OPTION_LENGTH]; // LB_OPTION
71 char arg_name[MAX_OPTION_LENGTH]; // --option
72 char default_value[MAX_OPTION_LENGTH];
73 char description[MAX_DESCRIPTION];
74 size_t offset;
75 option_type_t type;
76 option_flags_t flags;
77 } opts_dict_t;
78
79 /* Description is displaced 4 spaces */
80 #define OFFSET " "
81 static const opts_dict_t options_dictionary[] = {
82 // general options
83 {
84 .var_name = "LB_LEWI",
85 .arg_name = "--lewi",
86 .default_value = "no",
87 .description = OFFSET"Enable Lend When Idle. Processes using this mode can use LeWI\n"
88 OFFSET"API to lend and borrow resources.",
89 .offset = offsetof(options_t, lewi),
90 .type = OPT_BOOL_T,
91 .flags = OPT_READONLY | OPT_OPTIONAL
92 }, {
93 .var_name = "LB_DROM",
94 .arg_name = "--drom",
95 .default_value = "no",
96 .description = OFFSET"Enable the Dynamic Resource Ownership Manager Module. Processes\n"
97 OFFSET"using this mode can receive requests from other processes to\n"
98 OFFSET"change its own process mask.",
99 .offset = offsetof(options_t, drom),
100 .type = OPT_BOOL_T,
101 .flags = OPT_READONLY | OPT_OPTIONAL
102 }, {
103 .var_name = "LB_TALP",
104 .arg_name = "--talp",
105 .default_value = "no",
106 .description = OFFSET"Enable the TALP (Tracking Application Live Performance)\n"
107 OFFSET"module. Processes that enable this mode can obtain performance\n"
108 OFFSET"metrics at run time.",
109 .offset = offsetof(options_t, talp),
110 .type = OPT_BOOL_T,
111 .flags = OPT_OPTIONAL
112 },{
113 .var_name = "LB_BARRIER",
114 .arg_name = "--barrier",
115 .default_value = "yes",
116 .description = OFFSET"Enable the Shared Memory Barrier. Processes can perform\n"
117 OFFSET"intra-node barriers.",
118 .offset = offsetof(options_t, barrier),
119 .type = OPT_BOOL_T,
120 .flags = OPT_READONLY | OPT_OPTIONAL
121 }, {
122 .var_name = "LB_NULL",
123 .arg_name = "--ompt",
124 .default_value = "no",
125 .description = OFFSET"Enable OpenMP performance tool. If running with an OMPT capable\n"
126 OFFSET"runtime, DLB can register itself as OpenMP Tool and perform\n"
127 OFFSET"some tasks, like thread pinning reallocation when the process\n"
128 OFFSET"mask changes or some LeWI features if enabled.",
129 .offset = offsetof(options_t, ompt),
130 .type = OPT_BOOL_T,
131 .flags = OPT_READONLY | OPT_OPTIONAL
132 }, {
133 .var_name = "LB_MODE",
134 .arg_name = "--mode",
135 .default_value = "polling",
136 .description = OFFSET"Set interaction mode between DLB and the application. In polling\n"
137 OFFSET"mode, each process needs to poll DLB to acquire resources. In\n"
138 OFFSET"async mode, DLB creates a helper thread to call back the\n"
139 OFFSET"application when resources become available.",
140 .offset = offsetof(options_t, mode),
141 .type = OPT_MODE_T,
142 .flags = OPT_READONLY | OPT_OPTIONAL
143 },
144 // verbose
145 {
146 .var_name = "LB_NULL",
147 .arg_name = "--quiet",
148 .default_value = "no",
149 .description = OFFSET"Suppress VERBOSE and INFO messages from DLB, still shows\n"
150 OFFSET"WARNING and PANIC messages.",
151 .offset = offsetof(options_t, quiet),
152 .type = OPT_BOOL_T,
153 .flags = OPT_READONLY | OPT_OPTIONAL
154 }, {
155 .var_name = "LB_NULL",
156 .arg_name = "--silent",
157 .default_value = "no",
158 .description = OFFSET"Suppress all output from DLB, even error messages.",
159 .offset = offsetof(options_t, silent),
160 .type = OPT_BOOL_T,
161 .flags = OPT_READONLY | OPT_OPTIONAL
162 }, {
163 .var_name = "LB_VERBOSE",
164 .arg_name = "--verbose",
165 .default_value = "no",
166 .description = OFFSET"Select which verbose components will be printed. Multiple\n"
167 OFFSET"components may be selected.",
168 .offset = offsetof(options_t, verbose),
169 .type = OPT_VB_T,
170 .flags = OPT_READONLY | OPT_OPTIONAL
171 }, {
172 .var_name = "LB_VERBOSE_FORMAT",
173 .arg_name = "--verbose-format",
174 .default_value = "node:spid",
175 .description = OFFSET"Set the verbose format for the verbose messages. Multiple\n"
176 OFFSET"components may be selected but the order is predefined as\n"
177 OFFSET"shown in the possible values.",
178 .offset = offsetof(options_t, verbose_fmt),
179 .type = OPT_VBFMT_T,
180 .flags = OPT_READONLY | OPT_OPTIONAL
181 },
182 // instrument
183 {
184 .var_name = "LB_NULL",
185 .arg_name = "--instrument",
186 .default_value = "all",
187 .description = OFFSET"Enable Extrae instrumentation. This option requires the\n"
188 OFFSET"instrumented DLB library and the Extrae library. If both\n"
189 OFFSET"conditions are met, DLB will emit events such as the DLB\n"
190 OFFSET"calls, DLB modes, etc.",
191 .offset = offsetof(options_t, instrument),
192 .type = OPT_INST_T,
193 .flags = OPT_READONLY | OPT_OPTIONAL
194 }, {
195 .var_name = "LB_NULL",
196 .arg_name = "--instrument-counters",
197 .default_value = "no",
198 .description = OFFSET"Enable counters on DLB events. If this option is enabled, DLB\n"
199 OFFSET"will emit events to Extrae with hardware counters information.\n"
200 OFFSET"This may significantly increase the size of the tracefile.",
201 .offset = offsetof(options_t, instrument_counters),
202 .type = OPT_BOOL_T,
203 .flags = OPT_READONLY | OPT_OPTIONAL
204 }, {
205 .var_name = "LB_NULL",
206 .arg_name = "--instrument-extrae-nthreads",
207 .default_value = "0",
208 .description = OFFSET"Invoke Extrae_change_num_threads with the provided parameter\n"
209 OFFSET"at the start of the execution to pre-allocate a buffer per\n"
210 OFFSET"thread.",
211 .offset = offsetof(options_t, instrument_extrae_nthreads),
212 .type = OPT_INT_T,
213 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_ADVANCED
214 },
215 // LeWI
216 {
217 .var_name = "LB_NULL",
218 .arg_name = "--lewi-keep-one-cpu",
219 .default_value = "no",
220 .description = OFFSET"Whether the CPU of the thread that encounters a blocking call\n"
221 OFFSET"(MPI blocking call or DLB_Barrier) is also lent in the LeWI policy.\n"
222 OFFSET"This flag replaces the option --lewi-mpi, although negated.",
223 .offset = offsetof(options_t, lewi_keep_cpu_on_blocking_call),
224 .type = OPT_BOOL_T,
225 .flags = OPT_OPTIONAL
226 }, {
227 .var_name = "LB_NULL",
228 .arg_name = "--lewi-respect-cpuset",
229 .default_value = "yes",
230 .description = OFFSET"Whether to respect the set of CPUs registered in DLB to\n"
231 OFFSET"use with LeWI. If disabled, all unknown CPUs are available\n"
232 OFFSET"for any process to borrow.",
233 .offset = offsetof(options_t, lewi_respect_cpuset),
234 .type = OPT_BOOL_T,
235 .flags = OPT_OPTIONAL
236 }, {
237 .var_name = "LB_NULL",
238 .arg_name = "--lewi-respect-mask",
239 .default_value = "yes",
240 .description = OFFSET"Deprecated in favor of --lewi-respect-cpuset.\n",
241 .offset = offsetof(options_t, lewi_respect_cpuset),
242 .type = OPT_BOOL_T,
243 .flags = OPT_OPTIONAL | OPT_DEPRECATED
244 }, {
245 /* This is a deprecated option that overlaps with --lewi-keep-one-cpu.
246 * It must be defined afterwards so that the default value of the
247 * previous option does not overwrite this one */
248 .var_name = "LB_NULL",
249 .arg_name = "--lewi-mpi",
250 .default_value = "no",
251 .description = OFFSET"This option is now deprecated, but its previous behavior is now\n"
252 OFFSET"enabled by default.\n"
253 OFFSET"If you want to lend a CPU when in a blocking call, you may safely\n"
254 OFFSET"remove this option.\n"
255 OFFSET"If you want to keep this CPU, use --lewi-keep-one-cpu instead.",
256 .offset = offsetof(options_t, lewi_keep_cpu_on_blocking_call),
257 .type = OPT_NEG_BOOL_T,
258 .flags = OPT_OPTIONAL | OPT_DEPRECATED
259 }, {
260 .var_name = "LB_NULL",
261 .arg_name = "--lewi-mpi-calls",
262 .default_value = "all",
263 .description = OFFSET"Select which type of MPI calls will make LeWI to lend their\n"
264 OFFSET"CPUs. If set to all, LeWI will act on all blocking MPI calls,\n"
265 OFFSET"If set to other values, only those types will trigger LeWI.",
266 .offset = offsetof(options_t, lewi_mpi_calls),
267 .type = OPT_MPISET_T,
268 .flags = OPT_OPTIONAL
269 }, {
270 .var_name = "LB_NULL",
271 .arg_name = "--lewi-barrier",
272 .default_value = "yes",
273 .description = OFFSET"Select whether DLB_Barrier calls (unnamed barriers only) will\n"
274 OFFSET"activate LeWI and lend their CPUs. Named barriers can be\n"
275 OFFSET"configured individually in the source code, or using the\n"
276 OFFSET"--lewi-barrier-select.",
277 .offset = offsetof(options_t, lewi_barrier),
278 .type = OPT_BOOL_T,
279 .flags = OPT_OPTIONAL | OPT_READONLY
280 }, {
281 .var_name = "LB_NULL",
282 .arg_name = "--lewi-barrier-select",
283 .default_value = "",
284 .description = OFFSET"Comma separated values of barrier names that will activate\n"
285 OFFSET"LeWI. Warning: by setting this option to any non-blank value,\n"
286 OFFSET"the option --lewi-barrier is ignored. Use 'default' to also\n"
287 OFFSET"control the default unnamed barrier.\n"
288 OFFSET"e.g.: --lewi-barrier-select=default,barrier3",
289 .offset = offsetof(options_t, lewi_barrier_select),
290 .type = OPT_STR_T,
291 .flags = OPT_OPTIONAL | OPT_READONLY | OPT_ADVANCED
292 }, {
293 .var_name = "LB_NULL",
294 .arg_name = "--lewi-affinity",
295 .default_value = "auto",
296 .description = OFFSET"Select which affinity policy to use.\n"
297 OFFSET"With 'auto', DLB will infer the LeWI policy for either classic\n"
298 OFFSET"(no mask support) or LeWI_mask depending on a number of factors.\n"
299 OFFSET"To override the automatic detection, use either 'none' or 'mask'\n"
300 OFFSET"to select the respective policy.\n"
301 OFFSET"The tokens 'nearby-first', 'nearby-only', and 'spread-ifempty'\n"
302 OFFSET"also enforce mask support with extended policies.\n"
303 OFFSET"'nearby-first' is the default policy when LeWI has mask support\n"
304 OFFSET"and will instruct LeWI to assign resources that share the same\n"
305 OFFSET"socket or NUMA node with the current process first, then the\n"
306 OFFSET"rest.\n"
307 OFFSET"'nearby-only' will make LeWI assign only those resources that\n"
308 OFFSET"are near the process.\n"
309 OFFSET"'spread-ifempty' will also prioritise nearby resources, but the\n"
310 OFFSET"rest will only be considered if all CPUs in that socket or NUMA\n"
311 OFFSET"node has been lent to DLB.",
312 .offset = offsetof(options_t, lewi_affinity),
313 .type = OPT_LEWI_AFF_T,
314 .flags = OPT_OPTIONAL
315 }, {
316 .var_name = "LB_NULL",
317 .arg_name = "--lewi-ompt",
318 .default_value = "borrow",
319 .description = OFFSET"OMPT option flags for LeWI. If OMPT mode is enabled, set when\n"
320 OFFSET"DLB can automatically invoke LeWI functions to lend or borrow\n"
321 OFFSET"CPUs. If 'none' is set, LeWI will not be invoked automatically.\n"
322 OFFSET"If 'borrow' is set, DLB will try to borrow CPUs in certain\n"
323 OFFSET"situations; typically, before non nested parallel constructs if\n"
324 OFFSET"the OMPT thread manager is omp5 and on each task creation and\n"
325 OFFSET"task switch in other thread managers. (This option is the default\n"
326 OFFSET"and should be enough in most of the cases). If the flag 'lend'\n"
327 OFFSET"is set, DLB will lend all non used CPUs after each non nested\n"
328 OFFSET"parallel construct and task completion on external threads.\n"
329 OFFSET"Multiple flags can be selected at the same time.",
330 .offset = offsetof(options_t, lewi_ompt),
331 .type = OPT_OMPTOPTS_T,
332 .flags = OPT_OPTIONAL
333 }, {
334 .var_name = "LB_NULL",
335 .arg_name = "--lewi-greedy",
336 .default_value = "no",
337 .description = OFFSET"Greedy option for LeWI policy.",
338 .offset = offsetof(options_t, lewi_greedy),
339 .type = OPT_BOOL_T,
340 .flags = OPT_OPTIONAL
341 }, {
342 .var_name = "LB_NULL",
343 .arg_name = "--lewi-warmup",
344 .default_value = "no",
345 .description = OFFSET"Create as many threads as necessary during the process startup.",
346 .offset = offsetof(options_t, lewi_warmup),
347 .type = OPT_BOOL_T,
348 .flags = OPT_READONLY | OPT_OPTIONAL
349 }, {
350 .var_name = "LB_NULL",
351 .arg_name = "--lewi-max-parallelism",
352 .default_value = "0",
353 .description = OFFSET"Set the maximum level of parallelism for the LeWI algorithm.",
354 .offset = offsetof(options_t, lewi_max_parallelism),
355 .type = OPT_INT_T,
356 .flags = OPT_READONLY | OPT_OPTIONAL
357 }, {
358 .var_name = "LB_NULL",
359 .arg_name = "--lewi-color",
360 .default_value = "0",
361 .description = OFFSET"Set the LeWI color of the process, allowing the creation of\n"
362 OFFSET"different disjoint subgroups for resource sharing. Processes\n"
363 OFFSET"will only share resources with other processes of the same color.",
364 .offset = offsetof(options_t, lewi_color),
365 .type = OPT_INT_T,
366 .flags = OPT_READONLY | OPT_OPTIONAL
367 },
368 // talp
369 {
370 .var_name = "LB_NULL",
371 .arg_name = "--talp-openmp",
372 .default_value = "no",
373 .description = OFFSET"Select whether to measure OpenMP metrics. (Experimental)",
374 .offset = offsetof(options_t, talp_openmp),
375 .type = OPT_BOOL_T,
376 .flags = OPT_READONLY | OPT_OPTIONAL
377 },
378 {
379 .var_name = "LB_NULL",
380 .arg_name = "--talp-papi",
381 .default_value = "no",
382 .description = OFFSET"Select whether to collect PAPI counters.",
383 .offset = offsetof(options_t, talp_papi),
384 .type = OPT_BOOL_T,
385 .flags = OPT_READONLY | OPT_OPTIONAL
386 },
387 {
388 .var_name = "LB_TALP_SUMM",
389 .arg_name = "--talp-summary",
390 .default_value = "pop-metrics",
391 .description = OFFSET"List of summaries, separated by ':', to be written at the end\n"
392 OFFSET"of execution:\n"
393 OFFSET"'pop-metrics', the default option, will print a subset of the\n"
394 OFFSET"POP metrics if '--talp-output-file' is not specified.\n"
395 OFFSET"Otherwise, a more verbose file will be generated with all the\n"
396 OFFSET"metrics collected by TALP.\n"
397 OFFSET"'process' will report the measurements of each process for\n"
398 OFFSET"each registered region.\n"
399 OFFSET"\n"
400 OFFSET"Deprecated options:\n"
401 OFFSET"'pop-raw' will be removed in the next release. The output \n"
402 OFFSET"will be available using the 'pop-metrics' summary.\n"
403 OFFSET"'node' will be removed in the next release. Its data may\n"
404 OFFSET"be derived from the 'process' report.",
405 .offset = offsetof(options_t, talp_summary),
406 .type = OPT_TLPSUM_T,
407 .flags = OPT_READONLY | OPT_OPTIONAL
408 },
409 {
410 .var_name = "LB_NULL",
411 .arg_name = "--talp-output-file",
412 .default_value = "",
413 .description = OFFSET"Write TALP metrics to a file. If this option is not provided,\n"
414 OFFSET"the output is printed to stderr.\n"
415 OFFSET"Accepted formats: *.json, *.csv. Any other for plain text.\n"
416 OFFSET"\n"
417 OFFSET"Deprecated formats:\n"
418 OFFSET"The *.xml file ending is deprecated and will be removed in\n"
419 OFFSET"the next release.",
420 .offset = offsetof(options_t, talp_output_file),
421 .type = OPT_PTR_PATH_T,
422 .flags = OPT_READONLY | OPT_OPTIONAL
423 },
424 {
425 /* In the future, consider using an interval update timer instead of a boolean */
426 .var_name = "LB_NULL",
427 .arg_name = "--talp-external-profiler",
428 .default_value = "no",
429 .description = OFFSET"Enable live metrics update to the shared memory. This flag\n"
430 OFFSET"is only needed if there is an external program monitoring\n"
431 OFFSET"the application.",
432 .offset = offsetof(options_t, talp_external_profiler),
433 .type = OPT_BOOL_T,
434 .flags = OPT_READONLY | OPT_OPTIONAL
435 },
436 {
437 .var_name = "LB_NULL",
438 .arg_name = "--talp-regions-per-proc",
439 .default_value = "100",
440 .description = OFFSET"Number of TALP regions per process to allocate in the shared\n"
441 OFFSET"memory.",
442 .offset = offsetof(options_t, talp_regions_per_proc),
443 .type = OPT_INT_T,
444 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_ADVANCED
445 },
446 {
447 .var_name = "LB_NULL",
448 .arg_name = "--talp-region-select",
449 .default_value = "",
450 .description = OFFSET"Select TALP regions to enable. The option accepts the\n"
451 OFFSET"special values 'all', to enable all TALP regions, and 'none'\n"
452 OFFSET"to disable them all. An empty value is equivalent to 'all'.\n"
453 OFFSET"Additionally, a comma separated list of region names may be\n"
454 OFFSET"specified to enable only these regions. The global monitoring\n"
455 OFFSET"region may be specified with the special token 'global'.\n"
456 OFFSET"Note that names with spaces are not supported.\n"
457 OFFSET"e.g.: --talp-region-select=none\n"
458 OFFSET" --talp-region-select=global,region3",
459 .offset = offsetof(options_t, talp_region_select),
460 .type = OPT_STR_T,
461 .flags = OPT_READONLY | OPT_OPTIONAL
462 },
463 {
464 .var_name = "LB_NULL",
465 .arg_name = "--talp-model",
466 .default_value = "hybrid-v2",
467 .description = OFFSET"For development use only.\n"
468 OFFSET"Select which version of POP metrics to compute.",
469 .offset = offsetof(options_t, talp_model),
470 .type = OPT_TLPMOD_T,
471 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_ADVANCED
472 },
473 // barrier
474 {
475 .var_name = "LB_NULL",
476 .arg_name = "--barrier-id",
477 .default_value = "0",
478 .description = OFFSET"Barrier ID. Use different barrier id numbers for different\n"
479 OFFSET"processes to avoid unwanted synchronization.",
480 .offset = offsetof(options_t, barrier_id),
481 .type = OPT_INT_T,
482 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_ADVANCED
483 },
484 // misc
485 {
486 .var_name = "LB_SHM_KEY",
487 .arg_name = "--shm-key",
488 .default_value = "",
489 .description = OFFSET"Shared Memory key. By default, if key is empty, all processes\n"
490 OFFSET"will use a shared memory based on the user ID. If different\n"
491 OFFSET"processes start their execution with different keys, they will\n"
492 OFFSET"use different shared memories and they will not share resources.",
493 .offset = offsetof(options_t, shm_key),
494 .type = OPT_STR_T,
495 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_ADVANCED
496 }, {
497 .var_name = "LB_PREINIT_PID",
498 .arg_name = "--preinit-pid",
499 .default_value = "0",
500 .description = OFFSET"Process ID that pre-initializes the DLB process for DROM.",
501 .offset = offsetof(options_t, preinit_pid),
502 .type = OPT_INT_T,
503 .flags = OPT_READONLY | OPT_OPTIONAL | OPT_HIDDEN
504 }, {
505 .var_name = "LB_NULL",
506 .arg_name = "--ompt-thread-manager",
507 .default_value = "none",
508 .description = OFFSET"OMPT Thread Manager version.",
509 .offset = offsetof(options_t, omptm_version),
510 .type = OPT_OMPTM_T,
511 .flags = OPT_OPTIONAL
512 }, {
513 .var_name = "LB_DEBUG_OPTS",
514 .arg_name = "--debug-opts",
515 .default_value = "",
516 .description = OFFSET"Debug options.",
517 .offset = offsetof(options_t, debug_opts),
518 .type = OPT_DBG_T,
519 .flags = OPT_OPTIONAL | OPT_ADVANCED
520 }
521 };
522 #undef OFFSET
523
524 enum { NUM_OPTIONS = sizeof(options_dictionary)/sizeof(opts_dict_t) };
525
526
527 426 static const opts_dict_t* get_entry_by_name(const char *name) {
528 int i;
529
2/2
✓ Branch 0 taken 6938 times.
✓ Branch 1 taken 2 times.
6940 for (i=0; i<NUM_OPTIONS; ++i) {
530 6938 const opts_dict_t *entry = &options_dictionary[i];
531
1/2
✓ Branch 0 taken 6938 times.
✗ Branch 1 not taken.
6938 if (strcasecmp(entry->var_name, name) == 0
532
2/2
✓ Branch 0 taken 424 times.
✓ Branch 1 taken 6514 times.
6938 || strcasecmp(entry->arg_name, name) == 0) {
533 424 return entry;
534 }
535 }
536 2 return NULL;
537 }
538
539 155 static int set_ptr_path_value(void *option, const char *str_value) {
540 155 int path_len = snprintf(NULL, 0, "%s", str_value) + 1;
541
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 154 times.
155 if (path_len > 1) {
542 1 *(char**)option = malloc(sizeof(char) * path_len);
543 1 snprintf(*(char**)option, path_len, "%s", str_value);
544 } else {
545 154 *(char**)option = NULL;
546 }
547 155 return DLB_SUCCESS;
548 }
549
550 5953 static int set_value(option_type_t type, void *option, const char *str_value) {
551
16/18
✓ Branch 0 taken 2586 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 954 times.
✓ Branch 3 taken 489 times.
✓ Branch 4 taken 155 times.
✓ Branch 5 taken 204 times.
✓ Branch 6 taken 156 times.
✓ Branch 7 taken 156 times.
✓ Branch 8 taken 157 times.
✓ Branch 9 taken 156 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 156 times.
✓ Branch 12 taken 157 times.
✓ Branch 13 taken 156 times.
✓ Branch 14 taken 156 times.
✓ Branch 15 taken 156 times.
✓ Branch 16 taken 155 times.
✗ Branch 17 not taken.
5953 switch(type) {
552 2586 case OPT_BOOL_T:
553 2586 return parse_bool(str_value, (bool*)option);
554 4 case OPT_NEG_BOOL_T:
555 4 return parse_negated_bool(str_value, (bool*)option);
556 954 case OPT_INT_T:
557 954 return parse_int(str_value, (int*)option);
558 489 case OPT_STR_T:
559 489 snprintf(option, MAX_OPTION_LENGTH, "%s", str_value);
560 489 return DLB_SUCCESS;
561 155 case OPT_PTR_PATH_T:
562 155 return set_ptr_path_value(option, str_value);
563 204 case OPT_VB_T:
564 204 return parse_verbose_opts(str_value, (verbose_opts_t*)option);
565 156 case OPT_VBFMT_T:
566 156 return parse_verbose_fmt(str_value, (verbose_fmt_t*)option);
567 156 case OPT_INST_T:
568 156 return parse_instrument_items(str_value, (instrument_items_t*)option);
569 157 case OPT_DBG_T:
570 157 return parse_debug_opts(str_value, (debug_opts_t*)option);
571 156 case OPT_LEWI_AFF_T:
572 156 return parse_lewi_affinity(str_value, (lewi_affinity_t*)option);
573 case OPT_MASK_T:
574 mu_parse_mask(str_value, (cpu_set_t*)option);
575 return DLB_SUCCESS;
576 156 case OPT_MODE_T:
577 156 return parse_mode(str_value, (interaction_mode_t*)option);
578 157 case OPT_MPISET_T:
579 157 return parse_mpiset(str_value, (mpi_set_t*)option);
580 156 case OPT_OMPTOPTS_T:
581 156 return parse_omptool_opts(str_value, (omptool_opts_t*)option);
582 156 case OPT_TLPSUM_T:
583 156 return parse_talp_summary(str_value, (talp_summary_t*)option);
584 156 case OPT_TLPMOD_T:
585 156 return parse_talp_model(str_value, (talp_model_t*)option);
586 155 case OPT_OMPTM_T:
587 155 return parse_omptm_version(str_value, (omptm_version_t*)option);
588 }
589 return DLB_ERR_NOENT;
590 }
591
592 134 static const char * get_value(option_type_t type, const void *option) {
593 static char int_value[8];
594
15/18
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
134 switch(type) {
595 70 case OPT_BOOL_T:
596
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 56 times.
70 return *(bool*)option ? "yes" : "no";
597 case OPT_NEG_BOOL_T:
598 return *(bool*)option ? "no" : "yes";
599 11 case OPT_INT_T:
600 11 sprintf(int_value, "%d", *(int*)option);
601 11 return int_value;
602 7 case OPT_STR_T:
603 7 return (char*)option;
604 4 case OPT_PTR_PATH_T:
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 return *(const char**)option ? *(const char**)option : "";
606 4 case OPT_VB_T:
607 4 return verbose_opts_tostr(*(verbose_opts_t*)option);
608 4 case OPT_VBFMT_T:
609 4 return verbose_fmt_tostr(*(verbose_fmt_t*)option);
610 4 case OPT_INST_T:
611 4 return instrument_items_tostr(*(instrument_items_t*)option);
612 1 case OPT_DBG_T:
613 1 return debug_opts_tostr(*(debug_opts_t*)option);
614 4 case OPT_LEWI_AFF_T:
615 4 return lewi_affinity_tostr(*(lewi_affinity_t*)option);
616 case OPT_MASK_T:
617 return mu_to_str((cpu_set_t*)option);
618 6 case OPT_MODE_T:
619 6 return mode_tostr(*(interaction_mode_t*)option);
620 6 case OPT_MPISET_T:
621 6 return mpiset_tostr(*(mpi_set_t*)option);
622 4 case OPT_OMPTOPTS_T:
623 4 return omptool_opts_tostr(*(omptool_opts_t*)option);
624 4 case OPT_TLPSUM_T:
625 4 return talp_summary_tostr(*(talp_summary_t*)option);
626 1 case OPT_TLPMOD_T:
627 1 return talp_model_tostr(*(talp_model_t*)option);
628 4 case OPT_OMPTM_T:
629 4 return omptm_version_tostr(*(omptm_version_t*)option);
630 }
631 return "unknown";
632 }
633
634 1 static bool values_are_equivalent(option_type_t type, const char *value1, const char *value2) {
635
1/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1 switch(type) {
636 1 case OPT_BOOL_T:
637 1 return equivalent_bool(value1, value2);
638 case OPT_NEG_BOOL_T:
639 return equivalent_negated_bool(value1, value2);
640 case OPT_INT_T:
641 return equivalent_int(value1, value2);
642 case OPT_STR_T:
643 return strcmp(value1, value2) == 0;
644 case OPT_PTR_PATH_T:
645 return *(const char**)value1 && *(const char**)value2
646 && strcmp(*(const char**)value1, *(const char**)value2) == 0;
647 case OPT_VB_T:
648 return equivalent_verbose_opts(value1, value2);
649 case OPT_VBFMT_T:
650 return equivalent_verbose_fmt(value1, value2);
651 case OPT_INST_T:
652 return equivalent_instrument_items(value1, value2);
653 case OPT_DBG_T:
654 return equivalent_debug_opts(value1, value2);
655 case OPT_LEWI_AFF_T:
656 return equivalent_lewi_affinity(value1, value2);
657 case OPT_MASK_T:
658 return mu_equivalent_masks(value1, value2);
659 case OPT_MODE_T:
660 return equivalent_mode(value1, value2);
661 case OPT_MPISET_T:
662 return equivalent_mpiset(value1, value2);
663 case OPT_OMPTOPTS_T:
664 return equivalent_omptool_opts(value1, value2);
665 case OPT_TLPSUM_T:
666 return equivalent_talp_summary(value1, value2);
667 case OPT_TLPMOD_T:
668 return equivalent_talp_model(value1, value2);
669 case OPT_OMPTM_T:
670 return equivalent_omptm_version_opts(value1, value2);
671 }
672 return false;
673 }
674
675 15 static void copy_value(option_type_t type, void *dest, const char *src) {
676
13/18
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
15 switch(type) {
677 1 case OPT_BOOL_T:
678 1 memcpy(dest, src, sizeof(bool));
679 1 break;
680 1 case OPT_NEG_BOOL_T:
681 1 memcpy(dest, src, sizeof(bool));
682 1 break;
683 2 case OPT_INT_T:
684 2 memcpy(dest, src, sizeof(int));
685 2 break;
686 2 case OPT_STR_T:
687 2 memcpy(dest, src, sizeof(char)*MAX_OPTION_LENGTH);
688 2 break;
689 case OPT_PTR_PATH_T:
690 fatal("copy_value of type OPT_PTR_PATH_T not supported");
691 break;
692 1 case OPT_VB_T:
693 1 memcpy(dest, src, sizeof(verbose_opts_t));
694 1 break;
695 1 case OPT_VBFMT_T:
696 1 memcpy(dest, src, sizeof(verbose_fmt_t));
697 1 break;
698 1 case OPT_INST_T:
699 1 memcpy(dest, src, sizeof(instrument_items_t));
700 1 break;
701 case OPT_DBG_T:
702 memcpy(dest, src, sizeof(debug_opts_t));
703 break;
704 1 case OPT_LEWI_AFF_T:
705 1 memcpy(dest, src, sizeof(lewi_affinity_t));
706 1 break;
707 case OPT_MASK_T:
708 memcpy(dest, src, sizeof(cpu_set_t));
709 break;
710 1 case OPT_MODE_T:
711 1 memcpy(dest, src, sizeof(interaction_mode_t));
712 1 break;
713 1 case OPT_MPISET_T:
714 1 memcpy(dest, src, sizeof(mpi_set_t));
715 1 break;
716 1 case OPT_OMPTOPTS_T:
717 1 memcpy(dest, src, sizeof(omptool_opts_t));
718 1 break;
719 1 case OPT_TLPSUM_T:
720 1 memcpy(dest, src, sizeof(talp_summary_t));
721 1 break;
722 1 case OPT_TLPMOD_T:
723 1 memcpy(dest, src, sizeof(talp_model_t));
724 1 break;
725 case OPT_OMPTM_T:
726 memcpy(dest, src, sizeof(omptm_version_t));
727 break;
728 }
729 15 }
730
731 /* Parse DLB_ARGS and remove argument if found */
732 5956 static void parse_dlb_args(char *dlb_args, const char *arg_name, char* arg_value, size_t arg_max_len) {
733 5956 *arg_value = 0;
734 /* Tokenize a copy of dlb_args with " "(blank) delimiter */
735 5956 char *progress = dlb_args;
736 5956 char *end_space = NULL;
737 5956 size_t len = strlen(dlb_args) + 1;
738 5956 char *dlb_args_copy = malloc(sizeof(char)*len);
739 5956 strcpy(dlb_args_copy, dlb_args);
740 5956 char *token = strtok_r(dlb_args_copy, " ", &end_space);
741
2/2
✓ Branch 0 taken 6834 times.
✓ Branch 1 taken 5956 times.
12790 while (token) {
742 /* Each token is a complete string representing an option */
743
744 6834 bool remove_token = false;
745 /* token length must be computed before tokenizing into arg=val */
746 6834 size_t token_len = strlen(token);
747 /* progress pointer must be updated each iteration to skip spaces */
748
2/2
✓ Branch 0 taken 8018 times.
✓ Branch 1 taken 6834 times.
14852 while(isspace((unsigned char)*progress)) progress++;
749
750
2/2
✓ Branch 0 taken 5982 times.
✓ Branch 1 taken 852 times.
6834 if (strchr(token, '=')) {
751 /* Option is of the form --argument=value */
752 char *end_equal;
753 5982 char *argument = strtok_r(token, "=", &end_equal);
754
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 5739 times.
5982 if (strcmp(argument, arg_name) == 0) {
755 /* Obtain value */
756 243 char *value = strtok_r(NULL, "=", &end_equal);
757
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 1 times.
243 if (value) {
758 242 snprintf(arg_value, arg_max_len, "%s", value);
759 } else {
760 1 warning("Bad format parsing of DLB_ARGS. Option %s with empty value", token);
761 }
762 243 remove_token = true;
763 }
764 } else {
765 /* Option is of the form --argument/--no-argument */
766 852 char *argument = token;
767
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 709 times.
852 if (strcmp(argument, arg_name) == 0) {
768 /* Option value is 'yes' */
769 143 strcpy(arg_value, "yes");
770 143 remove_token = true;
771
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 687 times.
709 } else if (strncmp(argument, "--no-", 5) == 0
772
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 && strcmp(argument+5, arg_name+2) == 0) {
773 /* Option value is 'no' */
774 18 strcpy(arg_value, "no");
775 18 remove_token = true;
776 }
777 }
778
779
2/2
✓ Branch 0 taken 404 times.
✓ Branch 1 taken 6430 times.
6834 if (remove_token) {
780 /* Remove token from dlb_args */
781 404 char *dest = progress;
782 404 char *src = progress + token_len;
783 404 size_t n = strlen(src) + 1;
784 404 memmove(dest, src, n);
785 } else {
786 /* Token is not removed, update parsed progress pointer */
787 6430 progress += token_len;
788 }
789
790 /* next token */
791 6834 token = strtok_r(NULL, " ", &end_space);
792 }
793 5956 free(dlb_args_copy);
794 5956 }
795
796 /* Initialize options struct from either argument, or env. variable */
797 155 void options_init(options_t *options, const char *dlb_args) {
798 /* Copy dlb_args into a local buffer */
799 155 char *dlb_args_from_api = NULL;
800
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 28 times.
155 if (dlb_args) {
801 127 size_t len = strlen(dlb_args) + 1;
802 127 dlb_args_from_api = malloc(sizeof(char)*len);
803 127 strcpy(dlb_args_from_api, dlb_args);
804 }
805
806 /* Copy either DLB_ARGS or LB_ARGS into a local buffer */
807 155 char *dlb_args_from_env = NULL;
808 155 const char *env = getenv("DLB_ARGS");
809
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 24 times.
155 if (!env) {
810 131 env = getenv("LB_ARGS");
811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
131 if (env) {
812 warning("LB_ARGS is deprecated, please use DLB_ARGS");
813 }
814 }
815
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 131 times.
155 if (env) {
816 24 size_t len = strlen(env) + 1;
817 24 dlb_args_from_env = malloc(sizeof(char)*len);
818 24 strcpy(dlb_args_from_env, env);
819 }
820
821 /* Preallocate two buffers large enough to save any intermediate option value */
822 155 char *arg_value_from_api = malloc(sizeof(char)*PATH_MAX);
823 155 char *arg_value_from_env = malloc(sizeof(char)*PATH_MAX);
824
825 int i;
826
2/2
✓ Branch 0 taken 6045 times.
✓ Branch 1 taken 155 times.
6200 for (i=0; i<NUM_OPTIONS; ++i) {
827 6045 const opts_dict_t *entry = &options_dictionary[i];
828 6045 const char *rhs = NULL; /* pointer to rhs to be parsed */
829
830 /* Set-up specific argument length */
831 size_t arg_max_len;
832
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 5890 times.
6045 switch (entry->type) {
833 155 case OPT_PTR_PATH_T:
834 155 arg_max_len = PATH_MAX-1;
835 155 break;
836 5890 default:
837 5890 arg_max_len = MAX_OPTION_LENGTH-1;
838 5890 break;
839 }
840
841 /* Reset intermediate buffers */
842 6045 arg_value_from_api[0] = '\0';
843 6045 arg_value_from_env[0] = '\0';
844
845 /* Parse dlb_args from API */
846
2/2
✓ Branch 0 taken 4953 times.
✓ Branch 1 taken 1092 times.
6045 if (dlb_args_from_api) {
847 4953 parse_dlb_args(dlb_args_from_api, entry->arg_name, arg_value_from_api, arg_max_len);
848
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 4642 times.
4953 if (strlen(arg_value_from_api) > 0) {
849 311 rhs = arg_value_from_api;
850 }
851 }
852
853 /* Parse DLB_ARGS from env */
854
2/2
✓ Branch 0 taken 936 times.
✓ Branch 1 taken 5109 times.
6045 if (dlb_args_from_env) {
855 936 parse_dlb_args(dlb_args_from_env, entry->arg_name, arg_value_from_env, arg_max_len);
856
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 880 times.
936 if (strlen(arg_value_from_env) > 0) {
857
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 55 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
56 if (rhs && !values_are_equivalent(entry->type, rhs, arg_value_from_env)) {
858 1 warning("Overwriting option %s = %s",
859 1 entry->arg_name, arg_value_from_env);
860 }
861 56 rhs = arg_value_from_env;
862 }
863 }
864
865 /* Parse LB_option (to be deprecated soon) */
866 6045 const char *arg_value = getenv(entry->var_name);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6045 times.
6045 if (arg_value) {
868 if (rhs) {
869 warning("Ignoring option %s = %s due to DLB_ARGS precedence",
870 entry->var_name, arg_value);
871 } else {
872 warning("Option %s is to be deprecated in the near future, please use DLB_ARGS",
873 entry->var_name);
874 rhs = arg_value;
875 }
876 }
877
878 /* Warn if option is deprecated and has rhs */
879
4/4
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 5735 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 307 times.
6045 if (entry->flags & OPT_DEPRECATED && rhs) {
880 3 warning("Option %s is deprecated:\n%s", entry->arg_name, entry->description);
881 }
882
883 /* Skip iteration if option is not used anymore */
884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6045 times.
6045 if (entry->flags & OPT_UNUSED) {
885 continue;
886 }
887
888 /* Assign option = rhs, and nullify rhs if error */
889
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 5679 times.
6045 if (rhs) {
890 366 int error = set_value(entry->type, (char*)options+entry->offset, rhs);
891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 if (error) {
892 warning("Unrecognized %s value: %s. Setting default %s",
893 entry->arg_name, rhs, entry->default_value);
894 rhs = NULL;
895 }
896 }
897
898 /* Set default value if needed */
899
4/4
✓ Branch 0 taken 5679 times.
✓ Branch 1 taken 366 times.
✓ Branch 2 taken 5372 times.
✓ Branch 3 taken 307 times.
6045 if (!rhs && !(entry->flags & OPT_DEPRECATED)) {
900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5372 times.
5372 fatal_cond(!(entry->flags & OPT_OPTIONAL),
901 "Variable %s must be defined", entry->arg_name);
902 5372 int error = set_value(entry->type, (char*)options+entry->offset, entry->default_value);
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5372 times.
5372 fatal_cond(error, "Internal error parsing default value %s=%s. Please, report bug at %s.",
904 entry->arg_name, entry->default_value, PACKAGE_BUGREPORT);
905 }
906 }
907
908 /* Free intermediate buffers */
909 155 free(arg_value_from_api);
910 155 free(arg_value_from_env);
911
912 /* Safety checks and free local buffers */
913
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 28 times.
155 if (dlb_args_from_api) {
914 127 char *str = dlb_args_from_api;
915
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 127 times.
335 while(isspace((unsigned char)*str)) str++;
916
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 124 times.
127 if (strlen(str) > 0) {
917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (options->debug_opts & DBG_WERROR) {
918 fatal("Unrecognized flags from DLB_Init: %s", str);
919 } else {
920 3 warning("Unrecognized flags from DLB_Init: %s", str);
921 }
922 }
923 127 free(dlb_args_from_api);
924 }
925
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 131 times.
155 if (dlb_args_from_env) {
926 24 char *str = dlb_args_from_env;
927
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 24 times.
60 while(isspace((unsigned char)*str)) str++;
928
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
24 if (strlen(str) > 0) {
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (options->debug_opts & DBG_WERROR) {
930 fatal("Unrecognized flags from DLB_ARGS: %s", str);
931 } else {
932 1 warning("Unrecognized flags from DLB_ARGS: %s", str);
933 }
934 }
935 24 free(dlb_args_from_env);
936 }
937 155 }
938
939 85 void options_finalize(options_t *options) {
940
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 84 times.
85 if (options->talp_output_file) {
941 1 free(options->talp_output_file);
942 1 options->talp_output_file = NULL;
943 }
944 85 }
945
946 /* Obtain value of specific entry, either from DLB_ARGS or from thread_spd->options */
947 226 void options_parse_entry(const char *var_name, void *option) {
948 226 const opts_dict_t *entry = get_entry_by_name(var_name);
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 ensure(entry, "%s: bad variable name '%s'", __func__, var_name);
950
951
4/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 179 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 32 times.
226 if (thread_spd && thread_spd->dlb_initialized) {
952 15 copy_value(entry->type, option, (char*)&thread_spd->options + entry->offset);
953 } else {
954 /* Simplified options_init just for this entry */
955
956 /* Copy DLB_ARGS into a local buffer */
957 211 char *dlb_args_from_env = NULL;
958 211 const char *env = getenv("DLB_ARGS");
959
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 144 times.
211 if (env) {
960 67 size_t len = strlen(env) + 1;
961 67 dlb_args_from_env = malloc(sizeof(char)*len);
962 67 strcpy(dlb_args_from_env, env);
963 }
964
965 /* Pointer to rhs to be parsed */
966 211 const char *rhs = NULL;
967
968 /* Set-up specific argument length */
969 size_t arg_max_len;
970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211 times.
211 switch (entry->type) {
971 case OPT_PTR_PATH_T:
972 arg_max_len = PATH_MAX-1;
973 break;
974 211 default:
975 211 arg_max_len = MAX_OPTION_LENGTH-1;
976 211 break;
977 }
978
979 /* Preallocate a buffer large enough to save the option value */
980 211 char *arg_value_from_env = malloc(sizeof(char)*(arg_max_len+1));
981 211 arg_value_from_env[0] = '\0';
982
983 /* Parse DLB_ARGS from env */
984
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 144 times.
211 if (dlb_args_from_env) {
985 67 parse_dlb_args(dlb_args_from_env, entry->arg_name, arg_value_from_env, arg_max_len);
986
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 37 times.
67 if (strlen(arg_value_from_env) > 0) {
987 30 rhs = arg_value_from_env;
988 }
989 }
990
991 /* Assign option = rhs, and nullify rhs if error */
992
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 181 times.
211 if (rhs) {
993 30 int error = set_value(entry->type, option, rhs);
994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (error) {
995 rhs = NULL;
996 }
997 }
998
999 /* Set default value if needed */
1000
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 30 times.
211 if (!rhs) {
1001 181 set_value(entry->type, option, entry->default_value);
1002 }
1003
1004 /* Free buffers */
1005 211 free(arg_value_from_env);
1006
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 144 times.
211 if (dlb_args_from_env) {
1007 67 free(dlb_args_from_env);
1008 }
1009 }
1010 226 }
1011
1012 /* API Setter */
1013 8 int options_set_variable(options_t *options, const char *var_name, const char *value) {
1014 int error;
1015 8 const opts_dict_t *entry = get_entry_by_name(var_name);
1016
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (entry) {
1017
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (entry->flags & OPT_READONLY) {
1018 3 error = DLB_ERR_PERM;
1019 } else {
1020 4 error = set_value(entry->type, (char*)options+entry->offset, value);
1021 }
1022 } else {
1023 1 error = DLB_ERR_NOENT;
1024 }
1025
1026 8 return error;
1027 }
1028
1029 /* API Getter */
1030 12 int options_get_variable(const options_t *options, const char *var_name, char *value) {
1031 int error;
1032 12 const opts_dict_t *entry = get_entry_by_name(var_name);
1033
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (entry) {
1034 11 sprintf(value, "%s", get_value(entry->type, (char*)options+entry->offset));
1035 11 error = DLB_SUCCESS;
1036 } else {
1037 1 error = DLB_ERR_NOENT;
1038 }
1039
1040 12 return error;
1041 }
1042
1043 /* API Printer. Also, dlb -h/-hh output */
1044 4 void options_print_variables(const options_t *options, bool print_extended) {
1045
1046 /* Initialize buffer */
1047 print_buffer_t buffer;
1048 4 printbuffer_init(&buffer);
1049
1050 /* Set up intermediate buffer per entry */
1051 enum { MAX_ENTRY_LEN = 256 };
1052 char entry_buffer[MAX_ENTRY_LEN];
1053
1054 /* Header (last \n is not needed) */
1055 4 printbuffer_append(&buffer,
1056 "DLB Options:\n\n"
1057 "DLB is configured by setting these flags in the DLB_ARGS environment variable.\n"
1058 "Possible options are listed below:\n\n"
1059 "Option Current value Possible value (type) / [choice] / {val1:val2}\n"
1060 "--------------------------------------------------------------------------------------"
1061 );
1062
1063 int i;
1064
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 4 times.
160 for (i=0; i<NUM_OPTIONS; ++i) {
1065 156 const opts_dict_t *entry = &options_dictionary[i];
1066
1067 /* Skip if deprecated */
1068
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 148 times.
156 if (entry->flags & OPT_DEPRECATED) continue;
1069
1070 /* Skip if hidden */
1071
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 144 times.
148 if (entry->flags & OPT_HIDDEN) continue;
1072
1073 /* Skip if advanced (unless print_extended) */
1074
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 116 times.
144 if (entry->flags & OPT_ADVANCED
1075
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7 times.
28 && !print_extended) continue;
1076
1077 /* Reset entry buffer */
1078 123 entry_buffer[0] = '\0';
1079 123 char *b = entry_buffer;
1080 123 size_t max_entry_len = MAX_ENTRY_LEN;
1081
1082 /* Name */
1083 123 size_t name_len = strlen(entry->arg_name) + 1;
1084
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 6 times.
123 if (name_len < 24) {
1085 /* Option + tabs until column 24 */
1086
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 20 times.
214 b += snprintf(b, max_entry_len, "%s:%s",
1087 117 entry->arg_name,
1088
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 41 times.
97 name_len < 8 ? "\t\t\t" : name_len < 16 ? "\t\t" : "\t");
1089 } else {
1090 /* Long option, break line */
1091 6 b += snprintf(b, max_entry_len, "%s:\n\t\t\t",
1092 6 entry->arg_name);
1093 }
1094
1095 /* Check if output was truncated, and update remaining entry length */
1096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 fatal_cond((b - entry_buffer) >= MAX_ENTRY_LEN,
1097 "Output truncated in in %s. Please report bug at %s",
1098 __func__, PACKAGE_BUGREPORT);
1099 123 max_entry_len = MAX_ENTRY_LEN - (b - entry_buffer);
1100
1101 /* Value */
1102 123 const char *value = get_value(entry->type, (char*)options+entry->offset);
1103 123 size_t value_len = strlen(value) + 1;
1104
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 110 times.
136 b += snprintf(b, max_entry_len, "%s %s",
1105 value,
1106
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 value_len < 8 ? "\t\t" : value_len < 16 ? "\t" : "");
1107
1108 /* Check if output was truncated, and update remaining entry length */
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 fatal_cond((b - entry_buffer) >= MAX_ENTRY_LEN,
1110 "Output truncated in in %s. Please report bug at %s",
1111 __func__, PACKAGE_BUGREPORT);
1112 123 max_entry_len = MAX_ENTRY_LEN - (b - entry_buffer);
1113
1114 /* Choices */
1115
15/18
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
123 switch(entry->type) {
1116 64 case OPT_BOOL_T:
1117 64 b += snprintf(b, max_entry_len, "(bool)");
1118 64 break;
1119 case OPT_NEG_BOOL_T:
1120 b += snprintf(b, max_entry_len, "(bool)");
1121 break;
1122 11 case OPT_INT_T:
1123 11 b += snprintf(b, max_entry_len, "(int)");
1124 11 break;
1125 6 case OPT_STR_T:
1126 6 b += snprintf(b, max_entry_len, "(string)");
1127 6 break;
1128 4 case OPT_PTR_PATH_T:
1129 4 b += snprintf(b, max_entry_len, "(path)");
1130 4 break;
1131 4 case OPT_VB_T:
1132 4 b += snprintf(b, max_entry_len, "{%s}", get_verbose_opts_choices());
1133 4 break;
1134 4 case OPT_VBFMT_T:
1135 4 b += snprintf(b, max_entry_len, "{%s}", get_verbose_fmt_choices());
1136 4 break;
1137 4 case OPT_INST_T:
1138 4 b += snprintf(b, max_entry_len, "{%s}", get_instrument_items_choices());
1139 4 break;
1140 1 case OPT_DBG_T:
1141 1 b += snprintf(b, max_entry_len, "{%s}", get_debug_opts_choices());
1142 1 break;
1143 4 case OPT_LEWI_AFF_T:
1144 4 b += snprintf(b, max_entry_len, "[%s]", get_lewi_affinity_choices());
1145 4 break;
1146 case OPT_MASK_T:
1147 b += snprintf(b, max_entry_len, "(cpuset)");
1148 break;
1149 4 case OPT_MODE_T:
1150 4 b += snprintf(b, max_entry_len, "[%s]", get_mode_choices());
1151 4 break;
1152 4 case OPT_MPISET_T:
1153 4 b += snprintf(b, max_entry_len, "[%s]", get_mpiset_choices());
1154 4 break;
1155 4 case OPT_OMPTOPTS_T:
1156 4 b += snprintf(b, max_entry_len, "[%s]", get_omptool_opts_choices());
1157 4 break;
1158 4 case OPT_TLPSUM_T:
1159 4 b += snprintf(b, max_entry_len, "{%s}", get_talp_summary_choices());
1160 4 break;
1161 1 case OPT_TLPMOD_T:
1162 1 b += snprintf(b, max_entry_len, "[%s]", get_talp_model_choices());
1163 1 break;
1164 4 case OPT_OMPTM_T:
1165 4 b += snprintf(b, max_entry_len, "[%s]", get_omptm_version_choices());
1166 4 break;
1167 }
1168
1169 /* Check if output was truncated */
1170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 fatal_cond((b - entry_buffer) >= MAX_ENTRY_LEN,
1171 "Buffer overflow in %s. Please report bug at %s",
1172 __func__, PACKAGE_BUGREPORT);
1173
1174 /* Append entry listing */
1175 123 printbuffer_append(&buffer, entry_buffer);
1176
1177 /* Append long description if print_extended */
1178
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 87 times.
123 if (print_extended) {
1179 36 printbuffer_append(&buffer, entry->description);
1180 36 printbuffer_append(&buffer, "");
1181 }
1182
1183 }
1184
1185 /* Footer (last \n is not needed) */
1186 4 printbuffer_append(&buffer,
1187 "\n"
1188 "Boolean options accept both standalone flags and 'yes'/'no' parameters.\n"
1189 "These are equivalent flags:\n"
1190 " export DLB_ARGS=\"--lewi --no-drom\"\n"
1191 " export DLB_ARGS=\"--lewi=yes --drom=no\"");
1192
1193 /* This function must print always and ignore options --quiet and --silent */
1194 4 info0_force_print("%s", buffer.addr);
1195
1196 4 printbuffer_destroy(&buffer);
1197 4 }
1198
1199 /* Print which LeWI flags are enabled during DLB_Init */
1200 45 void options_print_lewi_flags(const options_t *options) {
1201 const opts_dict_t *entry;
1202
1203 // --lewi-mpi
1204 bool default_lewi_keep_one_cpu;
1205 45 entry = get_entry_by_name("--lewi-keep-one-cpu");
1206 45 parse_bool(entry->default_value, &default_lewi_keep_one_cpu);
1207
1208 // --lewi-mpi-calls
1209 mpi_set_t default_lewi_mpi_calls;
1210 45 entry = get_entry_by_name("--lewi-mpi-calls");
1211 45 parse_mpiset(entry->default_value, &default_lewi_mpi_calls);
1212
1213 // --lewi-affinity
1214 lewi_affinity_t default_lewi_affinity;
1215 45 entry = get_entry_by_name("--lewi-affinity");
1216 45 parse_lewi_affinity(entry->default_value, &default_lewi_affinity);
1217
1218 // --lewi-ompt
1219 omptool_opts_t default_lewi_ompt;
1220 45 entry = get_entry_by_name("--lewi-ompt");
1221 45 parse_omptool_opts(entry->default_value, &default_lewi_ompt);
1222
1223
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 if (options->lewi_keep_cpu_on_blocking_call != default_lewi_keep_one_cpu
1224
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 || options->lewi_mpi_calls != default_lewi_mpi_calls
1225
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 || options->lewi_affinity != default_lewi_affinity
1226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 || options->lewi_ompt != default_lewi_ompt) {
1227 info0("LeWI options:");
1228 if (options->lewi_keep_cpu_on_blocking_call != default_lewi_keep_one_cpu) {
1229 info0(" --lewi-keep-one-cpu");
1230 }
1231 if (options->lewi_mpi_calls != default_lewi_mpi_calls) {
1232 info0(" --lewi-mpi-calls=%s", mpiset_tostr(options->lewi_mpi_calls));
1233 }
1234 if (options->lewi_affinity != default_lewi_affinity) {
1235 info0(" --lewi-affinity=%s", lewi_affinity_tostr(options->lewi_affinity));
1236 }
1237 if (options->lewi_ompt != default_lewi_ompt) {
1238 info0(" --lewi-ompt=%s", omptool_opts_tostr(options->lewi_ompt));
1239 }
1240 }
1241 45 }
1242