LLVM OpenMP* Runtime Library
kmp_settings.cpp
1/*
2 * kmp_settings.cpp -- Initialize environment variables
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#include "kmp.h"
14#include "kmp_affinity.h"
15#include "kmp_atomic.h"
16#if KMP_USE_HIER_SCHED
17#include "kmp_dispatch_hier.h"
18#endif
19#include "kmp_environment.h"
20#include "kmp_i18n.h"
21#include "kmp_io.h"
22#include "kmp_itt.h"
23#include "kmp_lock.h"
24#include "kmp_settings.h"
25#include "kmp_str.h"
26#include "kmp_wrapper_getpid.h"
27#include <ctype.h> // toupper()
28#if OMPD_SUPPORT
29#include "ompd-specific.h"
30#endif
31
32static int __kmp_env_toPrint(char const *name, int flag);
33
34bool __kmp_env_format = 0; // 0 - old format; 1 - new format
35
36// -----------------------------------------------------------------------------
37// Helper string functions. Subject to move to kmp_str.
38
39#ifdef USE_LOAD_BALANCE
40static double __kmp_convert_to_double(char const *s) {
41 double result;
42
43 if (KMP_SSCANF(s, "%lf", &result) < 1) {
44 result = 0.0;
45 }
46
47 return result;
48}
49#endif
50
51#ifdef KMP_DEBUG
52static unsigned int __kmp_readstr_with_sentinel(char *dest, char const *src,
53 size_t len, char sentinel) {
54 unsigned int i;
55 for (i = 0; i < len; i++) {
56 if ((*src == '\0') || (*src == sentinel)) {
57 break;
58 }
59 *(dest++) = *(src++);
60 }
61 *dest = '\0';
62 return i;
63}
64#endif
65
66static int __kmp_match_with_sentinel(char const *a, char const *b, size_t len,
67 char sentinel) {
68 size_t l = 0;
69
70 if (a == NULL)
71 a = "";
72 if (b == NULL)
73 b = "";
74 while (*a && *b && *b != sentinel) {
75 char ca = *a, cb = *b;
76
77 if (ca >= 'a' && ca <= 'z')
78 ca -= 'a' - 'A';
79 if (cb >= 'a' && cb <= 'z')
80 cb -= 'a' - 'A';
81 if (ca != cb)
82 return FALSE;
83 ++l;
84 ++a;
85 ++b;
86 }
87 return l >= len;
88}
89
90// Expected usage:
91// token is the token to check for.
92// buf is the string being parsed.
93// *end returns the char after the end of the token.
94// it is not modified unless a match occurs.
95//
96// Example 1:
97//
98// if (__kmp_match_str("token", buf, *end) {
99// <do something>
100// buf = end;
101// }
102//
103// Example 2:
104//
105// if (__kmp_match_str("token", buf, *end) {
106// char *save = **end;
107// **end = sentinel;
108// <use any of the __kmp*_with_sentinel() functions>
109// **end = save;
110// buf = end;
111// }
112
113static int __kmp_match_str(char const *token, char const *buf,
114 const char **end) {
115
116 KMP_ASSERT(token != NULL);
117 KMP_ASSERT(buf != NULL);
118 KMP_ASSERT(end != NULL);
119
120 while (*token && *buf) {
121 char ct = *token, cb = *buf;
122
123 if (ct >= 'a' && ct <= 'z')
124 ct -= 'a' - 'A';
125 if (cb >= 'a' && cb <= 'z')
126 cb -= 'a' - 'A';
127 if (ct != cb)
128 return FALSE;
129 ++token;
130 ++buf;
131 }
132 if (*token) {
133 return FALSE;
134 }
135 *end = buf;
136 return TRUE;
137}
138
139#if KMP_OS_DARWIN
140static size_t __kmp_round4k(size_t size) {
141 size_t _4k = 4 * 1024;
142 if (size & (_4k - 1)) {
143 size &= ~(_4k - 1);
144 if (size <= KMP_SIZE_T_MAX - _4k) {
145 size += _4k; // Round up if there is no overflow.
146 }
147 }
148 return size;
149} // __kmp_round4k
150#endif
151
152/* Here, multipliers are like __kmp_convert_to_seconds, but floating-point
153 values are allowed, and the return value is in milliseconds. The default
154 multiplier is milliseconds. Returns INT_MAX only if the value specified
155 matches "infinit*". Returns -1 if specified string is invalid. */
156int __kmp_convert_to_milliseconds(char const *data) {
157 int ret, nvalues, factor;
158 char mult, extra;
159 double value;
160
161 if (data == NULL)
162 return (-1);
163 if (__kmp_str_match("infinit", -1, data))
164 return (INT_MAX);
165 value = (double)0.0;
166 mult = '\0';
167 nvalues = KMP_SSCANF(data, "%lf%c%c", &value, &mult, &extra);
168 if (nvalues < 1)
169 return (-1);
170 if (nvalues == 1)
171 mult = '\0';
172 if (nvalues == 3)
173 return (-1);
174
175 if (value < 0)
176 return (-1);
177
178 switch (mult) {
179 case '\0':
180 /* default is milliseconds */
181 factor = 1;
182 break;
183 case 's':
184 case 'S':
185 factor = 1000;
186 break;
187 case 'm':
188 case 'M':
189 factor = 1000 * 60;
190 break;
191 case 'h':
192 case 'H':
193 factor = 1000 * 60 * 60;
194 break;
195 case 'd':
196 case 'D':
197 factor = 1000 * 24 * 60 * 60;
198 break;
199 default:
200 return (-1);
201 }
202
203 if (value >= ((INT_MAX - 1) / factor))
204 ret = INT_MAX - 1; /* Don't allow infinite value here */
205 else
206 ret = (int)(value * (double)factor); /* truncate to int */
207
208 return ret;
209}
210
211static int __kmp_strcasecmp_with_sentinel(char const *a, char const *b,
212 char sentinel) {
213 if (a == NULL)
214 a = "";
215 if (b == NULL)
216 b = "";
217 while (*a && *b && *b != sentinel) {
218 char ca = *a, cb = *b;
219
220 if (ca >= 'a' && ca <= 'z')
221 ca -= 'a' - 'A';
222 if (cb >= 'a' && cb <= 'z')
223 cb -= 'a' - 'A';
224 if (ca != cb)
225 return (int)(unsigned char)*a - (int)(unsigned char)*b;
226 ++a;
227 ++b;
228 }
229 return *a ? (*b && *b != sentinel)
230 ? (int)(unsigned char)*a - (int)(unsigned char)*b
231 : 1
232 : (*b && *b != sentinel) ? -1
233 : 0;
234}
235
236// =============================================================================
237// Table structures and helper functions.
238
239typedef struct __kmp_setting kmp_setting_t;
240typedef struct __kmp_stg_ss_data kmp_stg_ss_data_t;
241typedef struct __kmp_stg_wp_data kmp_stg_wp_data_t;
242typedef struct __kmp_stg_fr_data kmp_stg_fr_data_t;
243
244typedef void (*kmp_stg_parse_func_t)(char const *name, char const *value,
245 void *data);
246typedef void (*kmp_stg_print_func_t)(kmp_str_buf_t *buffer, char const *name,
247 void *data);
248
249struct __kmp_setting {
250 char const *name; // Name of setting (environment variable).
251 kmp_stg_parse_func_t parse; // Parser function.
252 kmp_stg_print_func_t print; // Print function.
253 void *data; // Data passed to parser and printer.
254 int set; // Variable set during this "session"
255 // (__kmp_env_initialize() or kmp_set_defaults() call).
256 int defined; // Variable set in any "session".
257}; // struct __kmp_setting
258
259struct __kmp_stg_ss_data {
260 size_t factor; // Default factor: 1 for KMP_STACKSIZE, 1024 for others.
261 kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
262}; // struct __kmp_stg_ss_data
263
264struct __kmp_stg_wp_data {
265 int omp; // 0 -- KMP_LIBRARY, 1 -- OMP_WAIT_POLICY.
266 kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
267}; // struct __kmp_stg_wp_data
268
269struct __kmp_stg_fr_data {
270 int force; // 0 -- KMP_DETERMINISTIC_REDUCTION, 1 -- KMP_FORCE_REDUCTION.
271 kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
272}; // struct __kmp_stg_fr_data
273
274static int __kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
275 char const *name, // Name of variable.
276 char const *value, // Value of the variable.
277 kmp_setting_t **rivals // List of rival settings (must include current one).
278);
279
280// -----------------------------------------------------------------------------
281// Helper parse functions.
282
283static void __kmp_stg_parse_bool(char const *name, char const *value,
284 int *out) {
285 if (__kmp_str_match_true(value)) {
286 *out = TRUE;
287 } else if (__kmp_str_match_false(value)) {
288 *out = FALSE;
289 } else {
290 __kmp_msg(kmp_ms_warning, KMP_MSG(BadBoolValue, name, value),
291 KMP_HNT(ValidBoolValues), __kmp_msg_null);
292 }
293} // __kmp_stg_parse_bool
294
295// placed here in order to use __kmp_round4k static function
296void __kmp_check_stksize(size_t *val) {
297 // if system stack size is too big then limit the size for worker threads
298 if (*val > KMP_DEFAULT_STKSIZE * 16) // just a heuristics...
299 *val = KMP_DEFAULT_STKSIZE * 16;
300 if (*val < KMP_MIN_STKSIZE)
301 *val = KMP_MIN_STKSIZE;
302 if (*val > KMP_MAX_STKSIZE)
303 *val = KMP_MAX_STKSIZE; // dead code currently, but may work in future
304#if KMP_OS_DARWIN
305 *val = __kmp_round4k(*val);
306#endif // KMP_OS_DARWIN
307}
308
309static void __kmp_stg_parse_size(char const *name, char const *value,
310 size_t size_min, size_t size_max,
311 int *is_specified, size_t *out,
312 size_t factor) {
313 char const *msg = NULL;
314#if KMP_OS_DARWIN
315 size_min = __kmp_round4k(size_min);
316 size_max = __kmp_round4k(size_max);
317#endif // KMP_OS_DARWIN
318 if (value) {
319 if (is_specified != NULL) {
320 *is_specified = 1;
321 }
322 __kmp_str_to_size(value, out, factor, &msg);
323 if (msg == NULL) {
324 if (*out > size_max) {
325 *out = size_max;
326 msg = KMP_I18N_STR(ValueTooLarge);
327 } else if (*out < size_min) {
328 *out = size_min;
329 msg = KMP_I18N_STR(ValueTooSmall);
330 } else {
331#if KMP_OS_DARWIN
332 size_t round4k = __kmp_round4k(*out);
333 if (*out != round4k) {
334 *out = round4k;
335 msg = KMP_I18N_STR(NotMultiple4K);
336 }
337#endif
338 }
339 } else {
340 // If integer overflow occurred, * out == KMP_SIZE_T_MAX. Cut it to
341 // size_max silently.
342 if (*out < size_min) {
343 *out = size_max;
344 } else if (*out > size_max) {
345 *out = size_max;
346 }
347 }
348 if (msg != NULL) {
349 // Message is not empty. Print warning.
350 kmp_str_buf_t buf;
351 __kmp_str_buf_init(&buf);
352 __kmp_str_buf_print_size(&buf, *out);
353 KMP_WARNING(ParseSizeIntWarn, name, value, msg);
354 KMP_INFORM(Using_str_Value, name, buf.str);
355 __kmp_str_buf_free(&buf);
356 }
357 }
358} // __kmp_stg_parse_size
359
360static void __kmp_stg_parse_str(char const *name, char const *value,
361 char **out) {
362 __kmp_str_free(out);
363 *out = __kmp_str_format("%s", value);
364} // __kmp_stg_parse_str
365
366static void __kmp_stg_parse_int(
367 char const
368 *name, // I: Name of environment variable (used in warning messages).
369 char const *value, // I: Value of environment variable to parse.
370 int min, // I: Minimum allowed value.
371 int max, // I: Maximum allowed value.
372 int *out // O: Output (parsed) value.
373) {
374 char const *msg = NULL;
375 kmp_uint64 uint = *out;
376 __kmp_str_to_uint(value, &uint, &msg);
377 if (msg == NULL) {
378 if (uint < (unsigned int)min) {
379 msg = KMP_I18N_STR(ValueTooSmall);
380 uint = min;
381 } else if (uint > (unsigned int)max) {
382 msg = KMP_I18N_STR(ValueTooLarge);
383 uint = max;
384 }
385 } else {
386 // If overflow occurred msg contains error message and uint is very big. Cut
387 // tmp it to INT_MAX.
388 if (uint < (unsigned int)min) {
389 uint = min;
390 } else if (uint > (unsigned int)max) {
391 uint = max;
392 }
393 }
394 if (msg != NULL) {
395 // Message is not empty. Print warning.
396 kmp_str_buf_t buf;
397 KMP_WARNING(ParseSizeIntWarn, name, value, msg);
398 __kmp_str_buf_init(&buf);
399 __kmp_str_buf_print(&buf, "%" KMP_UINT64_SPEC "", uint);
400 KMP_INFORM(Using_uint64_Value, name, buf.str);
401 __kmp_str_buf_free(&buf);
402 }
403 __kmp_type_convert(uint, out);
404} // __kmp_stg_parse_int
405
406#if KMP_DEBUG_ADAPTIVE_LOCKS
407static void __kmp_stg_parse_file(char const *name, char const *value,
408 const char *suffix, char **out) {
409 char buffer[256];
410 char *t;
411 int hasSuffix;
412 __kmp_str_free(out);
413 t = (char *)strrchr(value, '.');
414 hasSuffix = t && __kmp_str_eqf(t, suffix);
415 t = __kmp_str_format("%s%s", value, hasSuffix ? "" : suffix);
416 __kmp_expand_file_name(buffer, sizeof(buffer), t);
417 __kmp_str_free(&t);
418 *out = __kmp_str_format("%s", buffer);
419} // __kmp_stg_parse_file
420#endif
421
422#ifdef KMP_DEBUG
423static char *par_range_to_print = NULL;
424
425static void __kmp_stg_parse_par_range(char const *name, char const *value,
426 int *out_range, char *out_routine,
427 char *out_file, int *out_lb,
428 int *out_ub) {
429 size_t len = KMP_STRLEN(value) + 1;
430 par_range_to_print = (char *)KMP_INTERNAL_MALLOC(len + 1);
431 KMP_STRNCPY_S(par_range_to_print, len + 1, value, len + 1);
432 __kmp_par_range = +1;
433 __kmp_par_range_lb = 0;
434 __kmp_par_range_ub = INT_MAX;
435 for (;;) {
436 unsigned int len;
437 if (*value == '\0') {
438 break;
439 }
440 if (!__kmp_strcasecmp_with_sentinel("routine", value, '=')) {
441 value = strchr(value, '=') + 1;
442 len = __kmp_readstr_with_sentinel(out_routine, value,
443 KMP_PAR_RANGE_ROUTINE_LEN - 1, ',');
444 if (len == 0) {
445 goto par_range_error;
446 }
447 value = strchr(value, ',');
448 if (value != NULL) {
449 value++;
450 }
451 continue;
452 }
453 if (!__kmp_strcasecmp_with_sentinel("filename", value, '=')) {
454 value = strchr(value, '=') + 1;
455 len = __kmp_readstr_with_sentinel(out_file, value,
456 KMP_PAR_RANGE_FILENAME_LEN - 1, ',');
457 if (len == 0) {
458 goto par_range_error;
459 }
460 value = strchr(value, ',');
461 if (value != NULL) {
462 value++;
463 }
464 continue;
465 }
466 if ((!__kmp_strcasecmp_with_sentinel("range", value, '=')) ||
467 (!__kmp_strcasecmp_with_sentinel("incl_range", value, '='))) {
468 value = strchr(value, '=') + 1;
469 if (KMP_SSCANF(value, "%d:%d", out_lb, out_ub) != 2) {
470 goto par_range_error;
471 }
472 *out_range = +1;
473 value = strchr(value, ',');
474 if (value != NULL) {
475 value++;
476 }
477 continue;
478 }
479 if (!__kmp_strcasecmp_with_sentinel("excl_range", value, '=')) {
480 value = strchr(value, '=') + 1;
481 if (KMP_SSCANF(value, "%d:%d", out_lb, out_ub) != 2) {
482 goto par_range_error;
483 }
484 *out_range = -1;
485 value = strchr(value, ',');
486 if (value != NULL) {
487 value++;
488 }
489 continue;
490 }
491 par_range_error:
492 KMP_WARNING(ParRangeSyntax, name);
493 __kmp_par_range = 0;
494 break;
495 }
496} // __kmp_stg_parse_par_range
497#endif
498
499int __kmp_initial_threads_capacity(int req_nproc) {
500 int nth = 32;
501
502 /* MIN( MAX( 32, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ),
503 * __kmp_max_nth) */
504 if (nth < (4 * req_nproc))
505 nth = (4 * req_nproc);
506 if (nth < (4 * __kmp_xproc))
507 nth = (4 * __kmp_xproc);
508
509 // If hidden helper task is enabled, we initialize the thread capacity with
510 // extra __kmp_hidden_helper_threads_num.
511 if (__kmp_enable_hidden_helper) {
512 nth += __kmp_hidden_helper_threads_num;
513 }
514
515 if (nth > __kmp_max_nth)
516 nth = __kmp_max_nth;
517
518 return nth;
519}
520
521int __kmp_default_tp_capacity(int req_nproc, int max_nth,
522 int all_threads_specified) {
523 int nth = 128;
524
525 if (all_threads_specified)
526 return max_nth;
527 /* MIN( MAX (128, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ),
528 * __kmp_max_nth ) */
529 if (nth < (4 * req_nproc))
530 nth = (4 * req_nproc);
531 if (nth < (4 * __kmp_xproc))
532 nth = (4 * __kmp_xproc);
533
534 if (nth > __kmp_max_nth)
535 nth = __kmp_max_nth;
536
537 return nth;
538}
539
540// -----------------------------------------------------------------------------
541// Helper print functions.
542
543static void __kmp_stg_print_bool(kmp_str_buf_t *buffer, char const *name,
544 int value) {
545 if (__kmp_env_format) {
546 KMP_STR_BUF_PRINT_BOOL;
547 } else {
548 __kmp_str_buf_print(buffer, " %s=%s\n", name, value ? "true" : "false");
549 }
550} // __kmp_stg_print_bool
551
552static void __kmp_stg_print_int(kmp_str_buf_t *buffer, char const *name,
553 int value) {
554 if (__kmp_env_format) {
555 KMP_STR_BUF_PRINT_INT;
556 } else {
557 __kmp_str_buf_print(buffer, " %s=%d\n", name, value);
558 }
559} // __kmp_stg_print_int
560
561static void __kmp_stg_print_uint64(kmp_str_buf_t *buffer, char const *name,
562 kmp_uint64 value) {
563 if (__kmp_env_format) {
564 KMP_STR_BUF_PRINT_UINT64;
565 } else {
566 __kmp_str_buf_print(buffer, " %s=%" KMP_UINT64_SPEC "\n", name, value);
567 }
568} // __kmp_stg_print_uint64
569
570static void __kmp_stg_print_str(kmp_str_buf_t *buffer, char const *name,
571 char const *value) {
572 if (__kmp_env_format) {
573 KMP_STR_BUF_PRINT_STR;
574 } else {
575 __kmp_str_buf_print(buffer, " %s=%s\n", name, value);
576 }
577} // __kmp_stg_print_str
578
579static void __kmp_stg_print_size(kmp_str_buf_t *buffer, char const *name,
580 size_t value) {
581 if (__kmp_env_format) {
582 KMP_STR_BUF_PRINT_NAME_EX(name);
583 __kmp_str_buf_print_size(buffer, value);
584 __kmp_str_buf_print(buffer, "'\n");
585 } else {
586 __kmp_str_buf_print(buffer, " %s=", name);
587 __kmp_str_buf_print_size(buffer, value);
588 __kmp_str_buf_print(buffer, "\n");
589 return;
590 }
591} // __kmp_stg_print_size
592
593// =============================================================================
594// Parse and print functions.
595
596// -----------------------------------------------------------------------------
597// KMP_DEVICE_THREAD_LIMIT, KMP_ALL_THREADS
598
599static void __kmp_stg_parse_device_thread_limit(char const *name,
600 char const *value, void *data) {
601 kmp_setting_t **rivals = (kmp_setting_t **)data;
602 int rc;
603 if (strcmp(name, "KMP_ALL_THREADS") == 0) {
604 KMP_INFORM(EnvVarDeprecated, name, "KMP_DEVICE_THREAD_LIMIT");
605 }
606 rc = __kmp_stg_check_rivals(name, value, rivals);
607 if (rc) {
608 return;
609 }
610 if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
611 __kmp_max_nth = __kmp_xproc;
612 __kmp_allThreadsSpecified = 1;
613 } else {
614 __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_max_nth);
615 __kmp_allThreadsSpecified = 0;
616 }
617 K_DIAG(1, ("__kmp_max_nth == %d\n", __kmp_max_nth));
618
619} // __kmp_stg_parse_device_thread_limit
620
621static void __kmp_stg_print_device_thread_limit(kmp_str_buf_t *buffer,
622 char const *name, void *data) {
623 __kmp_stg_print_int(buffer, name, __kmp_max_nth);
624} // __kmp_stg_print_device_thread_limit
625
626// -----------------------------------------------------------------------------
627// OMP_THREAD_LIMIT
628static void __kmp_stg_parse_thread_limit(char const *name, char const *value,
629 void *data) {
630 __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_cg_max_nth);
631 K_DIAG(1, ("__kmp_cg_max_nth == %d\n", __kmp_cg_max_nth));
632
633} // __kmp_stg_parse_thread_limit
634
635static void __kmp_stg_print_thread_limit(kmp_str_buf_t *buffer,
636 char const *name, void *data) {
637 __kmp_stg_print_int(buffer, name, __kmp_cg_max_nth);
638} // __kmp_stg_print_thread_limit
639
640// -----------------------------------------------------------------------------
641// OMP_NUM_TEAMS
642static void __kmp_stg_parse_nteams(char const *name, char const *value,
643 void *data) {
644 __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_nteams);
645 K_DIAG(1, ("__kmp_nteams == %d\n", __kmp_nteams));
646} // __kmp_stg_parse_nteams
647
648static void __kmp_stg_print_nteams(kmp_str_buf_t *buffer, char const *name,
649 void *data) {
650 __kmp_stg_print_int(buffer, name, __kmp_nteams);
651} // __kmp_stg_print_nteams
652
653// -----------------------------------------------------------------------------
654// OMP_TEAMS_THREAD_LIMIT
655static void __kmp_stg_parse_teams_th_limit(char const *name, char const *value,
656 void *data) {
657 __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth,
658 &__kmp_teams_thread_limit);
659 K_DIAG(1, ("__kmp_teams_thread_limit == %d\n", __kmp_teams_thread_limit));
660} // __kmp_stg_parse_teams_th_limit
661
662static void __kmp_stg_print_teams_th_limit(kmp_str_buf_t *buffer,
663 char const *name, void *data) {
664 __kmp_stg_print_int(buffer, name, __kmp_teams_thread_limit);
665} // __kmp_stg_print_teams_th_limit
666
667// -----------------------------------------------------------------------------
668// KMP_TEAMS_THREAD_LIMIT
669static void __kmp_stg_parse_teams_thread_limit(char const *name,
670 char const *value, void *data) {
671 __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_teams_max_nth);
672} // __kmp_stg_teams_thread_limit
673
674static void __kmp_stg_print_teams_thread_limit(kmp_str_buf_t *buffer,
675 char const *name, void *data) {
676 __kmp_stg_print_int(buffer, name, __kmp_teams_max_nth);
677} // __kmp_stg_print_teams_thread_limit
678
679// -----------------------------------------------------------------------------
680// KMP_USE_YIELD
681static void __kmp_stg_parse_use_yield(char const *name, char const *value,
682 void *data) {
683 __kmp_stg_parse_int(name, value, 0, 2, &__kmp_use_yield);
684 __kmp_use_yield_exp_set = 1;
685} // __kmp_stg_parse_use_yield
686
687static void __kmp_stg_print_use_yield(kmp_str_buf_t *buffer, char const *name,
688 void *data) {
689 __kmp_stg_print_int(buffer, name, __kmp_use_yield);
690} // __kmp_stg_print_use_yield
691
692// -----------------------------------------------------------------------------
693// KMP_BLOCKTIME
694
695static void __kmp_stg_parse_blocktime(char const *name, char const *value,
696 void *data) {
697 __kmp_dflt_blocktime = __kmp_convert_to_milliseconds(value);
698 if (__kmp_dflt_blocktime < 0) {
699 __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
700 __kmp_msg(kmp_ms_warning, KMP_MSG(InvalidValue, name, value),
701 __kmp_msg_null);
702 KMP_INFORM(Using_int_Value, name, __kmp_dflt_blocktime);
703 __kmp_env_blocktime = FALSE; // Revert to default as if var not set.
704 } else {
705 if (__kmp_dflt_blocktime < KMP_MIN_BLOCKTIME) {
706 __kmp_dflt_blocktime = KMP_MIN_BLOCKTIME;
707 __kmp_msg(kmp_ms_warning, KMP_MSG(SmallValue, name, value),
708 __kmp_msg_null);
709 KMP_INFORM(MinValueUsing, name, __kmp_dflt_blocktime);
710 } else if (__kmp_dflt_blocktime > KMP_MAX_BLOCKTIME) {
711 __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
712 __kmp_msg(kmp_ms_warning, KMP_MSG(LargeValue, name, value),
713 __kmp_msg_null);
714 KMP_INFORM(MaxValueUsing, name, __kmp_dflt_blocktime);
715 }
716 __kmp_env_blocktime = TRUE; // KMP_BLOCKTIME was specified.
717 }
718#if KMP_USE_MONITOR
719 // calculate number of monitor thread wakeup intervals corresponding to
720 // blocktime.
721 __kmp_monitor_wakeups =
722 KMP_WAKEUPS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
723 __kmp_bt_intervals =
724 KMP_INTERVALS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
725#endif
726 K_DIAG(1, ("__kmp_env_blocktime == %d\n", __kmp_env_blocktime));
727 if (__kmp_env_blocktime) {
728 K_DIAG(1, ("__kmp_dflt_blocktime == %d\n", __kmp_dflt_blocktime));
729 }
730} // __kmp_stg_parse_blocktime
731
732static void __kmp_stg_print_blocktime(kmp_str_buf_t *buffer, char const *name,
733 void *data) {
734 __kmp_stg_print_int(buffer, name, __kmp_dflt_blocktime);
735} // __kmp_stg_print_blocktime
736
737// -----------------------------------------------------------------------------
738// KMP_DUPLICATE_LIB_OK
739
740static void __kmp_stg_parse_duplicate_lib_ok(char const *name,
741 char const *value, void *data) {
742 /* actually this variable is not supported, put here for compatibility with
743 earlier builds and for static/dynamic combination */
744 __kmp_stg_parse_bool(name, value, &__kmp_duplicate_library_ok);
745} // __kmp_stg_parse_duplicate_lib_ok
746
747static void __kmp_stg_print_duplicate_lib_ok(kmp_str_buf_t *buffer,
748 char const *name, void *data) {
749 __kmp_stg_print_bool(buffer, name, __kmp_duplicate_library_ok);
750} // __kmp_stg_print_duplicate_lib_ok
751
752// -----------------------------------------------------------------------------
753// KMP_INHERIT_FP_CONTROL
754
755#if KMP_ARCH_X86 || KMP_ARCH_X86_64
756
757static void __kmp_stg_parse_inherit_fp_control(char const *name,
758 char const *value, void *data) {
759 __kmp_stg_parse_bool(name, value, &__kmp_inherit_fp_control);
760} // __kmp_stg_parse_inherit_fp_control
761
762static void __kmp_stg_print_inherit_fp_control(kmp_str_buf_t *buffer,
763 char const *name, void *data) {
764#if KMP_DEBUG
765 __kmp_stg_print_bool(buffer, name, __kmp_inherit_fp_control);
766#endif /* KMP_DEBUG */
767} // __kmp_stg_print_inherit_fp_control
768
769#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
770
771// Used for OMP_WAIT_POLICY
772static char const *blocktime_str = NULL;
773
774// -----------------------------------------------------------------------------
775// KMP_LIBRARY, OMP_WAIT_POLICY
776
777static void __kmp_stg_parse_wait_policy(char const *name, char const *value,
778 void *data) {
779
780 kmp_stg_wp_data_t *wait = (kmp_stg_wp_data_t *)data;
781 int rc;
782
783 rc = __kmp_stg_check_rivals(name, value, wait->rivals);
784 if (rc) {
785 return;
786 }
787
788 if (wait->omp) {
789 if (__kmp_str_match("ACTIVE", 1, value)) {
790 __kmp_library = library_turnaround;
791 if (blocktime_str == NULL) {
792 // KMP_BLOCKTIME not specified, so set default to "infinite".
793 __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
794 }
795 } else if (__kmp_str_match("PASSIVE", 1, value)) {
796 __kmp_library = library_throughput;
797 if (blocktime_str == NULL) {
798 // KMP_BLOCKTIME not specified, so set default to 0.
799 __kmp_dflt_blocktime = 0;
800 }
801 } else {
802 KMP_WARNING(StgInvalidValue, name, value);
803 }
804 } else {
805 if (__kmp_str_match("serial", 1, value)) { /* S */
806 __kmp_library = library_serial;
807 } else if (__kmp_str_match("throughput", 2, value)) { /* TH */
808 __kmp_library = library_throughput;
809 if (blocktime_str == NULL) {
810 // KMP_BLOCKTIME not specified, so set default to 0.
811 __kmp_dflt_blocktime = 0;
812 }
813 } else if (__kmp_str_match("turnaround", 2, value)) { /* TU */
814 __kmp_library = library_turnaround;
815 } else if (__kmp_str_match("dedicated", 1, value)) { /* D */
816 __kmp_library = library_turnaround;
817 } else if (__kmp_str_match("multiuser", 1, value)) { /* M */
818 __kmp_library = library_throughput;
819 if (blocktime_str == NULL) {
820 // KMP_BLOCKTIME not specified, so set default to 0.
821 __kmp_dflt_blocktime = 0;
822 }
823 } else {
824 KMP_WARNING(StgInvalidValue, name, value);
825 }
826 }
827} // __kmp_stg_parse_wait_policy
828
829static void __kmp_stg_print_wait_policy(kmp_str_buf_t *buffer, char const *name,
830 void *data) {
831
832 kmp_stg_wp_data_t *wait = (kmp_stg_wp_data_t *)data;
833 char const *value = NULL;
834
835 if (wait->omp) {
836 switch (__kmp_library) {
837 case library_turnaround: {
838 value = "ACTIVE";
839 } break;
840 case library_throughput: {
841 value = "PASSIVE";
842 } break;
843 }
844 } else {
845 switch (__kmp_library) {
846 case library_serial: {
847 value = "serial";
848 } break;
849 case library_turnaround: {
850 value = "turnaround";
851 } break;
852 case library_throughput: {
853 value = "throughput";
854 } break;
855 }
856 }
857 if (value != NULL) {
858 __kmp_stg_print_str(buffer, name, value);
859 }
860
861} // __kmp_stg_print_wait_policy
862
863#if KMP_USE_MONITOR
864// -----------------------------------------------------------------------------
865// KMP_MONITOR_STACKSIZE
866
867static void __kmp_stg_parse_monitor_stacksize(char const *name,
868 char const *value, void *data) {
869 __kmp_stg_parse_size(name, value, __kmp_sys_min_stksize, KMP_MAX_STKSIZE,
870 NULL, &__kmp_monitor_stksize, 1);
871} // __kmp_stg_parse_monitor_stacksize
872
873static void __kmp_stg_print_monitor_stacksize(kmp_str_buf_t *buffer,
874 char const *name, void *data) {
875 if (__kmp_env_format) {
876 if (__kmp_monitor_stksize > 0)
877 KMP_STR_BUF_PRINT_NAME_EX(name);
878 else
879 KMP_STR_BUF_PRINT_NAME;
880 } else {
881 __kmp_str_buf_print(buffer, " %s", name);
882 }
883 if (__kmp_monitor_stksize > 0) {
884 __kmp_str_buf_print_size(buffer, __kmp_monitor_stksize);
885 } else {
886 __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
887 }
888 if (__kmp_env_format && __kmp_monitor_stksize) {
889 __kmp_str_buf_print(buffer, "'\n");
890 }
891} // __kmp_stg_print_monitor_stacksize
892#endif // KMP_USE_MONITOR
893
894// -----------------------------------------------------------------------------
895// KMP_SETTINGS
896
897static void __kmp_stg_parse_settings(char const *name, char const *value,
898 void *data) {
899 __kmp_stg_parse_bool(name, value, &__kmp_settings);
900} // __kmp_stg_parse_settings
901
902static void __kmp_stg_print_settings(kmp_str_buf_t *buffer, char const *name,
903 void *data) {
904 __kmp_stg_print_bool(buffer, name, __kmp_settings);
905} // __kmp_stg_print_settings
906
907// -----------------------------------------------------------------------------
908// KMP_STACKPAD
909
910static void __kmp_stg_parse_stackpad(char const *name, char const *value,
911 void *data) {
912 __kmp_stg_parse_int(name, // Env var name
913 value, // Env var value
914 KMP_MIN_STKPADDING, // Min value
915 KMP_MAX_STKPADDING, // Max value
916 &__kmp_stkpadding // Var to initialize
917 );
918} // __kmp_stg_parse_stackpad
919
920static void __kmp_stg_print_stackpad(kmp_str_buf_t *buffer, char const *name,
921 void *data) {
922 __kmp_stg_print_int(buffer, name, __kmp_stkpadding);
923} // __kmp_stg_print_stackpad
924
925// -----------------------------------------------------------------------------
926// KMP_STACKOFFSET
927
928static void __kmp_stg_parse_stackoffset(char const *name, char const *value,
929 void *data) {
930 __kmp_stg_parse_size(name, // Env var name
931 value, // Env var value
932 KMP_MIN_STKOFFSET, // Min value
933 KMP_MAX_STKOFFSET, // Max value
934 NULL, //
935 &__kmp_stkoffset, // Var to initialize
936 1);
937} // __kmp_stg_parse_stackoffset
938
939static void __kmp_stg_print_stackoffset(kmp_str_buf_t *buffer, char const *name,
940 void *data) {
941 __kmp_stg_print_size(buffer, name, __kmp_stkoffset);
942} // __kmp_stg_print_stackoffset
943
944// -----------------------------------------------------------------------------
945// KMP_STACKSIZE, OMP_STACKSIZE, GOMP_STACKSIZE
946
947static void __kmp_stg_parse_stacksize(char const *name, char const *value,
948 void *data) {
949
950 kmp_stg_ss_data_t *stacksize = (kmp_stg_ss_data_t *)data;
951 int rc;
952
953 rc = __kmp_stg_check_rivals(name, value, stacksize->rivals);
954 if (rc) {
955 return;
956 }
957 __kmp_stg_parse_size(name, // Env var name
958 value, // Env var value
959 __kmp_sys_min_stksize, // Min value
960 KMP_MAX_STKSIZE, // Max value
961 &__kmp_env_stksize, //
962 &__kmp_stksize, // Var to initialize
963 stacksize->factor);
964
965} // __kmp_stg_parse_stacksize
966
967// This function is called for printing both KMP_STACKSIZE (factor is 1) and
968// OMP_STACKSIZE (factor is 1024). Currently it is not possible to print
969// OMP_STACKSIZE value in bytes. We can consider adding this possibility by a
970// customer request in future.
971static void __kmp_stg_print_stacksize(kmp_str_buf_t *buffer, char const *name,
972 void *data) {
973 kmp_stg_ss_data_t *stacksize = (kmp_stg_ss_data_t *)data;
974 if (__kmp_env_format) {
975 KMP_STR_BUF_PRINT_NAME_EX(name);
976 __kmp_str_buf_print_size(buffer, (__kmp_stksize % 1024)
977 ? __kmp_stksize / stacksize->factor
978 : __kmp_stksize);
979 __kmp_str_buf_print(buffer, "'\n");
980 } else {
981 __kmp_str_buf_print(buffer, " %s=", name);
982 __kmp_str_buf_print_size(buffer, (__kmp_stksize % 1024)
983 ? __kmp_stksize / stacksize->factor
984 : __kmp_stksize);
985 __kmp_str_buf_print(buffer, "\n");
986 }
987} // __kmp_stg_print_stacksize
988
989// -----------------------------------------------------------------------------
990// KMP_VERSION
991
992static void __kmp_stg_parse_version(char const *name, char const *value,
993 void *data) {
994 __kmp_stg_parse_bool(name, value, &__kmp_version);
995} // __kmp_stg_parse_version
996
997static void __kmp_stg_print_version(kmp_str_buf_t *buffer, char const *name,
998 void *data) {
999 __kmp_stg_print_bool(buffer, name, __kmp_version);
1000} // __kmp_stg_print_version
1001
1002// -----------------------------------------------------------------------------
1003// KMP_WARNINGS
1004
1005static void __kmp_stg_parse_warnings(char const *name, char const *value,
1006 void *data) {
1007 __kmp_stg_parse_bool(name, value, &__kmp_generate_warnings);
1008 if (__kmp_generate_warnings != kmp_warnings_off) {
1009 // AC: only 0/1 values documented, so reset to explicit to distinguish from
1010 // default setting
1011 __kmp_generate_warnings = kmp_warnings_explicit;
1012 }
1013} // __kmp_stg_parse_warnings
1014
1015static void __kmp_stg_print_warnings(kmp_str_buf_t *buffer, char const *name,
1016 void *data) {
1017 // AC: TODO: change to print_int? (needs documentation change)
1018 __kmp_stg_print_bool(buffer, name, __kmp_generate_warnings);
1019} // __kmp_stg_print_warnings
1020
1021// -----------------------------------------------------------------------------
1022// KMP_NESTING_MODE
1023
1024static void __kmp_stg_parse_nesting_mode(char const *name, char const *value,
1025 void *data) {
1026 __kmp_stg_parse_int(name, value, 0, INT_MAX, &__kmp_nesting_mode);
1027#if KMP_AFFINITY_SUPPORTED && KMP_USE_HWLOC
1028 if (__kmp_nesting_mode > 0)
1029 __kmp_affinity_top_method = affinity_top_method_hwloc;
1030#endif
1031} // __kmp_stg_parse_nesting_mode
1032
1033static void __kmp_stg_print_nesting_mode(kmp_str_buf_t *buffer,
1034 char const *name, void *data) {
1035 if (__kmp_env_format) {
1036 KMP_STR_BUF_PRINT_NAME;
1037 } else {
1038 __kmp_str_buf_print(buffer, " %s", name);
1039 }
1040 __kmp_str_buf_print(buffer, "=%d\n", __kmp_nesting_mode);
1041} // __kmp_stg_print_nesting_mode
1042
1043// -----------------------------------------------------------------------------
1044// OMP_NESTED, OMP_NUM_THREADS
1045
1046static void __kmp_stg_parse_nested(char const *name, char const *value,
1047 void *data) {
1048 int nested;
1049 KMP_INFORM(EnvVarDeprecated, name, "OMP_MAX_ACTIVE_LEVELS");
1050 __kmp_stg_parse_bool(name, value, &nested);
1051 if (nested) {
1052 if (!__kmp_dflt_max_active_levels_set)
1053 __kmp_dflt_max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
1054 } else { // nesting explicitly turned off
1055 __kmp_dflt_max_active_levels = 1;
1056 __kmp_dflt_max_active_levels_set = true;
1057 }
1058} // __kmp_stg_parse_nested
1059
1060static void __kmp_stg_print_nested(kmp_str_buf_t *buffer, char const *name,
1061 void *data) {
1062 if (__kmp_env_format) {
1063 KMP_STR_BUF_PRINT_NAME;
1064 } else {
1065 __kmp_str_buf_print(buffer, " %s", name);
1066 }
1067 __kmp_str_buf_print(buffer, ": deprecated; max-active-levels-var=%d\n",
1068 __kmp_dflt_max_active_levels);
1069} // __kmp_stg_print_nested
1070
1071static void __kmp_parse_nested_num_threads(const char *var, const char *env,
1072 kmp_nested_nthreads_t *nth_array) {
1073 const char *next = env;
1074 const char *scan = next;
1075
1076 int total = 0; // Count elements that were set. It'll be used as an array size
1077 int prev_comma = FALSE; // For correct processing sequential commas
1078
1079 // Count the number of values in the env. var string
1080 for (;;) {
1081 SKIP_WS(next);
1082
1083 if (*next == '\0') {
1084 break;
1085 }
1086 // Next character is not an integer or not a comma => end of list
1087 if (((*next < '0') || (*next > '9')) && (*next != ',')) {
1088 KMP_WARNING(NthSyntaxError, var, env);
1089 return;
1090 }
1091 // The next character is ','
1092 if (*next == ',') {
1093 // ',' is the first character
1094 if (total == 0 || prev_comma) {
1095 total++;
1096 }
1097 prev_comma = TRUE;
1098 next++; // skip ','
1099 SKIP_WS(next);
1100 }
1101 // Next character is a digit
1102 if (*next >= '0' && *next <= '9') {
1103 prev_comma = FALSE;
1104 SKIP_DIGITS(next);
1105 total++;
1106 const char *tmp = next;
1107 SKIP_WS(tmp);
1108 if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
1109 KMP_WARNING(NthSpacesNotAllowed, var, env);
1110 return;
1111 }
1112 }
1113 }
1114 if (!__kmp_dflt_max_active_levels_set && total > 1)
1115 __kmp_dflt_max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
1116 KMP_DEBUG_ASSERT(total > 0);
1117 if (total <= 0) {
1118 KMP_WARNING(NthSyntaxError, var, env);
1119 return;
1120 }
1121
1122 // Check if the nested nthreads array exists
1123 if (!nth_array->nth) {
1124 // Allocate an array of double size
1125 nth_array->nth = (int *)KMP_INTERNAL_MALLOC(sizeof(int) * total * 2);
1126 if (nth_array->nth == NULL) {
1127 KMP_FATAL(MemoryAllocFailed);
1128 }
1129 nth_array->size = total * 2;
1130 } else {
1131 if (nth_array->size < total) {
1132 // Increase the array size
1133 do {
1134 nth_array->size *= 2;
1135 } while (nth_array->size < total);
1136
1137 nth_array->nth = (int *)KMP_INTERNAL_REALLOC(
1138 nth_array->nth, sizeof(int) * nth_array->size);
1139 if (nth_array->nth == NULL) {
1140 KMP_FATAL(MemoryAllocFailed);
1141 }
1142 }
1143 }
1144 nth_array->used = total;
1145 int i = 0;
1146
1147 prev_comma = FALSE;
1148 total = 0;
1149 // Save values in the array
1150 for (;;) {
1151 SKIP_WS(scan);
1152 if (*scan == '\0') {
1153 break;
1154 }
1155 // The next character is ','
1156 if (*scan == ',') {
1157 // ',' in the beginning of the list
1158 if (total == 0) {
1159 // The value is supposed to be equal to __kmp_avail_proc but it is
1160 // unknown at the moment.
1161 // So let's put a placeholder (#threads = 0) to correct it later.
1162 nth_array->nth[i++] = 0;
1163 total++;
1164 } else if (prev_comma) {
1165 // Num threads is inherited from the previous level
1166 nth_array->nth[i] = nth_array->nth[i - 1];
1167 i++;
1168 total++;
1169 }
1170 prev_comma = TRUE;
1171 scan++; // skip ','
1172 SKIP_WS(scan);
1173 }
1174 // Next character is a digit
1175 if (*scan >= '0' && *scan <= '9') {
1176 int num;
1177 const char *buf = scan;
1178 char const *msg = NULL;
1179 prev_comma = FALSE;
1180 SKIP_DIGITS(scan);
1181 total++;
1182
1183 num = __kmp_str_to_int(buf, *scan);
1184 if (num < KMP_MIN_NTH) {
1185 msg = KMP_I18N_STR(ValueTooSmall);
1186 num = KMP_MIN_NTH;
1187 } else if (num > __kmp_sys_max_nth) {
1188 msg = KMP_I18N_STR(ValueTooLarge);
1189 num = __kmp_sys_max_nth;
1190 }
1191 if (msg != NULL) {
1192 // Message is not empty. Print warning.
1193 KMP_WARNING(ParseSizeIntWarn, var, env, msg);
1194 KMP_INFORM(Using_int_Value, var, num);
1195 }
1196 nth_array->nth[i++] = num;
1197 }
1198 }
1199}
1200
1201static void __kmp_stg_parse_num_threads(char const *name, char const *value,
1202 void *data) {
1203 // TODO: Remove this option. OMP_NUM_THREADS is a list of positive integers!
1204 if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
1205 // The array of 1 element
1206 __kmp_nested_nth.nth = (int *)KMP_INTERNAL_MALLOC(sizeof(int));
1207 __kmp_nested_nth.size = __kmp_nested_nth.used = 1;
1208 __kmp_nested_nth.nth[0] = __kmp_dflt_team_nth = __kmp_dflt_team_nth_ub =
1209 __kmp_xproc;
1210 } else {
1211 __kmp_parse_nested_num_threads(name, value, &__kmp_nested_nth);
1212 if (__kmp_nested_nth.nth) {
1213 __kmp_dflt_team_nth = __kmp_nested_nth.nth[0];
1214 if (__kmp_dflt_team_nth_ub < __kmp_dflt_team_nth) {
1215 __kmp_dflt_team_nth_ub = __kmp_dflt_team_nth;
1216 }
1217 }
1218 }
1219 K_DIAG(1, ("__kmp_dflt_team_nth == %d\n", __kmp_dflt_team_nth));
1220} // __kmp_stg_parse_num_threads
1221
1222static void __kmp_stg_parse_num_hidden_helper_threads(char const *name,
1223 char const *value,
1224 void *data) {
1225 __kmp_stg_parse_int(name, value, 0, 16, &__kmp_hidden_helper_threads_num);
1226 // If the number of hidden helper threads is zero, we disable hidden helper
1227 // task
1228 if (__kmp_hidden_helper_threads_num == 0) {
1229 __kmp_enable_hidden_helper = FALSE;
1230 }
1231} // __kmp_stg_parse_num_hidden_helper_threads
1232
1233static void __kmp_stg_print_num_hidden_helper_threads(kmp_str_buf_t *buffer,
1234 char const *name,
1235 void *data) {
1236 __kmp_stg_print_int(buffer, name, __kmp_hidden_helper_threads_num);
1237} // __kmp_stg_print_num_hidden_helper_threads
1238
1239static void __kmp_stg_parse_use_hidden_helper(char const *name,
1240 char const *value, void *data) {
1241 __kmp_stg_parse_bool(name, value, &__kmp_enable_hidden_helper);
1242#if !KMP_OS_LINUX
1243 __kmp_enable_hidden_helper = FALSE;
1244 K_DIAG(1,
1245 ("__kmp_stg_parse_use_hidden_helper: Disable hidden helper task on "
1246 "non-Linux platform although it is enabled by user explicitly.\n"));
1247#endif
1248} // __kmp_stg_parse_use_hidden_helper
1249
1250static void __kmp_stg_print_use_hidden_helper(kmp_str_buf_t *buffer,
1251 char const *name, void *data) {
1252 __kmp_stg_print_bool(buffer, name, __kmp_enable_hidden_helper);
1253} // __kmp_stg_print_use_hidden_helper
1254
1255static void __kmp_stg_print_num_threads(kmp_str_buf_t *buffer, char const *name,
1256 void *data) {
1257 if (__kmp_env_format) {
1258 KMP_STR_BUF_PRINT_NAME;
1259 } else {
1260 __kmp_str_buf_print(buffer, " %s", name);
1261 }
1262 if (__kmp_nested_nth.used) {
1263 kmp_str_buf_t buf;
1264 __kmp_str_buf_init(&buf);
1265 for (int i = 0; i < __kmp_nested_nth.used; i++) {
1266 __kmp_str_buf_print(&buf, "%d", __kmp_nested_nth.nth[i]);
1267 if (i < __kmp_nested_nth.used - 1) {
1268 __kmp_str_buf_print(&buf, ",");
1269 }
1270 }
1271 __kmp_str_buf_print(buffer, "='%s'\n", buf.str);
1272 __kmp_str_buf_free(&buf);
1273 } else {
1274 __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1275 }
1276} // __kmp_stg_print_num_threads
1277
1278// -----------------------------------------------------------------------------
1279// OpenMP 3.0: KMP_TASKING, OMP_MAX_ACTIVE_LEVELS,
1280
1281static void __kmp_stg_parse_tasking(char const *name, char const *value,
1282 void *data) {
1283 __kmp_stg_parse_int(name, value, 0, (int)tskm_max,
1284 (int *)&__kmp_tasking_mode);
1285} // __kmp_stg_parse_tasking
1286
1287static void __kmp_stg_print_tasking(kmp_str_buf_t *buffer, char const *name,
1288 void *data) {
1289 __kmp_stg_print_int(buffer, name, __kmp_tasking_mode);
1290} // __kmp_stg_print_tasking
1291
1292static void __kmp_stg_parse_task_stealing(char const *name, char const *value,
1293 void *data) {
1294 __kmp_stg_parse_int(name, value, 0, 1,
1295 (int *)&__kmp_task_stealing_constraint);
1296} // __kmp_stg_parse_task_stealing
1297
1298static void __kmp_stg_print_task_stealing(kmp_str_buf_t *buffer,
1299 char const *name, void *data) {
1300 __kmp_stg_print_int(buffer, name, __kmp_task_stealing_constraint);
1301} // __kmp_stg_print_task_stealing
1302
1303static void __kmp_stg_parse_max_active_levels(char const *name,
1304 char const *value, void *data) {
1305 kmp_uint64 tmp_dflt = 0;
1306 char const *msg = NULL;
1307 if (!__kmp_dflt_max_active_levels_set) {
1308 // Don't overwrite __kmp_dflt_max_active_levels if we get an invalid setting
1309 __kmp_str_to_uint(value, &tmp_dflt, &msg);
1310 if (msg != NULL) { // invalid setting; print warning and ignore
1311 KMP_WARNING(ParseSizeIntWarn, name, value, msg);
1312 } else if (tmp_dflt > KMP_MAX_ACTIVE_LEVELS_LIMIT) {
1313 // invalid setting; print warning and ignore
1314 msg = KMP_I18N_STR(ValueTooLarge);
1315 KMP_WARNING(ParseSizeIntWarn, name, value, msg);
1316 } else { // valid setting
1317 __kmp_type_convert(tmp_dflt, &(__kmp_dflt_max_active_levels));
1318 __kmp_dflt_max_active_levels_set = true;
1319 }
1320 }
1321} // __kmp_stg_parse_max_active_levels
1322
1323static void __kmp_stg_print_max_active_levels(kmp_str_buf_t *buffer,
1324 char const *name, void *data) {
1325 __kmp_stg_print_int(buffer, name, __kmp_dflt_max_active_levels);
1326} // __kmp_stg_print_max_active_levels
1327
1328// -----------------------------------------------------------------------------
1329// OpenMP 4.0: OMP_DEFAULT_DEVICE
1330static void __kmp_stg_parse_default_device(char const *name, char const *value,
1331 void *data) {
1332 __kmp_stg_parse_int(name, value, 0, KMP_MAX_DEFAULT_DEVICE_LIMIT,
1333 &__kmp_default_device);
1334} // __kmp_stg_parse_default_device
1335
1336static void __kmp_stg_print_default_device(kmp_str_buf_t *buffer,
1337 char const *name, void *data) {
1338 __kmp_stg_print_int(buffer, name, __kmp_default_device);
1339} // __kmp_stg_print_default_device
1340
1341// -----------------------------------------------------------------------------
1342// OpenMP 5.0: OMP_TARGET_OFFLOAD
1343static void __kmp_stg_parse_target_offload(char const *name, char const *value,
1344 void *data) {
1345 const char *next = value;
1346 const char *scan = next;
1347
1348 __kmp_target_offload = tgt_default;
1349 SKIP_WS(next);
1350 if (*next == '\0')
1351 return;
1352 scan = next;
1353 if (!__kmp_strcasecmp_with_sentinel("mandatory", scan, 0)) {
1354 __kmp_target_offload = tgt_mandatory;
1355 } else if (!__kmp_strcasecmp_with_sentinel("disabled", scan, 0)) {
1356 __kmp_target_offload = tgt_disabled;
1357 } else if (!__kmp_strcasecmp_with_sentinel("default", scan, 0)) {
1358 __kmp_target_offload = tgt_default;
1359 } else {
1360 KMP_WARNING(SyntaxErrorUsing, name, "DEFAULT");
1361 }
1362
1363} // __kmp_stg_parse_target_offload
1364
1365static void __kmp_stg_print_target_offload(kmp_str_buf_t *buffer,
1366 char const *name, void *data) {
1367 const char *value = NULL;
1368 if (__kmp_target_offload == tgt_default)
1369 value = "DEFAULT";
1370 else if (__kmp_target_offload == tgt_mandatory)
1371 value = "MANDATORY";
1372 else if (__kmp_target_offload == tgt_disabled)
1373 value = "DISABLED";
1374 KMP_DEBUG_ASSERT(value);
1375 if (__kmp_env_format) {
1376 KMP_STR_BUF_PRINT_NAME;
1377 } else {
1378 __kmp_str_buf_print(buffer, " %s", name);
1379 }
1380 __kmp_str_buf_print(buffer, "=%s\n", value);
1381} // __kmp_stg_print_target_offload
1382
1383// -----------------------------------------------------------------------------
1384// OpenMP 4.5: OMP_MAX_TASK_PRIORITY
1385static void __kmp_stg_parse_max_task_priority(char const *name,
1386 char const *value, void *data) {
1387 __kmp_stg_parse_int(name, value, 0, KMP_MAX_TASK_PRIORITY_LIMIT,
1388 &__kmp_max_task_priority);
1389} // __kmp_stg_parse_max_task_priority
1390
1391static void __kmp_stg_print_max_task_priority(kmp_str_buf_t *buffer,
1392 char const *name, void *data) {
1393 __kmp_stg_print_int(buffer, name, __kmp_max_task_priority);
1394} // __kmp_stg_print_max_task_priority
1395
1396// KMP_TASKLOOP_MIN_TASKS
1397// taskloop threshold to switch from recursive to linear tasks creation
1398static void __kmp_stg_parse_taskloop_min_tasks(char const *name,
1399 char const *value, void *data) {
1400 int tmp;
1401 __kmp_stg_parse_int(name, value, 0, INT_MAX, &tmp);
1402 __kmp_taskloop_min_tasks = tmp;
1403} // __kmp_stg_parse_taskloop_min_tasks
1404
1405static void __kmp_stg_print_taskloop_min_tasks(kmp_str_buf_t *buffer,
1406 char const *name, void *data) {
1407 __kmp_stg_print_uint64(buffer, name, __kmp_taskloop_min_tasks);
1408} // __kmp_stg_print_taskloop_min_tasks
1409
1410// -----------------------------------------------------------------------------
1411// KMP_DISP_NUM_BUFFERS
1412static void __kmp_stg_parse_disp_buffers(char const *name, char const *value,
1413 void *data) {
1414 if (TCR_4(__kmp_init_serial)) {
1415 KMP_WARNING(EnvSerialWarn, name);
1416 return;
1417 } // read value before serial initialization only
1418 __kmp_stg_parse_int(name, value, KMP_MIN_DISP_NUM_BUFF, KMP_MAX_DISP_NUM_BUFF,
1419 &__kmp_dispatch_num_buffers);
1420} // __kmp_stg_parse_disp_buffers
1421
1422static void __kmp_stg_print_disp_buffers(kmp_str_buf_t *buffer,
1423 char const *name, void *data) {
1424 __kmp_stg_print_int(buffer, name, __kmp_dispatch_num_buffers);
1425} // __kmp_stg_print_disp_buffers
1426
1427#if KMP_NESTED_HOT_TEAMS
1428// -----------------------------------------------------------------------------
1429// KMP_HOT_TEAMS_MAX_LEVEL, KMP_HOT_TEAMS_MODE
1430
1431static void __kmp_stg_parse_hot_teams_level(char const *name, char const *value,
1432 void *data) {
1433 if (TCR_4(__kmp_init_parallel)) {
1434 KMP_WARNING(EnvParallelWarn, name);
1435 return;
1436 } // read value before first parallel only
1437 __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1438 &__kmp_hot_teams_max_level);
1439} // __kmp_stg_parse_hot_teams_level
1440
1441static void __kmp_stg_print_hot_teams_level(kmp_str_buf_t *buffer,
1442 char const *name, void *data) {
1443 __kmp_stg_print_int(buffer, name, __kmp_hot_teams_max_level);
1444} // __kmp_stg_print_hot_teams_level
1445
1446static void __kmp_stg_parse_hot_teams_mode(char const *name, char const *value,
1447 void *data) {
1448 if (TCR_4(__kmp_init_parallel)) {
1449 KMP_WARNING(EnvParallelWarn, name);
1450 return;
1451 } // read value before first parallel only
1452 __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1453 &__kmp_hot_teams_mode);
1454} // __kmp_stg_parse_hot_teams_mode
1455
1456static void __kmp_stg_print_hot_teams_mode(kmp_str_buf_t *buffer,
1457 char const *name, void *data) {
1458 __kmp_stg_print_int(buffer, name, __kmp_hot_teams_mode);
1459} // __kmp_stg_print_hot_teams_mode
1460
1461#endif // KMP_NESTED_HOT_TEAMS
1462
1463// -----------------------------------------------------------------------------
1464// KMP_HANDLE_SIGNALS
1465
1466#if KMP_HANDLE_SIGNALS
1467
1468static void __kmp_stg_parse_handle_signals(char const *name, char const *value,
1469 void *data) {
1470 __kmp_stg_parse_bool(name, value, &__kmp_handle_signals);
1471} // __kmp_stg_parse_handle_signals
1472
1473static void __kmp_stg_print_handle_signals(kmp_str_buf_t *buffer,
1474 char const *name, void *data) {
1475 __kmp_stg_print_bool(buffer, name, __kmp_handle_signals);
1476} // __kmp_stg_print_handle_signals
1477
1478#endif // KMP_HANDLE_SIGNALS
1479
1480// -----------------------------------------------------------------------------
1481// KMP_X_DEBUG, KMP_DEBUG, KMP_DEBUG_BUF_*, KMP_DIAG
1482
1483#ifdef KMP_DEBUG
1484
1485#define KMP_STG_X_DEBUG(x) \
1486 static void __kmp_stg_parse_##x##_debug(char const *name, char const *value, \
1487 void *data) { \
1488 __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_##x##_debug); \
1489 } /* __kmp_stg_parse_x_debug */ \
1490 static void __kmp_stg_print_##x##_debug(kmp_str_buf_t *buffer, \
1491 char const *name, void *data) { \
1492 __kmp_stg_print_int(buffer, name, kmp_##x##_debug); \
1493 } /* __kmp_stg_print_x_debug */
1494
1495KMP_STG_X_DEBUG(a)
1496KMP_STG_X_DEBUG(b)
1497KMP_STG_X_DEBUG(c)
1498KMP_STG_X_DEBUG(d)
1499KMP_STG_X_DEBUG(e)
1500KMP_STG_X_DEBUG(f)
1501
1502#undef KMP_STG_X_DEBUG
1503
1504static void __kmp_stg_parse_debug(char const *name, char const *value,
1505 void *data) {
1506 int debug = 0;
1507 __kmp_stg_parse_int(name, value, 0, INT_MAX, &debug);
1508 if (kmp_a_debug < debug) {
1509 kmp_a_debug = debug;
1510 }
1511 if (kmp_b_debug < debug) {
1512 kmp_b_debug = debug;
1513 }
1514 if (kmp_c_debug < debug) {
1515 kmp_c_debug = debug;
1516 }
1517 if (kmp_d_debug < debug) {
1518 kmp_d_debug = debug;
1519 }
1520 if (kmp_e_debug < debug) {
1521 kmp_e_debug = debug;
1522 }
1523 if (kmp_f_debug < debug) {
1524 kmp_f_debug = debug;
1525 }
1526} // __kmp_stg_parse_debug
1527
1528static void __kmp_stg_parse_debug_buf(char const *name, char const *value,
1529 void *data) {
1530 __kmp_stg_parse_bool(name, value, &__kmp_debug_buf);
1531 // !!! TODO: Move buffer initialization of of this file! It may works
1532 // incorrectly if KMP_DEBUG_BUF is parsed before KMP_DEBUG_BUF_LINES or
1533 // KMP_DEBUG_BUF_CHARS.
1534 if (__kmp_debug_buf) {
1535 int i;
1536 int elements = __kmp_debug_buf_lines * __kmp_debug_buf_chars;
1537
1538 /* allocate and initialize all entries in debug buffer to empty */
1539 __kmp_debug_buffer = (char *)__kmp_page_allocate(elements * sizeof(char));
1540 for (i = 0; i < elements; i += __kmp_debug_buf_chars)
1541 __kmp_debug_buffer[i] = '\0';
1542
1543 __kmp_debug_count = 0;
1544 }
1545 K_DIAG(1, ("__kmp_debug_buf = %d\n", __kmp_debug_buf));
1546} // __kmp_stg_parse_debug_buf
1547
1548static void __kmp_stg_print_debug_buf(kmp_str_buf_t *buffer, char const *name,
1549 void *data) {
1550 __kmp_stg_print_bool(buffer, name, __kmp_debug_buf);
1551} // __kmp_stg_print_debug_buf
1552
1553static void __kmp_stg_parse_debug_buf_atomic(char const *name,
1554 char const *value, void *data) {
1555 __kmp_stg_parse_bool(name, value, &__kmp_debug_buf_atomic);
1556} // __kmp_stg_parse_debug_buf_atomic
1557
1558static void __kmp_stg_print_debug_buf_atomic(kmp_str_buf_t *buffer,
1559 char const *name, void *data) {
1560 __kmp_stg_print_bool(buffer, name, __kmp_debug_buf_atomic);
1561} // __kmp_stg_print_debug_buf_atomic
1562
1563static void __kmp_stg_parse_debug_buf_chars(char const *name, char const *value,
1564 void *data) {
1565 __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_CHARS_MIN, INT_MAX,
1566 &__kmp_debug_buf_chars);
1567} // __kmp_stg_debug_parse_buf_chars
1568
1569static void __kmp_stg_print_debug_buf_chars(kmp_str_buf_t *buffer,
1570 char const *name, void *data) {
1571 __kmp_stg_print_int(buffer, name, __kmp_debug_buf_chars);
1572} // __kmp_stg_print_debug_buf_chars
1573
1574static void __kmp_stg_parse_debug_buf_lines(char const *name, char const *value,
1575 void *data) {
1576 __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_LINES_MIN, INT_MAX,
1577 &__kmp_debug_buf_lines);
1578} // __kmp_stg_parse_debug_buf_lines
1579
1580static void __kmp_stg_print_debug_buf_lines(kmp_str_buf_t *buffer,
1581 char const *name, void *data) {
1582 __kmp_stg_print_int(buffer, name, __kmp_debug_buf_lines);
1583} // __kmp_stg_print_debug_buf_lines
1584
1585static void __kmp_stg_parse_diag(char const *name, char const *value,
1586 void *data) {
1587 __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_diag);
1588} // __kmp_stg_parse_diag
1589
1590static void __kmp_stg_print_diag(kmp_str_buf_t *buffer, char const *name,
1591 void *data) {
1592 __kmp_stg_print_int(buffer, name, kmp_diag);
1593} // __kmp_stg_print_diag
1594
1595#endif // KMP_DEBUG
1596
1597// -----------------------------------------------------------------------------
1598// KMP_ALIGN_ALLOC
1599
1600static void __kmp_stg_parse_align_alloc(char const *name, char const *value,
1601 void *data) {
1602 __kmp_stg_parse_size(name, value, CACHE_LINE, INT_MAX, NULL,
1603 &__kmp_align_alloc, 1);
1604} // __kmp_stg_parse_align_alloc
1605
1606static void __kmp_stg_print_align_alloc(kmp_str_buf_t *buffer, char const *name,
1607 void *data) {
1608 __kmp_stg_print_size(buffer, name, __kmp_align_alloc);
1609} // __kmp_stg_print_align_alloc
1610
1611// -----------------------------------------------------------------------------
1612// KMP_PLAIN_BARRIER, KMP_FORKJOIN_BARRIER, KMP_REDUCTION_BARRIER
1613
1614// TODO: Remove __kmp_barrier_branch_bit_env_name varibale, remove loops from
1615// parse and print functions, pass required info through data argument.
1616
1617static void __kmp_stg_parse_barrier_branch_bit(char const *name,
1618 char const *value, void *data) {
1619 const char *var;
1620
1621 /* ---------- Barrier branch bit control ------------ */
1622 for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1623 var = __kmp_barrier_branch_bit_env_name[i];
1624 if ((strcmp(var, name) == 0) && (value != 0)) {
1625 char *comma;
1626
1627 comma = CCAST(char *, strchr(value, ','));
1628 __kmp_barrier_gather_branch_bits[i] =
1629 (kmp_uint32)__kmp_str_to_int(value, ',');
1630 /* is there a specified release parameter? */
1631 if (comma == NULL) {
1632 __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
1633 } else {
1634 __kmp_barrier_release_branch_bits[i] =
1635 (kmp_uint32)__kmp_str_to_int(comma + 1, 0);
1636
1637 if (__kmp_barrier_release_branch_bits[i] > KMP_MAX_BRANCH_BIT