GCC Code Coverage Report


Directory: src/
File: src/support/options.c
Date: 2026-03-27 16:05:46
Exec Total Coverage
Lines: 407 492 82.7%
Functions: 14 14 100.0%
Branches: 213 283 75.3%

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