1 /*
2  * kmp_settings.cpp -- Initialize environment variables
3  */
4 
5 //===----------------------------------------------------------------------===//
6 //
7 //                     The LLVM Compiler Infrastructure
8 //
9 // This file is dual licensed under the MIT and the University of Illinois Open
10 // Source Licenses. See LICENSE.txt for details.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "kmp.h"
15 #include "kmp_affinity.h"
16 #include "kmp_atomic.h"
17 #if KMP_USE_HIER_SCHED
18 #include "kmp_dispatch_hier.h"
19 #endif
20 #include "kmp_environment.h"
21 #include "kmp_i18n.h"
22 #include "kmp_io.h"
23 #include "kmp_itt.h"
24 #include "kmp_lock.h"
25 #include "kmp_settings.h"
26 #include "kmp_str.h"
27 #include "kmp_wrapper_getpid.h"
28 #include <ctype.h> // toupper()
29 
30 static int __kmp_env_toPrint(char const *name, int flag);
31 
32 bool __kmp_env_format = 0; // 0 - old format; 1 - new format
33 
34 // -----------------------------------------------------------------------------
35 // Helper string functions. Subject to move to kmp_str.
36 
37 static double __kmp_convert_to_double(char const *s) {
38   double result;
39 
40   if (KMP_SSCANF(s, "%lf", &result) < 1) {
41     result = 0.0;
42   }
43 
44   return result;
45 }
46 
47 #ifdef KMP_DEBUG
48 static unsigned int __kmp_readstr_with_sentinel(char *dest, char const *src,
49                                                 size_t len, char sentinel) {
50   unsigned int i;
51   for (i = 0; i < len; i++) {
52     if ((*src == '\0') || (*src == sentinel)) {
53       break;
54     }
55     *(dest++) = *(src++);
56   }
57   *dest = '\0';
58   return i;
59 }
60 #endif
61 
62 static int __kmp_match_with_sentinel(char const *a, char const *b, size_t len,
63                                      char sentinel) {
64   size_t l = 0;
65 
66   if (a == NULL)
67     a = "";
68   if (b == NULL)
69     b = "";
70   while (*a && *b && *b != sentinel) {
71     char ca = *a, cb = *b;
72 
73     if (ca >= 'a' && ca <= 'z')
74       ca -= 'a' - 'A';
75     if (cb >= 'a' && cb <= 'z')
76       cb -= 'a' - 'A';
77     if (ca != cb)
78       return FALSE;
79     ++l;
80     ++a;
81     ++b;
82   }
83   return l >= len;
84 }
85 
86 // Expected usage:
87 //     token is the token to check for.
88 //     buf is the string being parsed.
89 //     *end returns the char after the end of the token.
90 //        it is not modified unless a match occurs.
91 //
92 // Example 1:
93 //
94 //     if (__kmp_match_str("token", buf, *end) {
95 //         <do something>
96 //         buf = end;
97 //     }
98 //
99 //  Example 2:
100 //
101 //     if (__kmp_match_str("token", buf, *end) {
102 //         char *save = **end;
103 //         **end = sentinel;
104 //         <use any of the __kmp*_with_sentinel() functions>
105 //         **end = save;
106 //         buf = end;
107 //     }
108 
109 static int __kmp_match_str(char const *token, char const *buf,
110                            const char **end) {
111 
112   KMP_ASSERT(token != NULL);
113   KMP_ASSERT(buf != NULL);
114   KMP_ASSERT(end != NULL);
115 
116   while (*token && *buf) {
117     char ct = *token, cb = *buf;
118 
119     if (ct >= 'a' && ct <= 'z')
120       ct -= 'a' - 'A';
121     if (cb >= 'a' && cb <= 'z')
122       cb -= 'a' - 'A';
123     if (ct != cb)
124       return FALSE;
125     ++token;
126     ++buf;
127   }
128   if (*token) {
129     return FALSE;
130   }
131   *end = buf;
132   return TRUE;
133 }
134 
135 static size_t __kmp_round4k(size_t size) {
136   size_t _4k = 4 * 1024;
137   if (size & (_4k - 1)) {
138     size &= ~(_4k - 1);
139     if (size <= KMP_SIZE_T_MAX - _4k) {
140       size += _4k; // Round up if there is no overflow.
141     }
142   }
143   return size;
144 } // __kmp_round4k
145 
146 /* Here, multipliers are like __kmp_convert_to_seconds, but floating-point
147    values are allowed, and the return value is in milliseconds.  The default
148    multiplier is milliseconds.  Returns INT_MAX only if the value specified
149    matches "infinit*".  Returns -1 if specified string is invalid. */
150 int __kmp_convert_to_milliseconds(char const *data) {
151   int ret, nvalues, factor;
152   char mult, extra;
153   double value;
154 
155   if (data == NULL)
156     return (-1);
157   if (__kmp_str_match("infinit", -1, data))
158     return (INT_MAX);
159   value = (double)0.0;
160   mult = '\0';
161   nvalues = KMP_SSCANF(data, "%lf%c%c", &value, &mult, &extra);
162   if (nvalues < 1)
163     return (-1);
164   if (nvalues == 1)
165     mult = '\0';
166   if (nvalues == 3)
167     return (-1);
168 
169   if (value < 0)
170     return (-1);
171 
172   switch (mult) {
173   case '\0':
174     /*  default is milliseconds  */
175     factor = 1;
176     break;
177   case 's':
178   case 'S':
179     factor = 1000;
180     break;
181   case 'm':
182   case 'M':
183     factor = 1000 * 60;
184     break;
185   case 'h':
186   case 'H':
187     factor = 1000 * 60 * 60;
188     break;
189   case 'd':
190   case 'D':
191     factor = 1000 * 24 * 60 * 60;
192     break;
193   default:
194     return (-1);
195   }
196 
197   if (value >= ((INT_MAX - 1) / factor))
198     ret = INT_MAX - 1; /* Don't allow infinite value here */
199   else
200     ret = (int)(value * (double)factor); /* truncate to int  */
201 
202   return ret;
203 }
204 
205 static int __kmp_strcasecmp_with_sentinel(char const *a, char const *b,
206                                           char sentinel) {
207   if (a == NULL)
208     a = "";
209   if (b == NULL)
210     b = "";
211   while (*a && *b && *b != sentinel) {
212     char ca = *a, cb = *b;
213 
214     if (ca >= 'a' && ca <= 'z')
215       ca -= 'a' - 'A';
216     if (cb >= 'a' && cb <= 'z')
217       cb -= 'a' - 'A';
218     if (ca != cb)
219       return (int)(unsigned char)*a - (int)(unsigned char)*b;
220     ++a;
221     ++b;
222   }
223   return *a
224              ? (*b && *b != sentinel)
225                    ? (int)(unsigned char)*a - (int)(unsigned char)*b
226                    : 1
227              : (*b && *b != sentinel) ? -1 : 0;
228 }
229 
230 // =============================================================================
231 // Table structures and helper functions.
232 
233 typedef struct __kmp_setting kmp_setting_t;
234 typedef struct __kmp_stg_ss_data kmp_stg_ss_data_t;
235 typedef struct __kmp_stg_wp_data kmp_stg_wp_data_t;
236 typedef struct __kmp_stg_fr_data kmp_stg_fr_data_t;
237 
238 typedef void (*kmp_stg_parse_func_t)(char const *name, char const *value,
239                                      void *data);
240 typedef void (*kmp_stg_print_func_t)(kmp_str_buf_t *buffer, char const *name,
241                                      void *data);
242 
243 struct __kmp_setting {
244   char const *name; // Name of setting (environment variable).
245   kmp_stg_parse_func_t parse; // Parser function.
246   kmp_stg_print_func_t print; // Print function.
247   void *data; // Data passed to parser and printer.
248   int set; // Variable set during this "session"
249   //     (__kmp_env_initialize() or kmp_set_defaults() call).
250   int defined; // Variable set in any "session".
251 }; // struct __kmp_setting
252 
253 struct __kmp_stg_ss_data {
254   size_t factor; // Default factor: 1 for KMP_STACKSIZE, 1024 for others.
255   kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
256 }; // struct __kmp_stg_ss_data
257 
258 struct __kmp_stg_wp_data {
259   int omp; // 0 -- KMP_LIBRARY, 1 -- OMP_WAIT_POLICY.
260   kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
261 }; // struct __kmp_stg_wp_data
262 
263 struct __kmp_stg_fr_data {
264   int force; // 0 -- KMP_DETERMINISTIC_REDUCTION, 1 -- KMP_FORCE_REDUCTION.
265   kmp_setting_t **rivals; // Array of pointers to rivals (including itself).
266 }; // struct __kmp_stg_fr_data
267 
268 static int __kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
269     char const *name, // Name of variable.
270     char const *value, // Value of the variable.
271     kmp_setting_t **rivals // List of rival settings (must include current one).
272     );
273 
274 // -----------------------------------------------------------------------------
275 // Helper parse functions.
276 
277 static void __kmp_stg_parse_bool(char const *name, char const *value,
278                                  int *out) {
279   if (__kmp_str_match_true(value)) {
280     *out = TRUE;
281   } else if (__kmp_str_match_false(value)) {
282     *out = FALSE;
283   } else {
284     __kmp_msg(kmp_ms_warning, KMP_MSG(BadBoolValue, name, value),
285               KMP_HNT(ValidBoolValues), __kmp_msg_null);
286   }
287 } // __kmp_stg_parse_bool
288 
289 static void __kmp_stg_parse_size(char const *name, char const *value,
290                                  size_t size_min, size_t size_max,
291                                  int *is_specified, size_t *out,
292                                  size_t factor) {
293   char const *msg = NULL;
294 #if KMP_OS_DARWIN
295   size_min = __kmp_round4k(size_min);
296   size_max = __kmp_round4k(size_max);
297 #endif // KMP_OS_DARWIN
298   if (value) {
299     if (is_specified != NULL) {
300       *is_specified = 1;
301     }
302     __kmp_str_to_size(value, out, factor, &msg);
303     if (msg == NULL) {
304       if (*out > size_max) {
305         *out = size_max;
306         msg = KMP_I18N_STR(ValueTooLarge);
307       } else if (*out < size_min) {
308         *out = size_min;
309         msg = KMP_I18N_STR(ValueTooSmall);
310       } else {
311 #if KMP_OS_DARWIN
312         size_t round4k = __kmp_round4k(*out);
313         if (*out != round4k) {
314           *out = round4k;
315           msg = KMP_I18N_STR(NotMultiple4K);
316         }
317 #endif
318       }
319     } else {
320       // If integer overflow occurred, * out == KMP_SIZE_T_MAX. Cut it to
321       // size_max silently.
322       if (*out < size_min) {
323         *out = size_max;
324       } else if (*out > size_max) {
325         *out = size_max;
326       }
327     }
328     if (msg != NULL) {
329       // Message is not empty. Print warning.
330       kmp_str_buf_t buf;
331       __kmp_str_buf_init(&buf);
332       __kmp_str_buf_print_size(&buf, *out);
333       KMP_WARNING(ParseSizeIntWarn, name, value, msg);
334       KMP_INFORM(Using_str_Value, name, buf.str);
335       __kmp_str_buf_free(&buf);
336     }
337   }
338 } // __kmp_stg_parse_size
339 
340 static void __kmp_stg_parse_str(char const *name, char const *value,
341                                 char **out) {
342   __kmp_str_free(out);
343   *out = __kmp_str_format("%s", value);
344 } // __kmp_stg_parse_str
345 
346 static void __kmp_stg_parse_int(
347     char const
348         *name, // I: Name of environment variable (used in warning messages).
349     char const *value, // I: Value of environment variable to parse.
350     int min, // I: Miminal allowed value.
351     int max, // I: Maximum allowed value.
352     int *out // O: Output (parsed) value.
353     ) {
354   char const *msg = NULL;
355   kmp_uint64 uint = *out;
356   __kmp_str_to_uint(value, &uint, &msg);
357   if (msg == NULL) {
358     if (uint < (unsigned int)min) {
359       msg = KMP_I18N_STR(ValueTooSmall);
360       uint = min;
361     } else if (uint > (unsigned int)max) {
362       msg = KMP_I18N_STR(ValueTooLarge);
363       uint = max;
364     }
365   } else {
366     // If overflow occurred msg contains error message and uint is very big. Cut
367     // tmp it to INT_MAX.
368     if (uint < (unsigned int)min) {
369       uint = min;
370     } else if (uint > (unsigned int)max) {
371       uint = max;
372     }
373   }
374   if (msg != NULL) {
375     // Message is not empty. Print warning.
376     kmp_str_buf_t buf;
377     KMP_WARNING(ParseSizeIntWarn, name, value, msg);
378     __kmp_str_buf_init(&buf);
379     __kmp_str_buf_print(&buf, "%" KMP_UINT64_SPEC "", uint);
380     KMP_INFORM(Using_uint64_Value, name, buf.str);
381     __kmp_str_buf_free(&buf);
382   }
383   *out = uint;
384 } // __kmp_stg_parse_int
385 
386 #if KMP_DEBUG_ADAPTIVE_LOCKS
387 static void __kmp_stg_parse_file(char const *name, char const *value,
388                                  const char *suffix, char **out) {
389   char buffer[256];
390   char *t;
391   int hasSuffix;
392   __kmp_str_free(out);
393   t = (char *)strrchr(value, '.');
394   hasSuffix = t && __kmp_str_eqf(t, suffix);
395   t = __kmp_str_format("%s%s", value, hasSuffix ? "" : suffix);
396   __kmp_expand_file_name(buffer, sizeof(buffer), t);
397   __kmp_str_free(&t);
398   *out = __kmp_str_format("%s", buffer);
399 } // __kmp_stg_parse_file
400 #endif
401 
402 #ifdef KMP_DEBUG
403 static char *par_range_to_print = NULL;
404 
405 static void __kmp_stg_parse_par_range(char const *name, char const *value,
406                                       int *out_range, char *out_routine,
407                                       char *out_file, int *out_lb,
408                                       int *out_ub) {
409   size_t len = KMP_STRLEN(value + 1);
410   par_range_to_print = (char *)KMP_INTERNAL_MALLOC(len + 1);
411   KMP_STRNCPY_S(par_range_to_print, len + 1, value, len + 1);
412   __kmp_par_range = +1;
413   __kmp_par_range_lb = 0;
414   __kmp_par_range_ub = INT_MAX;
415   for (;;) {
416     unsigned int len;
417     if ((value == NULL) || (*value == '\0')) {
418       break;
419     }
420     if (!__kmp_strcasecmp_with_sentinel("routine", value, '=')) {
421       value = strchr(value, '=') + 1;
422       len = __kmp_readstr_with_sentinel(out_routine, value,
423                                         KMP_PAR_RANGE_ROUTINE_LEN - 1, ',');
424       if (len == 0) {
425         goto par_range_error;
426       }
427       value = strchr(value, ',');
428       if (value != NULL) {
429         value++;
430       }
431       continue;
432     }
433     if (!__kmp_strcasecmp_with_sentinel("filename", value, '=')) {
434       value = strchr(value, '=') + 1;
435       len = __kmp_readstr_with_sentinel(out_file, value,
436                                         KMP_PAR_RANGE_FILENAME_LEN - 1, ',');
437       if (len == 0) {
438         goto par_range_error;
439       }
440       value = strchr(value, ',');
441       if (value != NULL) {
442         value++;
443       }
444       continue;
445     }
446     if ((!__kmp_strcasecmp_with_sentinel("range", value, '=')) ||
447         (!__kmp_strcasecmp_with_sentinel("incl_range", value, '='))) {
448       value = strchr(value, '=') + 1;
449       if (KMP_SSCANF(value, "%d:%d", out_lb, out_ub) != 2) {
450         goto par_range_error;
451       }
452       *out_range = +1;
453       value = strchr(value, ',');
454       if (value != NULL) {
455         value++;
456       }
457       continue;
458     }
459     if (!__kmp_strcasecmp_with_sentinel("excl_range", value, '=')) {
460       value = strchr(value, '=') + 1;
461       if (KMP_SSCANF(value, "%d:%d", out_lb, out_ub) != 2) {
462         goto par_range_error;
463       }
464       *out_range = -1;
465       value = strchr(value, ',');
466       if (value != NULL) {
467         value++;
468       }
469       continue;
470     }
471   par_range_error:
472     KMP_WARNING(ParRangeSyntax, name);
473     __kmp_par_range = 0;
474     break;
475   }
476 } // __kmp_stg_parse_par_range
477 #endif
478 
479 int __kmp_initial_threads_capacity(int req_nproc) {
480   int nth = 32;
481 
482   /* MIN( MAX( 32, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ),
483    * __kmp_max_nth) */
484   if (nth < (4 * req_nproc))
485     nth = (4 * req_nproc);
486   if (nth < (4 * __kmp_xproc))
487     nth = (4 * __kmp_xproc);
488 
489   if (nth > __kmp_max_nth)
490     nth = __kmp_max_nth;
491 
492   return nth;
493 }
494 
495 int __kmp_default_tp_capacity(int req_nproc, int max_nth,
496                               int all_threads_specified) {
497   int nth = 128;
498 
499   if (all_threads_specified)
500     return max_nth;
501   /* MIN( MAX (128, 4 * $OMP_NUM_THREADS, 4 * omp_get_num_procs() ),
502    * __kmp_max_nth ) */
503   if (nth < (4 * req_nproc))
504     nth = (4 * req_nproc);
505   if (nth < (4 * __kmp_xproc))
506     nth = (4 * __kmp_xproc);
507 
508   if (nth > __kmp_max_nth)
509     nth = __kmp_max_nth;
510 
511   return nth;
512 }
513 
514 // -----------------------------------------------------------------------------
515 // Helper print functions.
516 
517 static void __kmp_stg_print_bool(kmp_str_buf_t *buffer, char const *name,
518                                  int value) {
519   if (__kmp_env_format) {
520     KMP_STR_BUF_PRINT_BOOL;
521   } else {
522     __kmp_str_buf_print(buffer, "   %s=%s\n", name, value ? "true" : "false");
523   }
524 } // __kmp_stg_print_bool
525 
526 static void __kmp_stg_print_int(kmp_str_buf_t *buffer, char const *name,
527                                 int value) {
528   if (__kmp_env_format) {
529     KMP_STR_BUF_PRINT_INT;
530   } else {
531     __kmp_str_buf_print(buffer, "   %s=%d\n", name, value);
532   }
533 } // __kmp_stg_print_int
534 
535 static void __kmp_stg_print_uint64(kmp_str_buf_t *buffer, char const *name,
536                                    kmp_uint64 value) {
537   if (__kmp_env_format) {
538     KMP_STR_BUF_PRINT_UINT64;
539   } else {
540     __kmp_str_buf_print(buffer, "   %s=%" KMP_UINT64_SPEC "\n", name, value);
541   }
542 } // __kmp_stg_print_uint64
543 
544 static void __kmp_stg_print_str(kmp_str_buf_t *buffer, char const *name,
545                                 char const *value) {
546   if (__kmp_env_format) {
547     KMP_STR_BUF_PRINT_STR;
548   } else {
549     __kmp_str_buf_print(buffer, "   %s=%s\n", name, value);
550   }
551 } // __kmp_stg_print_str
552 
553 static void __kmp_stg_print_size(kmp_str_buf_t *buffer, char const *name,
554                                  size_t value) {
555   if (__kmp_env_format) {
556     KMP_STR_BUF_PRINT_NAME_EX(name);
557     __kmp_str_buf_print_size(buffer, value);
558     __kmp_str_buf_print(buffer, "'\n");
559   } else {
560     __kmp_str_buf_print(buffer, "   %s=", name);
561     __kmp_str_buf_print_size(buffer, value);
562     __kmp_str_buf_print(buffer, "\n");
563     return;
564   }
565 } // __kmp_stg_print_size
566 
567 // =============================================================================
568 // Parse and print functions.
569 
570 // -----------------------------------------------------------------------------
571 // KMP_DEVICE_THREAD_LIMIT, KMP_ALL_THREADS
572 
573 static void __kmp_stg_parse_device_thread_limit(char const *name,
574                                                 char const *value, void *data) {
575   kmp_setting_t **rivals = (kmp_setting_t **)data;
576   int rc;
577   if (strcmp(name, "KMP_ALL_THREADS") == 0) {
578     KMP_INFORM(EnvVarDeprecated, name, "KMP_DEVICE_THREAD_LIMIT");
579   }
580   rc = __kmp_stg_check_rivals(name, value, rivals);
581   if (rc) {
582     return;
583   }
584   if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
585     __kmp_max_nth = __kmp_xproc;
586     __kmp_allThreadsSpecified = 1;
587   } else {
588     __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_max_nth);
589     __kmp_allThreadsSpecified = 0;
590   }
591   K_DIAG(1, ("__kmp_max_nth == %d\n", __kmp_max_nth));
592 
593 } // __kmp_stg_parse_device_thread_limit
594 
595 static void __kmp_stg_print_device_thread_limit(kmp_str_buf_t *buffer,
596                                                 char const *name, void *data) {
597   __kmp_stg_print_int(buffer, name, __kmp_max_nth);
598 } // __kmp_stg_print_device_thread_limit
599 
600 // -----------------------------------------------------------------------------
601 // OMP_THREAD_LIMIT
602 static void __kmp_stg_parse_thread_limit(char const *name, char const *value,
603                                          void *data) {
604   __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_cg_max_nth);
605   K_DIAG(1, ("__kmp_cg_max_nth == %d\n", __kmp_cg_max_nth));
606 
607 } // __kmp_stg_parse_thread_limit
608 
609 static void __kmp_stg_print_thread_limit(kmp_str_buf_t *buffer,
610                                          char const *name, void *data) {
611   __kmp_stg_print_int(buffer, name, __kmp_cg_max_nth);
612 } // __kmp_stg_print_thread_limit
613 
614 // -----------------------------------------------------------------------------
615 // KMP_TEAMS_THREAD_LIMIT
616 static void __kmp_stg_parse_teams_thread_limit(char const *name,
617                                                char const *value, void *data) {
618   __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_teams_max_nth);
619 } // __kmp_stg_teams_thread_limit
620 
621 static void __kmp_stg_print_teams_thread_limit(kmp_str_buf_t *buffer,
622                                                char const *name, void *data) {
623   __kmp_stg_print_int(buffer, name, __kmp_teams_max_nth);
624 } // __kmp_stg_print_teams_thread_limit
625 
626 // -----------------------------------------------------------------------------
627 // KMP_BLOCKTIME
628 
629 static void __kmp_stg_parse_blocktime(char const *name, char const *value,
630                                       void *data) {
631   __kmp_dflt_blocktime = __kmp_convert_to_milliseconds(value);
632   if (__kmp_dflt_blocktime < 0) {
633     __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
634     __kmp_msg(kmp_ms_warning, KMP_MSG(InvalidValue, name, value),
635               __kmp_msg_null);
636     KMP_INFORM(Using_int_Value, name, __kmp_dflt_blocktime);
637     __kmp_env_blocktime = FALSE; // Revert to default as if var not set.
638   } else {
639     if (__kmp_dflt_blocktime < KMP_MIN_BLOCKTIME) {
640       __kmp_dflt_blocktime = KMP_MIN_BLOCKTIME;
641       __kmp_msg(kmp_ms_warning, KMP_MSG(SmallValue, name, value),
642                 __kmp_msg_null);
643       KMP_INFORM(MinValueUsing, name, __kmp_dflt_blocktime);
644     } else if (__kmp_dflt_blocktime > KMP_MAX_BLOCKTIME) {
645       __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
646       __kmp_msg(kmp_ms_warning, KMP_MSG(LargeValue, name, value),
647                 __kmp_msg_null);
648       KMP_INFORM(MaxValueUsing, name, __kmp_dflt_blocktime);
649     }
650     __kmp_env_blocktime = TRUE; // KMP_BLOCKTIME was specified.
651   }
652 #if KMP_USE_MONITOR
653   // calculate number of monitor thread wakeup intervals corresponding to
654   // blocktime.
655   __kmp_monitor_wakeups =
656       KMP_WAKEUPS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
657   __kmp_bt_intervals =
658       KMP_INTERVALS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
659 #endif
660   K_DIAG(1, ("__kmp_env_blocktime == %d\n", __kmp_env_blocktime));
661   if (__kmp_env_blocktime) {
662     K_DIAG(1, ("__kmp_dflt_blocktime == %d\n", __kmp_dflt_blocktime));
663   }
664 } // __kmp_stg_parse_blocktime
665 
666 static void __kmp_stg_print_blocktime(kmp_str_buf_t *buffer, char const *name,
667                                       void *data) {
668   __kmp_stg_print_int(buffer, name, __kmp_dflt_blocktime);
669 } // __kmp_stg_print_blocktime
670 
671 // -----------------------------------------------------------------------------
672 // KMP_DUPLICATE_LIB_OK
673 
674 static void __kmp_stg_parse_duplicate_lib_ok(char const *name,
675                                              char const *value, void *data) {
676   /* actually this variable is not supported, put here for compatibility with
677      earlier builds and for static/dynamic combination */
678   __kmp_stg_parse_bool(name, value, &__kmp_duplicate_library_ok);
679 } // __kmp_stg_parse_duplicate_lib_ok
680 
681 static void __kmp_stg_print_duplicate_lib_ok(kmp_str_buf_t *buffer,
682                                              char const *name, void *data) {
683   __kmp_stg_print_bool(buffer, name, __kmp_duplicate_library_ok);
684 } // __kmp_stg_print_duplicate_lib_ok
685 
686 // -----------------------------------------------------------------------------
687 // KMP_INHERIT_FP_CONTROL
688 
689 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
690 
691 static void __kmp_stg_parse_inherit_fp_control(char const *name,
692                                                char const *value, void *data) {
693   __kmp_stg_parse_bool(name, value, &__kmp_inherit_fp_control);
694 } // __kmp_stg_parse_inherit_fp_control
695 
696 static void __kmp_stg_print_inherit_fp_control(kmp_str_buf_t *buffer,
697                                                char const *name, void *data) {
698 #if KMP_DEBUG
699   __kmp_stg_print_bool(buffer, name, __kmp_inherit_fp_control);
700 #endif /* KMP_DEBUG */
701 } // __kmp_stg_print_inherit_fp_control
702 
703 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
704 
705 // Used for OMP_WAIT_POLICY
706 static char const *blocktime_str = NULL;
707 
708 // -----------------------------------------------------------------------------
709 // KMP_LIBRARY, OMP_WAIT_POLICY
710 
711 static void __kmp_stg_parse_wait_policy(char const *name, char const *value,
712                                         void *data) {
713 
714   kmp_stg_wp_data_t *wait = (kmp_stg_wp_data_t *)data;
715   int rc;
716 
717   rc = __kmp_stg_check_rivals(name, value, wait->rivals);
718   if (rc) {
719     return;
720   }
721 
722   if (wait->omp) {
723     if (__kmp_str_match("ACTIVE", 1, value)) {
724       __kmp_library = library_turnaround;
725       if (blocktime_str == NULL) {
726         // KMP_BLOCKTIME not specified, so set default to "infinite".
727         __kmp_dflt_blocktime = KMP_MAX_BLOCKTIME;
728       }
729     } else if (__kmp_str_match("PASSIVE", 1, value)) {
730       __kmp_library = library_throughput;
731       if (blocktime_str == NULL) {
732         // KMP_BLOCKTIME not specified, so set default to 0.
733         __kmp_dflt_blocktime = 0;
734       }
735     } else {
736       KMP_WARNING(StgInvalidValue, name, value);
737     }
738   } else {
739     if (__kmp_str_match("serial", 1, value)) { /* S */
740       __kmp_library = library_serial;
741     } else if (__kmp_str_match("throughput", 2, value)) { /* TH */
742       __kmp_library = library_throughput;
743     } else if (__kmp_str_match("turnaround", 2, value)) { /* TU */
744       __kmp_library = library_turnaround;
745     } else if (__kmp_str_match("dedicated", 1, value)) { /* D */
746       __kmp_library = library_turnaround;
747     } else if (__kmp_str_match("multiuser", 1, value)) { /* M */
748       __kmp_library = library_throughput;
749     } else {
750       KMP_WARNING(StgInvalidValue, name, value);
751     }
752   }
753   __kmp_aux_set_library(__kmp_library);
754 
755 } // __kmp_stg_parse_wait_policy
756 
757 static void __kmp_stg_print_wait_policy(kmp_str_buf_t *buffer, char const *name,
758                                         void *data) {
759 
760   kmp_stg_wp_data_t *wait = (kmp_stg_wp_data_t *)data;
761   char const *value = NULL;
762 
763   if (wait->omp) {
764     switch (__kmp_library) {
765     case library_turnaround: {
766       value = "ACTIVE";
767     } break;
768     case library_throughput: {
769       value = "PASSIVE";
770     } break;
771     }
772   } else {
773     switch (__kmp_library) {
774     case library_serial: {
775       value = "serial";
776     } break;
777     case library_turnaround: {
778       value = "turnaround";
779     } break;
780     case library_throughput: {
781       value = "throughput";
782     } break;
783     }
784   }
785   if (value != NULL) {
786     __kmp_stg_print_str(buffer, name, value);
787   }
788 
789 } // __kmp_stg_print_wait_policy
790 
791 #if KMP_USE_MONITOR
792 // -----------------------------------------------------------------------------
793 // KMP_MONITOR_STACKSIZE
794 
795 static void __kmp_stg_parse_monitor_stacksize(char const *name,
796                                               char const *value, void *data) {
797   __kmp_stg_parse_size(name, value, __kmp_sys_min_stksize, KMP_MAX_STKSIZE,
798                        NULL, &__kmp_monitor_stksize, 1);
799 } // __kmp_stg_parse_monitor_stacksize
800 
801 static void __kmp_stg_print_monitor_stacksize(kmp_str_buf_t *buffer,
802                                               char const *name, void *data) {
803   if (__kmp_env_format) {
804     if (__kmp_monitor_stksize > 0)
805       KMP_STR_BUF_PRINT_NAME_EX(name);
806     else
807       KMP_STR_BUF_PRINT_NAME;
808   } else {
809     __kmp_str_buf_print(buffer, "   %s", name);
810   }
811   if (__kmp_monitor_stksize > 0) {
812     __kmp_str_buf_print_size(buffer, __kmp_monitor_stksize);
813   } else {
814     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
815   }
816   if (__kmp_env_format && __kmp_monitor_stksize) {
817     __kmp_str_buf_print(buffer, "'\n");
818   }
819 } // __kmp_stg_print_monitor_stacksize
820 #endif // KMP_USE_MONITOR
821 
822 // -----------------------------------------------------------------------------
823 // KMP_SETTINGS
824 
825 static void __kmp_stg_parse_settings(char const *name, char const *value,
826                                      void *data) {
827   __kmp_stg_parse_bool(name, value, &__kmp_settings);
828 } // __kmp_stg_parse_settings
829 
830 static void __kmp_stg_print_settings(kmp_str_buf_t *buffer, char const *name,
831                                      void *data) {
832   __kmp_stg_print_bool(buffer, name, __kmp_settings);
833 } // __kmp_stg_print_settings
834 
835 // -----------------------------------------------------------------------------
836 // KMP_STACKPAD
837 
838 static void __kmp_stg_parse_stackpad(char const *name, char const *value,
839                                      void *data) {
840   __kmp_stg_parse_int(name, // Env var name
841                       value, // Env var value
842                       KMP_MIN_STKPADDING, // Min value
843                       KMP_MAX_STKPADDING, // Max value
844                       &__kmp_stkpadding // Var to initialize
845                       );
846 } // __kmp_stg_parse_stackpad
847 
848 static void __kmp_stg_print_stackpad(kmp_str_buf_t *buffer, char const *name,
849                                      void *data) {
850   __kmp_stg_print_int(buffer, name, __kmp_stkpadding);
851 } // __kmp_stg_print_stackpad
852 
853 // -----------------------------------------------------------------------------
854 // KMP_STACKOFFSET
855 
856 static void __kmp_stg_parse_stackoffset(char const *name, char const *value,
857                                         void *data) {
858   __kmp_stg_parse_size(name, // Env var name
859                        value, // Env var value
860                        KMP_MIN_STKOFFSET, // Min value
861                        KMP_MAX_STKOFFSET, // Max value
862                        NULL, //
863                        &__kmp_stkoffset, // Var to initialize
864                        1);
865 } // __kmp_stg_parse_stackoffset
866 
867 static void __kmp_stg_print_stackoffset(kmp_str_buf_t *buffer, char const *name,
868                                         void *data) {
869   __kmp_stg_print_size(buffer, name, __kmp_stkoffset);
870 } // __kmp_stg_print_stackoffset
871 
872 // -----------------------------------------------------------------------------
873 // KMP_STACKSIZE, OMP_STACKSIZE, GOMP_STACKSIZE
874 
875 static void __kmp_stg_parse_stacksize(char const *name, char const *value,
876                                       void *data) {
877 
878   kmp_stg_ss_data_t *stacksize = (kmp_stg_ss_data_t *)data;
879   int rc;
880 
881   rc = __kmp_stg_check_rivals(name, value, stacksize->rivals);
882   if (rc) {
883     return;
884   }
885   __kmp_stg_parse_size(name, // Env var name
886                        value, // Env var value
887                        __kmp_sys_min_stksize, // Min value
888                        KMP_MAX_STKSIZE, // Max value
889                        &__kmp_env_stksize, //
890                        &__kmp_stksize, // Var to initialize
891                        stacksize->factor);
892 
893 } // __kmp_stg_parse_stacksize
894 
895 // This function is called for printing both KMP_STACKSIZE (factor is 1) and
896 // OMP_STACKSIZE (factor is 1024). Currently it is not possible to print
897 // OMP_STACKSIZE value in bytes. We can consider adding this possibility by a
898 // customer request in future.
899 static void __kmp_stg_print_stacksize(kmp_str_buf_t *buffer, char const *name,
900                                       void *data) {
901   kmp_stg_ss_data_t *stacksize = (kmp_stg_ss_data_t *)data;
902   if (__kmp_env_format) {
903     KMP_STR_BUF_PRINT_NAME_EX(name);
904     __kmp_str_buf_print_size(buffer, (__kmp_stksize % 1024)
905                                          ? __kmp_stksize / stacksize->factor
906                                          : __kmp_stksize);
907     __kmp_str_buf_print(buffer, "'\n");
908   } else {
909     __kmp_str_buf_print(buffer, "   %s=", name);
910     __kmp_str_buf_print_size(buffer, (__kmp_stksize % 1024)
911                                          ? __kmp_stksize / stacksize->factor
912                                          : __kmp_stksize);
913     __kmp_str_buf_print(buffer, "\n");
914   }
915 } // __kmp_stg_print_stacksize
916 
917 // -----------------------------------------------------------------------------
918 // KMP_VERSION
919 
920 static void __kmp_stg_parse_version(char const *name, char const *value,
921                                     void *data) {
922   __kmp_stg_parse_bool(name, value, &__kmp_version);
923 } // __kmp_stg_parse_version
924 
925 static void __kmp_stg_print_version(kmp_str_buf_t *buffer, char const *name,
926                                     void *data) {
927   __kmp_stg_print_bool(buffer, name, __kmp_version);
928 } // __kmp_stg_print_version
929 
930 // -----------------------------------------------------------------------------
931 // KMP_WARNINGS
932 
933 static void __kmp_stg_parse_warnings(char const *name, char const *value,
934                                      void *data) {
935   __kmp_stg_parse_bool(name, value, &__kmp_generate_warnings);
936   if (__kmp_generate_warnings != kmp_warnings_off) {
937     // AC: only 0/1 values documented, so reset to explicit to distinguish from
938     // default setting
939     __kmp_generate_warnings = kmp_warnings_explicit;
940   }
941 } // __kmp_stg_parse_warnings
942 
943 static void __kmp_stg_print_warnings(kmp_str_buf_t *buffer, char const *name,
944                                      void *data) {
945   // AC: TODO: change to print_int? (needs documentation change)
946   __kmp_stg_print_bool(buffer, name, __kmp_generate_warnings);
947 } // __kmp_stg_print_warnings
948 
949 // -----------------------------------------------------------------------------
950 // OMP_NESTED, OMP_NUM_THREADS
951 
952 static void __kmp_stg_parse_nested(char const *name, char const *value,
953                                    void *data) {
954   __kmp_stg_parse_bool(name, value, &__kmp_dflt_nested);
955 } // __kmp_stg_parse_nested
956 
957 static void __kmp_stg_print_nested(kmp_str_buf_t *buffer, char const *name,
958                                    void *data) {
959   __kmp_stg_print_bool(buffer, name, __kmp_dflt_nested);
960 } // __kmp_stg_print_nested
961 
962 static void __kmp_parse_nested_num_threads(const char *var, const char *env,
963                                            kmp_nested_nthreads_t *nth_array) {
964   const char *next = env;
965   const char *scan = next;
966 
967   int total = 0; // Count elements that were set. It'll be used as an array size
968   int prev_comma = FALSE; // For correct processing sequential commas
969 
970   // Count the number of values in the env. var string
971   for (;;) {
972     SKIP_WS(next);
973 
974     if (*next == '\0') {
975       break;
976     }
977     // Next character is not an integer or not a comma => end of list
978     if (((*next < '0') || (*next > '9')) && (*next != ',')) {
979       KMP_WARNING(NthSyntaxError, var, env);
980       return;
981     }
982     // The next character is ','
983     if (*next == ',') {
984       // ',' is the fisrt character
985       if (total == 0 || prev_comma) {
986         total++;
987       }
988       prev_comma = TRUE;
989       next++; // skip ','
990       SKIP_WS(next);
991     }
992     // Next character is a digit
993     if (*next >= '0' && *next <= '9') {
994       prev_comma = FALSE;
995       SKIP_DIGITS(next);
996       total++;
997       const char *tmp = next;
998       SKIP_WS(tmp);
999       if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
1000         KMP_WARNING(NthSpacesNotAllowed, var, env);
1001         return;
1002       }
1003     }
1004   }
1005   KMP_DEBUG_ASSERT(total > 0);
1006   if (total <= 0) {
1007     KMP_WARNING(NthSyntaxError, var, env);
1008     return;
1009   }
1010 
1011   // Check if the nested nthreads array exists
1012   if (!nth_array->nth) {
1013     // Allocate an array of double size
1014     nth_array->nth = (int *)KMP_INTERNAL_MALLOC(sizeof(int) * total * 2);
1015     if (nth_array->nth == NULL) {
1016       KMP_FATAL(MemoryAllocFailed);
1017     }
1018     nth_array->size = total * 2;
1019   } else {
1020     if (nth_array->size < total) {
1021       // Increase the array size
1022       do {
1023         nth_array->size *= 2;
1024       } while (nth_array->size < total);
1025 
1026       nth_array->nth = (int *)KMP_INTERNAL_REALLOC(
1027           nth_array->nth, sizeof(int) * nth_array->size);
1028       if (nth_array->nth == NULL) {
1029         KMP_FATAL(MemoryAllocFailed);
1030       }
1031     }
1032   }
1033   nth_array->used = total;
1034   int i = 0;
1035 
1036   prev_comma = FALSE;
1037   total = 0;
1038   // Save values in the array
1039   for (;;) {
1040     SKIP_WS(scan);
1041     if (*scan == '\0') {
1042       break;
1043     }
1044     // The next character is ','
1045     if (*scan == ',') {
1046       // ',' in the beginning of the list
1047       if (total == 0) {
1048         // The value is supposed to be equal to __kmp_avail_proc but it is
1049         // unknown at the moment.
1050         // So let's put a placeholder (#threads = 0) to correct it later.
1051         nth_array->nth[i++] = 0;
1052         total++;
1053       } else if (prev_comma) {
1054         // Num threads is inherited from the previous level
1055         nth_array->nth[i] = nth_array->nth[i - 1];
1056         i++;
1057         total++;
1058       }
1059       prev_comma = TRUE;
1060       scan++; // skip ','
1061       SKIP_WS(scan);
1062     }
1063     // Next character is a digit
1064     if (*scan >= '0' && *scan <= '9') {
1065       int num;
1066       const char *buf = scan;
1067       char const *msg = NULL;
1068       prev_comma = FALSE;
1069       SKIP_DIGITS(scan);
1070       total++;
1071 
1072       num = __kmp_str_to_int(buf, *scan);
1073       if (num < KMP_MIN_NTH) {
1074         msg = KMP_I18N_STR(ValueTooSmall);
1075         num = KMP_MIN_NTH;
1076       } else if (num > __kmp_sys_max_nth) {
1077         msg = KMP_I18N_STR(ValueTooLarge);
1078         num = __kmp_sys_max_nth;
1079       }
1080       if (msg != NULL) {
1081         // Message is not empty. Print warning.
1082         KMP_WARNING(ParseSizeIntWarn, var, env, msg);
1083         KMP_INFORM(Using_int_Value, var, num);
1084       }
1085       nth_array->nth[i++] = num;
1086     }
1087   }
1088 }
1089 
1090 static void __kmp_stg_parse_num_threads(char const *name, char const *value,
1091                                         void *data) {
1092   // TODO: Remove this option. OMP_NUM_THREADS is a list of positive integers!
1093   if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
1094     // The array of 1 element
1095     __kmp_nested_nth.nth = (int *)KMP_INTERNAL_MALLOC(sizeof(int));
1096     __kmp_nested_nth.size = __kmp_nested_nth.used = 1;
1097     __kmp_nested_nth.nth[0] = __kmp_dflt_team_nth = __kmp_dflt_team_nth_ub =
1098         __kmp_xproc;
1099   } else {
1100     __kmp_parse_nested_num_threads(name, value, &__kmp_nested_nth);
1101     if (__kmp_nested_nth.nth) {
1102       __kmp_dflt_team_nth = __kmp_nested_nth.nth[0];
1103       if (__kmp_dflt_team_nth_ub < __kmp_dflt_team_nth) {
1104         __kmp_dflt_team_nth_ub = __kmp_dflt_team_nth;
1105       }
1106     }
1107   }
1108   K_DIAG(1, ("__kmp_dflt_team_nth == %d\n", __kmp_dflt_team_nth));
1109 } // __kmp_stg_parse_num_threads
1110 
1111 static void __kmp_stg_print_num_threads(kmp_str_buf_t *buffer, char const *name,
1112                                         void *data) {
1113   if (__kmp_env_format) {
1114     KMP_STR_BUF_PRINT_NAME;
1115   } else {
1116     __kmp_str_buf_print(buffer, "   %s", name);
1117   }
1118   if (__kmp_nested_nth.used) {
1119     kmp_str_buf_t buf;
1120     __kmp_str_buf_init(&buf);
1121     for (int i = 0; i < __kmp_nested_nth.used; i++) {
1122       __kmp_str_buf_print(&buf, "%d", __kmp_nested_nth.nth[i]);
1123       if (i < __kmp_nested_nth.used - 1) {
1124         __kmp_str_buf_print(&buf, ",");
1125       }
1126     }
1127     __kmp_str_buf_print(buffer, "='%s'\n", buf.str);
1128     __kmp_str_buf_free(&buf);
1129   } else {
1130     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1131   }
1132 } // __kmp_stg_print_num_threads
1133 
1134 // -----------------------------------------------------------------------------
1135 // OpenMP 3.0: KMP_TASKING, OMP_MAX_ACTIVE_LEVELS,
1136 
1137 static void __kmp_stg_parse_tasking(char const *name, char const *value,
1138                                     void *data) {
1139   __kmp_stg_parse_int(name, value, 0, (int)tskm_max,
1140                       (int *)&__kmp_tasking_mode);
1141 } // __kmp_stg_parse_tasking
1142 
1143 static void __kmp_stg_print_tasking(kmp_str_buf_t *buffer, char const *name,
1144                                     void *data) {
1145   __kmp_stg_print_int(buffer, name, __kmp_tasking_mode);
1146 } // __kmp_stg_print_tasking
1147 
1148 static void __kmp_stg_parse_task_stealing(char const *name, char const *value,
1149                                           void *data) {
1150   __kmp_stg_parse_int(name, value, 0, 1,
1151                       (int *)&__kmp_task_stealing_constraint);
1152 } // __kmp_stg_parse_task_stealing
1153 
1154 static void __kmp_stg_print_task_stealing(kmp_str_buf_t *buffer,
1155                                           char const *name, void *data) {
1156   __kmp_stg_print_int(buffer, name, __kmp_task_stealing_constraint);
1157 } // __kmp_stg_print_task_stealing
1158 
1159 static void __kmp_stg_parse_max_active_levels(char const *name,
1160                                               char const *value, void *data) {
1161   __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1162                       &__kmp_dflt_max_active_levels);
1163 } // __kmp_stg_parse_max_active_levels
1164 
1165 static void __kmp_stg_print_max_active_levels(kmp_str_buf_t *buffer,
1166                                               char const *name, void *data) {
1167   __kmp_stg_print_int(buffer, name, __kmp_dflt_max_active_levels);
1168 } // __kmp_stg_print_max_active_levels
1169 
1170 #if OMP_40_ENABLED
1171 // -----------------------------------------------------------------------------
1172 // OpenMP 4.0: OMP_DEFAULT_DEVICE
1173 static void __kmp_stg_parse_default_device(char const *name, char const *value,
1174                                            void *data) {
1175   __kmp_stg_parse_int(name, value, 0, KMP_MAX_DEFAULT_DEVICE_LIMIT,
1176                       &__kmp_default_device);
1177 } // __kmp_stg_parse_default_device
1178 
1179 static void __kmp_stg_print_default_device(kmp_str_buf_t *buffer,
1180                                            char const *name, void *data) {
1181   __kmp_stg_print_int(buffer, name, __kmp_default_device);
1182 } // __kmp_stg_print_default_device
1183 #endif
1184 
1185 #if OMP_50_ENABLED
1186 // -----------------------------------------------------------------------------
1187 // OpenMP 5.0: OMP_TARGET_OFFLOAD
1188 static void __kmp_stg_parse_target_offload(char const *name, char const *value,
1189                                            void *data) {
1190   const char *next = value;
1191   const char *scan = next;
1192 
1193   __kmp_target_offload = tgt_default;
1194   SKIP_WS(next);
1195   if (*next == '\0')
1196     return;
1197   scan = next;
1198   if (__kmp_match_str("MANDATORY", scan, &next)) {
1199     __kmp_target_offload = tgt_mandatory;
1200   } else if (__kmp_match_str("DISABLED", scan, &next)) {
1201     __kmp_target_offload = tgt_disabled;
1202   } else if (__kmp_match_str("DEFAULT", scan, &next)) {
1203     __kmp_target_offload = tgt_default;
1204   } else {
1205     KMP_WARNING(SyntaxErrorUsing, name, "DEFAULT");
1206   }
1207 
1208 } // __kmp_stg_parse_target_offload
1209 
1210 static void __kmp_stg_print_target_offload(kmp_str_buf_t *buffer,
1211                                            char const *name, void *data) {
1212   const char *value = NULL;
1213   if (__kmp_target_offload == tgt_default)
1214     value = "DEFAULT";
1215   else if (__kmp_target_offload == tgt_mandatory)
1216     value = "MANDATORY";
1217   else if (__kmp_target_offload == tgt_disabled)
1218     value = "DISABLED";
1219   if (value) {
1220     __kmp_str_buf_print(buffer, "   %s=%s\n", name, value);
1221   }
1222 } // __kmp_stg_print_target_offload
1223 #endif
1224 
1225 #if OMP_45_ENABLED
1226 // -----------------------------------------------------------------------------
1227 // OpenMP 4.5: OMP_MAX_TASK_PRIORITY
1228 static void __kmp_stg_parse_max_task_priority(char const *name,
1229                                               char const *value, void *data) {
1230   __kmp_stg_parse_int(name, value, 0, KMP_MAX_TASK_PRIORITY_LIMIT,
1231                       &__kmp_max_task_priority);
1232 } // __kmp_stg_parse_max_task_priority
1233 
1234 static void __kmp_stg_print_max_task_priority(kmp_str_buf_t *buffer,
1235                                               char const *name, void *data) {
1236   __kmp_stg_print_int(buffer, name, __kmp_max_task_priority);
1237 } // __kmp_stg_print_max_task_priority
1238 
1239 // KMP_TASKLOOP_MIN_TASKS
1240 // taskloop threashold to switch from recursive to linear tasks creation
1241 static void __kmp_stg_parse_taskloop_min_tasks(char const *name,
1242                                                char const *value, void *data) {
1243   int tmp;
1244   __kmp_stg_parse_int(name, value, 0, INT_MAX, &tmp);
1245   __kmp_taskloop_min_tasks = tmp;
1246 } // __kmp_stg_parse_taskloop_min_tasks
1247 
1248 static void __kmp_stg_print_taskloop_min_tasks(kmp_str_buf_t *buffer,
1249                                                char const *name, void *data) {
1250   __kmp_stg_print_int(buffer, name, __kmp_taskloop_min_tasks);
1251 } // __kmp_stg_print_taskloop_min_tasks
1252 #endif // OMP_45_ENABLED
1253 
1254 // -----------------------------------------------------------------------------
1255 // KMP_DISP_NUM_BUFFERS
1256 static void __kmp_stg_parse_disp_buffers(char const *name, char const *value,
1257                                          void *data) {
1258   if (TCR_4(__kmp_init_serial)) {
1259     KMP_WARNING(EnvSerialWarn, name);
1260     return;
1261   } // read value before serial initialization only
1262   __kmp_stg_parse_int(name, value, 1, KMP_MAX_NTH, &__kmp_dispatch_num_buffers);
1263 } // __kmp_stg_parse_disp_buffers
1264 
1265 static void __kmp_stg_print_disp_buffers(kmp_str_buf_t *buffer,
1266                                          char const *name, void *data) {
1267   __kmp_stg_print_int(buffer, name, __kmp_dispatch_num_buffers);
1268 } // __kmp_stg_print_disp_buffers
1269 
1270 #if KMP_NESTED_HOT_TEAMS
1271 // -----------------------------------------------------------------------------
1272 // KMP_HOT_TEAMS_MAX_LEVEL, KMP_HOT_TEAMS_MODE
1273 
1274 static void __kmp_stg_parse_hot_teams_level(char const *name, char const *value,
1275                                             void *data) {
1276   if (TCR_4(__kmp_init_parallel)) {
1277     KMP_WARNING(EnvParallelWarn, name);
1278     return;
1279   } // read value before first parallel only
1280   __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1281                       &__kmp_hot_teams_max_level);
1282 } // __kmp_stg_parse_hot_teams_level
1283 
1284 static void __kmp_stg_print_hot_teams_level(kmp_str_buf_t *buffer,
1285                                             char const *name, void *data) {
1286   __kmp_stg_print_int(buffer, name, __kmp_hot_teams_max_level);
1287 } // __kmp_stg_print_hot_teams_level
1288 
1289 static void __kmp_stg_parse_hot_teams_mode(char const *name, char const *value,
1290                                            void *data) {
1291   if (TCR_4(__kmp_init_parallel)) {
1292     KMP_WARNING(EnvParallelWarn, name);
1293     return;
1294   } // read value before first parallel only
1295   __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1296                       &__kmp_hot_teams_mode);
1297 } // __kmp_stg_parse_hot_teams_mode
1298 
1299 static void __kmp_stg_print_hot_teams_mode(kmp_str_buf_t *buffer,
1300                                            char const *name, void *data) {
1301   __kmp_stg_print_int(buffer, name, __kmp_hot_teams_mode);
1302 } // __kmp_stg_print_hot_teams_mode
1303 
1304 #endif // KMP_NESTED_HOT_TEAMS
1305 
1306 // -----------------------------------------------------------------------------
1307 // KMP_HANDLE_SIGNALS
1308 
1309 #if KMP_HANDLE_SIGNALS
1310 
1311 static void __kmp_stg_parse_handle_signals(char const *name, char const *value,
1312                                            void *data) {
1313   __kmp_stg_parse_bool(name, value, &__kmp_handle_signals);
1314 } // __kmp_stg_parse_handle_signals
1315 
1316 static void __kmp_stg_print_handle_signals(kmp_str_buf_t *buffer,
1317                                            char const *name, void *data) {
1318   __kmp_stg_print_bool(buffer, name, __kmp_handle_signals);
1319 } // __kmp_stg_print_handle_signals
1320 
1321 #endif // KMP_HANDLE_SIGNALS
1322 
1323 // -----------------------------------------------------------------------------
1324 // KMP_X_DEBUG, KMP_DEBUG, KMP_DEBUG_BUF_*, KMP_DIAG
1325 
1326 #ifdef KMP_DEBUG
1327 
1328 #define KMP_STG_X_DEBUG(x)                                                     \
1329   static void __kmp_stg_parse_##x##_debug(char const *name, char const *value, \
1330                                           void *data) {                        \
1331     __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_##x##_debug);            \
1332   } /* __kmp_stg_parse_x_debug */                                              \
1333   static void __kmp_stg_print_##x##_debug(kmp_str_buf_t *buffer,               \
1334                                           char const *name, void *data) {      \
1335     __kmp_stg_print_int(buffer, name, kmp_##x##_debug);                        \
1336   } /* __kmp_stg_print_x_debug */
1337 
1338 KMP_STG_X_DEBUG(a)
1339 KMP_STG_X_DEBUG(b)
1340 KMP_STG_X_DEBUG(c)
1341 KMP_STG_X_DEBUG(d)
1342 KMP_STG_X_DEBUG(e)
1343 KMP_STG_X_DEBUG(f)
1344 
1345 #undef KMP_STG_X_DEBUG
1346 
1347 static void __kmp_stg_parse_debug(char const *name, char const *value,
1348                                   void *data) {
1349   int debug = 0;
1350   __kmp_stg_parse_int(name, value, 0, INT_MAX, &debug);
1351   if (kmp_a_debug < debug) {
1352     kmp_a_debug = debug;
1353   }
1354   if (kmp_b_debug < debug) {
1355     kmp_b_debug = debug;
1356   }
1357   if (kmp_c_debug < debug) {
1358     kmp_c_debug = debug;
1359   }
1360   if (kmp_d_debug < debug) {
1361     kmp_d_debug = debug;
1362   }
1363   if (kmp_e_debug < debug) {
1364     kmp_e_debug = debug;
1365   }
1366   if (kmp_f_debug < debug) {
1367     kmp_f_debug = debug;
1368   }
1369 } // __kmp_stg_parse_debug
1370 
1371 static void __kmp_stg_parse_debug_buf(char const *name, char const *value,
1372                                       void *data) {
1373   __kmp_stg_parse_bool(name, value, &__kmp_debug_buf);
1374   // !!! TODO: Move buffer initialization of of this file! It may works
1375   // incorrectly if KMP_DEBUG_BUF is parsed before KMP_DEBUG_BUF_LINES or
1376   // KMP_DEBUG_BUF_CHARS.
1377   if (__kmp_debug_buf) {
1378     int i;
1379     int elements = __kmp_debug_buf_lines * __kmp_debug_buf_chars;
1380 
1381     /* allocate and initialize all entries in debug buffer to empty */
1382     __kmp_debug_buffer = (char *)__kmp_page_allocate(elements * sizeof(char));
1383     for (i = 0; i < elements; i += __kmp_debug_buf_chars)
1384       __kmp_debug_buffer[i] = '\0';
1385 
1386     __kmp_debug_count = 0;
1387   }
1388   K_DIAG(1, ("__kmp_debug_buf = %d\n", __kmp_debug_buf));
1389 } // __kmp_stg_parse_debug_buf
1390 
1391 static void __kmp_stg_print_debug_buf(kmp_str_buf_t *buffer, char const *name,
1392                                       void *data) {
1393   __kmp_stg_print_bool(buffer, name, __kmp_debug_buf);
1394 } // __kmp_stg_print_debug_buf
1395 
1396 static void __kmp_stg_parse_debug_buf_atomic(char const *name,
1397                                              char const *value, void *data) {
1398   __kmp_stg_parse_bool(name, value, &__kmp_debug_buf_atomic);
1399 } // __kmp_stg_parse_debug_buf_atomic
1400 
1401 static void __kmp_stg_print_debug_buf_atomic(kmp_str_buf_t *buffer,
1402                                              char const *name, void *data) {
1403   __kmp_stg_print_bool(buffer, name, __kmp_debug_buf_atomic);
1404 } // __kmp_stg_print_debug_buf_atomic
1405 
1406 static void __kmp_stg_parse_debug_buf_chars(char const *name, char const *value,
1407                                             void *data) {
1408   __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_CHARS_MIN, INT_MAX,
1409                       &__kmp_debug_buf_chars);
1410 } // __kmp_stg_debug_parse_buf_chars
1411 
1412 static void __kmp_stg_print_debug_buf_chars(kmp_str_buf_t *buffer,
1413                                             char const *name, void *data) {
1414   __kmp_stg_print_int(buffer, name, __kmp_debug_buf_chars);
1415 } // __kmp_stg_print_debug_buf_chars
1416 
1417 static void __kmp_stg_parse_debug_buf_lines(char const *name, char const *value,
1418                                             void *data) {
1419   __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_LINES_MIN, INT_MAX,
1420                       &__kmp_debug_buf_lines);
1421 } // __kmp_stg_parse_debug_buf_lines
1422 
1423 static void __kmp_stg_print_debug_buf_lines(kmp_str_buf_t *buffer,
1424                                             char const *name, void *data) {
1425   __kmp_stg_print_int(buffer, name, __kmp_debug_buf_lines);
1426 } // __kmp_stg_print_debug_buf_lines
1427 
1428 static void __kmp_stg_parse_diag(char const *name, char const *value,
1429                                  void *data) {
1430   __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_diag);
1431 } // __kmp_stg_parse_diag
1432 
1433 static void __kmp_stg_print_diag(kmp_str_buf_t *buffer, char const *name,
1434                                  void *data) {
1435   __kmp_stg_print_int(buffer, name, kmp_diag);
1436 } // __kmp_stg_print_diag
1437 
1438 #endif // KMP_DEBUG
1439 
1440 // -----------------------------------------------------------------------------
1441 // KMP_ALIGN_ALLOC
1442 
1443 static void __kmp_stg_parse_align_alloc(char const *name, char const *value,
1444                                         void *data) {
1445   __kmp_stg_parse_size(name, value, CACHE_LINE, INT_MAX, NULL,
1446                        &__kmp_align_alloc, 1);
1447 } // __kmp_stg_parse_align_alloc
1448 
1449 static void __kmp_stg_print_align_alloc(kmp_str_buf_t *buffer, char const *name,
1450                                         void *data) {
1451   __kmp_stg_print_size(buffer, name, __kmp_align_alloc);
1452 } // __kmp_stg_print_align_alloc
1453 
1454 // -----------------------------------------------------------------------------
1455 // KMP_PLAIN_BARRIER, KMP_FORKJOIN_BARRIER, KMP_REDUCTION_BARRIER
1456 
1457 // TODO: Remove __kmp_barrier_branch_bit_env_name varibale, remove loops from
1458 // parse and print functions, pass required info through data argument.
1459 
1460 static void __kmp_stg_parse_barrier_branch_bit(char const *name,
1461                                                char const *value, void *data) {
1462   const char *var;
1463 
1464   /* ---------- Barrier branch bit control ------------ */
1465   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1466     var = __kmp_barrier_branch_bit_env_name[i];
1467     if ((strcmp(var, name) == 0) && (value != 0)) {
1468       char *comma;
1469 
1470       comma = CCAST(char *, strchr(value, ','));
1471       __kmp_barrier_gather_branch_bits[i] =
1472           (kmp_uint32)__kmp_str_to_int(value, ',');
1473       /* is there a specified release parameter? */
1474       if (comma == NULL) {
1475         __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
1476       } else {
1477         __kmp_barrier_release_branch_bits[i] =
1478             (kmp_uint32)__kmp_str_to_int(comma + 1, 0);
1479 
1480         if (__kmp_barrier_release_branch_bits[i] > KMP_MAX_BRANCH_BITS) {
1481           __kmp_msg(kmp_ms_warning,
1482                     KMP_MSG(BarrReleaseValueInvalid, name, comma + 1),
1483                     __kmp_msg_null);
1484           __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
1485         }
1486       }
1487       if (__kmp_barrier_gather_branch_bits[i] > KMP_MAX_BRANCH_BITS) {
1488         KMP_WARNING(BarrGatherValueInvalid, name, value);
1489         KMP_INFORM(Using_uint_Value, name, __kmp_barrier_gather_bb_dflt);
1490         __kmp_barrier_gather_branch_bits[i] = __kmp_barrier_gather_bb_dflt;
1491       }
1492     }
1493     K_DIAG(1, ("%s == %d,%d\n", __kmp_barrier_branch_bit_env_name[i],
1494                __kmp_barrier_gather_branch_bits[i],
1495                __kmp_barrier_release_branch_bits[i]))
1496   }
1497 } // __kmp_stg_parse_barrier_branch_bit
1498 
1499 static void __kmp_stg_print_barrier_branch_bit(kmp_str_buf_t *buffer,
1500                                                char const *name, void *data) {
1501   const char *var;
1502   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1503     var = __kmp_barrier_branch_bit_env_name[i];
1504     if (strcmp(var, name) == 0) {
1505       if (__kmp_env_format) {
1506         KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_branch_bit_env_name[i]);
1507       } else {
1508         __kmp_str_buf_print(buffer, "   %s='",
1509                             __kmp_barrier_branch_bit_env_name[i]);
1510       }
1511       __kmp_str_buf_print(buffer, "%d,%d'\n",
1512                           __kmp_barrier_gather_branch_bits[i],
1513                           __kmp_barrier_release_branch_bits[i]);
1514     }
1515   }
1516 } // __kmp_stg_print_barrier_branch_bit
1517 
1518 // ----------------------------------------------------------------------------
1519 // KMP_PLAIN_BARRIER_PATTERN, KMP_FORKJOIN_BARRIER_PATTERN,
1520 // KMP_REDUCTION_BARRIER_PATTERN
1521 
1522 // TODO: Remove __kmp_barrier_pattern_name variable, remove loops from parse and
1523 // print functions, pass required data to functions through data argument.
1524 
1525 static void __kmp_stg_parse_barrier_pattern(char const *name, char const *value,
1526                                             void *data) {
1527   const char *var;
1528   /* ---------- Barrier method control ------------ */
1529 
1530   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1531     var = __kmp_barrier_pattern_env_name[i];
1532 
1533     if ((strcmp(var, name) == 0) && (value != 0)) {
1534       int j;
1535       char *comma = CCAST(char *, strchr(value, ','));
1536 
1537       /* handle first parameter: gather pattern */
1538       for (j = bp_linear_bar; j < bp_last_bar; j++) {
1539         if (__kmp_match_with_sentinel(__kmp_barrier_pattern_name[j], value, 1,
1540                                       ',')) {
1541           __kmp_barrier_gather_pattern[i] = (kmp_bar_pat_e)j;
1542           break;
1543         }
1544       }
1545       if (j == bp_last_bar) {
1546         KMP_WARNING(BarrGatherValueInvalid, name, value);
1547         KMP_INFORM(Using_str_Value, name,
1548                    __kmp_barrier_pattern_name[bp_linear_bar]);
1549       }
1550 
1551       /* handle second parameter: release pattern */
1552       if (comma != NULL) {
1553         for (j = bp_linear_bar; j < bp_last_bar; j++) {
1554           if (__kmp_str_match(__kmp_barrier_pattern_name[j], 1, comma + 1)) {
1555             __kmp_barrier_release_pattern[i] = (kmp_bar_pat_e)j;
1556             break;
1557           }
1558         }
1559         if (j == bp_last_bar) {
1560           __kmp_msg(kmp_ms_warning,
1561                     KMP_MSG(BarrReleaseValueInvalid, name, comma + 1),
1562                     __kmp_msg_null);
1563           KMP_INFORM(Using_str_Value, name,
1564                      __kmp_barrier_pattern_name[bp_linear_bar]);
1565         }
1566       }
1567     }
1568   }
1569 } // __kmp_stg_parse_barrier_pattern
1570 
1571 static void __kmp_stg_print_barrier_pattern(kmp_str_buf_t *buffer,
1572                                             char const *name, void *data) {
1573   const char *var;
1574   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1575     var = __kmp_barrier_pattern_env_name[i];
1576     if (strcmp(var, name) == 0) {
1577       int j = __kmp_barrier_gather_pattern[i];
1578       int k = __kmp_barrier_release_pattern[i];
1579       if (__kmp_env_format) {
1580         KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_pattern_env_name[i]);
1581       } else {
1582         __kmp_str_buf_print(buffer, "   %s='",
1583                             __kmp_barrier_pattern_env_name[i]);
1584       }
1585       __kmp_str_buf_print(buffer, "%s,%s'\n", __kmp_barrier_pattern_name[j],
1586                           __kmp_barrier_pattern_name[k]);
1587     }
1588   }
1589 } // __kmp_stg_print_barrier_pattern
1590 
1591 // -----------------------------------------------------------------------------
1592 // KMP_ABORT_DELAY
1593 
1594 static void __kmp_stg_parse_abort_delay(char const *name, char const *value,
1595                                         void *data) {
1596   // Units of KMP_DELAY_ABORT are seconds, units of __kmp_abort_delay is
1597   // milliseconds.
1598   int delay = __kmp_abort_delay / 1000;
1599   __kmp_stg_parse_int(name, value, 0, INT_MAX / 1000, &delay);
1600   __kmp_abort_delay = delay * 1000;
1601 } // __kmp_stg_parse_abort_delay
1602 
1603 static void __kmp_stg_print_abort_delay(kmp_str_buf_t *buffer, char const *name,
1604                                         void *data) {
1605   __kmp_stg_print_int(buffer, name, __kmp_abort_delay);
1606 } // __kmp_stg_print_abort_delay
1607 
1608 // -----------------------------------------------------------------------------
1609 // KMP_CPUINFO_FILE
1610 
1611 static void __kmp_stg_parse_cpuinfo_file(char const *name, char const *value,
1612                                          void *data) {
1613 #if KMP_AFFINITY_SUPPORTED
1614   __kmp_stg_parse_str(name, value, &__kmp_cpuinfo_file);
1615   K_DIAG(1, ("__kmp_cpuinfo_file == %s\n", __kmp_cpuinfo_file));
1616 #endif
1617 } //__kmp_stg_parse_cpuinfo_file
1618 
1619 static void __kmp_stg_print_cpuinfo_file(kmp_str_buf_t *buffer,
1620                                          char const *name, void *data) {
1621 #if KMP_AFFINITY_SUPPORTED
1622   if (__kmp_env_format) {
1623     KMP_STR_BUF_PRINT_NAME;
1624   } else {
1625     __kmp_str_buf_print(buffer, "   %s", name);
1626   }
1627   if (__kmp_cpuinfo_file) {
1628     __kmp_str_buf_print(buffer, "='%s'\n", __kmp_cpuinfo_file);
1629   } else {
1630     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1631   }
1632 #endif
1633 } //__kmp_stg_print_cpuinfo_file
1634 
1635 // -----------------------------------------------------------------------------
1636 // KMP_FORCE_REDUCTION, KMP_DETERMINISTIC_REDUCTION
1637 
1638 static void __kmp_stg_parse_force_reduction(char const *name, char const *value,
1639                                             void *data) {
1640   kmp_stg_fr_data_t *reduction = (kmp_stg_fr_data_t *)data;
1641   int rc;
1642 
1643   rc = __kmp_stg_check_rivals(name, value, reduction->rivals);
1644   if (rc) {
1645     return;
1646   }
1647   if (reduction->force) {
1648     if (value != 0) {
1649       if (__kmp_str_match("critical", 0, value))
1650         __kmp_force_reduction_method = critical_reduce_block;
1651       else if (__kmp_str_match("atomic", 0, value))
1652         __kmp_force_reduction_method = atomic_reduce_block;
1653       else if (__kmp_str_match("tree", 0, value))
1654         __kmp_force_reduction_method = tree_reduce_block;
1655       else {
1656         KMP_FATAL(UnknownForceReduction, name, value);
1657       }
1658     }
1659   } else {
1660     __kmp_stg_parse_bool(name, value, &__kmp_determ_red);
1661     if (__kmp_determ_red) {
1662       __kmp_force_reduction_method = tree_reduce_block;
1663     } else {
1664       __kmp_force_reduction_method = reduction_method_not_defined;
1665     }
1666   }
1667   K_DIAG(1, ("__kmp_force_reduction_method == %d\n",
1668              __kmp_force_reduction_method));
1669 } // __kmp_stg_parse_force_reduction
1670 
1671 static void __kmp_stg_print_force_reduction(kmp_str_buf_t *buffer,
1672                                             char const *name, void *data) {
1673 
1674   kmp_stg_fr_data_t *reduction = (kmp_stg_fr_data_t *)data;
1675   if (reduction->force) {
1676     if (__kmp_force_reduction_method == critical_reduce_block) {
1677       __kmp_stg_print_str(buffer, name, "critical");
1678     } else if (__kmp_force_reduction_method == atomic_reduce_block) {
1679       __kmp_stg_print_str(buffer, name, "atomic");
1680     } else if (__kmp_force_reduction_method == tree_reduce_block) {
1681       __kmp_stg_print_str(buffer, name, "tree");
1682     } else {
1683       if (__kmp_env_format) {
1684         KMP_STR_BUF_PRINT_NAME;
1685       } else {
1686         __kmp_str_buf_print(buffer, "   %s", name);
1687       }
1688       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1689     }
1690   } else {
1691     __kmp_stg_print_bool(buffer, name, __kmp_determ_red);
1692   }
1693 
1694 } // __kmp_stg_print_force_reduction
1695 
1696 // -----------------------------------------------------------------------------
1697 // KMP_STORAGE_MAP
1698 
1699 static void __kmp_stg_parse_storage_map(char const *name, char const *value,
1700                                         void *data) {
1701   if (__kmp_str_match("verbose", 1, value)) {
1702     __kmp_storage_map = TRUE;
1703     __kmp_storage_map_verbose = TRUE;
1704     __kmp_storage_map_verbose_specified = TRUE;
1705 
1706   } else {
1707     __kmp_storage_map_verbose = FALSE;
1708     __kmp_stg_parse_bool(name, value, &__kmp_storage_map); // !!!
1709   }
1710 } // __kmp_stg_parse_storage_map
1711 
1712 static void __kmp_stg_print_storage_map(kmp_str_buf_t *buffer, char const *name,
1713                                         void *data) {
1714   if (__kmp_storage_map_verbose || __kmp_storage_map_verbose_specified) {
1715     __kmp_stg_print_str(buffer, name, "verbose");
1716   } else {
1717     __kmp_stg_print_bool(buffer, name, __kmp_storage_map);
1718   }
1719 } // __kmp_stg_print_storage_map
1720 
1721 // -----------------------------------------------------------------------------
1722 // KMP_ALL_THREADPRIVATE
1723 
1724 static void __kmp_stg_parse_all_threadprivate(char const *name,
1725                                               char const *value, void *data) {
1726   __kmp_stg_parse_int(name, value,
1727                       __kmp_allThreadsSpecified ? __kmp_max_nth : 1,
1728                       __kmp_max_nth, &__kmp_tp_capacity);
1729 } // __kmp_stg_parse_all_threadprivate
1730 
1731 static void __kmp_stg_print_all_threadprivate(kmp_str_buf_t *buffer,
1732                                               char const *name, void *data) {
1733   __kmp_stg_print_int(buffer, name, __kmp_tp_capacity);
1734 }
1735 
1736 // -----------------------------------------------------------------------------
1737 // KMP_FOREIGN_THREADS_THREADPRIVATE
1738 
1739 static void __kmp_stg_parse_foreign_threads_threadprivate(char const *name,
1740                                                           char const *value,
1741                                                           void *data) {
1742   __kmp_stg_parse_bool(name, value, &__kmp_foreign_tp);
1743 } // __kmp_stg_parse_foreign_threads_threadprivate
1744 
1745 static void __kmp_stg_print_foreign_threads_threadprivate(kmp_str_buf_t *buffer,
1746                                                           char const *name,
1747                                                           void *data) {
1748   __kmp_stg_print_bool(buffer, name, __kmp_foreign_tp);
1749 } // __kmp_stg_print_foreign_threads_threadprivate
1750 
1751 // -----------------------------------------------------------------------------
1752 // KMP_AFFINITY, GOMP_CPU_AFFINITY, KMP_TOPOLOGY_METHOD
1753 
1754 #if KMP_AFFINITY_SUPPORTED
1755 // Parse the proc id list.  Return TRUE if successful, FALSE otherwise.
1756 static int __kmp_parse_affinity_proc_id_list(const char *var, const char *env,
1757                                              const char **nextEnv,
1758                                              char **proclist) {
1759   const char *scan = env;
1760   const char *next = scan;
1761   int empty = TRUE;
1762 
1763   *proclist = NULL;
1764 
1765   for (;;) {
1766     int start, end, stride;
1767 
1768     SKIP_WS(scan);
1769     next = scan;
1770     if (*next == '\0') {
1771       break;
1772     }
1773 
1774     if (*next == '{') {
1775       int num;
1776       next++; // skip '{'
1777       SKIP_WS(next);
1778       scan = next;
1779 
1780       // Read the first integer in the set.
1781       if ((*next < '0') || (*next > '9')) {
1782         KMP_WARNING(AffSyntaxError, var);
1783         return FALSE;
1784       }
1785       SKIP_DIGITS(next);
1786       num = __kmp_str_to_int(scan, *next);
1787       KMP_ASSERT(num >= 0);
1788 
1789       for (;;) {
1790         // Check for end of set.
1791         SKIP_WS(next);
1792         if (*next == '}') {
1793           next++; // skip '}'
1794           break;
1795         }
1796 
1797         // Skip optional comma.
1798         if (*next == ',') {
1799           next++;
1800         }
1801         SKIP_WS(next);
1802 
1803         // Read the next integer in the set.
1804         scan = next;
1805         if ((*next < '0') || (*next > '9')) {
1806           KMP_WARNING(AffSyntaxError, var);
1807           return FALSE;
1808         }
1809 
1810         SKIP_DIGITS(next);
1811         num = __kmp_str_to_int(scan, *next);
1812         KMP_ASSERT(num >= 0);
1813       }
1814       empty = FALSE;
1815 
1816       SKIP_WS(next);
1817       if (*next == ',') {
1818         next++;
1819       }
1820       scan = next;
1821       continue;
1822     }
1823 
1824     // Next character is not an integer => end of list
1825     if ((*next < '0') || (*next > '9')) {
1826       if (empty) {
1827         KMP_WARNING(AffSyntaxError, var);
1828         return FALSE;
1829       }
1830       break;
1831     }
1832 
1833     // Read the first integer.
1834     SKIP_DIGITS(next);
1835     start = __kmp_str_to_int(scan, *next);
1836     KMP_ASSERT(start >= 0);
1837     SKIP_WS(next);
1838 
1839     // If this isn't a range, then go on.
1840     if (*next != '-') {
1841       empty = FALSE;
1842 
1843       // Skip optional comma.
1844       if (*next == ',') {
1845         next++;
1846       }
1847       scan = next;
1848       continue;
1849     }
1850 
1851     // This is a range.  Skip over the '-' and read in the 2nd int.
1852     next++; // skip '-'
1853     SKIP_WS(next);
1854     scan = next;
1855     if ((*next < '0') || (*next > '9')) {
1856       KMP_WARNING(AffSyntaxError, var);
1857       return FALSE;
1858     }
1859     SKIP_DIGITS(next);
1860     end = __kmp_str_to_int(scan, *next);
1861     KMP_ASSERT(end >= 0);
1862 
1863     // Check for a stride parameter
1864     stride = 1;
1865     SKIP_WS(next);
1866     if (*next == ':') {
1867       // A stride is specified.  Skip over the ':" and read the 3rd int.
1868       int sign = +1;
1869       next++; // skip ':'
1870       SKIP_WS(next);
1871       scan = next;
1872       if (*next == '-') {
1873         sign = -1;
1874         next++;
1875         SKIP_WS(next);
1876         scan = next;
1877       }
1878       if ((*next < '0') || (*next > '9')) {
1879         KMP_WARNING(AffSyntaxError, var);
1880         return FALSE;
1881       }
1882       SKIP_DIGITS(next);
1883       stride = __kmp_str_to_int(scan, *next);
1884       KMP_ASSERT(stride >= 0);
1885       stride *= sign;
1886     }
1887 
1888     // Do some range checks.
1889     if (stride == 0) {
1890       KMP_WARNING(AffZeroStride, var);
1891       return FALSE;
1892     }
1893     if (stride > 0) {
1894       if (start > end) {
1895         KMP_WARNING(AffStartGreaterEnd, var, start, end);
1896         return FALSE;
1897       }
1898     } else {
1899       if (start < end) {
1900         KMP_WARNING(AffStrideLessZero, var, start, end);
1901         return FALSE;
1902       }
1903     }
1904     if ((end - start) / stride > 65536) {
1905       KMP_WARNING(AffRangeTooBig, var, end, start, stride);
1906       return FALSE;
1907     }
1908 
1909     empty = FALSE;
1910 
1911     // Skip optional comma.
1912     SKIP_WS(next);
1913     if (*next == ',') {
1914       next++;
1915     }
1916     scan = next;
1917   }
1918 
1919   *nextEnv = next;
1920 
1921   {
1922     int len = next - env;
1923     char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
1924     KMP_MEMCPY_S(retlist, (len + 1) * sizeof(char), env, len * sizeof(char));
1925     retlist[len] = '\0';
1926     *proclist = retlist;
1927   }
1928   return TRUE;
1929 }
1930 
1931 // If KMP_AFFINITY is specified without a type, then
1932 // __kmp_affinity_notype should point to its setting.
1933 static kmp_setting_t *__kmp_affinity_notype = NULL;
1934 
1935 static void __kmp_parse_affinity_env(char const *name, char const *value,
1936                                      enum affinity_type *out_type,
1937                                      char **out_proclist, int *out_verbose,
1938                                      int *out_warn, int *out_respect,
1939                                      enum affinity_gran *out_gran,
1940                                      int *out_gran_levels, int *out_dups,
1941                                      int *out_compact, int *out_offset) {
1942   char *buffer = NULL; // Copy of env var value.
1943   char *buf = NULL; // Buffer for strtok_r() function.
1944   char *next = NULL; // end of token / start of next.
1945   const char *start; // start of current token (for err msgs)
1946   int count = 0; // Counter of parsed integer numbers.
1947   int number[2]; // Parsed numbers.
1948 
1949   // Guards.
1950   int type = 0;
1951   int proclist = 0;
1952   int max_proclist = 0;
1953   int verbose = 0;
1954   int warnings = 0;
1955   int respect = 0;
1956   int gran = 0;
1957   int dups = 0;
1958 
1959   KMP_ASSERT(value != NULL);
1960 
1961   if (TCR_4(__kmp_init_middle)) {
1962     KMP_WARNING(EnvMiddleWarn, name);
1963     __kmp_env_toPrint(name, 0);
1964     return;
1965   }
1966   __kmp_env_toPrint(name, 1);
1967 
1968   buffer =
1969       __kmp_str_format("%s", value); // Copy env var to keep original intact.
1970   buf = buffer;
1971   SKIP_WS(buf);
1972 
1973 // Helper macros.
1974 
1975 // If we see a parse error, emit a warning and scan to the next ",".
1976 //
1977 // FIXME - there's got to be a better way to print an error
1978 // message, hopefully without overwritting peices of buf.
1979 #define EMIT_WARN(skip, errlist)                                               \
1980   {                                                                            \
1981     char ch;                                                                   \
1982     if (skip) {                                                                \
1983       SKIP_TO(next, ',');                                                      \
1984     }                                                                          \
1985     ch = *next;                                                                \
1986     *next = '\0';                                                              \
1987     KMP_WARNING errlist;                                                       \
1988     *next = ch;                                                                \
1989     if (skip) {                                                                \
1990       if (ch == ',')                                                           \
1991         next++;                                                                \
1992     }                                                                          \
1993     buf = next;                                                                \
1994   }
1995 
1996 #define _set_param(_guard, _var, _val)                                         \
1997   {                                                                            \
1998     if (_guard == 0) {                                                         \
1999       _var = _val;                                                             \
2000     } else {                                                                   \
2001       EMIT_WARN(FALSE, (AffParamDefined, name, start));                        \
2002     }                                                                          \
2003     ++_guard;                                                                  \
2004   }
2005 
2006 #define set_type(val) _set_param(type, *out_type, val)
2007 #define set_verbose(val) _set_param(verbose, *out_verbose, val)
2008 #define set_warnings(val) _set_param(warnings, *out_warn, val)
2009 #define set_respect(val) _set_param(respect, *out_respect, val)
2010 #define set_dups(val) _set_param(dups, *out_dups, val)
2011 #define set_proclist(val) _set_param(proclist, *out_proclist, val)
2012 
2013 #define set_gran(val, levels)                                                  \
2014   {                                                                            \
2015     if (gran == 0) {                                                           \
2016       *out_gran = val;                                                         \
2017       *out_gran_levels = levels;                                               \
2018     } else {                                                                   \
2019       EMIT_WARN(FALSE, (AffParamDefined, name, start));                        \
2020     }                                                                          \
2021     ++gran;                                                                    \
2022   }
2023 
2024 #if OMP_40_ENABLED
2025   KMP_DEBUG_ASSERT((__kmp_nested_proc_bind.bind_types != NULL) &&
2026                    (__kmp_nested_proc_bind.used > 0));
2027 #endif
2028 
2029   while (*buf != '\0') {
2030     start = next = buf;
2031 
2032     if (__kmp_match_str("none", buf, CCAST(const char **, &next))) {
2033       set_type(affinity_none);
2034 #if OMP_40_ENABLED
2035       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
2036 #endif
2037       buf = next;
2038     } else if (__kmp_match_str("scatter", buf, CCAST(const char **, &next))) {
2039       set_type(affinity_scatter);
2040 #if OMP_40_ENABLED
2041       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2042 #endif
2043       buf = next;
2044     } else if (__kmp_match_str("compact", buf, CCAST(const char **, &next))) {
2045       set_type(affinity_compact);
2046 #if OMP_40_ENABLED
2047       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2048 #endif
2049       buf = next;
2050     } else if (__kmp_match_str("logical", buf, CCAST(const char **, &next))) {
2051       set_type(affinity_logical);
2052 #if OMP_40_ENABLED
2053       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2054 #endif
2055       buf = next;
2056     } else if (__kmp_match_str("physical", buf, CCAST(const char **, &next))) {
2057       set_type(affinity_physical);
2058 #if OMP_40_ENABLED
2059       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2060 #endif
2061       buf = next;
2062     } else if (__kmp_match_str("explicit", buf, CCAST(const char **, &next))) {
2063       set_type(affinity_explicit);
2064 #if OMP_40_ENABLED
2065       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2066 #endif
2067       buf = next;
2068     } else if (__kmp_match_str("balanced", buf, CCAST(const char **, &next))) {
2069       set_type(affinity_balanced);
2070 #if OMP_40_ENABLED
2071       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2072 #endif
2073       buf = next;
2074     } else if (__kmp_match_str("disabled", buf, CCAST(const char **, &next))) {
2075       set_type(affinity_disabled);
2076 #if OMP_40_ENABLED
2077       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
2078 #endif
2079       buf = next;
2080     } else if (__kmp_match_str("verbose", buf, CCAST(const char **, &next))) {
2081       set_verbose(TRUE);
2082       buf = next;
2083     } else if (__kmp_match_str("noverbose", buf, CCAST(const char **, &next))) {
2084       set_verbose(FALSE);
2085       buf = next;
2086     } else if (__kmp_match_str("warnings", buf, CCAST(const char **, &next))) {
2087       set_warnings(TRUE);
2088       buf = next;
2089     } else if (__kmp_match_str("nowarnings", buf,
2090                                CCAST(const char **, &next))) {
2091       set_warnings(FALSE);
2092       buf = next;
2093     } else if (__kmp_match_str("respect", buf, CCAST(const char **, &next))) {
2094       set_respect(TRUE);
2095       buf = next;
2096     } else if (__kmp_match_str("norespect", buf, CCAST(const char **, &next))) {
2097       set_respect(FALSE);
2098       buf = next;
2099     } else if (__kmp_match_str("duplicates", buf,
2100                                CCAST(const char **, &next)) ||
2101                __kmp_match_str("dups", buf, CCAST(const char **, &next))) {
2102       set_dups(TRUE);
2103       buf = next;
2104     } else if (__kmp_match_str("noduplicates", buf,
2105                                CCAST(const char **, &next)) ||
2106                __kmp_match_str("nodups", buf, CCAST(const char **, &next))) {
2107       set_dups(FALSE);
2108       buf = next;
2109     } else if (__kmp_match_str("granularity", buf,
2110                                CCAST(const char **, &next)) ||
2111                __kmp_match_str("gran", buf, CCAST(const char **, &next))) {
2112       SKIP_WS(next);
2113       if (*next != '=') {
2114         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2115         continue;
2116       }
2117       next++; // skip '='
2118       SKIP_WS(next);
2119 
2120       buf = next;
2121       if (__kmp_match_str("fine", buf, CCAST(const char **, &next))) {
2122         set_gran(affinity_gran_fine, -1);
2123         buf = next;
2124       } else if (__kmp_match_str("thread", buf, CCAST(const char **, &next))) {
2125         set_gran(affinity_gran_thread, -1);
2126         buf = next;
2127       } else if (__kmp_match_str("core", buf, CCAST(const char **, &next))) {
2128         set_gran(affinity_gran_core, -1);
2129         buf = next;
2130 #if KMP_USE_HWLOC
2131       } else if (__kmp_match_str("tile", buf, CCAST(const char **, &next))) {
2132         set_gran(affinity_gran_tile, -1);
2133         buf = next;
2134 #endif
2135       } else if (__kmp_match_str("package", buf, CCAST(const char **, &next))) {
2136         set_gran(affinity_gran_package, -1);
2137         buf = next;
2138       } else if (__kmp_match_str("node", buf, CCAST(const char **, &next))) {
2139         set_gran(affinity_gran_node, -1);
2140         buf = next;
2141 #if KMP_GROUP_AFFINITY
2142       } else if (__kmp_match_str("group", buf, CCAST(const char **, &next))) {
2143         set_gran(affinity_gran_group, -1);
2144         buf = next;
2145 #endif /* KMP_GROUP AFFINITY */
2146       } else if ((*buf >= '0') && (*buf <= '9')) {
2147         int n;
2148         next = buf;
2149         SKIP_DIGITS(next);
2150         n = __kmp_str_to_int(buf, *next);
2151         KMP_ASSERT(n >= 0);
2152         buf = next;
2153         set_gran(affinity_gran_default, n);
2154       } else {
2155         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2156         continue;
2157       }
2158     } else if (__kmp_match_str("proclist", buf, CCAST(const char **, &next))) {
2159       char *temp_proclist;
2160 
2161       SKIP_WS(next);
2162       if (*next != '=') {
2163         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2164         continue;
2165       }
2166       next++; // skip '='
2167       SKIP_WS(next);
2168       if (*next != '[') {
2169         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2170         continue;
2171       }
2172       next++; // skip '['
2173       buf = next;
2174       if (!__kmp_parse_affinity_proc_id_list(
2175               name, buf, CCAST(const char **, &next), &temp_proclist)) {
2176         // warning already emitted.
2177         SKIP_TO(next, ']');
2178         if (*next == ']')
2179           next++;
2180         SKIP_TO(next, ',');
2181         if (*next == ',')
2182           next++;
2183         buf = next;
2184         continue;
2185       }
2186       if (*next != ']') {
2187         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2188         continue;
2189       }
2190       next++; // skip ']'
2191       set_proclist(temp_proclist);
2192     } else if ((*buf >= '0') && (*buf <= '9')) {
2193       // Parse integer numbers -- permute and offset.
2194       int n;
2195       next = buf;
2196       SKIP_DIGITS(next);
2197       n = __kmp_str_to_int(buf, *next);
2198       KMP_ASSERT(n >= 0);
2199       buf = next;
2200       if (count < 2) {
2201         number[count] = n;
2202       } else {
2203         KMP_WARNING(AffManyParams, name, start);
2204       }
2205       ++count;
2206     } else {
2207       EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2208       continue;
2209     }
2210 
2211     SKIP_WS(next);
2212     if (*next == ',') {
2213       next++;
2214       SKIP_WS(next);
2215     } else if (*next != '\0') {
2216       const char *temp = next;
2217       EMIT_WARN(TRUE, (ParseExtraCharsWarn, name, temp));
2218       continue;
2219     }
2220     buf = next;
2221   } // while
2222 
2223 #undef EMIT_WARN
2224 #undef _set_param
2225 #undef set_type
2226 #undef set_verbose
2227 #undef set_warnings
2228 #undef set_respect
2229 #undef set_granularity
2230 
2231   __kmp_str_free(&buffer);
2232 
2233   if (proclist) {
2234     if (!type) {
2235       KMP_WARNING(AffProcListNoType, name);
2236       *out_type = affinity_explicit;
2237 #if OMP_40_ENABLED
2238       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2239 #endif
2240     } else if (*out_type != affinity_explicit) {
2241       KMP_WARNING(AffProcListNotExplicit, name);
2242       KMP_ASSERT(*out_proclist != NULL);
2243       KMP_INTERNAL_FREE(*out_proclist);
2244       *out_proclist = NULL;
2245     }
2246   }
2247   switch (*out_type) {
2248   case affinity_logical:
2249   case affinity_physical: {
2250     if (count > 0) {
2251       *out_offset = number[0];
2252     }
2253     if (count > 1) {
2254       KMP_WARNING(AffManyParamsForLogic, name, number[1]);
2255     }
2256   } break;
2257   case affinity_balanced: {
2258     if (count > 0) {
2259       *out_compact = number[0];
2260     }
2261     if (count > 1) {
2262       *out_offset = number[1];
2263     }
2264 
2265     if (__kmp_affinity_gran == affinity_gran_default) {
2266 #if KMP_MIC_SUPPORTED
2267       if (__kmp_mic_type != non_mic) {
2268         if (__kmp_affinity_verbose || __kmp_affinity_warnings) {
2269           KMP_WARNING(AffGranUsing, "KMP_AFFINITY", "fine");
2270         }
2271         __kmp_affinity_gran = affinity_gran_fine;
2272       } else
2273 #endif
2274       {
2275         if (__kmp_affinity_verbose || __kmp_affinity_warnings) {
2276           KMP_WARNING(AffGranUsing, "KMP_AFFINITY", "core");
2277         }
2278         __kmp_affinity_gran = affinity_gran_core;
2279       }
2280     }
2281   } break;
2282   case affinity_scatter:
2283   case affinity_compact: {
2284     if (count > 0) {
2285       *out_compact = number[0];
2286     }
2287     if (count > 1) {
2288       *out_offset = number[1];
2289     }
2290   } break;
2291   case affinity_explicit: {
2292     if (*out_proclist == NULL) {
2293       KMP_WARNING(AffNoProcList, name);
2294       __kmp_affinity_type = affinity_none;
2295     }
2296     if (count > 0) {
2297       KMP_WARNING(AffNoParam, name, "explicit");
2298     }
2299   } break;
2300   case affinity_none: {
2301     if (count > 0) {
2302       KMP_WARNING(AffNoParam, name, "none");
2303     }
2304   } break;
2305   case affinity_disabled: {
2306     if (count > 0) {
2307       KMP_WARNING(AffNoParam, name, "disabled");
2308     }
2309   } break;
2310   case affinity_default: {
2311     if (count > 0) {
2312       KMP_WARNING(AffNoParam, name, "default");
2313     }
2314   } break;
2315   default: { KMP_ASSERT(0); }
2316   }
2317 } // __kmp_parse_affinity_env
2318 
2319 static void __kmp_stg_parse_affinity(char const *name, char const *value,
2320                                      void *data) {
2321   kmp_setting_t **rivals = (kmp_setting_t **)data;
2322   int rc;
2323 
2324   rc = __kmp_stg_check_rivals(name, value, rivals);
2325   if (rc) {
2326     return;
2327   }
2328 
2329   __kmp_parse_affinity_env(name, value, &__kmp_affinity_type,
2330                            &__kmp_affinity_proclist, &__kmp_affinity_verbose,
2331                            &__kmp_affinity_warnings,
2332                            &__kmp_affinity_respect_mask, &__kmp_affinity_gran,
2333                            &__kmp_affinity_gran_levels, &__kmp_affinity_dups,
2334                            &__kmp_affinity_compact, &__kmp_affinity_offset);
2335 
2336 } // __kmp_stg_parse_affinity
2337 
2338 static void __kmp_stg_print_affinity(kmp_str_buf_t *buffer, char const *name,
2339                                      void *data) {
2340   if (__kmp_env_format) {
2341     KMP_STR_BUF_PRINT_NAME_EX(name);
2342   } else {
2343     __kmp_str_buf_print(buffer, "   %s='", name);
2344   }
2345   if (__kmp_affinity_verbose) {
2346     __kmp_str_buf_print(buffer, "%s,", "verbose");
2347   } else {
2348     __kmp_str_buf_print(buffer, "%s,", "noverbose");
2349   }
2350   if (__kmp_affinity_warnings) {
2351     __kmp_str_buf_print(buffer, "%s,", "warnings");
2352   } else {
2353     __kmp_str_buf_print(buffer, "%s,", "nowarnings");
2354   }
2355   if (KMP_AFFINITY_CAPABLE()) {
2356     if (__kmp_affinity_respect_mask) {
2357       __kmp_str_buf_print(buffer, "%s,", "respect");
2358     } else {
2359       __kmp_str_buf_print(buffer, "%s,", "norespect");
2360     }
2361     switch (__kmp_affinity_gran) {
2362     case affinity_gran_default:
2363       __kmp_str_buf_print(buffer, "%s", "granularity=default,");
2364       break;
2365     case affinity_gran_fine:
2366       __kmp_str_buf_print(buffer, "%s", "granularity=fine,");
2367       break;
2368     case affinity_gran_thread:
2369       __kmp_str_buf_print(buffer, "%s", "granularity=thread,");
2370       break;
2371     case affinity_gran_core:
2372       __kmp_str_buf_print(buffer, "%s", "granularity=core,");
2373       break;
2374     case affinity_gran_package:
2375       __kmp_str_buf_print(buffer, "%s", "granularity=package,");
2376       break;
2377     case affinity_gran_node:
2378       __kmp_str_buf_print(buffer, "%s", "granularity=node,");
2379       break;
2380 #if KMP_GROUP_AFFINITY
2381     case affinity_gran_group:
2382       __kmp_str_buf_print(buffer, "%s", "granularity=group,");
2383       break;
2384 #endif /* KMP_GROUP_AFFINITY */
2385     }
2386   }
2387   if (!KMP_AFFINITY_CAPABLE()) {
2388     __kmp_str_buf_print(buffer, "%s", "disabled");
2389   } else
2390     switch (__kmp_affinity_type) {
2391     case affinity_none:
2392       __kmp_str_buf_print(buffer, "%s", "none");
2393       break;
2394     case affinity_physical:
2395       __kmp_str_buf_print(buffer, "%s,%d", "physical", __kmp_affinity_offset);
2396       break;
2397     case affinity_logical:
2398       __kmp_str_buf_print(buffer, "%s,%d", "logical", __kmp_affinity_offset);
2399       break;
2400     case affinity_compact:
2401       __kmp_str_buf_print(buffer, "%s,%d,%d", "compact", __kmp_affinity_compact,
2402                           __kmp_affinity_offset);
2403       break;
2404     case affinity_scatter:
2405       __kmp_str_buf_print(buffer, "%s,%d,%d", "scatter", __kmp_affinity_compact,
2406                           __kmp_affinity_offset);
2407       break;
2408     case affinity_explicit:
2409       __kmp_str_buf_print(buffer, "%s=[%s],%s", "proclist",
2410                           __kmp_affinity_proclist, "explicit");
2411       break;
2412     case affinity_balanced:
2413       __kmp_str_buf_print(buffer, "%s,%d,%d", "balanced",
2414                           __kmp_affinity_compact, __kmp_affinity_offset);
2415       break;
2416     case affinity_disabled:
2417       __kmp_str_buf_print(buffer, "%s", "disabled");
2418       break;
2419     case affinity_default:
2420       __kmp_str_buf_print(buffer, "%s", "default");
2421       break;
2422     default:
2423       __kmp_str_buf_print(buffer, "%s", "<unknown>");
2424       break;
2425     }
2426   __kmp_str_buf_print(buffer, "'\n");
2427 } //__kmp_stg_print_affinity
2428 
2429 #ifdef KMP_GOMP_COMPAT
2430 
2431 static void __kmp_stg_parse_gomp_cpu_affinity(char const *name,
2432                                               char const *value, void *data) {
2433   const char *next = NULL;
2434   char *temp_proclist;
2435   kmp_setting_t **rivals = (kmp_setting_t **)data;
2436   int rc;
2437 
2438   rc = __kmp_stg_check_rivals(name, value, rivals);
2439   if (rc) {
2440     return;
2441   }
2442 
2443   if (TCR_4(__kmp_init_middle)) {
2444     KMP_WARNING(EnvMiddleWarn, name);
2445     __kmp_env_toPrint(name, 0);
2446     return;
2447   }
2448 
2449   __kmp_env_toPrint(name, 1);
2450 
2451   if (__kmp_parse_affinity_proc_id_list(name, value, &next, &temp_proclist)) {
2452     SKIP_WS(next);
2453     if (*next == '\0') {
2454       // GOMP_CPU_AFFINITY => granularity=fine,explicit,proclist=...
2455       __kmp_affinity_proclist = temp_proclist;
2456       __kmp_affinity_type = affinity_explicit;
2457       __kmp_affinity_gran = affinity_gran_fine;
2458 #if OMP_40_ENABLED
2459       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2460 #endif
2461     } else {
2462       KMP_WARNING(AffSyntaxError, name);
2463       if (temp_proclist != NULL) {
2464         KMP_INTERNAL_FREE((void *)temp_proclist);
2465       }
2466     }
2467   } else {
2468     // Warning already emitted
2469     __kmp_affinity_type = affinity_none;
2470 #if OMP_40_ENABLED
2471     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
2472 #endif
2473   }
2474 } // __kmp_stg_parse_gomp_cpu_affinity
2475 
2476 #endif /* KMP_GOMP_COMPAT */
2477 
2478 #if OMP_40_ENABLED
2479 
2480 /*-----------------------------------------------------------------------------
2481 The OMP_PLACES proc id list parser. Here is the grammar:
2482 
2483 place_list := place
2484 place_list := place , place_list
2485 place := num
2486 place := place : num
2487 place := place : num : signed
2488 place := { subplacelist }
2489 place := ! place                  // (lowest priority)
2490 subplace_list := subplace
2491 subplace_list := subplace , subplace_list
2492 subplace := num
2493 subplace := num : num
2494 subplace := num : num : signed
2495 signed := num
2496 signed := + signed
2497 signed := - signed
2498 -----------------------------------------------------------------------------*/
2499 
2500 static int __kmp_parse_subplace_list(const char *var, const char **scan) {
2501   const char *next;
2502 
2503   for (;;) {
2504     int start, count, stride;
2505 
2506     //
2507     // Read in the starting proc id
2508     //
2509     SKIP_WS(*scan);
2510     if ((**scan < '0') || (**scan > '9')) {
2511       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2512       return FALSE;
2513     }
2514     next = *scan;
2515     SKIP_DIGITS(next);
2516     start = __kmp_str_to_int(*scan, *next);
2517     KMP_ASSERT(start >= 0);
2518     *scan = next;
2519 
2520     // valid follow sets are ',' ':' and '}'
2521     SKIP_WS(*scan);
2522     if (**scan == '}') {
2523       break;
2524     }
2525     if (**scan == ',') {
2526       (*scan)++; // skip ','
2527       continue;
2528     }
2529     if (**scan != ':') {
2530       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2531       return FALSE;
2532     }
2533     (*scan)++; // skip ':'
2534 
2535     // Read count parameter
2536     SKIP_WS(*scan);
2537     if ((**scan < '0') || (**scan > '9')) {
2538       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2539       return FALSE;
2540     }
2541     next = *scan;
2542     SKIP_DIGITS(next);
2543     count = __kmp_str_to_int(*scan, *next);
2544     KMP_ASSERT(count >= 0);
2545     *scan = next;
2546 
2547     // valid follow sets are ',' ':' and '}'
2548     SKIP_WS(*scan);
2549     if (**scan == '}') {
2550       break;
2551     }
2552     if (**scan == ',') {
2553       (*scan)++; // skip ','
2554       continue;
2555     }
2556     if (**scan != ':') {
2557       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2558       return FALSE;
2559     }
2560     (*scan)++; // skip ':'
2561 
2562     // Read stride parameter
2563     int sign = +1;
2564     for (;;) {
2565       SKIP_WS(*scan);
2566       if (**scan == '+') {
2567         (*scan)++; // skip '+'
2568         continue;
2569       }
2570       if (**scan == '-') {
2571         sign *= -1;
2572         (*scan)++; // skip '-'
2573         continue;
2574       }
2575       break;
2576     }
2577     SKIP_WS(*scan);
2578     if ((**scan < '0') || (**scan > '9')) {
2579       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2580       return FALSE;
2581     }
2582     next = *scan;
2583     SKIP_DIGITS(next);
2584     stride = __kmp_str_to_int(*scan, *next);
2585     KMP_ASSERT(stride >= 0);
2586     *scan = next;
2587     stride *= sign;
2588 
2589     // valid follow sets are ',' and '}'
2590     SKIP_WS(*scan);
2591     if (**scan == '}') {
2592       break;
2593     }
2594     if (**scan == ',') {
2595       (*scan)++; // skip ','
2596       continue;
2597     }
2598 
2599     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2600     return FALSE;
2601   }
2602   return TRUE;
2603 }
2604 
2605 static int __kmp_parse_place(const char *var, const char **scan) {
2606   const char *next;
2607 
2608   // valid follow sets are '{' '!' and num
2609   SKIP_WS(*scan);
2610   if (**scan == '{') {
2611     (*scan)++; // skip '{'
2612     if (!__kmp_parse_subplace_list(var, scan)) {
2613       return FALSE;
2614     }
2615     if (**scan != '}') {
2616       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2617       return FALSE;
2618     }
2619     (*scan)++; // skip '}'
2620   } else if (**scan == '!') {
2621     (*scan)++; // skip '!'
2622     return __kmp_parse_place(var, scan); //'!' has lower precedence than ':'
2623   } else if ((**scan >= '0') && (**scan <= '9')) {
2624     next = *scan;
2625     SKIP_DIGITS(next);
2626     int proc = __kmp_str_to_int(*scan, *next);
2627     KMP_ASSERT(proc >= 0);
2628     *scan = next;
2629   } else {
2630     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2631     return FALSE;
2632   }
2633   return TRUE;
2634 }
2635 
2636 static int __kmp_parse_place_list(const char *var, const char *env,
2637                                   char **place_list) {
2638   const char *scan = env;
2639   const char *next = scan;
2640 
2641   for (;;) {
2642     int start, count, stride;
2643 
2644     if (!__kmp_parse_place(var, &scan)) {
2645       return FALSE;
2646     }
2647 
2648     // valid follow sets are ',' ':' and EOL
2649     SKIP_WS(scan);
2650     if (*scan == '\0') {
2651       break;
2652     }
2653     if (*scan == ',') {
2654       scan++; // skip ','
2655       continue;
2656     }
2657     if (*scan != ':') {
2658       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2659       return FALSE;
2660     }
2661     scan++; // skip ':'
2662 
2663     // Read count parameter
2664     SKIP_WS(scan);
2665     if ((*scan < '0') || (*scan > '9')) {
2666       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2667       return FALSE;
2668     }
2669     next = scan;
2670     SKIP_DIGITS(next);
2671     count = __kmp_str_to_int(scan, *next);
2672     KMP_ASSERT(count >= 0);
2673     scan = next;
2674 
2675     // valid follow sets are ',' ':' and EOL
2676     SKIP_WS(scan);
2677     if (*scan == '\0') {
2678       break;
2679     }
2680     if (*scan == ',') {
2681       scan++; // skip ','
2682       continue;
2683     }
2684     if (*scan != ':') {
2685       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2686       return FALSE;
2687     }
2688     scan++; // skip ':'
2689 
2690     // Read stride parameter
2691     int sign = +1;
2692     for (;;) {
2693       SKIP_WS(scan);
2694       if (*scan == '+') {
2695         scan++; // skip '+'
2696         continue;
2697       }
2698       if (*scan == '-') {
2699         sign *= -1;
2700         scan++; // skip '-'
2701         continue;
2702       }
2703       break;
2704     }
2705     SKIP_WS(scan);
2706     if ((*scan < '0') || (*scan > '9')) {
2707       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2708       return FALSE;
2709     }
2710     next = scan;
2711     SKIP_DIGITS(next);
2712     stride = __kmp_str_to_int(scan, *next);
2713     KMP_ASSERT(stride >= 0);
2714     scan = next;
2715     stride *= sign;
2716 
2717     // valid follow sets are ',' and EOL
2718     SKIP_WS(scan);
2719     if (*scan == '\0') {
2720       break;
2721     }
2722     if (*scan == ',') {
2723       scan++; // skip ','
2724       continue;
2725     }
2726 
2727     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2728     return FALSE;
2729   }
2730 
2731   {
2732     int len = scan - env;
2733     char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
2734     KMP_MEMCPY_S(retlist, (len + 1) * sizeof(char), env, len * sizeof(char));
2735     retlist[len] = '\0';
2736     *place_list = retlist;
2737   }
2738   return TRUE;
2739 }
2740 
2741 static void __kmp_stg_parse_places(char const *name, char const *value,
2742                                    void *data) {
2743   int count;
2744   const char *scan = value;
2745   const char *next = scan;
2746   const char *kind = "\"threads\"";
2747   kmp_setting_t **rivals = (kmp_setting_t **)data;
2748   int rc;
2749 
2750   rc = __kmp_stg_check_rivals(name, value, rivals);
2751   if (rc) {
2752     return;
2753   }
2754 
2755   // If OMP_PROC_BIND is not specified but OMP_PLACES is,
2756   // then let OMP_PROC_BIND default to true.
2757   if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2758     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2759   }
2760 
2761   //__kmp_affinity_num_places = 0;
2762 
2763   if (__kmp_match_str("threads", scan, &next)) {
2764     scan = next;
2765     __kmp_affinity_type = affinity_compact;
2766     __kmp_affinity_gran = affinity_gran_thread;
2767     __kmp_affinity_dups = FALSE;
2768     kind = "\"threads\"";
2769   } else if (__kmp_match_str("cores", scan, &next)) {
2770     scan = next;
2771     __kmp_affinity_type = affinity_compact;
2772     __kmp_affinity_gran = affinity_gran_core;
2773     __kmp_affinity_dups = FALSE;
2774     kind = "\"cores\"";
2775 #if KMP_USE_HWLOC
2776   } else if (__kmp_match_str("tiles", scan, &next)) {
2777     scan = next;
2778     __kmp_affinity_type = affinity_compact;
2779     __kmp_affinity_gran = affinity_gran_tile;
2780     __kmp_affinity_dups = FALSE;
2781     kind = "\"tiles\"";
2782 #endif
2783   } else if (__kmp_match_str("sockets", scan, &next)) {
2784     scan = next;
2785     __kmp_affinity_type = affinity_compact;
2786     __kmp_affinity_gran = affinity_gran_package;
2787     __kmp_affinity_dups = FALSE;
2788     kind = "\"sockets\"";
2789   } else {
2790     if (__kmp_affinity_proclist != NULL) {
2791       KMP_INTERNAL_FREE((void *)__kmp_affinity_proclist);
2792       __kmp_affinity_proclist = NULL;
2793     }
2794     if (__kmp_parse_place_list(name, value, &__kmp_affinity_proclist)) {
2795       __kmp_affinity_type = affinity_explicit;
2796       __kmp_affinity_gran = affinity_gran_fine;
2797       __kmp_affinity_dups = FALSE;
2798       if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2799         __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2800       }
2801     }
2802     return;
2803   }
2804 
2805   if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2806     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2807   }
2808 
2809   SKIP_WS(scan);
2810   if (*scan == '\0') {
2811     return;
2812   }
2813 
2814   // Parse option count parameter in parentheses
2815   if (*scan != '(') {
2816     KMP_WARNING(SyntaxErrorUsing, name, kind);
2817     return;
2818   }
2819   scan++; // skip '('
2820 
2821   SKIP_WS(scan);
2822   next = scan;
2823   SKIP_DIGITS(next);
2824   count = __kmp_str_to_int(scan, *next);
2825   KMP_ASSERT(count >= 0);
2826   scan = next;
2827 
2828   SKIP_WS(scan);
2829   if (*scan != ')') {
2830     KMP_WARNING(SyntaxErrorUsing, name, kind);
2831     return;
2832   }
2833   scan++; // skip ')'
2834 
2835   SKIP_WS(scan);
2836   if (*scan != '\0') {
2837     KMP_WARNING(ParseExtraCharsWarn, name, scan);
2838   }
2839   __kmp_affinity_num_places = count;
2840 }
2841 
2842 static void __kmp_stg_print_places(kmp_str_buf_t *buffer, char const *name,
2843                                    void *data) {
2844   if (__kmp_env_format) {
2845     KMP_STR_BUF_PRINT_NAME;
2846   } else {
2847     __kmp_str_buf_print(buffer, "   %s", name);
2848   }
2849   if ((__kmp_nested_proc_bind.used == 0) ||
2850       (__kmp_nested_proc_bind.bind_types == NULL) ||
2851       (__kmp_nested_proc_bind.bind_types[0] == proc_bind_false)) {
2852     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2853   } else if (__kmp_affinity_type == affinity_explicit) {
2854     if (__kmp_affinity_proclist != NULL) {
2855       __kmp_str_buf_print(buffer, "='%s'\n", __kmp_affinity_proclist);
2856     } else {
2857       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2858     }
2859   } else if (__kmp_affinity_type == affinity_compact) {
2860     int num;
2861     if (__kmp_affinity_num_masks > 0) {
2862       num = __kmp_affinity_num_masks;
2863     } else if (__kmp_affinity_num_places > 0) {
2864       num = __kmp_affinity_num_places;
2865     } else {
2866       num = 0;
2867     }
2868     if (__kmp_affinity_gran == affinity_gran_thread) {
2869       if (num > 0) {
2870         __kmp_str_buf_print(buffer, "='threads(%d)'\n", num);
2871       } else {
2872         __kmp_str_buf_print(buffer, "='threads'\n");
2873       }
2874     } else if (__kmp_affinity_gran == affinity_gran_core) {
2875       if (num > 0) {
2876         __kmp_str_buf_print(buffer, "='cores(%d)' \n", num);
2877       } else {
2878         __kmp_str_buf_print(buffer, "='cores'\n");
2879       }
2880 #if KMP_USE_HWLOC
2881     } else if (__kmp_affinity_gran == affinity_gran_tile) {
2882       if (num > 0) {
2883         __kmp_str_buf_print(buffer, "='tiles(%d)' \n", num);
2884       } else {
2885         __kmp_str_buf_print(buffer, "='tiles'\n");
2886       }
2887 #endif
2888     } else if (__kmp_affinity_gran == affinity_gran_package) {
2889       if (num > 0) {
2890         __kmp_str_buf_print(buffer, "='sockets(%d)'\n", num);
2891       } else {
2892         __kmp_str_buf_print(buffer, "='sockets'\n");
2893       }
2894     } else {
2895       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2896     }
2897   } else {
2898     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2899   }
2900 }
2901 
2902 #endif /* OMP_40_ENABLED */
2903 
2904 #if (!OMP_40_ENABLED)
2905 
2906 static void __kmp_stg_parse_proc_bind(char const *name, char const *value,
2907                                       void *data) {
2908   int enabled;
2909   kmp_setting_t **rivals = (kmp_setting_t **)data;
2910   int rc;
2911 
2912   rc = __kmp_stg_check_rivals(name, value, rivals);
2913   if (rc) {
2914     return;
2915   }
2916 
2917   // In OMP 3.1, OMP_PROC_BIND is strictly a boolean
2918   __kmp_stg_parse_bool(name, value, &enabled);
2919   if (enabled) {
2920     // OMP_PROC_BIND => granularity=fine,scatter on MIC
2921     // OMP_PROC_BIND => granularity=core,scatter elsewhere
2922     __kmp_affinity_type = affinity_scatter;
2923 #if KMP_MIC_SUPPORTED
2924     if (__kmp_mic_type != non_mic)
2925       __kmp_affinity_gran = affinity_gran_fine;
2926     else
2927 #endif
2928       __kmp_affinity_gran = affinity_gran_core;
2929   } else {
2930     __kmp_affinity_type = affinity_none;
2931   }
2932 } // __kmp_parse_proc_bind
2933 
2934 #endif /* if (! OMP_40_ENABLED) */
2935 
2936 static void __kmp_stg_parse_topology_method(char const *name, char const *value,
2937                                             void *data) {
2938   if (__kmp_str_match("all", 1, value)) {
2939     __kmp_affinity_top_method = affinity_top_method_all;
2940   }
2941 #if KMP_USE_HWLOC
2942   else if (__kmp_str_match("hwloc", 1, value)) {
2943     __kmp_affinity_top_method = affinity_top_method_hwloc;
2944   }
2945 #endif
2946 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
2947   else if (__kmp_str_match("x2apic id", 9, value) ||
2948            __kmp_str_match("x2apic_id", 9, value) ||
2949            __kmp_str_match("x2apic-id", 9, value) ||
2950            __kmp_str_match("x2apicid", 8, value) ||
2951            __kmp_str_match("cpuid leaf 11", 13, value) ||
2952            __kmp_str_match("cpuid_leaf_11", 13, value) ||
2953            __kmp_str_match("cpuid-leaf-11", 13, value) ||
2954            __kmp_str_match("cpuid leaf11", 12, value) ||
2955            __kmp_str_match("cpuid_leaf11", 12, value) ||
2956            __kmp_str_match("cpuid-leaf11", 12, value) ||
2957            __kmp_str_match("cpuidleaf 11", 12, value) ||
2958            __kmp_str_match("cpuidleaf_11", 12, value) ||
2959            __kmp_str_match("cpuidleaf-11", 12, value) ||
2960            __kmp_str_match("cpuidleaf11", 11, value) ||
2961            __kmp_str_match("cpuid 11", 8, value) ||
2962            __kmp_str_match("cpuid_11", 8, value) ||
2963            __kmp_str_match("cpuid-11", 8, value) ||
2964            __kmp_str_match("cpuid11", 7, value) ||
2965            __kmp_str_match("leaf 11", 7, value) ||
2966            __kmp_str_match("leaf_11", 7, value) ||
2967            __kmp_str_match("leaf-11", 7, value) ||
2968            __kmp_str_match("leaf11", 6, value)) {
2969     __kmp_affinity_top_method = affinity_top_method_x2apicid;
2970   } else if (__kmp_str_match("apic id", 7, value) ||
2971              __kmp_str_match("apic_id", 7, value) ||
2972              __kmp_str_match("apic-id", 7, value) ||
2973              __kmp_str_match("apicid", 6, value) ||
2974              __kmp_str_match("cpuid leaf 4", 12, value) ||
2975              __kmp_str_match("cpuid_leaf_4", 12, value) ||
2976              __kmp_str_match("cpuid-leaf-4", 12, value) ||
2977              __kmp_str_match("cpuid leaf4", 11, value) ||
2978              __kmp_str_match("cpuid_leaf4", 11, value) ||
2979              __kmp_str_match("cpuid-leaf4", 11, value) ||
2980              __kmp_str_match("cpuidleaf 4", 11, value) ||
2981              __kmp_str_match("cpuidleaf_4", 11, value) ||
2982              __kmp_str_match("cpuidleaf-4", 11, value) ||
2983              __kmp_str_match("cpuidleaf4", 10, value) ||
2984              __kmp_str_match("cpuid 4", 7, value) ||
2985              __kmp_str_match("cpuid_4", 7, value) ||
2986              __kmp_str_match("cpuid-4", 7, value) ||
2987              __kmp_str_match("cpuid4", 6, value) ||
2988              __kmp_str_match("leaf 4", 6, value) ||
2989              __kmp_str_match("leaf_4", 6, value) ||
2990              __kmp_str_match("leaf-4", 6, value) ||
2991              __kmp_str_match("leaf4", 5, value)) {
2992     __kmp_affinity_top_method = affinity_top_method_apicid;
2993   }
2994 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
2995   else if (__kmp_str_match("/proc/cpuinfo", 2, value) ||
2996            __kmp_str_match("cpuinfo", 5, value)) {
2997     __kmp_affinity_top_method = affinity_top_method_cpuinfo;
2998   }
2999 #if KMP_GROUP_AFFINITY
3000   else if (__kmp_str_match("group", 1, value)) {
3001     __kmp_affinity_top_method = affinity_top_method_group;
3002   }
3003 #endif /* KMP_GROUP_AFFINITY */
3004   else if (__kmp_str_match("flat", 1, value)) {
3005     __kmp_affinity_top_method = affinity_top_method_flat;
3006   } else {
3007     KMP_WARNING(StgInvalidValue, name, value);
3008   }
3009 } // __kmp_stg_parse_topology_method
3010 
3011 static void __kmp_stg_print_topology_method(kmp_str_buf_t *buffer,
3012                                             char const *name, void *data) {
3013   char const *value = NULL;
3014 
3015   switch (__kmp_affinity_top_method) {
3016   case affinity_top_method_default:
3017     value = "default";
3018     break;
3019 
3020   case affinity_top_method_all:
3021     value = "all";
3022     break;
3023 
3024 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
3025   case affinity_top_method_x2apicid:
3026     value = "x2APIC id";
3027     break;
3028 
3029   case affinity_top_method_apicid:
3030     value = "APIC id";
3031     break;
3032 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
3033 
3034 #if KMP_USE_HWLOC
3035   case affinity_top_method_hwloc:
3036     value = "hwloc";
3037     break;
3038 #endif
3039 
3040   case affinity_top_method_cpuinfo:
3041     value = "cpuinfo";
3042     break;
3043 
3044 #if KMP_GROUP_AFFINITY
3045   case affinity_top_method_group:
3046     value = "group";
3047     break;
3048 #endif /* KMP_GROUP_AFFINITY */
3049 
3050   case affinity_top_method_flat:
3051     value = "flat";
3052     break;
3053   }
3054 
3055   if (value != NULL) {
3056     __kmp_stg_print_str(buffer, name, value);
3057   }
3058 } // __kmp_stg_print_topology_method
3059 
3060 #endif /* KMP_AFFINITY_SUPPORTED */
3061 
3062 #if OMP_40_ENABLED
3063 
3064 // OMP_PROC_BIND / bind-var is functional on all 4.0 builds, including OS X*
3065 // OMP_PLACES / place-partition-var is not.
3066 static void __kmp_stg_parse_proc_bind(char const *name, char const *value,
3067                                       void *data) {
3068   kmp_setting_t **rivals = (kmp_setting_t **)data;
3069   int rc;
3070 
3071   rc = __kmp_stg_check_rivals(name, value, rivals);
3072   if (rc) {
3073     return;
3074   }
3075 
3076   // In OMP 4.0 OMP_PROC_BIND is a vector of proc_bind types.
3077   KMP_DEBUG_ASSERT((__kmp_nested_proc_bind.bind_types != NULL) &&
3078                    (__kmp_nested_proc_bind.used > 0));
3079 
3080   const char *buf = value;
3081   const char *next;
3082   int num;
3083   SKIP_WS(buf);
3084   if ((*buf >= '0') && (*buf <= '9')) {
3085     next = buf;
3086     SKIP_DIGITS(next);
3087     num = __kmp_str_to_int(buf, *next);
3088     KMP_ASSERT(num >= 0);
3089     buf = next;
3090     SKIP_WS(buf);
3091   } else {
3092     num = -1;
3093   }
3094 
3095   next = buf;
3096   if (__kmp_match_str("disabled", buf, &next)) {
3097     buf = next;
3098     SKIP_WS(buf);
3099 #if KMP_AFFINITY_SUPPORTED
3100     __kmp_affinity_type = affinity_disabled;
3101 #endif /* KMP_AFFINITY_SUPPORTED */
3102     __kmp_nested_proc_bind.used = 1;
3103     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3104   } else if ((num == (int)proc_bind_false) ||
3105              __kmp_match_str("false", buf, &next)) {
3106     buf = next;
3107     SKIP_WS(buf);
3108 #if KMP_AFFINITY_SUPPORTED
3109     __kmp_affinity_type = affinity_none;
3110 #endif /* KMP_AFFINITY_SUPPORTED */
3111     __kmp_nested_proc_bind.used = 1;
3112     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3113   } else if ((num == (int)proc_bind_true) ||
3114              __kmp_match_str("true", buf, &next)) {
3115     buf = next;
3116     SKIP_WS(buf);
3117     __kmp_nested_proc_bind.used = 1;
3118     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
3119   } else {
3120     // Count the number of values in the env var string
3121     const char *scan;
3122     int nelem = 1;
3123     for (scan = buf; *scan != '\0'; scan++) {
3124       if (*scan == ',') {
3125         nelem++;
3126       }
3127     }
3128 
3129     // Create / expand the nested proc_bind array as needed
3130     if (__kmp_nested_proc_bind.size < nelem) {
3131       __kmp_nested_proc_bind.bind_types =
3132           (kmp_proc_bind_t *)KMP_INTERNAL_REALLOC(
3133               __kmp_nested_proc_bind.bind_types,
3134               sizeof(kmp_proc_bind_t) * nelem);
3135       if (__kmp_nested_proc_bind.bind_types == NULL) {
3136         KMP_FATAL(MemoryAllocFailed);
3137       }
3138       __kmp_nested_proc_bind.size = nelem;
3139     }
3140     __kmp_nested_proc_bind.used = nelem;
3141 
3142     // Save values in the nested proc_bind array
3143     int i = 0;
3144     for (;;) {
3145       enum kmp_proc_bind_t bind;
3146 
3147       if ((num == (int)proc_bind_master) ||
3148           __kmp_match_str("master", buf, &next)) {
3149         buf = next;
3150         SKIP_WS(buf);
3151         bind = proc_bind_master;
3152       } else if ((num == (int)proc_bind_close) ||
3153                  __kmp_match_str("close", buf, &next)) {
3154         buf = next;
3155         SKIP_WS(buf);
3156         bind = proc_bind_close;
3157       } else if ((num == (int)proc_bind_spread) ||
3158                  __kmp_match_str("spread", buf, &next)) {
3159         buf = next;
3160         SKIP_WS(buf);
3161         bind = proc_bind_spread;
3162       } else {
3163         KMP_WARNING(StgInvalidValue, name, value);
3164         __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3165         __kmp_nested_proc_bind.used = 1;
3166         return;
3167       }
3168 
3169       __kmp_nested_proc_bind.bind_types[i++] = bind;
3170       if (i >= nelem) {
3171         break;
3172       }
3173       KMP_DEBUG_ASSERT(*buf == ',');
3174       buf++;
3175       SKIP_WS(buf);
3176 
3177       // Read next value if it was specified as an integer
3178       if ((*buf >= '0') && (*buf <= '9')) {
3179         next = buf;
3180         SKIP_DIGITS(next);
3181         num = __kmp_str_to_int(buf, *next);
3182         KMP_ASSERT(num >= 0);
3183         buf = next;
3184         SKIP_WS(buf);
3185       } else {
3186         num = -1;
3187       }
3188     }
3189     SKIP_WS(buf);
3190   }
3191   if (*buf != '\0') {
3192     KMP_WARNING(ParseExtraCharsWarn, name, buf);
3193   }
3194 }
3195 
3196 static void __kmp_stg_print_proc_bind(kmp_str_buf_t *buffer, char const *name,
3197                                       void *data) {
3198   int nelem = __kmp_nested_proc_bind.used;
3199   if (__kmp_env_format) {
3200     KMP_STR_BUF_PRINT_NAME;
3201   } else {
3202     __kmp_str_buf_print(buffer, "   %s", name);
3203   }
3204   if (nelem == 0) {
3205     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
3206   } else {
3207     int i;
3208     __kmp_str_buf_print(buffer, "='", name);
3209     for (i = 0; i < nelem; i++) {
3210       switch (__kmp_nested_proc_bind.bind_types[i]) {
3211       case proc_bind_false:
3212         __kmp_str_buf_print(buffer, "false");
3213         break;
3214 
3215       case proc_bind_true:
3216         __kmp_str_buf_print(buffer, "true");
3217         break;
3218 
3219       case proc_bind_master:
3220         __kmp_str_buf_print(buffer, "master");
3221         break;
3222 
3223       case proc_bind_close:
3224         __kmp_str_buf_print(buffer, "close");
3225         break;
3226 
3227       case proc_bind_spread:
3228         __kmp_str_buf_print(buffer, "spread");
3229         break;
3230 
3231       case proc_bind_intel:
3232         __kmp_str_buf_print(buffer, "intel");
3233         break;
3234 
3235       case proc_bind_default:
3236         __kmp_str_buf_print(buffer, "default");
3237         break;
3238       }
3239       if (i < nelem - 1) {
3240         __kmp_str_buf_print(buffer, ",");
3241       }
3242     }
3243     __kmp_str_buf_print(buffer, "'\n");
3244   }
3245 }
3246 
3247 #endif /* OMP_40_ENABLED */
3248 
3249 // -----------------------------------------------------------------------------
3250 // OMP_DYNAMIC
3251 
3252 static void __kmp_stg_parse_omp_dynamic(char const *name, char const *value,
3253                                         void *data) {
3254   __kmp_stg_parse_bool(name, value, &(__kmp_global.g.g_dynamic));
3255 } // __kmp_stg_parse_omp_dynamic
3256 
3257 static void __kmp_stg_print_omp_dynamic(kmp_str_buf_t *buffer, char const *name,
3258                                         void *data) {
3259   __kmp_stg_print_bool(buffer, name, __kmp_global.g.g_dynamic);
3260 } // __kmp_stg_print_omp_dynamic
3261 
3262 static void __kmp_stg_parse_kmp_dynamic_mode(char const *name,
3263                                              char const *value, void *data) {
3264   if (TCR_4(__kmp_init_parallel)) {
3265     KMP_WARNING(EnvParallelWarn, name);
3266     __kmp_env_toPrint(name, 0);
3267     return;
3268   }
3269 #ifdef USE_LOAD_BALANCE
3270   else if (__kmp_str_match("load balance", 2, value) ||
3271            __kmp_str_match("load_balance", 2, value) ||
3272            __kmp_str_match("load-balance", 2, value) ||
3273            __kmp_str_match("loadbalance", 2, value) ||
3274            __kmp_str_match("balance", 1, value)) {
3275     __kmp_global.g.g_dynamic_mode = dynamic_load_balance;
3276   }
3277 #endif /* USE_LOAD_BALANCE */
3278   else if (__kmp_str_match("thread limit", 1, value) ||
3279            __kmp_str_match("thread_limit", 1, value) ||
3280            __kmp_str_match("thread-limit", 1, value) ||
3281            __kmp_str_match("threadlimit", 1, value) ||
3282            __kmp_str_match("limit", 2, value)) {
3283     __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
3284   } else if (__kmp_str_match("random", 1, value)) {
3285     __kmp_global.g.g_dynamic_mode = dynamic_random;
3286   } else {
3287     KMP_WARNING(StgInvalidValue, name, value);
3288   }
3289 } //__kmp_stg_parse_kmp_dynamic_mode
3290 
3291 static void __kmp_stg_print_kmp_dynamic_mode(kmp_str_buf_t *buffer,
3292                                              char const *name, void *data) {
3293 #if KMP_DEBUG
3294   if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
3295     __kmp_str_buf_print(buffer, "   %s: %s \n", name, KMP_I18N_STR(NotDefined));
3296   }
3297 #ifdef USE_LOAD_BALANCE
3298   else if (__kmp_global.g.g_dynamic_mode == dynamic_load_balance) {
3299     __kmp_stg_print_str(buffer, name, "load balance");
3300   }
3301 #endif /* USE_LOAD_BALANCE */
3302   else if (__kmp_global.g.g_dynamic_mode == dynamic_thread_limit) {
3303     __kmp_stg_print_str(buffer, name, "thread limit");
3304   } else if (__kmp_global.g.g_dynamic_mode == dynamic_random) {
3305     __kmp_stg_print_str(buffer, name, "random");
3306   } else {
3307     KMP_ASSERT(0);
3308   }
3309 #endif /* KMP_DEBUG */
3310 } // __kmp_stg_print_kmp_dynamic_mode
3311 
3312 #ifdef USE_LOAD_BALANCE
3313 
3314 // -----------------------------------------------------------------------------
3315 // KMP_LOAD_BALANCE_INTERVAL
3316 
3317 static void __kmp_stg_parse_ld_balance_interval(char const *name,
3318                                                 char const *value, void *data) {
3319   double interval = __kmp_convert_to_double(value);
3320   if (interval >= 0) {
3321     __kmp_load_balance_interval = interval;
3322   } else {
3323     KMP_WARNING(StgInvalidValue, name, value);
3324   }
3325 } // __kmp_stg_parse_load_balance_interval
3326 
3327 static void __kmp_stg_print_ld_balance_interval(kmp_str_buf_t *buffer,
3328                                                 char const *name, void *data) {
3329 #if KMP_DEBUG
3330   __kmp_str_buf_print(buffer, "   %s=%8.6f\n", name,
3331                       __kmp_load_balance_interval);
3332 #endif /* KMP_DEBUG */
3333 } // __kmp_stg_print_load_balance_interval
3334 
3335 #endif /* USE_LOAD_BALANCE */
3336 
3337 // -----------------------------------------------------------------------------
3338 // KMP_INIT_AT_FORK
3339 
3340 static void __kmp_stg_parse_init_at_fork(char const *name, char const *value,
3341                                          void *data) {
3342   __kmp_stg_parse_bool(name, value, &__kmp_need_register_atfork);
3343   if (__kmp_need_register_atfork) {
3344     __kmp_need_register_atfork_specified = TRUE;
3345   }
3346 } // __kmp_stg_parse_init_at_fork
3347 
3348 static void __kmp_stg_print_init_at_fork(kmp_str_buf_t *buffer,
3349                                          char const *name, void *data) {
3350   __kmp_stg_print_bool(buffer, name, __kmp_need_register_atfork_specified);
3351 } // __kmp_stg_print_init_at_fork
3352 
3353 // -----------------------------------------------------------------------------
3354 // KMP_SCHEDULE
3355 
3356 static void __kmp_stg_parse_schedule(char const *name, char const *value,
3357                                      void *data) {
3358 
3359   if (value != NULL) {
3360     size_t length = KMP_STRLEN(value);
3361     if (length > INT_MAX) {
3362       KMP_WARNING(LongValue, name);
3363     } else {
3364       const char *semicolon;
3365       if (value[length - 1] == '"' || value[length - 1] == '\'')
3366         KMP_WARNING(UnbalancedQuotes, name);
3367       do {
3368         char sentinel;
3369 
3370         semicolon = strchr(value, ';');
3371         if (*value && semicolon != value) {
3372           const char *comma = strchr(value, ',');
3373 
3374           if (comma) {
3375             ++comma;
3376             sentinel = ',';
3377           } else
3378             sentinel = ';';
3379           if (!__kmp_strcasecmp_with_sentinel("static", value, sentinel)) {
3380             if (!__kmp_strcasecmp_with_sentinel("greedy", comma, ';')) {
3381               __kmp_static = kmp_sch_static_greedy;
3382               continue;
3383             } else if (!__kmp_strcasecmp_with_sentinel("balanced", comma,
3384                                                        ';')) {
3385               __kmp_static = kmp_sch_static_balanced;
3386               continue;
3387             }
3388           } else if (!__kmp_strcasecmp_with_sentinel("guided", value,
3389                                                      sentinel)) {
3390             if (!__kmp_strcasecmp_with_sentinel("iterative", comma, ';')) {
3391               __kmp_guided = kmp_sch_guided_iterative_chunked;
3392               continue;
3393             } else if (!__kmp_strcasecmp_with_sentinel("analytical", comma,
3394                                                        ';')) {
3395               /* analytical not allowed for too many threads */
3396               __kmp_guided = kmp_sch_guided_analytical_chunked;
3397               continue;
3398             }
3399           }
3400           KMP_WARNING(InvalidClause, name, value);
3401         } else
3402           KMP_WARNING(EmptyClause, name);
3403       } while ((value = semicolon ? semicolon + 1 : NULL));
3404     }
3405   }
3406 
3407 } // __kmp_stg_parse__schedule
3408 
3409 static void __kmp_stg_print_schedule(kmp_str_buf_t *buffer, char const *name,
3410                                      void *data) {
3411   if (__kmp_env_format) {
3412     KMP_STR_BUF_PRINT_NAME_EX(name);
3413   } else {
3414     __kmp_str_buf_print(buffer, "   %s='", name);
3415   }
3416   if (__kmp_static == kmp_sch_static_greedy) {
3417     __kmp_str_buf_print(buffer, "%s", "static,greedy");
3418   } else if (__kmp_static == kmp_sch_static_balanced) {
3419     __kmp_str_buf_print(buffer, "%s", "static,balanced");
3420   }
3421   if (__kmp_guided == kmp_sch_guided_iterative_chunked) {
3422     __kmp_str_buf_print(buffer, ";%s'\n", "guided,iterative");
3423   } else if (__kmp_guided == kmp_sch_guided_analytical_chunked) {
3424     __kmp_str_buf_print(buffer, ";%s'\n", "guided,analytical");
3425   }
3426 } // __kmp_stg_print_schedule
3427 
3428 // -----------------------------------------------------------------------------
3429 // OMP_SCHEDULE
3430 
3431 static inline void __kmp_omp_schedule_restore() {
3432 #if KMP_USE_HIER_SCHED
3433   __kmp_hier_scheds.deallocate();
3434 #endif
3435   __kmp_chunk = 0;
3436   __kmp_sched = kmp_sch_default;
3437 }
3438 
3439 static const char *__kmp_parse_single_omp_schedule(const char *name,
3440                                                    const char *value,
3441                                                    bool parse_hier = false) {
3442   /* get the specified scheduling style */
3443   const char *ptr = value;
3444   const char *comma = strchr(ptr, ',');
3445   const char *delim;
3446   int chunk = 0;
3447   enum sched_type sched = kmp_sch_default;
3448   if (*ptr == '\0')
3449     return NULL;
3450 #if KMP_USE_HIER_SCHED
3451   kmp_hier_layer_e layer = kmp_hier_layer_e::LAYER_THREAD;
3452   if (parse_hier) {
3453     if (!__kmp_strcasecmp_with_sentinel("L1", ptr, ',')) {
3454       layer = kmp_hier_layer_e::LAYER_L1;
3455     } else if (!__kmp_strcasecmp_with_sentinel("L2", ptr, ',')) {
3456       layer = kmp_hier_layer_e::LAYER_L2;
3457     } else if (!__kmp_strcasecmp_with_sentinel("L3", ptr, ',')) {
3458       layer = kmp_hier_layer_e::LAYER_L3;
3459     } else if (!__kmp_strcasecmp_with_sentinel("NUMA", ptr, ',')) {
3460       layer = kmp_hier_layer_e::LAYER_NUMA;
3461     }
3462     if (layer != kmp_hier_layer_e::LAYER_THREAD && !comma) {
3463       // If there is no comma after the layer, then this schedule is invalid
3464       KMP_WARNING(StgInvalidValue, name, value);
3465       __kmp_omp_schedule_restore();
3466       return NULL;
3467     } else if (layer != kmp_hier_layer_e::LAYER_THREAD) {
3468       ptr = ++comma;
3469       comma = strchr(ptr, ',');
3470     }
3471   }
3472   delim = ptr;
3473   while (*delim != ',' && *delim != ':' && *delim != '\0')
3474     delim++;
3475 #else // KMP_USE_HIER_SCHED
3476   delim = ptr;
3477   while (*delim != ',' && *delim != '\0')
3478     delim++;
3479 #endif // KMP_USE_HIER_SCHED
3480   if (!__kmp_strcasecmp_with_sentinel("dynamic", ptr, *delim)) /* DYNAMIC */
3481     sched = kmp_sch_dynamic_chunked;
3482   else if (!__kmp_strcasecmp_with_sentinel("guided", ptr, *delim)) /* GUIDED */
3483     sched = kmp_sch_guided_chunked;
3484   // AC: TODO: add AUTO schedule, and probably remove TRAPEZOIDAL (OMP 3.0 does
3485   // not allow it)
3486   else if (!__kmp_strcasecmp_with_sentinel("auto", ptr, *delim)) { /* AUTO */
3487     sched = kmp_sch_auto;
3488     if (comma) {
3489       __kmp_msg(kmp_ms_warning, KMP_MSG(IgnoreChunk, name, comma),
3490                 __kmp_msg_null);
3491       comma = NULL;
3492     }
3493   } else if (!__kmp_strcasecmp_with_sentinel("trapezoidal", ptr,
3494                                              *delim)) /* TRAPEZOIDAL */
3495     sched = kmp_sch_trapezoidal;
3496   else if (!__kmp_strcasecmp_with_sentinel("static", ptr, *delim)) /* STATIC */
3497     sched = kmp_sch_static;
3498 #if KMP_STATIC_STEAL_ENABLED
3499   else if (!__kmp_strcasecmp_with_sentinel("static_steal", ptr, *delim))
3500     sched = kmp_sch_static_steal;
3501 #endif
3502   else {
3503     KMP_WARNING(StgInvalidValue, name, value);
3504     __kmp_omp_schedule_restore();
3505     return NULL;
3506   }
3507   if (ptr && comma && *comma == *delim) {
3508     ptr = comma + 1;
3509     SKIP_DIGITS(ptr);
3510 
3511     if (sched == kmp_sch_static)
3512       sched = kmp_sch_static_chunked;
3513     ++comma;
3514     chunk = __kmp_str_to_int(comma, *ptr);
3515     if (chunk < 1) {
3516       chunk = KMP_DEFAULT_CHUNK;
3517       __kmp_msg(kmp_ms_warning, KMP_MSG(InvalidChunk, name, comma),
3518                 __kmp_msg_null);
3519       KMP_INFORM(Using_int_Value, name, __kmp_chunk);
3520       // AC: next block commented out until KMP_DEFAULT_CHUNK != KMP_MIN_CHUNK
3521       // (to improve code coverage :)
3522       //     The default chunk size is 1 according to standard, thus making
3523       //     KMP_MIN_CHUNK not 1 we would introduce mess:
3524       //     wrong chunk becomes 1, but it will be impossible to explicitely set
3525       //     1, because it becomes KMP_MIN_CHUNK...
3526       //                } else if ( chunk < KMP_MIN_CHUNK ) {
3527       //                    chunk = KMP_MIN_CHUNK;
3528     } else if (chunk > KMP_MAX_CHUNK) {
3529       chunk = KMP_MAX_CHUNK;
3530       __kmp_msg(kmp_ms_warning, KMP_MSG(LargeChunk, name, comma),
3531                 __kmp_msg_null);
3532       KMP_INFORM(Using_int_Value, name, chunk);
3533     }
3534   } else if (ptr) {
3535     SKIP_TOKEN(ptr);
3536   }
3537 #if KMP_USE_HIER_SCHED
3538   if (layer != kmp_hier_layer_e::LAYER_THREAD) {
3539     __kmp_hier_scheds.append(sched, chunk, layer);
3540   } else
3541 #endif
3542   {
3543     __kmp_chunk = chunk;
3544     __kmp_sched = sched;
3545   }
3546   return ptr;
3547 }
3548 
3549 static void __kmp_stg_parse_omp_schedule(char const *name, char const *value,
3550                                          void *data) {
3551   size_t length;
3552   const char *ptr = value;
3553   SKIP_WS(ptr);
3554   if (value) {
3555     length = KMP_STRLEN(value);
3556     if (length) {
3557       if (value[length - 1] == '"' || value[length - 1] == '\'')
3558         KMP_WARNING(UnbalancedQuotes, name);
3559 /* get the specified scheduling style */
3560 #if KMP_USE_HIER_SCHED
3561       if (!__kmp_strcasecmp_with_sentinel("EXPERIMENTAL", ptr, ' ')) {
3562         SKIP_TOKEN(ptr);
3563         SKIP_WS(ptr);
3564         while ((ptr = __kmp_parse_single_omp_schedule(name, ptr, true))) {
3565           while (*ptr == ' ' || *ptr == '\t' || *ptr == ':')
3566             ptr++;
3567         }
3568       } else
3569 #endif
3570         __kmp_parse_single_omp_schedule(name, ptr);
3571     } else
3572       KMP_WARNING(EmptyString, name);
3573   }
3574 #if KMP_USE_HIER_SCHED
3575   __kmp_hier_scheds.sort();
3576 #endif
3577   K_DIAG(1, ("__kmp_static == %d\n", __kmp_static))
3578   K_DIAG(1, ("__kmp_guided == %d\n", __kmp_guided))
3579   K_DIAG(1, ("__kmp_sched == %d\n", __kmp_sched))
3580   K_DIAG(1, ("__kmp_chunk == %d\n", __kmp_chunk))
3581 } // __kmp_stg_parse_omp_schedule
3582 
3583 static void __kmp_stg_print_omp_schedule(kmp_str_buf_t *buffer,
3584                                          char const *name, void *data) {
3585   if (__kmp_env_format) {
3586     KMP_STR_BUF_PRINT_NAME_EX(name);
3587   } else {
3588     __kmp_str_buf_print(buffer, "   %s='", name);
3589   }
3590   if (__kmp_chunk) {
3591     switch (__kmp_sched) {
3592     case kmp_sch_dynamic_chunked:
3593       __kmp_str_buf_print(buffer, "%s,%d'\n", "dynamic", __kmp_chunk);
3594       break;
3595     case kmp_sch_guided_iterative_chunked:
3596     case kmp_sch_guided_analytical_chunked:
3597       __kmp_str_buf_print(buffer, "%s,%d'\n", "guided", __kmp_chunk);
3598       break;
3599     case kmp_sch_trapezoidal:
3600       __kmp_str_buf_print(buffer, "%s,%d'\n", "trapezoidal", __kmp_chunk);
3601       break;
3602     case kmp_sch_static:
3603     case kmp_sch_static_chunked:
3604     case kmp_sch_static_balanced:
3605     case kmp_sch_static_greedy:
3606       __kmp_str_buf_print(buffer, "%s,%d'\n", "static", __kmp_chunk);
3607       break;
3608     case kmp_sch_static_steal:
3609       __kmp_str_buf_print(buffer, "%s,%d'\n", "static_steal", __kmp_chunk);
3610       break;
3611     case kmp_sch_auto:
3612       __kmp_str_buf_print(buffer, "%s,%d'\n", "auto", __kmp_chunk);
3613       break;
3614     }
3615   } else {
3616     switch (__kmp_sched) {
3617     case kmp_sch_dynamic_chunked:
3618       __kmp_str_buf_print(buffer, "%s'\n", "dynamic");
3619       break;
3620     case kmp_sch_guided_iterative_chunked:
3621     case kmp_sch_guided_analytical_chunked:
3622       __kmp_str_buf_print(buffer, "%s'\n", "guided");
3623       break;
3624     case kmp_sch_trapezoidal:
3625       __kmp_str_buf_print(buffer, "%s'\n", "trapezoidal");
3626       break;
3627     case kmp_sch_static:
3628     case kmp_sch_static_chunked:
3629     case kmp_sch_static_balanced:
3630     case kmp_sch_static_greedy:
3631       __kmp_str_buf_print(buffer, "%s'\n", "static");
3632       break;
3633     case kmp_sch_static_steal:
3634       __kmp_str_buf_print(buffer, "%s'\n", "static_steal");
3635       break;
3636     case kmp_sch_auto:
3637       __kmp_str_buf_print(buffer, "%s'\n", "auto");
3638       break;
3639     }
3640   }
3641 } // __kmp_stg_print_omp_schedule
3642 
3643 #if KMP_USE_HIER_SCHED
3644 // -----------------------------------------------------------------------------
3645 // KMP_DISP_HAND_THREAD
3646 static void __kmp_stg_parse_kmp_hand_thread(char const *name, char const *value,
3647                                             void *data) {
3648   __kmp_stg_parse_bool(name, value, &(__kmp_dispatch_hand_threading));
3649 } // __kmp_stg_parse_kmp_hand_thread
3650 
3651 static void __kmp_stg_print_kmp_hand_thread(kmp_str_buf_t *buffer,
3652                                             char const *name, void *data) {
3653   __kmp_stg_print_bool(buffer, name, __kmp_dispatch_hand_threading);
3654 } // __kmp_stg_print_kmp_hand_thread
3655 #endif
3656 
3657 // -----------------------------------------------------------------------------
3658 // KMP_ATOMIC_MODE
3659 
3660 static void __kmp_stg_parse_atomic_mode(char const *name, char const *value,
3661                                         void *data) {
3662   // Modes: 0 -- do not change default; 1 -- Intel perf mode, 2 -- GOMP
3663   // compatibility mode.
3664   int mode = 0;
3665   int max = 1;
3666 #ifdef KMP_GOMP_COMPAT
3667   max = 2;
3668 #endif /* KMP_GOMP_COMPAT */
3669   __kmp_stg_parse_int(name, value, 0, max, &mode);
3670   // TODO; parse_int is not very suitable for this case. In case of overflow it
3671   // is better to use
3672   // 0 rather that max value.
3673   if (mode > 0) {
3674     __kmp_atomic_mode = mode;
3675   }
3676 } // __kmp_stg_parse_atomic_mode
3677 
3678 static void __kmp_stg_print_atomic_mode(kmp_str_buf_t *buffer, char const *name,
3679                                         void *data) {
3680   __kmp_stg_print_int(buffer, name, __kmp_atomic_mode);
3681 } // __kmp_stg_print_atomic_mode
3682 
3683 // -----------------------------------------------------------------------------
3684 // KMP_CONSISTENCY_CHECK
3685 
3686 static void __kmp_stg_parse_consistency_check(char const *name,
3687                                               char const *value, void *data) {
3688   if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
3689     // Note, this will not work from kmp_set_defaults because th_cons stack was
3690     // not allocated
3691     // for existed thread(s) thus the first __kmp_push_<construct> will break
3692     // with assertion.
3693     // TODO: allocate th_cons if called from kmp_set_defaults.
3694     __kmp_env_consistency_check = TRUE;
3695   } else if (!__kmp_strcasecmp_with_sentinel("none", value, 0)) {
3696     __kmp_env_consistency_check = FALSE;
3697   } else {
3698     KMP_WARNING(StgInvalidValue, name, value);
3699   }
3700 } // __kmp_stg_parse_consistency_check
3701 
3702 static void __kmp_stg_print_consistency_check(kmp_str_buf_t *buffer,
3703                                               char const *name, void *data) {
3704 #if KMP_DEBUG
3705   const char *value = NULL;
3706 
3707   if (__kmp_env_consistency_check) {
3708     value = "all";
3709   } else {
3710     value = "none";
3711   }
3712 
3713   if (value != NULL) {
3714     __kmp_stg_print_str(buffer, name, value);
3715   }
3716 #endif /* KMP_DEBUG */
3717 } // __kmp_stg_print_consistency_check
3718 
3719 #if USE_ITT_BUILD
3720 // -----------------------------------------------------------------------------
3721 // KMP_ITT_PREPARE_DELAY
3722 
3723 #if USE_ITT_NOTIFY
3724 
3725 static void __kmp_stg_parse_itt_prepare_delay(char const *name,
3726                                               char const *value, void *data) {
3727   // Experimental code: KMP_ITT_PREPARE_DELAY specifies numbert of loop
3728   // iterations.
3729   int delay = 0;
3730   __kmp_stg_parse_int(name, value, 0, INT_MAX, &delay);
3731   __kmp_itt_prepare_delay = delay;
3732 } // __kmp_str_parse_itt_prepare_delay
3733 
3734 static void __kmp_stg_print_itt_prepare_delay(kmp_str_buf_t *buffer,
3735                                               char const *name, void *data) {
3736   __kmp_stg_print_uint64(buffer, name, __kmp_itt_prepare_delay);
3737 
3738 } // __kmp_str_print_itt_prepare_delay
3739 
3740 #endif // USE_ITT_NOTIFY
3741 #endif /* USE_ITT_BUILD */
3742 
3743 // -----------------------------------------------------------------------------
3744 // KMP_MALLOC_POOL_INCR
3745 
3746 static void __kmp_stg_parse_malloc_pool_incr(char const *name,
3747                                              char const *value, void *data) {
3748   __kmp_stg_parse_size(name, value, KMP_MIN_MALLOC_POOL_INCR,
3749                        KMP_MAX_MALLOC_POOL_INCR, NULL, &__kmp_malloc_pool_incr,
3750                        1);
3751 } // __kmp_stg_parse_malloc_pool_incr
3752 
3753 static void __kmp_stg_print_malloc_pool_incr(kmp_str_buf_t *buffer,
3754                                              char const *name, void *data) {
3755   __kmp_stg_print_size(buffer, name, __kmp_malloc_pool_incr);
3756 
3757 } // _kmp_stg_print_malloc_pool_incr
3758 
3759 #ifdef KMP_DEBUG
3760 
3761 // -----------------------------------------------------------------------------
3762 // KMP_PAR_RANGE
3763 
3764 static void __kmp_stg_parse_par_range_env(char const *name, char const *value,
3765                                           void *data) {
3766   __kmp_stg_parse_par_range(name, value, &__kmp_par_range,
3767                             __kmp_par_range_routine, __kmp_par_range_filename,
3768                             &__kmp_par_range_lb, &__kmp_par_range_ub);
3769 } // __kmp_stg_parse_par_range_env
3770 
3771 static void __kmp_stg_print_par_range_env(kmp_str_buf_t *buffer,
3772                                           char const *name, void *data) {
3773   if (__kmp_par_range != 0) {
3774     __kmp_stg_print_str(buffer, name, par_range_to_print);
3775   }
3776 } // __kmp_stg_print_par_range_env
3777 
3778 // -----------------------------------------------------------------------------
3779 // KMP_YIELD_CYCLE, KMP_YIELD_ON, KMP_YIELD_OFF
3780 
3781 static void __kmp_stg_parse_yield_cycle(char const *name, char const *value,
3782                                         void *data) {
3783   int flag = __kmp_yield_cycle;
3784   __kmp_stg_parse_bool(name, value, &flag);
3785   __kmp_yield_cycle = flag;
3786 } // __kmp_stg_parse_yield_cycle
3787 
3788 static void __kmp_stg_print_yield_cycle(kmp_str_buf_t *buffer, char const *name,
3789                                         void *data) {
3790   __kmp_stg_print_bool(buffer, name, __kmp_yield_cycle);
3791 } // __kmp_stg_print_yield_cycle
3792 
3793 static void __kmp_stg_parse_yield_on(char const *name, char const *value,
3794                                      void *data) {
3795   __kmp_stg_parse_int(name, value, 2, INT_MAX, &__kmp_yield_on_count);
3796 } // __kmp_stg_parse_yield_on
3797 
3798 static void __kmp_stg_print_yield_on(kmp_str_buf_t *buffer, char const *name,
3799                                      void *data) {
3800   __kmp_stg_print_int(buffer, name, __kmp_yield_on_count);
3801 } // __kmp_stg_print_yield_on
3802 
3803 static void __kmp_stg_parse_yield_off(char const *name, char const *value,
3804                                       void *data) {
3805   __kmp_stg_parse_int(name, value, 2, INT_MAX, &__kmp_yield_off_count);
3806 } // __kmp_stg_parse_yield_off
3807 
3808 static void __kmp_stg_print_yield_off(kmp_str_buf_t *buffer, char const *name,
3809                                       void *data) {
3810   __kmp_stg_print_int(buffer, name, __kmp_yield_off_count);
3811 } // __kmp_stg_print_yield_off
3812 
3813 #endif
3814 
3815 // -----------------------------------------------------------------------------
3816 // KMP_INIT_WAIT, KMP_NEXT_WAIT
3817 
3818 static void __kmp_stg_parse_init_wait(char const *name, char const *value,
3819                                       void *data) {
3820   int wait;
3821   KMP_ASSERT((__kmp_init_wait & 1) == 0);
3822   wait = __kmp_init_wait / 2;
3823   __kmp_stg_parse_int(name, value, KMP_MIN_INIT_WAIT, KMP_MAX_INIT_WAIT, &wait);
3824   __kmp_init_wait = wait * 2;
3825   KMP_ASSERT((__kmp_init_wait & 1) == 0);
3826   __kmp_yield_init = __kmp_init_wait;
3827 } // __kmp_stg_parse_init_wait
3828 
3829 static void __kmp_stg_print_init_wait(kmp_str_buf_t *buffer, char const *name,
3830                                       void *data) {
3831   __kmp_stg_print_int(buffer, name, __kmp_init_wait);
3832 } // __kmp_stg_print_init_wait
3833 
3834 static void __kmp_stg_parse_next_wait(char const *name, char const *value,
3835                                       void *data) {
3836   int wait;
3837   KMP_ASSERT((__kmp_next_wait & 1) == 0);
3838   wait = __kmp_next_wait / 2;
3839   __kmp_stg_parse_int(name, value, KMP_MIN_NEXT_WAIT, KMP_MAX_NEXT_WAIT, &wait);
3840   __kmp_next_wait = wait * 2;
3841   KMP_ASSERT((__kmp_next_wait & 1) == 0);
3842   __kmp_yield_next = __kmp_next_wait;
3843 } // __kmp_stg_parse_next_wait
3844 
3845 static void __kmp_stg_print_next_wait(kmp_str_buf_t *buffer, char const *name,
3846                                       void *data) {
3847   __kmp_stg_print_int(buffer, name, __kmp_next_wait);
3848 } //__kmp_stg_print_next_wait
3849 
3850 // -----------------------------------------------------------------------------
3851 // KMP_GTID_MODE
3852 
3853 static void __kmp_stg_parse_gtid_mode(char const *name, char const *value,
3854                                       void *data) {
3855   // Modes:
3856   //   0 -- do not change default
3857   //   1 -- sp search
3858   //   2 -- use "keyed" TLS var, i.e.
3859   //        pthread_getspecific(Linux* OS/OS X*) or TlsGetValue(Windows* OS)
3860   //   3 -- __declspec(thread) TLS var in tdata section
3861   int mode = 0;
3862   int max = 2;
3863 #ifdef KMP_TDATA_GTID
3864   max = 3;
3865 #endif /* KMP_TDATA_GTID */
3866   __kmp_stg_parse_int(name, value, 0, max, &mode);
3867   // TODO; parse_int is not very suitable for this case. In case of overflow it
3868   // is better to use 0 rather that max value.
3869   if (mode == 0) {
3870     __kmp_adjust_gtid_mode = TRUE;
3871   } else {
3872     __kmp_gtid_mode = mode;
3873     __kmp_adjust_gtid_mode = FALSE;
3874   }
3875 } // __kmp_str_parse_gtid_mode
3876 
3877 static void __kmp_stg_print_gtid_mode(kmp_str_buf_t *buffer, char const *name,
3878                                       void *data) {
3879   if (__kmp_adjust_gtid_mode) {
3880     __kmp_stg_print_int(buffer, name, 0);
3881   } else {
3882     __kmp_stg_print_int(buffer, name, __kmp_gtid_mode);
3883   }
3884 } // __kmp_stg_print_gtid_mode
3885 
3886 // -----------------------------------------------------------------------------
3887 // KMP_NUM_LOCKS_IN_BLOCK
3888 
3889 static void __kmp_stg_parse_lock_block(char const *name, char const *value,
3890                                        void *data) {
3891   __kmp_stg_parse_int(name, value, 0, KMP_INT_MAX, &__kmp_num_locks_in_block);
3892 } // __kmp_str_parse_lock_block
3893 
3894 static void __kmp_stg_print_lock_block(kmp_str_buf_t *buffer, char const *name,
3895                                        void *data) {
3896   __kmp_stg_print_int(buffer, name, __kmp_num_locks_in_block);
3897 } // __kmp_stg_print_lock_block
3898 
3899 // -----------------------------------------------------------------------------
3900 // KMP_LOCK_KIND
3901 
3902 #if KMP_USE_DYNAMIC_LOCK
3903 #define KMP_STORE_LOCK_SEQ(a) (__kmp_user_lock_seq = lockseq_##a)
3904 #else
3905 #define KMP_STORE_LOCK_SEQ(a)
3906 #endif
3907 
3908 static void __kmp_stg_parse_lock_kind(char const *name, char const *value,
3909                                       void *data) {
3910   if (__kmp_init_user_locks) {
3911     KMP_WARNING(EnvLockWarn, name);
3912     return;
3913   }
3914 
3915   if (__kmp_str_match("tas", 2, value) ||
3916       __kmp_str_match("test and set", 2, value) ||
3917       __kmp_str_match("test_and_set", 2, value) ||
3918       __kmp_str_match("test-and-set", 2, value) ||
3919       __kmp_str_match("test andset", 2, value) ||
3920       __kmp_str_match("test_andset", 2, value) ||
3921       __kmp_str_match("test-andset", 2, value) ||
3922       __kmp_str_match("testand set", 2, value) ||
3923       __kmp_str_match("testand_set", 2, value) ||
3924       __kmp_str_match("testand-set", 2, value) ||
3925       __kmp_str_match("testandset", 2, value)) {
3926     __kmp_user_lock_kind = lk_tas;
3927     KMP_STORE_LOCK_SEQ(tas);
3928   }
3929 #if KMP_USE_FUTEX
3930   else if (__kmp_str_match("futex", 1, value)) {
3931     if (__kmp_futex_determine_capable()) {
3932       __kmp_user_lock_kind = lk_futex;
3933       KMP_STORE_LOCK_SEQ(futex);
3934     } else {
3935       KMP_WARNING(FutexNotSupported, name, value);
3936     }
3937   }
3938 #endif
3939   else if (__kmp_str_match("ticket", 2, value)) {
3940     __kmp_user_lock_kind = lk_ticket;
3941     KMP_STORE_LOCK_SEQ(ticket);
3942   } else if (__kmp_str_match("queuing", 1, value) ||
3943              __kmp_str_match("queue", 1, value)) {
3944     __kmp_user_lock_kind = lk_queuing;
3945     KMP_STORE_LOCK_SEQ(queuing);
3946   } else if (__kmp_str_match("drdpa ticket", 1, value) ||
3947              __kmp_str_match("drdpa_ticket", 1, value) ||
3948              __kmp_str_match("drdpa-ticket", 1, value) ||
3949              __kmp_str_match("drdpaticket", 1, value) ||
3950              __kmp_str_match("drdpa", 1, value)) {
3951     __kmp_user_lock_kind = lk_drdpa;
3952     KMP_STORE_LOCK_SEQ(drdpa);
3953   }
3954 #if KMP_USE_ADAPTIVE_LOCKS
3955   else if (__kmp_str_match("adaptive", 1, value)) {
3956     if (__kmp_cpuinfo.rtm) { // ??? Is cpuinfo available here?
3957       __kmp_user_lock_kind = lk_adaptive;
3958       KMP_STORE_LOCK_SEQ(adaptive);
3959     } else {
3960       KMP_WARNING(AdaptiveNotSupported, name, value);
3961       __kmp_user_lock_kind = lk_queuing;
3962       KMP_STORE_LOCK_SEQ(queuing);
3963     }
3964   }
3965 #endif // KMP_USE_ADAPTIVE_LOCKS
3966 #if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
3967   else if (__kmp_str_match("rtm", 1, value)) {
3968     if (__kmp_cpuinfo.rtm) {
3969       __kmp_user_lock_kind = lk_rtm;
3970       KMP_STORE_LOCK_SEQ(rtm);
3971     } else {
3972       KMP_WARNING(AdaptiveNotSupported, name, value);
3973       __kmp_user_lock_kind = lk_queuing;
3974       KMP_STORE_LOCK_SEQ(queuing);
3975     }
3976   } else if (__kmp_str_match("hle", 1, value)) {
3977     __kmp_user_lock_kind = lk_hle;
3978     KMP_STORE_LOCK_SEQ(hle);
3979   }
3980 #endif
3981   else {
3982     KMP_WARNING(StgInvalidValue, name, value);
3983   }
3984 }
3985 
3986 static void __kmp_stg_print_lock_kind(kmp_str_buf_t *buffer, char const *name,
3987                                       void *data) {
3988   const char *value = NULL;
3989 
3990   switch (__kmp_user_lock_kind) {
3991   case lk_default:
3992     value = "default";
3993     break;
3994 
3995   case lk_tas:
3996     value = "tas";
3997     break;
3998 
3999 #if KMP_USE_FUTEX
4000   case lk_futex:
4001     value = "futex";
4002     break;
4003 #endif
4004 
4005 #if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
4006   case lk_rtm:
4007     value = "rtm";
4008     break;
4009 
4010   case lk_hle:
4011     value = "hle";
4012     break;
4013 #endif
4014 
4015   case lk_ticket:
4016     value = "ticket";
4017     break;
4018 
4019   case lk_queuing:
4020     value = "queuing";
4021     break;
4022 
4023   case lk_drdpa:
4024     value = "drdpa";
4025     break;
4026 #if KMP_USE_ADAPTIVE_LOCKS
4027   case lk_adaptive:
4028     value = "adaptive";
4029     break;
4030 #endif
4031   }
4032 
4033   if (value != NULL) {
4034     __kmp_stg_print_str(buffer, name, value);
4035   }
4036 }
4037 
4038 // -----------------------------------------------------------------------------
4039 // KMP_SPIN_BACKOFF_PARAMS
4040 
4041 // KMP_SPIN_BACKOFF_PARAMS=max_backoff[,min_tick] (max backoff size, min tick
4042 // for machine pause)
4043 static void __kmp_stg_parse_spin_backoff_params(const char *name,
4044                                                 const char *value, void *data) {
4045   const char *next = value;
4046 
4047   int total = 0; // Count elements that were set. It'll be used as an array size
4048   int prev_comma = FALSE; // For correct processing sequential commas
4049   int i;
4050 
4051   kmp_uint32 max_backoff = __kmp_spin_backoff_params.max_backoff;
4052   kmp_uint32 min_tick = __kmp_spin_backoff_params.min_tick;
4053 
4054   // Run only 3 iterations because it is enough to read two values or find a
4055   // syntax error
4056   for (i = 0; i < 3; i++) {
4057     SKIP_WS(next);
4058 
4059     if (*next == '\0') {
4060       break;
4061     }
4062     // Next character is not an integer or not a comma OR number of values > 2
4063     // => end of list
4064     if (((*next < '0' || *next > '9') && *next != ',') || total > 2) {
4065       KMP_WARNING(EnvSyntaxError, name, value);
4066       return;
4067     }
4068     // The next character is ','
4069     if (*next == ',') {
4070       // ',' is the fisrt character
4071       if (total == 0 || prev_comma) {
4072         total++;
4073       }
4074       prev_comma = TRUE;
4075       next++; // skip ','
4076       SKIP_WS(next);
4077     }
4078     // Next character is a digit
4079     if (*next >= '0' && *next <= '9') {
4080       int num;
4081       const char *buf = next;
4082       char const *msg = NULL;
4083       prev_comma = FALSE;
4084       SKIP_DIGITS(next);
4085       total++;
4086 
4087       const char *tmp = next;
4088       SKIP_WS(tmp);
4089       if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
4090         KMP_WARNING(EnvSpacesNotAllowed, name, value);
4091         return;
4092       }
4093 
4094       num = __kmp_str_to_int(buf, *next);
4095       if (num <= 0) { // The number of retries should be > 0
4096         msg = KMP_I18N_STR(ValueTooSmall);
4097         num = 1;
4098       } else if (num > KMP_INT_MAX) {
4099         msg = KMP_I18N_STR(ValueTooLarge);
4100         num = KMP_INT_MAX;
4101       }
4102       if (msg != NULL) {
4103         // Message is not empty. Print warning.
4104         KMP_WARNING(ParseSizeIntWarn, name, value, msg);
4105         KMP_INFORM(Using_int_Value, name, num);
4106       }
4107       if (total == 1) {
4108         max_backoff = num;
4109       } else if (total == 2) {
4110         min_tick = num;
4111       }
4112     }
4113   }
4114   KMP_DEBUG_ASSERT(total > 0);
4115   if (total <= 0) {
4116     KMP_WARNING(EnvSyntaxError, name, value);
4117     return;
4118   }
4119   __kmp_spin_backoff_params.max_backoff = max_backoff;
4120   __kmp_spin_backoff_params.min_tick = min_tick;
4121 }
4122 
4123 static void __kmp_stg_print_spin_backoff_params(kmp_str_buf_t *buffer,
4124                                                 char const *name, void *data) {
4125   if (__kmp_env_format) {
4126     KMP_STR_BUF_PRINT_NAME_EX(name);
4127   } else {
4128     __kmp_str_buf_print(buffer, "   %s='", name);
4129   }
4130   __kmp_str_buf_print(buffer, "%d,%d'\n", __kmp_spin_backoff_params.max_backoff,
4131                       __kmp_spin_backoff_params.min_tick);
4132 }
4133 
4134 #if KMP_USE_ADAPTIVE_LOCKS
4135 
4136 // -----------------------------------------------------------------------------
4137 // KMP_ADAPTIVE_LOCK_PROPS, KMP_SPECULATIVE_STATSFILE
4138 
4139 // Parse out values for the tunable parameters from a string of the form
4140 // KMP_ADAPTIVE_LOCK_PROPS=max_soft_retries[,max_badness]
4141 static void __kmp_stg_parse_adaptive_lock_props(const char *name,
4142                                                 const char *value, void *data) {
4143   int max_retries = 0;
4144   int max_badness = 0;
4145 
4146   const char *next = value;
4147 
4148   int total = 0; // Count elements that were set. It'll be used as an array size
4149   int prev_comma = FALSE; // For correct processing sequential commas
4150   int i;
4151 
4152   // Save values in the structure __kmp_speculative_backoff_params
4153   // Run only 3 iterations because it is enough to read two values or find a
4154   // syntax error
4155   for (i = 0; i < 3; i++) {
4156     SKIP_WS(next);
4157 
4158     if (*next == '\0') {
4159       break;
4160     }
4161     // Next character is not an integer or not a comma OR number of values > 2
4162     // => end of list
4163     if (((*next < '0' || *next > '9') && *next != ',') || total > 2) {
4164       KMP_WARNING(EnvSyntaxError, name, value);
4165       return;
4166     }
4167     // The next character is ','
4168     if (*next == ',') {
4169       // ',' is the fisrt character
4170       if (total == 0 || prev_comma) {
4171         total++;
4172       }
4173       prev_comma = TRUE;
4174       next++; // skip ','
4175       SKIP_WS(next);
4176     }
4177     // Next character is a digit
4178     if (*next >= '0' && *next <= '9') {
4179       int num;
4180       const char *buf = next;
4181       char const *msg = NULL;
4182       prev_comma = FALSE;
4183       SKIP_DIGITS(next);
4184       total++;
4185 
4186       const char *tmp = next;
4187       SKIP_WS(tmp);
4188       if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
4189         KMP_WARNING(EnvSpacesNotAllowed, name, value);
4190         return;
4191       }
4192 
4193       num = __kmp_str_to_int(buf, *next);
4194       if (num < 0) { // The number of retries should be >= 0
4195         msg = KMP_I18N_STR(ValueTooSmall);
4196         num = 1;
4197       } else if (num > KMP_INT_MAX) {
4198         msg = KMP_I18N_STR(ValueTooLarge);
4199         num = KMP_INT_MAX;
4200       }
4201       if (msg != NULL) {
4202         // Message is not empty. Print warning.
4203         KMP_WARNING(ParseSizeIntWarn, name, value, msg);
4204         KMP_INFORM(Using_int_Value, name, num);
4205       }
4206       if (total == 1) {
4207         max_retries = num;
4208       } else if (total == 2) {
4209         max_badness = num;
4210       }
4211     }
4212   }
4213   KMP_DEBUG_ASSERT(total > 0);
4214   if (total <= 0) {
4215     KMP_WARNING(EnvSyntaxError, name, value);
4216     return;
4217   }
4218   __kmp_adaptive_backoff_params.max_soft_retries = max_retries;
4219   __kmp_adaptive_backoff_params.max_badness = max_badness;
4220 }
4221 
4222 static void __kmp_stg_print_adaptive_lock_props(kmp_str_buf_t *buffer,
4223                                                 char const *name, void *data) {
4224   if (__kmp_env_format) {
4225     KMP_STR_BUF_PRINT_NAME_EX(name);
4226   } else {
4227     __kmp_str_buf_print(buffer, "   %s='", name);
4228   }
4229   __kmp_str_buf_print(buffer, "%d,%d'\n",
4230                       __kmp_adaptive_backoff_params.max_soft_retries,
4231                       __kmp_adaptive_backoff_params.max_badness);
4232 } // __kmp_stg_print_adaptive_lock_props
4233 
4234 #if KMP_DEBUG_ADAPTIVE_LOCKS
4235 
4236 static void __kmp_stg_parse_speculative_statsfile(char const *name,
4237                                                   char const *value,
4238                                                   void *data) {
4239   __kmp_stg_parse_file(name, value, "", CCAST(char**, &__kmp_speculative_statsfile));
4240 } // __kmp_stg_parse_speculative_statsfile
4241 
4242 static void __kmp_stg_print_speculative_statsfile(kmp_str_buf_t *buffer,
4243                                                   char const *name,
4244                                                   void *data) {
4245   if (__kmp_str_match("-", 0, __kmp_speculative_statsfile)) {
4246     __kmp_stg_print_str(buffer, name, "stdout");
4247   } else {
4248     __kmp_stg_print_str(buffer, name, __kmp_speculative_statsfile);
4249   }
4250 
4251 } // __kmp_stg_print_speculative_statsfile
4252 
4253 #endif // KMP_DEBUG_ADAPTIVE_LOCKS
4254 
4255 #endif // KMP_USE_ADAPTIVE_LOCKS
4256 
4257 // -----------------------------------------------------------------------------
4258 // KMP_HW_SUBSET (was KMP_PLACE_THREADS)
4259 
4260 // The longest observable sequense of items is
4261 // Socket-Node-Tile-Core-Thread
4262 // So, let's limit to 5 levels for now
4263 // The input string is usually short enough, let's use 512 limit for now
4264 #define MAX_T_LEVEL 5
4265 #define MAX_STR_LEN 512
4266 static void __kmp_stg_parse_hw_subset(char const *name, char const *value,
4267                                       void *data) {
4268   // Value example: 1s,5c@3,2T
4269   // Which means "use 1 socket, 5 cores with offset 3, 2 threads per core"
4270   kmp_setting_t **rivals = (kmp_setting_t **)data;
4271   if (strcmp(name, "KMP_PLACE_THREADS") == 0) {
4272     KMP_INFORM(EnvVarDeprecated, name, "KMP_HW_SUBSET");
4273   }
4274   if (__kmp_stg_check_rivals(name, value, rivals)) {
4275     return;
4276   }
4277 
4278   char *components[MAX_T_LEVEL];
4279   char const *digits = "0123456789";
4280   char input[MAX_STR_LEN];
4281   size_t len = 0, mlen = MAX_STR_LEN;
4282   int level = 0;
4283   // Canonize the string (remove spaces, unify delimiters, etc.)
4284   char *pos = CCAST(char *, value);
4285   while (*pos && mlen) {
4286     if (*pos != ' ') { // skip spaces
4287       if (len == 0 && *pos == ':') {
4288         __kmp_hws_abs_flag = 1; // if the first symbol is ":", skip it
4289       } else {
4290         input[len] = toupper(*pos);
4291         if (input[len] == 'X')
4292           input[len] = ','; // unify delimiters of levels
4293         if (input[len] == 'O' && strchr(digits, *(pos + 1)))
4294           input[len] = '@'; // unify delimiters of offset
4295         len++;
4296       }
4297     }
4298     mlen--;
4299     pos++;
4300   }
4301   if (len == 0 || mlen == 0)
4302     goto err; // contents is either empty or too long
4303   input[len] = '\0';
4304   __kmp_hws_requested = 1; // mark that subset requested
4305   // Split by delimiter
4306   pos = input;
4307   components[level++] = pos;
4308   while ((pos = strchr(pos, ','))) {
4309     *pos = '\0'; // modify input and avoid more copying
4310     components[level++] = ++pos; // expect something after ","
4311     if (level > MAX_T_LEVEL)
4312       goto err; // too many components provided
4313   }
4314   // Check each component
4315   for (int i = 0; i < level; ++i) {
4316     int offset = 0;
4317     int num = atoi(components[i]); // each component should start with a number
4318     if ((pos = strchr(components[i], '@'))) {
4319       offset = atoi(pos + 1); // save offset
4320       *pos = '\0'; // cut the offset from the component
4321     }
4322     pos = components[i] + strspn(components[i], digits);
4323     if (pos == components[i])
4324       goto err;
4325     // detect the component type
4326     switch (*pos) {
4327     case 'S': // Socket
4328       if (__kmp_hws_socket.num > 0)
4329         goto err; // duplicate is not allowed
4330       __kmp_hws_socket.num = num;
4331       __kmp_hws_socket.offset = offset;
4332       break;
4333     case 'N': // NUMA Node
4334       if (__kmp_hws_node.num > 0)
4335         goto err; // duplicate is not allowed
4336       __kmp_hws_node.num = num;
4337       __kmp_hws_node.offset = offset;
4338       break;
4339     case 'L': // Cache
4340       if (*(pos + 1) == '2') { // L2 - Tile
4341         if (__kmp_hws_tile.num > 0)
4342           goto err; // duplicate is not allowed
4343         __kmp_hws_tile.num = num;
4344         __kmp_hws_tile.offset = offset;
4345       } else if (*(pos + 1) == '3') { // L3 - Socket
4346         if (__kmp_hws_socket.num > 0)
4347           goto err; // duplicate is not allowed
4348         __kmp_hws_socket.num = num;
4349         __kmp_hws_socket.offset = offset;
4350       } else if (*(pos + 1) == '1') { // L1 - Core
4351         if (__kmp_hws_core.num > 0)
4352           goto err; // duplicate is not allowed
4353         __kmp_hws_core.num = num;
4354         __kmp_hws_core.offset = offset;
4355       }
4356       break;
4357     case 'C': // Core (or Cache?)
4358       if (*(pos + 1) != 'A') {
4359         if (__kmp_hws_core.num > 0)
4360           goto err; // duplicate is not allowed
4361         __kmp_hws_core.num = num;
4362         __kmp_hws_core.offset = offset;
4363       } else { // Cache
4364         char *d = pos + strcspn(pos, digits); // find digit
4365         if (*d == '2') { // L2 - Tile
4366           if (__kmp_hws_tile.num > 0)
4367             goto err; // duplicate is not allowed
4368           __kmp_hws_tile.num = num;
4369           __kmp_hws_tile.offset = offset;
4370         } else if (*d == '3') { // L3 - Socket
4371           if (__kmp_hws_socket.num > 0)
4372             goto err; // duplicate is not allowed
4373           __kmp_hws_socket.num = num;
4374           __kmp_hws_socket.offset = offset;
4375         } else if (*d == '1') { // L1 - Core
4376           if (__kmp_hws_core.num > 0)
4377             goto err; // duplicate is not allowed
4378           __kmp_hws_core.num = num;
4379           __kmp_hws_core.offset = offset;
4380         } else {
4381           goto err;
4382         }
4383       }
4384       break;
4385     case 'T': // Thread
4386       if (__kmp_hws_proc.num > 0)
4387         goto err; // duplicate is not allowed
4388       __kmp_hws_proc.num = num;
4389       __kmp_hws_proc.offset = offset;
4390       break;
4391     default:
4392       goto err;
4393     }
4394   }
4395   return;
4396 err:
4397   KMP_WARNING(AffHWSubsetInvalid, name, value);
4398   __kmp_hws_requested = 0; // mark that subset not requested
4399   return;
4400 }
4401 
4402 static void __kmp_stg_print_hw_subset(kmp_str_buf_t *buffer, char const *name,
4403                                       void *data) {
4404   if (__kmp_hws_requested) {
4405     int comma = 0;
4406     kmp_str_buf_t buf;
4407     __kmp_str_buf_init(&buf);
4408     if (__kmp_env_format)
4409       KMP_STR_BUF_PRINT_NAME_EX(name);
4410     else
4411       __kmp_str_buf_print(buffer, "   %s='", name);
4412     if (__kmp_hws_socket.num) {
4413       __kmp_str_buf_print(&buf, "%ds", __kmp_hws_socket.num);
4414       if (__kmp_hws_socket.offset)
4415         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_socket.offset);
4416       comma = 1;
4417     }
4418     if (__kmp_hws_node.num) {
4419       __kmp_str_buf_print(&buf, "%s%dn", comma ? "," : "", __kmp_hws_node.num);
4420       if (__kmp_hws_node.offset)
4421         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_node.offset);
4422       comma = 1;
4423     }
4424     if (__kmp_hws_tile.num) {
4425       __kmp_str_buf_print(&buf, "%s%dL2", comma ? "," : "", __kmp_hws_tile.num);
4426       if (__kmp_hws_tile.offset)
4427         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_tile.offset);
4428       comma = 1;
4429     }
4430     if (__kmp_hws_core.num) {
4431       __kmp_str_buf_print(&buf, "%s%dc", comma ? "," : "", __kmp_hws_core.num);
4432       if (__kmp_hws_core.offset)
4433         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_core.offset);
4434       comma = 1;
4435     }
4436     if (__kmp_hws_proc.num)
4437       __kmp_str_buf_print(&buf, "%s%dt", comma ? "," : "", __kmp_hws_proc.num);
4438     __kmp_str_buf_print(buffer, "%s'\n", buf.str);
4439     __kmp_str_buf_free(&buf);
4440   }
4441 }
4442 
4443 #if USE_ITT_BUILD
4444 // -----------------------------------------------------------------------------
4445 // KMP_FORKJOIN_FRAMES
4446 
4447 static void __kmp_stg_parse_forkjoin_frames(char const *name, char const *value,
4448                                             void *data) {
4449   __kmp_stg_parse_bool(name, value, &__kmp_forkjoin_frames);
4450 } // __kmp_stg_parse_forkjoin_frames
4451 
4452 static void __kmp_stg_print_forkjoin_frames(kmp_str_buf_t *buffer,
4453                                             char const *name, void *data) {
4454   __kmp_stg_print_bool(buffer, name, __kmp_forkjoin_frames);
4455 } // __kmp_stg_print_forkjoin_frames
4456 
4457 // -----------------------------------------------------------------------------
4458 // KMP_FORKJOIN_FRAMES_MODE
4459 
4460 static void __kmp_stg_parse_forkjoin_frames_mode(char const *name,
4461                                                  char const *value,
4462                                                  void *data) {
4463   __kmp_stg_parse_int(name, value, 0, 3, &__kmp_forkjoin_frames_mode);
4464 } // __kmp_stg_parse_forkjoin_frames
4465 
4466 static void __kmp_stg_print_forkjoin_frames_mode(kmp_str_buf_t *buffer,
4467                                                  char const *name, void *data) {
4468   __kmp_stg_print_int(buffer, name, __kmp_forkjoin_frames_mode);
4469 } // __kmp_stg_print_forkjoin_frames
4470 #endif /* USE_ITT_BUILD */
4471 
4472 // -----------------------------------------------------------------------------
4473 // OMP_DISPLAY_ENV
4474 
4475 #if OMP_40_ENABLED
4476 
4477 static void __kmp_stg_parse_omp_display_env(char const *name, char const *value,
4478                                             void *data) {
4479   if (__kmp_str_match("VERBOSE", 1, value)) {
4480     __kmp_display_env_verbose = TRUE;
4481   } else {
4482     __kmp_stg_parse_bool(name, value, &__kmp_display_env);
4483   }
4484 
4485 } // __kmp_stg_parse_omp_display_env
4486 
4487 static void __kmp_stg_print_omp_display_env(kmp_str_buf_t *buffer,
4488                                             char const *name, void *data) {
4489   if (__kmp_display_env_verbose) {
4490     __kmp_stg_print_str(buffer, name, "VERBOSE");
4491   } else {
4492     __kmp_stg_print_bool(buffer, name, __kmp_display_env);
4493   }
4494 } // __kmp_stg_print_omp_display_env
4495 
4496 static void __kmp_stg_parse_omp_cancellation(char const *name,
4497                                              char const *value, void *data) {
4498   if (TCR_4(__kmp_init_parallel)) {
4499     KMP_WARNING(EnvParallelWarn, name);
4500     return;
4501   } // read value before first parallel only
4502   __kmp_stg_parse_bool(name, value, &__kmp_omp_cancellation);
4503 } // __kmp_stg_parse_omp_cancellation
4504 
4505 static void __kmp_stg_print_omp_cancellation(kmp_str_buf_t *buffer,
4506                                              char const *name, void *data) {
4507   __kmp_stg_print_bool(buffer, name, __kmp_omp_cancellation);
4508 } // __kmp_stg_print_omp_cancellation
4509 
4510 #endif
4511 
4512 #if OMP_50_ENABLED && OMPT_SUPPORT
4513 
4514 static char *__kmp_tool_libraries = NULL;
4515 
4516 static void __kmp_stg_parse_omp_tool_libraries(char const *name,
4517                                                char const *value, void *data) {
4518   __kmp_stg_parse_str(name, value, &__kmp_tool_libraries);
4519 } // __kmp_stg_parse_omp_tool_libraries
4520 
4521 static void __kmp_stg_print_omp_tool_libraries(kmp_str_buf_t *buffer,
4522                                                char const *name, void *data) {
4523   if (__kmp_tool_libraries)
4524     __kmp_stg_print_str(buffer, name, __kmp_tool_libraries);
4525   else {
4526     if (__kmp_env_format) {
4527       KMP_STR_BUF_PRINT_NAME;
4528     } else {
4529       __kmp_str_buf_print(buffer, "   %s", name);
4530     }
4531     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
4532   }
4533 } // __kmp_stg_print_omp_tool_libraries
4534 
4535 #endif
4536 
4537 // Table.
4538 
4539 static kmp_setting_t __kmp_stg_table[] = {
4540 
4541     {"KMP_ALL_THREADS", __kmp_stg_parse_device_thread_limit, NULL, NULL, 0, 0},
4542     {"KMP_BLOCKTIME", __kmp_stg_parse_blocktime, __kmp_stg_print_blocktime,
4543      NULL, 0, 0},
4544     {"KMP_DUPLICATE_LIB_OK", __kmp_stg_parse_duplicate_lib_ok,
4545      __kmp_stg_print_duplicate_lib_ok, NULL, 0, 0},
4546     {"KMP_LIBRARY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy,
4547      NULL, 0, 0},
4548     {"KMP_DEVICE_THREAD_LIMIT", __kmp_stg_parse_device_thread_limit,
4549      __kmp_stg_print_device_thread_limit, NULL, 0, 0},
4550 #if KMP_USE_MONITOR
4551     {"KMP_MONITOR_STACKSIZE", __kmp_stg_parse_monitor_stacksize,
4552      __kmp_stg_print_monitor_stacksize, NULL, 0, 0},
4553 #endif
4554     {"KMP_SETTINGS", __kmp_stg_parse_settings, __kmp_stg_print_settings, NULL,
4555      0, 0},
4556     {"KMP_STACKOFFSET", __kmp_stg_parse_stackoffset,
4557      __kmp_stg_print_stackoffset, NULL, 0, 0},
4558     {"KMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize,
4559      NULL, 0, 0},
4560     {"KMP_STACKPAD", __kmp_stg_parse_stackpad, __kmp_stg_print_stackpad, NULL,
4561      0, 0},
4562     {"KMP_VERSION", __kmp_stg_parse_version, __kmp_stg_print_version, NULL, 0,
4563      0},
4564     {"KMP_WARNINGS", __kmp_stg_parse_warnings, __kmp_stg_print_warnings, NULL,
4565      0, 0},
4566 
4567     {"OMP_NESTED", __kmp_stg_parse_nested, __kmp_stg_print_nested, NULL, 0, 0},
4568     {"OMP_NUM_THREADS", __kmp_stg_parse_num_threads,
4569      __kmp_stg_print_num_threads, NULL, 0, 0},
4570     {"OMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize,
4571      NULL, 0, 0},
4572 
4573     {"KMP_TASKING", __kmp_stg_parse_tasking, __kmp_stg_print_tasking, NULL, 0,
4574      0},
4575     {"KMP_TASK_STEALING_CONSTRAINT", __kmp_stg_parse_task_stealing,
4576      __kmp_stg_print_task_stealing, NULL, 0, 0},
4577     {"OMP_MAX_ACTIVE_LEVELS", __kmp_stg_parse_max_active_levels,
4578      __kmp_stg_print_max_active_levels, NULL, 0, 0},
4579 #if OMP_40_ENABLED
4580     {"OMP_DEFAULT_DEVICE", __kmp_stg_parse_default_device,
4581      __kmp_stg_print_default_device, NULL, 0, 0},
4582 #endif
4583 #if OMP_50_ENABLED
4584     {"OMP_TARGET_OFFLOAD", __kmp_stg_parse_target_offload,
4585      __kmp_stg_print_target_offload, NULL, 0, 0},
4586 #endif
4587 #if OMP_45_ENABLED
4588     {"OMP_MAX_TASK_PRIORITY", __kmp_stg_parse_max_task_priority,
4589      __kmp_stg_print_max_task_priority, NULL, 0, 0},
4590     {"KMP_TASKLOOP_MIN_TASKS", __kmp_stg_parse_taskloop_min_tasks,
4591      __kmp_stg_print_taskloop_min_tasks, NULL, 0, 0},
4592 #endif
4593     {"OMP_THREAD_LIMIT", __kmp_stg_parse_thread_limit,
4594      __kmp_stg_print_thread_limit, NULL, 0, 0},
4595     {"KMP_TEAMS_THREAD_LIMIT", __kmp_stg_parse_teams_thread_limit,
4596      __kmp_stg_print_teams_thread_limit, NULL, 0, 0},
4597     {"OMP_WAIT_POLICY", __kmp_stg_parse_wait_policy,
4598      __kmp_stg_print_wait_policy, NULL, 0, 0},
4599     {"KMP_DISP_NUM_BUFFERS", __kmp_stg_parse_disp_buffers,
4600      __kmp_stg_print_disp_buffers, NULL, 0, 0},
4601 #if KMP_NESTED_HOT_TEAMS
4602     {"KMP_HOT_TEAMS_MAX_LEVEL", __kmp_stg_parse_hot_teams_level,
4603      __kmp_stg_print_hot_teams_level, NULL, 0, 0},
4604     {"KMP_HOT_TEAMS_MODE", __kmp_stg_parse_hot_teams_mode,
4605      __kmp_stg_print_hot_teams_mode, NULL, 0, 0},
4606 #endif // KMP_NESTED_HOT_TEAMS
4607 
4608 #if KMP_HANDLE_SIGNALS
4609     {"KMP_HANDLE_SIGNALS", __kmp_stg_parse_handle_signals,
4610      __kmp_stg_print_handle_signals, NULL, 0, 0},
4611 #endif
4612 
4613 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
4614     {"KMP_INHERIT_FP_CONTROL", __kmp_stg_parse_inherit_fp_control,
4615      __kmp_stg_print_inherit_fp_control, NULL, 0, 0},
4616 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
4617 
4618 #ifdef KMP_GOMP_COMPAT
4619     {"GOMP_STACKSIZE", __kmp_stg_parse_stacksize, NULL, NULL, 0, 0},
4620 #endif
4621 
4622 #ifdef KMP_DEBUG
4623     {"KMP_A_DEBUG", __kmp_stg_parse_a_debug, __kmp_stg_print_a_debug, NULL, 0,
4624      0},
4625     {"KMP_B_DEBUG", __kmp_stg_parse_b_debug, __kmp_stg_print_b_debug, NULL, 0,
4626      0},
4627     {"KMP_C_DEBUG", __kmp_stg_parse_c_debug, __kmp_stg_print_c_debug, NULL, 0,
4628      0},
4629     {"KMP_D_DEBUG", __kmp_stg_parse_d_debug, __kmp_stg_print_d_debug, NULL, 0,
4630      0},
4631     {"KMP_E_DEBUG", __kmp_stg_parse_e_debug, __kmp_stg_print_e_debug, NULL, 0,
4632      0},
4633     {"KMP_F_DEBUG", __kmp_stg_parse_f_debug, __kmp_stg_print_f_debug, NULL, 0,
4634      0},
4635     {"KMP_DEBUG", __kmp_stg_parse_debug, NULL, /* no print */ NULL, 0, 0},
4636     {"KMP_DEBUG_BUF", __kmp_stg_parse_debug_buf, __kmp_stg_print_debug_buf,
4637      NULL, 0, 0},
4638     {"KMP_DEBUG_BUF_ATOMIC", __kmp_stg_parse_debug_buf_atomic,
4639      __kmp_stg_print_debug_buf_atomic, NULL, 0, 0},
4640     {"KMP_DEBUG_BUF_CHARS", __kmp_stg_parse_debug_buf_chars,
4641      __kmp_stg_print_debug_buf_chars, NULL, 0, 0},
4642     {"KMP_DEBUG_BUF_LINES", __kmp_stg_parse_debug_buf_lines,
4643      __kmp_stg_print_debug_buf_lines, NULL, 0, 0},
4644     {"KMP_DIAG", __kmp_stg_parse_diag, __kmp_stg_print_diag, NULL, 0, 0},
4645 
4646     {"KMP_PAR_RANGE", __kmp_stg_parse_par_range_env,
4647      __kmp_stg_print_par_range_env, NULL, 0, 0},
4648     {"KMP_YIELD_CYCLE", __kmp_stg_parse_yield_cycle,
4649      __kmp_stg_print_yield_cycle, NULL, 0, 0},
4650     {"KMP_YIELD_ON", __kmp_stg_parse_yield_on, __kmp_stg_print_yield_on, NULL,
4651      0, 0},
4652     {"KMP_YIELD_OFF", __kmp_stg_parse_yield_off, __kmp_stg_print_yield_off,
4653      NULL, 0, 0},
4654 #endif // KMP_DEBUG
4655 
4656     {"KMP_ALIGN_ALLOC", __kmp_stg_parse_align_alloc,
4657      __kmp_stg_print_align_alloc, NULL, 0, 0},
4658 
4659     {"KMP_PLAIN_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4660      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4661     {"KMP_PLAIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4662      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4663     {"KMP_FORKJOIN_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4664      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4665     {"KMP_FORKJOIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4666      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4667 #if KMP_FAST_REDUCTION_BARRIER
4668     {"KMP_REDUCTION_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4669      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4670     {"KMP_REDUCTION_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4671      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4672 #endif
4673 
4674     {"KMP_ABORT_DELAY", __kmp_stg_parse_abort_delay,
4675      __kmp_stg_print_abort_delay, NULL, 0, 0},
4676     {"KMP_CPUINFO_FILE", __kmp_stg_parse_cpuinfo_file,
4677      __kmp_stg_print_cpuinfo_file, NULL, 0, 0},
4678     {"KMP_FORCE_REDUCTION", __kmp_stg_parse_force_reduction,
4679      __kmp_stg_print_force_reduction, NULL, 0, 0},
4680     {"KMP_DETERMINISTIC_REDUCTION", __kmp_stg_parse_force_reduction,
4681      __kmp_stg_print_force_reduction, NULL, 0, 0},
4682     {"KMP_STORAGE_MAP", __kmp_stg_parse_storage_map,
4683      __kmp_stg_print_storage_map, NULL, 0, 0},
4684     {"KMP_ALL_THREADPRIVATE", __kmp_stg_parse_all_threadprivate,
4685      __kmp_stg_print_all_threadprivate, NULL, 0, 0},
4686     {"KMP_FOREIGN_THREADS_THREADPRIVATE",
4687      __kmp_stg_parse_foreign_threads_threadprivate,
4688      __kmp_stg_print_foreign_threads_threadprivate, NULL, 0, 0},
4689 
4690 #if KMP_AFFINITY_SUPPORTED
4691     {"KMP_AFFINITY", __kmp_stg_parse_affinity, __kmp_stg_print_affinity, NULL,
4692      0, 0},
4693 #ifdef KMP_GOMP_COMPAT
4694     {"GOMP_CPU_AFFINITY", __kmp_stg_parse_gomp_cpu_affinity, NULL,
4695      /* no print */ NULL, 0, 0},
4696 #endif /* KMP_GOMP_COMPAT */
4697 #if OMP_40_ENABLED
4698     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind,
4699      NULL, 0, 0},
4700     {"OMP_PLACES", __kmp_stg_parse_places, __kmp_stg_print_places, NULL, 0, 0},
4701 #else
4702     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, NULL, /* no print */ NULL, 0,
4703      0},
4704 #endif /* OMP_40_ENABLED */
4705 
4706     {"KMP_TOPOLOGY_METHOD", __kmp_stg_parse_topology_method,
4707      __kmp_stg_print_topology_method, NULL, 0, 0},
4708 
4709 #else
4710 
4711 // KMP_AFFINITY is not supported on OS X*, nor is OMP_PLACES.
4712 // OMP_PROC_BIND and proc-bind-var are supported, however.
4713 #if OMP_40_ENABLED
4714     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind,
4715      NULL, 0, 0},
4716 #endif
4717 
4718 #endif // KMP_AFFINITY_SUPPORTED
4719 
4720     {"KMP_INIT_AT_FORK", __kmp_stg_parse_init_at_fork,
4721      __kmp_stg_print_init_at_fork, NULL, 0, 0},
4722     {"KMP_SCHEDULE", __kmp_stg_parse_schedule, __kmp_stg_print_schedule, NULL,
4723      0, 0},
4724     {"OMP_SCHEDULE", __kmp_stg_parse_omp_schedule, __kmp_stg_print_omp_schedule,
4725      NULL, 0, 0},
4726 #if KMP_USE_HIER_SCHED
4727     {"KMP_DISP_HAND_THREAD", __kmp_stg_parse_kmp_hand_thread,
4728      __kmp_stg_print_kmp_hand_thread, NULL, 0, 0},
4729 #endif
4730     {"KMP_ATOMIC_MODE", __kmp_stg_parse_atomic_mode,
4731      __kmp_stg_print_atomic_mode, NULL, 0, 0},
4732     {"KMP_CONSISTENCY_CHECK", __kmp_stg_parse_consistency_check,
4733      __kmp_stg_print_consistency_check, NULL, 0, 0},
4734 
4735 #if USE_ITT_BUILD && USE_ITT_NOTIFY
4736     {"KMP_ITT_PREPARE_DELAY", __kmp_stg_parse_itt_prepare_delay,
4737      __kmp_stg_print_itt_prepare_delay, NULL, 0, 0},
4738 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
4739     {"KMP_MALLOC_POOL_INCR", __kmp_stg_parse_malloc_pool_incr,
4740      __kmp_stg_print_malloc_pool_incr, NULL, 0, 0},
4741     {"KMP_INIT_WAIT", __kmp_stg_parse_init_wait, __kmp_stg_print_init_wait,
4742      NULL, 0, 0},
4743     {"KMP_NEXT_WAIT", __kmp_stg_parse_next_wait, __kmp_stg_print_next_wait,
4744      NULL, 0, 0},
4745     {"KMP_GTID_MODE", __kmp_stg_parse_gtid_mode, __kmp_stg_print_gtid_mode,
4746      NULL, 0, 0},
4747     {"OMP_DYNAMIC", __kmp_stg_parse_omp_dynamic, __kmp_stg_print_omp_dynamic,
4748      NULL, 0, 0},
4749     {"KMP_DYNAMIC_MODE", __kmp_stg_parse_kmp_dynamic_mode,
4750      __kmp_stg_print_kmp_dynamic_mode, NULL, 0, 0},
4751 
4752 #ifdef USE_LOAD_BALANCE
4753     {"KMP_LOAD_BALANCE_INTERVAL", __kmp_stg_parse_ld_balance_interval,
4754      __kmp_stg_print_ld_balance_interval, NULL, 0, 0},
4755 #endif
4756 
4757     {"KMP_NUM_LOCKS_IN_BLOCK", __kmp_stg_parse_lock_block,
4758      __kmp_stg_print_lock_block, NULL, 0, 0},
4759     {"KMP_LOCK_KIND", __kmp_stg_parse_lock_kind, __kmp_stg_print_lock_kind,
4760      NULL, 0, 0},
4761     {"KMP_SPIN_BACKOFF_PARAMS", __kmp_stg_parse_spin_backoff_params,
4762      __kmp_stg_print_spin_backoff_params, NULL, 0, 0},
4763 #if KMP_USE_ADAPTIVE_LOCKS
4764     {"KMP_ADAPTIVE_LOCK_PROPS", __kmp_stg_parse_adaptive_lock_props,
4765      __kmp_stg_print_adaptive_lock_props, NULL, 0, 0},
4766 #if KMP_DEBUG_ADAPTIVE_LOCKS
4767     {"KMP_SPECULATIVE_STATSFILE", __kmp_stg_parse_speculative_statsfile,
4768      __kmp_stg_print_speculative_statsfile, NULL, 0, 0},
4769 #endif
4770 #endif // KMP_USE_ADAPTIVE_LOCKS
4771     {"KMP_PLACE_THREADS", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset,
4772      NULL, 0, 0},
4773     {"KMP_HW_SUBSET", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset,
4774      NULL, 0, 0},
4775 #if USE_ITT_BUILD
4776     {"KMP_FORKJOIN_FRAMES", __kmp_stg_parse_forkjoin_frames,
4777      __kmp_stg_print_forkjoin_frames, NULL, 0, 0},
4778     {"KMP_FORKJOIN_FRAMES_MODE", __kmp_stg_parse_forkjoin_frames_mode,
4779      __kmp_stg_print_forkjoin_frames_mode, NULL, 0, 0},
4780 #endif
4781 
4782 #if OMP_40_ENABLED
4783     {"OMP_DISPLAY_ENV", __kmp_stg_parse_omp_display_env,
4784      __kmp_stg_print_omp_display_env, NULL, 0, 0},
4785     {"OMP_CANCELLATION", __kmp_stg_parse_omp_cancellation,
4786      __kmp_stg_print_omp_cancellation, NULL, 0, 0},
4787 #endif
4788 
4789 #if OMP_50_ENABLED && OMPT_SUPPORT
4790     {"OMP_TOOL_LIBRARIES", __kmp_stg_parse_omp_tool_libraries,
4791      __kmp_stg_print_omp_tool_libraries, NULL, 0, 0},
4792 #endif
4793 
4794     {"", NULL, NULL, NULL, 0, 0}}; // settings
4795 
4796 static int const __kmp_stg_count =
4797     sizeof(__kmp_stg_table) / sizeof(kmp_setting_t);
4798 
4799 static inline kmp_setting_t *__kmp_stg_find(char const *name) {
4800 
4801   int i;
4802   if (name != NULL) {
4803     for (i = 0; i < __kmp_stg_count; ++i) {
4804       if (strcmp(__kmp_stg_table[i].name, name) == 0) {
4805         return &__kmp_stg_table[i];
4806       }
4807     }
4808   }
4809   return NULL;
4810 
4811 } // __kmp_stg_find
4812 
4813 static int __kmp_stg_cmp(void const *_a, void const *_b) {
4814   const kmp_setting_t *a = RCAST(const kmp_setting_t *, _a);
4815   const kmp_setting_t *b = RCAST(const kmp_setting_t *, _b);
4816 
4817   // Process KMP_AFFINITY last.
4818   // It needs to come after OMP_PLACES and GOMP_CPU_AFFINITY.
4819   if (strcmp(a->name, "KMP_AFFINITY") == 0) {
4820     if (strcmp(b->name, "KMP_AFFINITY") == 0) {
4821       return 0;
4822     }
4823     return 1;
4824   } else if (strcmp(b->name, "KMP_AFFINITY") == 0) {
4825     return -1;
4826   }
4827   return strcmp(a->name, b->name);
4828 } // __kmp_stg_cmp
4829 
4830 static void __kmp_stg_init(void) {
4831 
4832   static int initialized = 0;
4833 
4834   if (!initialized) {
4835 
4836     // Sort table.
4837     qsort(__kmp_stg_table, __kmp_stg_count - 1, sizeof(kmp_setting_t),
4838           __kmp_stg_cmp);
4839 
4840     { // Initialize *_STACKSIZE data.
4841       kmp_setting_t *kmp_stacksize =
4842           __kmp_stg_find("KMP_STACKSIZE"); // 1st priority.
4843 #ifdef KMP_GOMP_COMPAT
4844       kmp_setting_t *gomp_stacksize =
4845           __kmp_stg_find("GOMP_STACKSIZE"); // 2nd priority.
4846 #endif
4847       kmp_setting_t *omp_stacksize =
4848           __kmp_stg_find("OMP_STACKSIZE"); // 3rd priority.
4849 
4850       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
4851       // !!! Compiler does not understand rivals is used and optimizes out
4852       // assignments
4853       // !!!     rivals[ i ++ ] = ...;
4854       static kmp_setting_t *volatile rivals[4];
4855       static kmp_stg_ss_data_t kmp_data = {1, CCAST(kmp_setting_t **, rivals)};
4856 #ifdef KMP_GOMP_COMPAT
4857       static kmp_stg_ss_data_t gomp_data = {1024,
4858                                             CCAST(kmp_setting_t **, rivals)};
4859 #endif
4860       static kmp_stg_ss_data_t omp_data = {1024,
4861                                            CCAST(kmp_setting_t **, rivals)};
4862       int i = 0;
4863 
4864       rivals[i++] = kmp_stacksize;
4865 #ifdef KMP_GOMP_COMPAT
4866       if (gomp_stacksize != NULL) {
4867         rivals[i++] = gomp_stacksize;
4868       }
4869 #endif
4870       rivals[i++] = omp_stacksize;
4871       rivals[i++] = NULL;
4872 
4873       kmp_stacksize->data = &kmp_data;
4874 #ifdef KMP_GOMP_COMPAT
4875       if (gomp_stacksize != NULL) {
4876         gomp_stacksize->data = &gomp_data;
4877       }
4878 #endif
4879       omp_stacksize->data = &omp_data;
4880     }
4881 
4882     { // Initialize KMP_LIBRARY and OMP_WAIT_POLICY data.
4883       kmp_setting_t *kmp_library =
4884           __kmp_stg_find("KMP_LIBRARY"); // 1st priority.
4885       kmp_setting_t *omp_wait_policy =
4886           __kmp_stg_find("OMP_WAIT_POLICY"); // 2nd priority.
4887 
4888       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
4889       static kmp_setting_t *volatile rivals[3];
4890       static kmp_stg_wp_data_t kmp_data = {0, CCAST(kmp_setting_t **, rivals)};
4891       static kmp_stg_wp_data_t omp_data = {1, CCAST(kmp_setting_t **, rivals)};
4892       int i = 0;
4893 
4894       rivals[i++] = kmp_library;
4895       if (omp_wait_policy != NULL) {
4896         rivals[i++] = omp_wait_policy;
4897       }
4898       rivals[i++] = NULL;
4899 
4900       kmp_library->data = &kmp_data;
4901       if (omp_wait_policy != NULL) {
4902         omp_wait_policy->data = &omp_data;
4903       }
4904     }
4905 
4906     { // Initialize KMP_DEVICE_THREAD_LIMIT and KMP_ALL_THREADS
4907       kmp_setting_t *kmp_device_thread_limit =
4908           __kmp_stg_find("KMP_DEVICE_THREAD_LIMIT"); // 1st priority.
4909       kmp_setting_t *kmp_all_threads =
4910           __kmp_stg_find("KMP_ALL_THREADS"); // 2nd priority.
4911 
4912       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
4913       static kmp_setting_t *volatile rivals[3];
4914       int i = 0;
4915 
4916       rivals[i++] = kmp_device_thread_limit;
4917       rivals[i++] = kmp_all_threads;
4918       rivals[i++] = NULL;
4919 
4920       kmp_device_thread_limit->data = CCAST(kmp_setting_t **, rivals);
4921       kmp_all_threads->data = CCAST(kmp_setting_t **, rivals);
4922     }
4923 
4924     { // Initialize KMP_HW_SUBSET and KMP_PLACE_THREADS
4925       // 1st priority
4926       kmp_setting_t *kmp_hw_subset = __kmp_stg_find("KMP_HW_SUBSET");
4927       // 2nd priority
4928       kmp_setting_t *kmp_place_threads = __kmp_stg_find("KMP_PLACE_THREADS");
4929 
4930       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
4931       static kmp_setting_t *volatile rivals[3];
4932       int i = 0;
4933 
4934       rivals[i++] = kmp_hw_subset;
4935       rivals[i++] = kmp_place_threads;
4936       rivals[i++] = NULL;
4937 
4938       kmp_hw_subset->data = CCAST(kmp_setting_t **, rivals);
4939       kmp_place_threads->data = CCAST(kmp_setting_t **, rivals);
4940     }
4941 
4942 #if KMP_AFFINITY_SUPPORTED
4943     { // Initialize KMP_AFFINITY, GOMP_CPU_AFFINITY, and OMP_PROC_BIND data.
4944       kmp_setting_t *kmp_affinity =
4945           __kmp_stg_find("KMP_AFFINITY"); // 1st priority.
4946       KMP_DEBUG_ASSERT(kmp_affinity != NULL);
4947 
4948 #ifdef KMP_GOMP_COMPAT
4949       kmp_setting_t *gomp_cpu_affinity =
4950           __kmp_stg_find("GOMP_CPU_AFFINITY"); // 2nd priority.
4951       KMP_DEBUG_ASSERT(gomp_cpu_affinity != NULL);
4952 #endif
4953 
4954       kmp_setting_t *omp_proc_bind =
4955           __kmp_stg_find("OMP_PROC_BIND"); // 3rd priority.
4956       KMP_DEBUG_ASSERT(omp_proc_bind != NULL);
4957 
4958       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
4959       static kmp_setting_t *volatile rivals[4];
4960       int i = 0;
4961 
4962       rivals[i++] = kmp_affinity;
4963 
4964 #ifdef KMP_GOMP_COMPAT
4965       rivals[i++] = gomp_cpu_affinity;
4966       gomp_cpu_affinity->data = CCAST(kmp_setting_t **, rivals);
4967 #endif
4968 
4969       rivals[i++] = omp_proc_bind;
4970       omp_proc_bind->data = CCAST(kmp_setting_t **, rivals);
4971       rivals[i++] = NULL;
4972 
4973 #if OMP_40_ENABLED
4974       static kmp_setting_t *volatile places_rivals[4];
4975       i = 0;
4976 
4977       kmp_setting_t *omp_places = __kmp_stg_find("OMP_PLACES"); // 3rd priority.
4978       KMP_DEBUG_ASSERT(omp_places != NULL);
4979 
4980       places_rivals[i++] = kmp_affinity;
4981 #ifdef KMP_GOMP_COMPAT
4982       places_rivals[i++] = gomp_cpu_affinity;
4983 #endif
4984       places_rivals[i++] = omp_places;
4985       omp_places->data = CCAST(kmp_setting_t **, places_rivals);
4986       places_rivals[i++] = NULL;
4987 #endif
4988     }
4989 #else
4990 // KMP_AFFINITY not supported, so OMP_PROC_BIND has no rivals.
4991 // OMP_PLACES not supported yet.
4992 #endif // KMP_AFFINITY_SUPPORTED
4993 
4994     { // Initialize KMP_DETERMINISTIC_REDUCTION and KMP_FORCE_REDUCTION data.
4995       kmp_setting_t *kmp_force_red =
4996           __kmp_stg_find("KMP_FORCE_REDUCTION"); // 1st priority.
4997       kmp_setting_t *kmp_determ_red =
4998           __kmp_stg_find("KMP_DETERMINISTIC_REDUCTION"); // 2nd priority.
4999 
5000       // !!! volatile keyword is Intel(R) C Compiler bug CQ49908 workaround.
5001       static kmp_setting_t *volatile rivals[3];
5002       static kmp_stg_fr_data_t force_data = {1,
5003                                              CCAST(kmp_setting_t **, rivals)};
5004       static kmp_stg_fr_data_t determ_data = {0,
5005                                               CCAST(kmp_setting_t **, rivals)};
5006       int i = 0;
5007 
5008       rivals[i++] = kmp_force_red;
5009       if (kmp_determ_red != NULL) {
5010         rivals[i++] = kmp_determ_red;
5011       }
5012       rivals[i++] = NULL;
5013 
5014       kmp_force_red->data = &force_data;
5015       if (kmp_determ_red != NULL) {
5016         kmp_determ_red->data = &determ_data;
5017       }
5018     }
5019 
5020     initialized = 1;
5021   }
5022 
5023   // Reset flags.
5024   int i;
5025   for (i = 0; i < __kmp_stg_count; ++i) {
5026     __kmp_stg_table[i].set = 0;
5027   }
5028 
5029 } // __kmp_stg_init
5030 
5031 static void __kmp_stg_parse(char const *name, char const *value) {
5032   // On Windows* OS there are some nameless variables like "C:=C:\" (yeah,
5033   // really nameless, they are presented in environment block as
5034   // "=C:=C\\\x00=D:=D:\\\x00...", so let us skip them.
5035   if (name[0] == 0) {
5036     return;
5037   }
5038 
5039   if (value != NULL) {
5040     kmp_setting_t *setting = __kmp_stg_find(name);
5041     if (setting != NULL) {
5042       setting->parse(name, value, setting->data);
5043       setting->defined = 1;
5044     }
5045   }
5046 
5047 } // __kmp_stg_parse
5048 
5049 static int __kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
5050     char const *name, // Name of variable.
5051     char const *value, // Value of the variable.
5052     kmp_setting_t **rivals // List of rival settings (must include current one).
5053     ) {
5054 
5055   if (rivals == NULL) {
5056     return 0;
5057   }
5058 
5059   // Loop thru higher priority settings (listed before current).
5060   int i = 0;
5061   for (; strcmp(rivals[i]->name, name) != 0; i++) {
5062     KMP_DEBUG_ASSERT(rivals[i] != NULL);
5063 
5064 #if KMP_AFFINITY_SUPPORTED
5065     if (rivals[i] == __kmp_affinity_notype) {
5066       // If KMP_AFFINITY is specified without a type name,
5067       // it does not rival OMP_PROC_BIND or GOMP_CPU_AFFINITY.
5068       continue;
5069     }
5070 #endif
5071 
5072     if (rivals[i]->set) {
5073       KMP_WARNING(StgIgnored, name, rivals[i]->name);
5074       return 1;
5075     }
5076   }
5077 
5078   ++i; // Skip current setting.
5079   return 0;
5080 
5081 } // __kmp_stg_check_rivals
5082 
5083 static int __kmp_env_toPrint(char const *name, int flag) {
5084   int rc = 0;
5085   kmp_setting_t *setting = __kmp_stg_find(name);
5086   if (setting != NULL) {
5087     rc = setting->defined;
5088     if (flag >= 0) {
5089       setting->defined = flag;
5090     }
5091   }
5092   return rc;
5093 }
5094 
5095 static void __kmp_aux_env_initialize(kmp_env_blk_t *block) {
5096 
5097   char const *value;
5098 
5099   /* OMP_NUM_THREADS */
5100   value = __kmp_env_blk_var(block, "OMP_NUM_THREADS");
5101   if (value) {
5102     ompc_set_num_threads(__kmp_dflt_team_nth);
5103   }
5104 
5105   /* KMP_BLOCKTIME */
5106   value = __kmp_env_blk_var(block, "KMP_BLOCKTIME");
5107   if (value) {
5108     kmpc_set_blocktime(__kmp_dflt_blocktime);
5109   }
5110 
5111   /* OMP_NESTED */
5112   value = __kmp_env_blk_var(block, "OMP_NESTED");
5113   if (value) {
5114     ompc_set_nested(__kmp_dflt_nested);
5115   }
5116 
5117   /* OMP_DYNAMIC */
5118   value = __kmp_env_blk_var(block, "OMP_DYNAMIC");
5119   if (value) {
5120     ompc_set_dynamic(__kmp_global.g.g_dynamic);
5121   }
5122 }
5123 
5124 void __kmp_env_initialize(char const *string) {
5125 
5126   kmp_env_blk_t block;
5127   int i;
5128 
5129   __kmp_stg_init();
5130 
5131   // Hack!!!
5132   if (string == NULL) {
5133     // __kmp_max_nth = __kmp_sys_max_nth;
5134     __kmp_threads_capacity =
5135         __kmp_initial_threads_capacity(__kmp_dflt_team_nth_ub);
5136   }
5137   __kmp_env_blk_init(&block, string);
5138 
5139   // update the set flag on all entries that have an env var
5140   for (i = 0; i < block.count; ++i) {
5141     if ((block.vars[i].name == NULL) || (*block.vars[i].name == '\0')) {
5142       continue;
5143     }
5144     if (block.vars[i].value == NULL) {
5145       continue;
5146     }
5147     kmp_setting_t *setting = __kmp_stg_find(block.vars[i].name);
5148     if (setting != NULL) {
5149       setting->set = 1;
5150     }
5151   }
5152 
5153   // We need to know if blocktime was set when processing OMP_WAIT_POLICY
5154   blocktime_str = __kmp_env_blk_var(&block, "KMP_BLOCKTIME");
5155 
5156   // Special case. If we parse environment, not a string, process KMP_WARNINGS
5157   // first.
5158   if (string == NULL) {
5159     char const *name = "KMP_WARNINGS";
5160     char const *value = __kmp_env_blk_var(&block, name);
5161     __kmp_stg_parse(name, value);
5162   }
5163 
5164 #if KMP_AFFINITY_SUPPORTED
5165   // Special case. KMP_AFFINITY is not a rival to other affinity env vars
5166   // if no affinity type is specified.  We want to allow
5167   // KMP_AFFINITY=[no],verbose/[no]warnings/etc.  to be enabled when
5168   // specifying the affinity type via GOMP_CPU_AFFINITY or the OMP 4.0
5169   // affinity mechanism.
5170   __kmp_affinity_notype = NULL;
5171   char const *aff_str = __kmp_env_blk_var(&block, "KMP_AFFINITY");
5172   if (aff_str != NULL) {
5173 // Check if the KMP_AFFINITY type is specified in the string.
5174 // We just search the string for "compact", "scatter", etc.
5175 // without really parsing the string.  The syntax of the
5176 // KMP_AFFINITY env var is such that none of the affinity
5177 // type names can appear anywhere other that the type
5178 // specifier, even as substrings.
5179 //
5180 // I can't find a case-insensitive version of strstr on Windows* OS.
5181 // Use the case-sensitive version for now.
5182 
5183 #if KMP_OS_WINDOWS
5184 #define FIND strstr
5185 #else
5186 #define FIND strcasestr
5187 #endif
5188 
5189     if ((FIND(aff_str, "none") == NULL) &&
5190         (FIND(aff_str, "physical") == NULL) &&
5191         (FIND(aff_str, "logical") == NULL) &&
5192         (FIND(aff_str, "compact") == NULL) &&
5193         (FIND(aff_str, "scatter") == NULL) &&
5194         (FIND(aff_str, "explicit") == NULL) &&
5195         (FIND(aff_str, "balanced") == NULL) &&
5196         (FIND(aff_str, "disabled") == NULL)) {
5197       __kmp_affinity_notype = __kmp_stg_find("KMP_AFFINITY");
5198     } else {
5199       // A new affinity type is specified.
5200       // Reset the affinity flags to their default values,
5201       // in case this is called from kmp_set_defaults().
5202       __kmp_affinity_type = affinity_default;
5203       __kmp_affinity_gran = affinity_gran_default;
5204       __kmp_affinity_top_method = affinity_top_method_default;
5205       __kmp_affinity_respect_mask = affinity_respect_mask_default;
5206     }
5207 #undef FIND
5208 
5209 #if OMP_40_ENABLED
5210     // Also reset the affinity flags if OMP_PROC_BIND is specified.
5211     aff_str = __kmp_env_blk_var(&block, "OMP_PROC_BIND");
5212     if (aff_str != NULL) {
5213       __kmp_affinity_type = affinity_default;
5214       __kmp_affinity_gran = affinity_gran_default;
5215       __kmp_affinity_top_method = affinity_top_method_default;
5216       __kmp_affinity_respect_mask = affinity_respect_mask_default;
5217     }
5218 #endif /* OMP_40_ENABLED */
5219   }
5220 
5221 #endif /* KMP_AFFINITY_SUPPORTED */
5222 
5223 #if OMP_40_ENABLED
5224   // Set up the nested proc bind type vector.
5225   if (__kmp_nested_proc_bind.bind_types == NULL) {
5226     __kmp_nested_proc_bind.bind_types =
5227         (kmp_proc_bind_t *)KMP_INTERNAL_MALLOC(sizeof(kmp_proc_bind_t));
5228     if (__kmp_nested_proc_bind.bind_types == NULL) {
5229       KMP_FATAL(MemoryAllocFailed);
5230     }
5231     __kmp_nested_proc_bind.size = 1;
5232     __kmp_nested_proc_bind.used = 1;
5233 #if KMP_AFFINITY_SUPPORTED
5234     __kmp_nested_proc_bind.bind_types[0] = proc_bind_default;
5235 #else
5236     // default proc bind is false if affinity not supported
5237     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5238 #endif
5239   }
5240 #endif /* OMP_40_ENABLED */
5241 
5242   // Now process all of the settings.
5243   for (i = 0; i < block.count; ++i) {
5244     __kmp_stg_parse(block.vars[i].name, block.vars[i].value);
5245   }
5246 
5247   // If user locks have been allocated yet, don't reset the lock vptr table.
5248   if (!__kmp_init_user_locks) {
5249     if (__kmp_user_lock_kind == lk_default) {
5250       __kmp_user_lock_kind = lk_queuing;
5251     }
5252 #if KMP_USE_DYNAMIC_LOCK
5253     __kmp_init_dynamic_user_locks();
5254 #else
5255     __kmp_set_user_lock_vptrs(__kmp_user_lock_kind);
5256 #endif
5257   } else {
5258     KMP_DEBUG_ASSERT(string != NULL); // kmp_set_defaults() was called
5259     KMP_DEBUG_ASSERT(__kmp_user_lock_kind != lk_default);
5260 // Binds lock functions again to follow the transition between different
5261 // KMP_CONSISTENCY_CHECK values. Calling this again is harmless as long
5262 // as we do not allow lock kind changes after making a call to any
5263 // user lock functions (true).
5264 #if KMP_USE_DYNAMIC_LOCK
5265     __kmp_init_dynamic_user_locks();
5266 #else
5267     __kmp_set_user_lock_vptrs(__kmp_user_lock_kind);
5268 #endif
5269   }
5270 
5271 #if KMP_AFFINITY_SUPPORTED
5272 
5273   if (!TCR_4(__kmp_init_middle)) {
5274 #if KMP_USE_HWLOC
5275     // Force using hwloc when either tiles or numa nodes requested within
5276     // KMP_HW_SUBSET and no other topology method is requested
5277     if ((__kmp_hws_node.num > 0 || __kmp_hws_tile.num > 0 ||
5278          __kmp_affinity_gran == affinity_gran_tile) &&
5279         (__kmp_affinity_top_method == affinity_top_method_default)) {
5280       __kmp_affinity_top_method = affinity_top_method_hwloc;
5281     }
5282 #endif
5283     // Determine if the machine/OS is actually capable of supporting
5284     // affinity.
5285     const char *var = "KMP_AFFINITY";
5286     KMPAffinity::pick_api();
5287 #if KMP_USE_HWLOC
5288     // If Hwloc topology discovery was requested but affinity was also disabled,
5289     // then tell user that Hwloc request is being ignored and use default
5290     // topology discovery method.
5291     if (__kmp_affinity_top_method == affinity_top_method_hwloc &&
5292         __kmp_affinity_dispatch->get_api_type() != KMPAffinity::HWLOC) {
5293       KMP_WARNING(AffIgnoringHwloc, var);
5294       __kmp_affinity_top_method = affinity_top_method_all;
5295     }
5296 #endif
5297     if (__kmp_affinity_type == affinity_disabled) {
5298       KMP_AFFINITY_DISABLE();
5299     } else if (!KMP_AFFINITY_CAPABLE()) {
5300       __kmp_affinity_dispatch->determine_capable(var);
5301       if (!KMP_AFFINITY_CAPABLE()) {
5302         if (__kmp_affinity_verbose ||
5303             (__kmp_affinity_warnings &&
5304              (__kmp_affinity_type != affinity_default) &&
5305              (__kmp_affinity_type != affinity_none) &&
5306              (__kmp_affinity_type != affinity_disabled))) {
5307           KMP_WARNING(AffNotSupported, var);
5308         }
5309         __kmp_affinity_type = affinity_disabled;
5310         __kmp_affinity_respect_mask = 0;
5311         __kmp_affinity_gran = affinity_gran_fine;
5312       }
5313     }
5314 
5315 #if OMP_40_ENABLED
5316     if (__kmp_affinity_type == affinity_disabled) {
5317       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5318     } else if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_true) {
5319       // OMP_PROC_BIND=true maps to OMP_PROC_BIND=spread.
5320       __kmp_nested_proc_bind.bind_types[0] = proc_bind_spread;
5321     }
5322 #endif /* OMP_40_ENABLED */
5323 
5324     if (KMP_AFFINITY_CAPABLE()) {
5325 
5326 #if KMP_GROUP_AFFINITY
5327       // This checks to see if the initial affinity mask is equal
5328       // to a single windows processor group.  If it is, then we do
5329       // not respect the initial affinity mask and instead, use the
5330       // entire machine.
5331       bool exactly_one_group = false;
5332       if (__kmp_num_proc_groups > 1) {
5333         int group;
5334         bool within_one_group;
5335         // Get the initial affinity mask and determine if it is
5336         // contained within a single group.
5337         kmp_affin_mask_t *init_mask;
5338         KMP_CPU_ALLOC(init_mask);
5339         __kmp_get_system_affinity(init_mask, TRUE);
5340         group = __kmp_get_proc_group(init_mask);
5341         within_one_group = (group >= 0);
5342         // If the initial affinity is within a single group,
5343         // then determine if it is equal to that single group.
5344         if (within_one_group) {
5345           DWORD num_bits_in_group = __kmp_GetActiveProcessorCount(group);
5346           int num_bits_in_mask = 0;
5347           for (int bit = init_mask->begin(); bit != init_mask->end();
5348                bit = init_mask->next(bit))
5349             num_bits_in_mask++;
5350           exactly_one_group = (num_bits_in_group == num_bits_in_mask);
5351         }
5352         KMP_CPU_FREE(init_mask);
5353       }
5354 
5355       // Handle the Win 64 group affinity stuff if there are multiple
5356       // processor groups, or if the user requested it, and OMP 4.0
5357       // affinity is not in effect.
5358       if (((__kmp_num_proc_groups > 1) &&
5359            (__kmp_affinity_type == affinity_default)
5360 #if OMP_40_ENABLED
5361            && (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default))
5362 #endif
5363           || (__kmp_affinity_top_method == affinity_top_method_group)) {
5364         if (__kmp_affinity_respect_mask == affinity_respect_mask_default &&
5365             exactly_one_group) {
5366           __kmp_affinity_respect_mask = FALSE;
5367         }
5368         if (__kmp_affinity_type == affinity_default) {
5369           __kmp_affinity_type = affinity_compact;
5370 #if OMP_40_ENABLED
5371           __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
5372 #endif
5373         }
5374         if (__kmp_affinity_top_method == affinity_top_method_default) {
5375           if (__kmp_affinity_gran == affinity_gran_default) {
5376             __kmp_affinity_top_method = affinity_top_method_group;
5377             __kmp_affinity_gran = affinity_gran_group;
5378           } else if (__kmp_affinity_gran == affinity_gran_group) {
5379             __kmp_affinity_top_method = affinity_top_method_group;
5380           } else {
5381             __kmp_affinity_top_method = affinity_top_method_all;
5382           }
5383         } else if (__kmp_affinity_top_method == affinity_top_method_group) {
5384           if (__kmp_affinity_gran == affinity_gran_default) {
5385             __kmp_affinity_gran = affinity_gran_group;
5386           } else if ((__kmp_affinity_gran != affinity_gran_group) &&
5387                      (__kmp_affinity_gran != affinity_gran_fine) &&
5388                      (__kmp_affinity_gran != affinity_gran_thread)) {
5389             const char *str = NULL;
5390             switch (__kmp_affinity_gran) {
5391             case affinity_gran_core:
5392               str = "core";
5393               break;
5394             case affinity_gran_package:
5395               str = "package";
5396               break;
5397             case affinity_gran_node:
5398               str = "node";
5399               break;
5400             case affinity_gran_tile:
5401               str = "tile";
5402               break;
5403             default:
5404               KMP_DEBUG_ASSERT(0);
5405             }
5406             KMP_WARNING(AffGranTopGroup, var, str);
5407             __kmp_affinity_gran = affinity_gran_fine;
5408           }
5409         } else {
5410           if (__kmp_affinity_gran == affinity_gran_default) {
5411             __kmp_affinity_gran = affinity_gran_core;
5412           } else if (__kmp_affinity_gran == affinity_gran_group) {
5413             const char *str = NULL;
5414             switch (__kmp_affinity_type) {
5415             case affinity_physical:
5416               str = "physical";
5417               break;
5418             case affinity_logical:
5419               str = "logical";
5420               break;
5421             case affinity_compact:
5422               str = "compact";
5423               break;
5424             case affinity_scatter:
5425               str = "scatter";
5426               break;
5427             case affinity_explicit:
5428               str = "explicit";
5429               break;
5430             // No MIC on windows, so no affinity_balanced case
5431             default:
5432               KMP_DEBUG_ASSERT(0);
5433             }
5434             KMP_WARNING(AffGranGroupType, var, str);
5435             __kmp_affinity_gran = affinity_gran_core;
5436           }
5437         }
5438       } else
5439 
5440 #endif /* KMP_GROUP_AFFINITY */
5441 
5442       {
5443         if (__kmp_affinity_respect_mask == affinity_respect_mask_default) {
5444 #if KMP_GROUP_AFFINITY
5445           if (__kmp_num_proc_groups > 1 && exactly_one_group) {
5446             __kmp_affinity_respect_mask = FALSE;
5447           } else
5448 #endif /* KMP_GROUP_AFFINITY */
5449           {
5450             __kmp_affinity_respect_mask = TRUE;
5451           }
5452         }
5453 #if OMP_40_ENABLED
5454         if ((__kmp_nested_proc_bind.bind_types[0] != proc_bind_intel) &&
5455             (__kmp_nested_proc_bind.bind_types[0] != proc_bind_default)) {
5456           if (__kmp_affinity_type == affinity_default) {
5457             __kmp_affinity_type = affinity_compact;
5458             __kmp_affinity_dups = FALSE;
5459           }
5460         } else
5461 #endif /* OMP_40_ENABLED */
5462             if (__kmp_affinity_type == affinity_default) {
5463 #if OMP_40_ENABLED
5464 #if KMP_MIC_SUPPORTED
5465           if (__kmp_mic_type != non_mic) {
5466             __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
5467           } else
5468 #endif
5469           {
5470             __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5471           }
5472 #endif /* OMP_40_ENABLED */
5473 #if KMP_MIC_SUPPORTED
5474           if (__kmp_mic_type != non_mic) {
5475             __kmp_affinity_type = affinity_scatter;
5476           } else
5477 #endif
5478           {
5479             __kmp_affinity_type = affinity_none;
5480           }
5481         }
5482         if ((__kmp_affinity_gran == affinity_gran_default) &&
5483             (__kmp_affinity_gran_levels < 0)) {
5484 #if KMP_MIC_SUPPORTED
5485           if (__kmp_mic_type != non_mic) {
5486             __kmp_affinity_gran = affinity_gran_fine;
5487           } else
5488 #endif
5489           {
5490             __kmp_affinity_gran = affinity_gran_core;
5491           }
5492         }
5493         if (__kmp_affinity_top_method == affinity_top_method_default) {
5494           __kmp_affinity_top_method = affinity_top_method_all;
5495         }
5496       }
5497     }
5498 
5499     K_DIAG(1, ("__kmp_affinity_type         == %d\n", __kmp_affinity_type));
5500     K_DIAG(1, ("__kmp_affinity_compact      == %d\n", __kmp_affinity_compact));
5501     K_DIAG(1, ("__kmp_affinity_offset       == %d\n", __kmp_affinity_offset));
5502     K_DIAG(1, ("__kmp_affinity_verbose      == %d\n", __kmp_affinity_verbose));
5503     K_DIAG(1, ("__kmp_affinity_warnings     == %d\n", __kmp_affinity_warnings));
5504     K_DIAG(1, ("__kmp_affinity_respect_mask == %d\n",
5505                __kmp_affinity_respect_mask));
5506     K_DIAG(1, ("__kmp_affinity_gran         == %d\n", __kmp_affinity_gran));
5507 
5508     KMP_DEBUG_ASSERT(__kmp_affinity_type != affinity_default);
5509 #if OMP_40_ENABLED
5510     KMP_DEBUG_ASSERT(__kmp_nested_proc_bind.bind_types[0] != proc_bind_default);
5511     K_DIAG(1, ("__kmp_nested_proc_bind.bind_types[0] == %d\n",
5512                __kmp_nested_proc_bind.bind_types[0]));
5513 #endif
5514   }
5515 
5516 #endif /* KMP_AFFINITY_SUPPORTED */
5517 
5518   if (__kmp_version) {
5519     __kmp_print_version_1();
5520   }
5521 
5522   // Post-initialization step: some env. vars need their value's further
5523   // processing
5524   if (string != NULL) { // kmp_set_defaults() was called
5525     __kmp_aux_env_initialize(&block);
5526   }
5527 
5528   __kmp_env_blk_free(&block);
5529 
5530   KMP_MB();
5531 
5532 } // __kmp_env_initialize
5533 
5534 void __kmp_env_print() {
5535 
5536   kmp_env_blk_t block;
5537   int i;
5538   kmp_str_buf_t buffer;
5539 
5540   __kmp_stg_init();
5541   __kmp_str_buf_init(&buffer);
5542 
5543   __kmp_env_blk_init(&block, NULL);
5544   __kmp_env_blk_sort(&block);
5545 
5546   // Print real environment values.
5547   __kmp_str_buf_print(&buffer, "\n%s\n\n", KMP_I18N_STR(UserSettings));
5548   for (i = 0; i < block.count; ++i) {
5549     char const *name = block.vars[i].name;
5550     char const *value = block.vars[i].value;
5551     if ((KMP_STRLEN(name) > 4 && strncmp(name, "KMP_", 4) == 0) ||
5552         strncmp(name, "OMP_", 4) == 0
5553 #ifdef KMP_GOMP_COMPAT
5554         || strncmp(name, "GOMP_", 5) == 0
5555 #endif // KMP_GOMP_COMPAT
5556         ) {
5557       __kmp_str_buf_print(&buffer, "   %s=%s\n", name, value);
5558     }
5559   }
5560   __kmp_str_buf_print(&buffer, "\n");
5561 
5562   // Print internal (effective) settings.
5563   __kmp_str_buf_print(&buffer, "%s\n\n", KMP_I18N_STR(EffectiveSettings));
5564   for (int i = 0; i < __kmp_stg_count; ++i) {
5565     if (__kmp_stg_table[i].print != NULL) {
5566       __kmp_stg_table[i].print(&buffer, __kmp_stg_table[i].name,
5567                                __kmp_stg_table[i].data);
5568     }
5569   }
5570 
5571   __kmp_printf("%s", buffer.str);
5572 
5573   __kmp_env_blk_free(&block);
5574   __kmp_str_buf_free(&buffer);
5575 
5576   __kmp_printf("\n");
5577 
5578 } // __kmp_env_print
5579 
5580 #if OMP_40_ENABLED
5581 void __kmp_env_print_2() {
5582 
5583   kmp_env_blk_t block;
5584   kmp_str_buf_t buffer;
5585 
5586   __kmp_env_format = 1;
5587 
5588   __kmp_stg_init();
5589   __kmp_str_buf_init(&buffer);
5590 
5591   __kmp_env_blk_init(&block, NULL);
5592   __kmp_env_blk_sort(&block);
5593 
5594   __kmp_str_buf_print(&buffer, "\n%s\n", KMP_I18N_STR(DisplayEnvBegin));
5595   __kmp_str_buf_print(&buffer, "   _OPENMP='%d'\n", __kmp_openmp_version);
5596 
5597   for (int i = 0; i < __kmp_stg_count; ++i) {
5598     if (__kmp_stg_table[i].print != NULL &&
5599         ((__kmp_display_env &&
5600           strncmp(__kmp_stg_table[i].name, "OMP_", 4) == 0) ||
5601          __kmp_display_env_verbose)) {
5602       __kmp_stg_table[i].print(&buffer, __kmp_stg_table[i].name,
5603                                __kmp_stg_table[i].data);
5604     }
5605   }
5606 
5607   __kmp_str_buf_print(&buffer, "%s\n", KMP_I18N_STR(DisplayEnvEnd));
5608   __kmp_str_buf_print(&buffer, "\n");
5609 
5610   __kmp_printf("%s", buffer.str);
5611 
5612   __kmp_env_blk_free(&block);
5613   __kmp_str_buf_free(&buffer);
5614 
5615   __kmp_printf("\n");
5616 
5617 } // __kmp_env_print_2
5618 #endif // OMP_40_ENABLED
5619 
5620 // end of file
5621