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