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 // Used for OMP_WAIT_POLICY
669 static char const *blocktime_str = NULL;
670 
671 // -----------------------------------------------------------------------------
672 // KMP_DUPLICATE_LIB_OK
673 
674 static void __kmp_stg_parse_duplicate_lib_ok(char const *name,
675                                              char const *value, void *data) {
676   /* actually this variable is not supported, put here for compatibility with
677      earlier builds and for static/dynamic combination */
678   __kmp_stg_parse_bool(name, value, &__kmp_duplicate_library_ok);
679 } // __kmp_stg_parse_duplicate_lib_ok
680 
681 static void __kmp_stg_print_duplicate_lib_ok(kmp_str_buf_t *buffer,
682                                              char const *name, void *data) {
683   __kmp_stg_print_bool(buffer, name, __kmp_duplicate_library_ok);
684 } // __kmp_stg_print_duplicate_lib_ok
685 
686 // -----------------------------------------------------------------------------
687 // KMP_INHERIT_FP_CONTROL
688 
689 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
690 
691 static void __kmp_stg_parse_inherit_fp_control(char const *name,
692                                                char const *value, void *data) {
693   __kmp_stg_parse_bool(name, value, &__kmp_inherit_fp_control);
694 } // __kmp_stg_parse_inherit_fp_control
695 
696 static void __kmp_stg_print_inherit_fp_control(kmp_str_buf_t *buffer,
697                                                char const *name, void *data) {
698 #if KMP_DEBUG
699   __kmp_stg_print_bool(buffer, name, __kmp_inherit_fp_control);
700 #endif /* KMP_DEBUG */
701 } // __kmp_stg_print_inherit_fp_control
702 
703 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
704 
705 // -----------------------------------------------------------------------------
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_45_ENABLED
1183 // -----------------------------------------------------------------------------
1184 // OpenMP 4.5: OMP_MAX_TASK_PRIORITY
1185 static void __kmp_stg_parse_max_task_priority(char const *name,
1186                                               char const *value, void *data) {
1187   __kmp_stg_parse_int(name, value, 0, KMP_MAX_TASK_PRIORITY_LIMIT,
1188                       &__kmp_max_task_priority);
1189 } // __kmp_stg_parse_max_task_priority
1190 
1191 static void __kmp_stg_print_max_task_priority(kmp_str_buf_t *buffer,
1192                                               char const *name, void *data) {
1193   __kmp_stg_print_int(buffer, name, __kmp_max_task_priority);
1194 } // __kmp_stg_print_max_task_priority
1195 
1196 // KMP_TASKLOOP_MIN_TASKS
1197 // taskloop threashold to switch from recursive to linear tasks creation
1198 static void __kmp_stg_parse_taskloop_min_tasks(char const *name,
1199                                                char const *value, void *data) {
1200   int tmp;
1201   __kmp_stg_parse_int(name, value, 0, INT_MAX, &tmp);
1202   __kmp_taskloop_min_tasks = tmp;
1203 } // __kmp_stg_parse_taskloop_min_tasks
1204 
1205 static void __kmp_stg_print_taskloop_min_tasks(kmp_str_buf_t *buffer,
1206                                                char const *name, void *data) {
1207   __kmp_stg_print_int(buffer, name, __kmp_taskloop_min_tasks);
1208 } // __kmp_stg_print_taskloop_min_tasks
1209 #endif // OMP_45_ENABLED
1210 
1211 // -----------------------------------------------------------------------------
1212 // KMP_DISP_NUM_BUFFERS
1213 static void __kmp_stg_parse_disp_buffers(char const *name, char const *value,
1214                                          void *data) {
1215   if (TCR_4(__kmp_init_serial)) {
1216     KMP_WARNING(EnvSerialWarn, name);
1217     return;
1218   } // read value before serial initialization only
1219   __kmp_stg_parse_int(name, value, 1, KMP_MAX_NTH, &__kmp_dispatch_num_buffers);
1220 } // __kmp_stg_parse_disp_buffers
1221 
1222 static void __kmp_stg_print_disp_buffers(kmp_str_buf_t *buffer,
1223                                          char const *name, void *data) {
1224   __kmp_stg_print_int(buffer, name, __kmp_dispatch_num_buffers);
1225 } // __kmp_stg_print_disp_buffers
1226 
1227 #if KMP_NESTED_HOT_TEAMS
1228 // -----------------------------------------------------------------------------
1229 // KMP_HOT_TEAMS_MAX_LEVEL, KMP_HOT_TEAMS_MODE
1230 
1231 static void __kmp_stg_parse_hot_teams_level(char const *name, char const *value,
1232                                             void *data) {
1233   if (TCR_4(__kmp_init_parallel)) {
1234     KMP_WARNING(EnvParallelWarn, name);
1235     return;
1236   } // read value before first parallel only
1237   __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1238                       &__kmp_hot_teams_max_level);
1239 } // __kmp_stg_parse_hot_teams_level
1240 
1241 static void __kmp_stg_print_hot_teams_level(kmp_str_buf_t *buffer,
1242                                             char const *name, void *data) {
1243   __kmp_stg_print_int(buffer, name, __kmp_hot_teams_max_level);
1244 } // __kmp_stg_print_hot_teams_level
1245 
1246 static void __kmp_stg_parse_hot_teams_mode(char const *name, char const *value,
1247                                            void *data) {
1248   if (TCR_4(__kmp_init_parallel)) {
1249     KMP_WARNING(EnvParallelWarn, name);
1250     return;
1251   } // read value before first parallel only
1252   __kmp_stg_parse_int(name, value, 0, KMP_MAX_ACTIVE_LEVELS_LIMIT,
1253                       &__kmp_hot_teams_mode);
1254 } // __kmp_stg_parse_hot_teams_mode
1255 
1256 static void __kmp_stg_print_hot_teams_mode(kmp_str_buf_t *buffer,
1257                                            char const *name, void *data) {
1258   __kmp_stg_print_int(buffer, name, __kmp_hot_teams_mode);
1259 } // __kmp_stg_print_hot_teams_mode
1260 
1261 #endif // KMP_NESTED_HOT_TEAMS
1262 
1263 // -----------------------------------------------------------------------------
1264 // KMP_HANDLE_SIGNALS
1265 
1266 #if KMP_HANDLE_SIGNALS
1267 
1268 static void __kmp_stg_parse_handle_signals(char const *name, char const *value,
1269                                            void *data) {
1270   __kmp_stg_parse_bool(name, value, &__kmp_handle_signals);
1271 } // __kmp_stg_parse_handle_signals
1272 
1273 static void __kmp_stg_print_handle_signals(kmp_str_buf_t *buffer,
1274                                            char const *name, void *data) {
1275   __kmp_stg_print_bool(buffer, name, __kmp_handle_signals);
1276 } // __kmp_stg_print_handle_signals
1277 
1278 #endif // KMP_HANDLE_SIGNALS
1279 
1280 // -----------------------------------------------------------------------------
1281 // KMP_X_DEBUG, KMP_DEBUG, KMP_DEBUG_BUF_*, KMP_DIAG
1282 
1283 #ifdef KMP_DEBUG
1284 
1285 #define KMP_STG_X_DEBUG(x)                                                     \
1286   static void __kmp_stg_parse_##x##_debug(char const *name, char const *value, \
1287                                           void *data) {                        \
1288     __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_##x##_debug);            \
1289   } /* __kmp_stg_parse_x_debug */                                              \
1290   static void __kmp_stg_print_##x##_debug(kmp_str_buf_t *buffer,               \
1291                                           char const *name, void *data) {      \
1292     __kmp_stg_print_int(buffer, name, kmp_##x##_debug);                        \
1293   } /* __kmp_stg_print_x_debug */
1294 
1295 KMP_STG_X_DEBUG(a)
1296 KMP_STG_X_DEBUG(b)
1297 KMP_STG_X_DEBUG(c)
1298 KMP_STG_X_DEBUG(d)
1299 KMP_STG_X_DEBUG(e)
1300 KMP_STG_X_DEBUG(f)
1301 
1302 #undef KMP_STG_X_DEBUG
1303 
1304 static void __kmp_stg_parse_debug(char const *name, char const *value,
1305                                   void *data) {
1306   int debug = 0;
1307   __kmp_stg_parse_int(name, value, 0, INT_MAX, &debug);
1308   if (kmp_a_debug < debug) {
1309     kmp_a_debug = debug;
1310   }
1311   if (kmp_b_debug < debug) {
1312     kmp_b_debug = debug;
1313   }
1314   if (kmp_c_debug < debug) {
1315     kmp_c_debug = debug;
1316   }
1317   if (kmp_d_debug < debug) {
1318     kmp_d_debug = debug;
1319   }
1320   if (kmp_e_debug < debug) {
1321     kmp_e_debug = debug;
1322   }
1323   if (kmp_f_debug < debug) {
1324     kmp_f_debug = debug;
1325   }
1326 } // __kmp_stg_parse_debug
1327 
1328 static void __kmp_stg_parse_debug_buf(char const *name, char const *value,
1329                                       void *data) {
1330   __kmp_stg_parse_bool(name, value, &__kmp_debug_buf);
1331   // !!! TODO: Move buffer initialization of of this file! It may works
1332   // incorrectly if KMP_DEBUG_BUF is parsed before KMP_DEBUG_BUF_LINES or
1333   // KMP_DEBUG_BUF_CHARS.
1334   if (__kmp_debug_buf) {
1335     int i;
1336     int elements = __kmp_debug_buf_lines * __kmp_debug_buf_chars;
1337 
1338     /* allocate and initialize all entries in debug buffer to empty */
1339     __kmp_debug_buffer = (char *)__kmp_page_allocate(elements * sizeof(char));
1340     for (i = 0; i < elements; i += __kmp_debug_buf_chars)
1341       __kmp_debug_buffer[i] = '\0';
1342 
1343     __kmp_debug_count = 0;
1344   }
1345   K_DIAG(1, ("__kmp_debug_buf = %d\n", __kmp_debug_buf));
1346 } // __kmp_stg_parse_debug_buf
1347 
1348 static void __kmp_stg_print_debug_buf(kmp_str_buf_t *buffer, char const *name,
1349                                       void *data) {
1350   __kmp_stg_print_bool(buffer, name, __kmp_debug_buf);
1351 } // __kmp_stg_print_debug_buf
1352 
1353 static void __kmp_stg_parse_debug_buf_atomic(char const *name,
1354                                              char const *value, void *data) {
1355   __kmp_stg_parse_bool(name, value, &__kmp_debug_buf_atomic);
1356 } // __kmp_stg_parse_debug_buf_atomic
1357 
1358 static void __kmp_stg_print_debug_buf_atomic(kmp_str_buf_t *buffer,
1359                                              char const *name, void *data) {
1360   __kmp_stg_print_bool(buffer, name, __kmp_debug_buf_atomic);
1361 } // __kmp_stg_print_debug_buf_atomic
1362 
1363 static void __kmp_stg_parse_debug_buf_chars(char const *name, char const *value,
1364                                             void *data) {
1365   __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_CHARS_MIN, INT_MAX,
1366                       &__kmp_debug_buf_chars);
1367 } // __kmp_stg_debug_parse_buf_chars
1368 
1369 static void __kmp_stg_print_debug_buf_chars(kmp_str_buf_t *buffer,
1370                                             char const *name, void *data) {
1371   __kmp_stg_print_int(buffer, name, __kmp_debug_buf_chars);
1372 } // __kmp_stg_print_debug_buf_chars
1373 
1374 static void __kmp_stg_parse_debug_buf_lines(char const *name, char const *value,
1375                                             void *data) {
1376   __kmp_stg_parse_int(name, value, KMP_DEBUG_BUF_LINES_MIN, INT_MAX,
1377                       &__kmp_debug_buf_lines);
1378 } // __kmp_stg_parse_debug_buf_lines
1379 
1380 static void __kmp_stg_print_debug_buf_lines(kmp_str_buf_t *buffer,
1381                                             char const *name, void *data) {
1382   __kmp_stg_print_int(buffer, name, __kmp_debug_buf_lines);
1383 } // __kmp_stg_print_debug_buf_lines
1384 
1385 static void __kmp_stg_parse_diag(char const *name, char const *value,
1386                                  void *data) {
1387   __kmp_stg_parse_int(name, value, 0, INT_MAX, &kmp_diag);
1388 } // __kmp_stg_parse_diag
1389 
1390 static void __kmp_stg_print_diag(kmp_str_buf_t *buffer, char const *name,
1391                                  void *data) {
1392   __kmp_stg_print_int(buffer, name, kmp_diag);
1393 } // __kmp_stg_print_diag
1394 
1395 #endif // KMP_DEBUG
1396 
1397 // -----------------------------------------------------------------------------
1398 // KMP_ALIGN_ALLOC
1399 
1400 static void __kmp_stg_parse_align_alloc(char const *name, char const *value,
1401                                         void *data) {
1402   __kmp_stg_parse_size(name, value, CACHE_LINE, INT_MAX, NULL,
1403                        &__kmp_align_alloc, 1);
1404 } // __kmp_stg_parse_align_alloc
1405 
1406 static void __kmp_stg_print_align_alloc(kmp_str_buf_t *buffer, char const *name,
1407                                         void *data) {
1408   __kmp_stg_print_size(buffer, name, __kmp_align_alloc);
1409 } // __kmp_stg_print_align_alloc
1410 
1411 // -----------------------------------------------------------------------------
1412 // KMP_PLAIN_BARRIER, KMP_FORKJOIN_BARRIER, KMP_REDUCTION_BARRIER
1413 
1414 // TODO: Remove __kmp_barrier_branch_bit_env_name varibale, remove loops from
1415 // parse and print functions, pass required info through data argument.
1416 
1417 static void __kmp_stg_parse_barrier_branch_bit(char const *name,
1418                                                char const *value, void *data) {
1419   const char *var;
1420 
1421   /* ---------- Barrier branch bit control ------------ */
1422   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1423     var = __kmp_barrier_branch_bit_env_name[i];
1424     if ((strcmp(var, name) == 0) && (value != 0)) {
1425       char *comma;
1426 
1427       comma = CCAST(char *, strchr(value, ','));
1428       __kmp_barrier_gather_branch_bits[i] =
1429           (kmp_uint32)__kmp_str_to_int(value, ',');
1430       /* is there a specified release parameter? */
1431       if (comma == NULL) {
1432         __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
1433       } else {
1434         __kmp_barrier_release_branch_bits[i] =
1435             (kmp_uint32)__kmp_str_to_int(comma + 1, 0);
1436 
1437         if (__kmp_barrier_release_branch_bits[i] > KMP_MAX_BRANCH_BITS) {
1438           __kmp_msg(kmp_ms_warning,
1439                     KMP_MSG(BarrReleaseValueInvalid, name, comma + 1),
1440                     __kmp_msg_null);
1441           __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
1442         }
1443       }
1444       if (__kmp_barrier_gather_branch_bits[i] > KMP_MAX_BRANCH_BITS) {
1445         KMP_WARNING(BarrGatherValueInvalid, name, value);
1446         KMP_INFORM(Using_uint_Value, name, __kmp_barrier_gather_bb_dflt);
1447         __kmp_barrier_gather_branch_bits[i] = __kmp_barrier_gather_bb_dflt;
1448       }
1449     }
1450     K_DIAG(1, ("%s == %d,%d\n", __kmp_barrier_branch_bit_env_name[i],
1451                __kmp_barrier_gather_branch_bits[i],
1452                __kmp_barrier_release_branch_bits[i]))
1453   }
1454 } // __kmp_stg_parse_barrier_branch_bit
1455 
1456 static void __kmp_stg_print_barrier_branch_bit(kmp_str_buf_t *buffer,
1457                                                char const *name, void *data) {
1458   const char *var;
1459   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1460     var = __kmp_barrier_branch_bit_env_name[i];
1461     if (strcmp(var, name) == 0) {
1462       if (__kmp_env_format) {
1463         KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_branch_bit_env_name[i]);
1464       } else {
1465         __kmp_str_buf_print(buffer, "   %s='",
1466                             __kmp_barrier_branch_bit_env_name[i]);
1467       }
1468       __kmp_str_buf_print(buffer, "%d,%d'\n",
1469                           __kmp_barrier_gather_branch_bits[i],
1470                           __kmp_barrier_release_branch_bits[i]);
1471     }
1472   }
1473 } // __kmp_stg_print_barrier_branch_bit
1474 
1475 // ----------------------------------------------------------------------------
1476 // KMP_PLAIN_BARRIER_PATTERN, KMP_FORKJOIN_BARRIER_PATTERN,
1477 // KMP_REDUCTION_BARRIER_PATTERN
1478 
1479 // TODO: Remove __kmp_barrier_pattern_name variable, remove loops from parse and
1480 // print functions, pass required data to functions through data argument.
1481 
1482 static void __kmp_stg_parse_barrier_pattern(char const *name, char const *value,
1483                                             void *data) {
1484   const char *var;
1485   /* ---------- Barrier method control ------------ */
1486 
1487   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1488     var = __kmp_barrier_pattern_env_name[i];
1489 
1490     if ((strcmp(var, name) == 0) && (value != 0)) {
1491       int j;
1492       char *comma = CCAST(char *, strchr(value, ','));
1493 
1494       /* handle first parameter: gather pattern */
1495       for (j = bp_linear_bar; j < bp_last_bar; j++) {
1496         if (__kmp_match_with_sentinel(__kmp_barrier_pattern_name[j], value, 1,
1497                                       ',')) {
1498           __kmp_barrier_gather_pattern[i] = (kmp_bar_pat_e)j;
1499           break;
1500         }
1501       }
1502       if (j == bp_last_bar) {
1503         KMP_WARNING(BarrGatherValueInvalid, name, value);
1504         KMP_INFORM(Using_str_Value, name,
1505                    __kmp_barrier_pattern_name[bp_linear_bar]);
1506       }
1507 
1508       /* handle second parameter: release pattern */
1509       if (comma != NULL) {
1510         for (j = bp_linear_bar; j < bp_last_bar; j++) {
1511           if (__kmp_str_match(__kmp_barrier_pattern_name[j], 1, comma + 1)) {
1512             __kmp_barrier_release_pattern[i] = (kmp_bar_pat_e)j;
1513             break;
1514           }
1515         }
1516         if (j == bp_last_bar) {
1517           __kmp_msg(kmp_ms_warning,
1518                     KMP_MSG(BarrReleaseValueInvalid, name, comma + 1),
1519                     __kmp_msg_null);
1520           KMP_INFORM(Using_str_Value, name,
1521                      __kmp_barrier_pattern_name[bp_linear_bar]);
1522         }
1523       }
1524     }
1525   }
1526 } // __kmp_stg_parse_barrier_pattern
1527 
1528 static void __kmp_stg_print_barrier_pattern(kmp_str_buf_t *buffer,
1529                                             char const *name, void *data) {
1530   const char *var;
1531   for (int i = bs_plain_barrier; i < bs_last_barrier; i++) {
1532     var = __kmp_barrier_pattern_env_name[i];
1533     if (strcmp(var, name) == 0) {
1534       int j = __kmp_barrier_gather_pattern[i];
1535       int k = __kmp_barrier_release_pattern[i];
1536       if (__kmp_env_format) {
1537         KMP_STR_BUF_PRINT_NAME_EX(__kmp_barrier_pattern_env_name[i]);
1538       } else {
1539         __kmp_str_buf_print(buffer, "   %s='",
1540                             __kmp_barrier_pattern_env_name[i]);
1541       }
1542       __kmp_str_buf_print(buffer, "%s,%s'\n", __kmp_barrier_pattern_name[j],
1543                           __kmp_barrier_pattern_name[k]);
1544     }
1545   }
1546 } // __kmp_stg_print_barrier_pattern
1547 
1548 // -----------------------------------------------------------------------------
1549 // KMP_ABORT_DELAY
1550 
1551 static void __kmp_stg_parse_abort_delay(char const *name, char const *value,
1552                                         void *data) {
1553   // Units of KMP_DELAY_ABORT are seconds, units of __kmp_abort_delay is
1554   // milliseconds.
1555   int delay = __kmp_abort_delay / 1000;
1556   __kmp_stg_parse_int(name, value, 0, INT_MAX / 1000, &delay);
1557   __kmp_abort_delay = delay * 1000;
1558 } // __kmp_stg_parse_abort_delay
1559 
1560 static void __kmp_stg_print_abort_delay(kmp_str_buf_t *buffer, char const *name,
1561                                         void *data) {
1562   __kmp_stg_print_int(buffer, name, __kmp_abort_delay);
1563 } // __kmp_stg_print_abort_delay
1564 
1565 // -----------------------------------------------------------------------------
1566 // KMP_CPUINFO_FILE
1567 
1568 static void __kmp_stg_parse_cpuinfo_file(char const *name, char const *value,
1569                                          void *data) {
1570 #if KMP_AFFINITY_SUPPORTED
1571   __kmp_stg_parse_str(name, value, &__kmp_cpuinfo_file);
1572   K_DIAG(1, ("__kmp_cpuinfo_file == %s\n", __kmp_cpuinfo_file));
1573 #endif
1574 } //__kmp_stg_parse_cpuinfo_file
1575 
1576 static void __kmp_stg_print_cpuinfo_file(kmp_str_buf_t *buffer,
1577                                          char const *name, void *data) {
1578 #if KMP_AFFINITY_SUPPORTED
1579   if (__kmp_env_format) {
1580     KMP_STR_BUF_PRINT_NAME;
1581   } else {
1582     __kmp_str_buf_print(buffer, "   %s", name);
1583   }
1584   if (__kmp_cpuinfo_file) {
1585     __kmp_str_buf_print(buffer, "='%s'\n", __kmp_cpuinfo_file);
1586   } else {
1587     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1588   }
1589 #endif
1590 } //__kmp_stg_print_cpuinfo_file
1591 
1592 // -----------------------------------------------------------------------------
1593 // KMP_FORCE_REDUCTION, KMP_DETERMINISTIC_REDUCTION
1594 
1595 static void __kmp_stg_parse_force_reduction(char const *name, char const *value,
1596                                             void *data) {
1597   kmp_stg_fr_data_t *reduction = (kmp_stg_fr_data_t *)data;
1598   int rc;
1599 
1600   rc = __kmp_stg_check_rivals(name, value, reduction->rivals);
1601   if (rc) {
1602     return;
1603   }
1604   if (reduction->force) {
1605     if (value != 0) {
1606       if (__kmp_str_match("critical", 0, value))
1607         __kmp_force_reduction_method = critical_reduce_block;
1608       else if (__kmp_str_match("atomic", 0, value))
1609         __kmp_force_reduction_method = atomic_reduce_block;
1610       else if (__kmp_str_match("tree", 0, value))
1611         __kmp_force_reduction_method = tree_reduce_block;
1612       else {
1613         KMP_FATAL(UnknownForceReduction, name, value);
1614       }
1615     }
1616   } else {
1617     __kmp_stg_parse_bool(name, value, &__kmp_determ_red);
1618     if (__kmp_determ_red) {
1619       __kmp_force_reduction_method = tree_reduce_block;
1620     } else {
1621       __kmp_force_reduction_method = reduction_method_not_defined;
1622     }
1623   }
1624   K_DIAG(1, ("__kmp_force_reduction_method == %d\n",
1625              __kmp_force_reduction_method));
1626 } // __kmp_stg_parse_force_reduction
1627 
1628 static void __kmp_stg_print_force_reduction(kmp_str_buf_t *buffer,
1629                                             char const *name, void *data) {
1630 
1631   kmp_stg_fr_data_t *reduction = (kmp_stg_fr_data_t *)data;
1632   if (reduction->force) {
1633     if (__kmp_force_reduction_method == critical_reduce_block) {
1634       __kmp_stg_print_str(buffer, name, "critical");
1635     } else if (__kmp_force_reduction_method == atomic_reduce_block) {
1636       __kmp_stg_print_str(buffer, name, "atomic");
1637     } else if (__kmp_force_reduction_method == tree_reduce_block) {
1638       __kmp_stg_print_str(buffer, name, "tree");
1639     } else {
1640       if (__kmp_env_format) {
1641         KMP_STR_BUF_PRINT_NAME;
1642       } else {
1643         __kmp_str_buf_print(buffer, "   %s", name);
1644       }
1645       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
1646     }
1647   } else {
1648     __kmp_stg_print_bool(buffer, name, __kmp_determ_red);
1649   }
1650 
1651 } // __kmp_stg_print_force_reduction
1652 
1653 // -----------------------------------------------------------------------------
1654 // KMP_STORAGE_MAP
1655 
1656 static void __kmp_stg_parse_storage_map(char const *name, char const *value,
1657                                         void *data) {
1658   if (__kmp_str_match("verbose", 1, value)) {
1659     __kmp_storage_map = TRUE;
1660     __kmp_storage_map_verbose = TRUE;
1661     __kmp_storage_map_verbose_specified = TRUE;
1662 
1663   } else {
1664     __kmp_storage_map_verbose = FALSE;
1665     __kmp_stg_parse_bool(name, value, &__kmp_storage_map); // !!!
1666   }
1667 } // __kmp_stg_parse_storage_map
1668 
1669 static void __kmp_stg_print_storage_map(kmp_str_buf_t *buffer, char const *name,
1670                                         void *data) {
1671   if (__kmp_storage_map_verbose || __kmp_storage_map_verbose_specified) {
1672     __kmp_stg_print_str(buffer, name, "verbose");
1673   } else {
1674     __kmp_stg_print_bool(buffer, name, __kmp_storage_map);
1675   }
1676 } // __kmp_stg_print_storage_map
1677 
1678 // -----------------------------------------------------------------------------
1679 // KMP_ALL_THREADPRIVATE
1680 
1681 static void __kmp_stg_parse_all_threadprivate(char const *name,
1682                                               char const *value, void *data) {
1683   __kmp_stg_parse_int(name, value,
1684                       __kmp_allThreadsSpecified ? __kmp_max_nth : 1,
1685                       __kmp_max_nth, &__kmp_tp_capacity);
1686 } // __kmp_stg_parse_all_threadprivate
1687 
1688 static void __kmp_stg_print_all_threadprivate(kmp_str_buf_t *buffer,
1689                                               char const *name, void *data) {
1690   __kmp_stg_print_int(buffer, name, __kmp_tp_capacity);
1691 }
1692 
1693 // -----------------------------------------------------------------------------
1694 // KMP_FOREIGN_THREADS_THREADPRIVATE
1695 
1696 static void __kmp_stg_parse_foreign_threads_threadprivate(char const *name,
1697                                                           char const *value,
1698                                                           void *data) {
1699   __kmp_stg_parse_bool(name, value, &__kmp_foreign_tp);
1700 } // __kmp_stg_parse_foreign_threads_threadprivate
1701 
1702 static void __kmp_stg_print_foreign_threads_threadprivate(kmp_str_buf_t *buffer,
1703                                                           char const *name,
1704                                                           void *data) {
1705   __kmp_stg_print_bool(buffer, name, __kmp_foreign_tp);
1706 } // __kmp_stg_print_foreign_threads_threadprivate
1707 
1708 // -----------------------------------------------------------------------------
1709 // KMP_AFFINITY, GOMP_CPU_AFFINITY, KMP_TOPOLOGY_METHOD
1710 
1711 #if KMP_AFFINITY_SUPPORTED
1712 // Parse the proc id list.  Return TRUE if successful, FALSE otherwise.
1713 static int __kmp_parse_affinity_proc_id_list(const char *var, const char *env,
1714                                              const char **nextEnv,
1715                                              char **proclist) {
1716   const char *scan = env;
1717   const char *next = scan;
1718   int empty = TRUE;
1719 
1720   *proclist = NULL;
1721 
1722   for (;;) {
1723     int start, end, stride;
1724 
1725     SKIP_WS(scan);
1726     next = scan;
1727     if (*next == '\0') {
1728       break;
1729     }
1730 
1731     if (*next == '{') {
1732       int num;
1733       next++; // skip '{'
1734       SKIP_WS(next);
1735       scan = next;
1736 
1737       // Read the first integer in the set.
1738       if ((*next < '0') || (*next > '9')) {
1739         KMP_WARNING(AffSyntaxError, var);
1740         return FALSE;
1741       }
1742       SKIP_DIGITS(next);
1743       num = __kmp_str_to_int(scan, *next);
1744       KMP_ASSERT(num >= 0);
1745 
1746       for (;;) {
1747         // Check for end of set.
1748         SKIP_WS(next);
1749         if (*next == '}') {
1750           next++; // skip '}'
1751           break;
1752         }
1753 
1754         // Skip optional comma.
1755         if (*next == ',') {
1756           next++;
1757         }
1758         SKIP_WS(next);
1759 
1760         // Read the next integer in the set.
1761         scan = next;
1762         if ((*next < '0') || (*next > '9')) {
1763           KMP_WARNING(AffSyntaxError, var);
1764           return FALSE;
1765         }
1766 
1767         SKIP_DIGITS(next);
1768         num = __kmp_str_to_int(scan, *next);
1769         KMP_ASSERT(num >= 0);
1770       }
1771       empty = FALSE;
1772 
1773       SKIP_WS(next);
1774       if (*next == ',') {
1775         next++;
1776       }
1777       scan = next;
1778       continue;
1779     }
1780 
1781     // Next character is not an integer => end of list
1782     if ((*next < '0') || (*next > '9')) {
1783       if (empty) {
1784         KMP_WARNING(AffSyntaxError, var);
1785         return FALSE;
1786       }
1787       break;
1788     }
1789 
1790     // Read the first integer.
1791     SKIP_DIGITS(next);
1792     start = __kmp_str_to_int(scan, *next);
1793     KMP_ASSERT(start >= 0);
1794     SKIP_WS(next);
1795 
1796     // If this isn't a range, then go on.
1797     if (*next != '-') {
1798       empty = FALSE;
1799 
1800       // Skip optional comma.
1801       if (*next == ',') {
1802         next++;
1803       }
1804       scan = next;
1805       continue;
1806     }
1807 
1808     // This is a range.  Skip over the '-' and read in the 2nd int.
1809     next++; // skip '-'
1810     SKIP_WS(next);
1811     scan = next;
1812     if ((*next < '0') || (*next > '9')) {
1813       KMP_WARNING(AffSyntaxError, var);
1814       return FALSE;
1815     }
1816     SKIP_DIGITS(next);
1817     end = __kmp_str_to_int(scan, *next);
1818     KMP_ASSERT(end >= 0);
1819 
1820     // Check for a stride parameter
1821     stride = 1;
1822     SKIP_WS(next);
1823     if (*next == ':') {
1824       // A stride is specified.  Skip over the ':" and read the 3rd int.
1825       int sign = +1;
1826       next++; // skip ':'
1827       SKIP_WS(next);
1828       scan = next;
1829       if (*next == '-') {
1830         sign = -1;
1831         next++;
1832         SKIP_WS(next);
1833         scan = next;
1834       }
1835       if ((*next < '0') || (*next > '9')) {
1836         KMP_WARNING(AffSyntaxError, var);
1837         return FALSE;
1838       }
1839       SKIP_DIGITS(next);
1840       stride = __kmp_str_to_int(scan, *next);
1841       KMP_ASSERT(stride >= 0);
1842       stride *= sign;
1843     }
1844 
1845     // Do some range checks.
1846     if (stride == 0) {
1847       KMP_WARNING(AffZeroStride, var);
1848       return FALSE;
1849     }
1850     if (stride > 0) {
1851       if (start > end) {
1852         KMP_WARNING(AffStartGreaterEnd, var, start, end);
1853         return FALSE;
1854       }
1855     } else {
1856       if (start < end) {
1857         KMP_WARNING(AffStrideLessZero, var, start, end);
1858         return FALSE;
1859       }
1860     }
1861     if ((end - start) / stride > 65536) {
1862       KMP_WARNING(AffRangeTooBig, var, end, start, stride);
1863       return FALSE;
1864     }
1865 
1866     empty = FALSE;
1867 
1868     // Skip optional comma.
1869     SKIP_WS(next);
1870     if (*next == ',') {
1871       next++;
1872     }
1873     scan = next;
1874   }
1875 
1876   *nextEnv = next;
1877 
1878   {
1879     int len = next - env;
1880     char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
1881     KMP_MEMCPY_S(retlist, (len + 1) * sizeof(char), env, len * sizeof(char));
1882     retlist[len] = '\0';
1883     *proclist = retlist;
1884   }
1885   return TRUE;
1886 }
1887 
1888 // If KMP_AFFINITY is specified without a type, then
1889 // __kmp_affinity_notype should point to its setting.
1890 static kmp_setting_t *__kmp_affinity_notype = NULL;
1891 
1892 static void __kmp_parse_affinity_env(char const *name, char const *value,
1893                                      enum affinity_type *out_type,
1894                                      char **out_proclist, int *out_verbose,
1895                                      int *out_warn, int *out_respect,
1896                                      enum affinity_gran *out_gran,
1897                                      int *out_gran_levels, int *out_dups,
1898                                      int *out_compact, int *out_offset) {
1899   char *buffer = NULL; // Copy of env var value.
1900   char *buf = NULL; // Buffer for strtok_r() function.
1901   char *next = NULL; // end of token / start of next.
1902   const char *start; // start of current token (for err msgs)
1903   int count = 0; // Counter of parsed integer numbers.
1904   int number[2]; // Parsed numbers.
1905 
1906   // Guards.
1907   int type = 0;
1908   int proclist = 0;
1909   int max_proclist = 0;
1910   int verbose = 0;
1911   int warnings = 0;
1912   int respect = 0;
1913   int gran = 0;
1914   int dups = 0;
1915 
1916   KMP_ASSERT(value != NULL);
1917 
1918   if (TCR_4(__kmp_init_middle)) {
1919     KMP_WARNING(EnvMiddleWarn, name);
1920     __kmp_env_toPrint(name, 0);
1921     return;
1922   }
1923   __kmp_env_toPrint(name, 1);
1924 
1925   buffer =
1926       __kmp_str_format("%s", value); // Copy env var to keep original intact.
1927   buf = buffer;
1928   SKIP_WS(buf);
1929 
1930 // Helper macros.
1931 
1932 // If we see a parse error, emit a warning and scan to the next ",".
1933 //
1934 // FIXME - there's got to be a better way to print an error
1935 // message, hopefully without overwritting peices of buf.
1936 #define EMIT_WARN(skip, errlist)                                               \
1937   {                                                                            \
1938     char ch;                                                                   \
1939     if (skip) {                                                                \
1940       SKIP_TO(next, ',');                                                      \
1941     }                                                                          \
1942     ch = *next;                                                                \
1943     *next = '\0';                                                              \
1944     KMP_WARNING errlist;                                                       \
1945     *next = ch;                                                                \
1946     if (skip) {                                                                \
1947       if (ch == ',')                                                           \
1948         next++;                                                                \
1949     }                                                                          \
1950     buf = next;                                                                \
1951   }
1952 
1953 #define _set_param(_guard, _var, _val)                                         \
1954   {                                                                            \
1955     if (_guard == 0) {                                                         \
1956       _var = _val;                                                             \
1957     } else {                                                                   \
1958       EMIT_WARN(FALSE, (AffParamDefined, name, start));                        \
1959     }                                                                          \
1960     ++_guard;                                                                  \
1961   }
1962 
1963 #define set_type(val) _set_param(type, *out_type, val)
1964 #define set_verbose(val) _set_param(verbose, *out_verbose, val)
1965 #define set_warnings(val) _set_param(warnings, *out_warn, val)
1966 #define set_respect(val) _set_param(respect, *out_respect, val)
1967 #define set_dups(val) _set_param(dups, *out_dups, val)
1968 #define set_proclist(val) _set_param(proclist, *out_proclist, val)
1969 
1970 #define set_gran(val, levels)                                                  \
1971   {                                                                            \
1972     if (gran == 0) {                                                           \
1973       *out_gran = val;                                                         \
1974       *out_gran_levels = levels;                                               \
1975     } else {                                                                   \
1976       EMIT_WARN(FALSE, (AffParamDefined, name, start));                        \
1977     }                                                                          \
1978     ++gran;                                                                    \
1979   }
1980 
1981 #if OMP_40_ENABLED
1982   KMP_DEBUG_ASSERT((__kmp_nested_proc_bind.bind_types != NULL) &&
1983                    (__kmp_nested_proc_bind.used > 0));
1984 #endif
1985 
1986   while (*buf != '\0') {
1987     start = next = buf;
1988 
1989     if (__kmp_match_str("none", buf, CCAST(const char **, &next))) {
1990       set_type(affinity_none);
1991 #if OMP_40_ENABLED
1992       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
1993 #endif
1994       buf = next;
1995     } else if (__kmp_match_str("scatter", buf, CCAST(const char **, &next))) {
1996       set_type(affinity_scatter);
1997 #if OMP_40_ENABLED
1998       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
1999 #endif
2000       buf = next;
2001     } else if (__kmp_match_str("compact", buf, CCAST(const char **, &next))) {
2002       set_type(affinity_compact);
2003 #if OMP_40_ENABLED
2004       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2005 #endif
2006       buf = next;
2007     } else if (__kmp_match_str("logical", buf, CCAST(const char **, &next))) {
2008       set_type(affinity_logical);
2009 #if OMP_40_ENABLED
2010       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2011 #endif
2012       buf = next;
2013     } else if (__kmp_match_str("physical", buf, CCAST(const char **, &next))) {
2014       set_type(affinity_physical);
2015 #if OMP_40_ENABLED
2016       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2017 #endif
2018       buf = next;
2019     } else if (__kmp_match_str("explicit", buf, CCAST(const char **, &next))) {
2020       set_type(affinity_explicit);
2021 #if OMP_40_ENABLED
2022       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2023 #endif
2024       buf = next;
2025     } else if (__kmp_match_str("balanced", buf, CCAST(const char **, &next))) {
2026       set_type(affinity_balanced);
2027 #if OMP_40_ENABLED
2028       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2029 #endif
2030       buf = next;
2031     } else if (__kmp_match_str("disabled", buf, CCAST(const char **, &next))) {
2032       set_type(affinity_disabled);
2033 #if OMP_40_ENABLED
2034       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
2035 #endif
2036       buf = next;
2037     } else if (__kmp_match_str("verbose", buf, CCAST(const char **, &next))) {
2038       set_verbose(TRUE);
2039       buf = next;
2040     } else if (__kmp_match_str("noverbose", buf, CCAST(const char **, &next))) {
2041       set_verbose(FALSE);
2042       buf = next;
2043     } else if (__kmp_match_str("warnings", buf, CCAST(const char **, &next))) {
2044       set_warnings(TRUE);
2045       buf = next;
2046     } else if (__kmp_match_str("nowarnings", buf,
2047                                CCAST(const char **, &next))) {
2048       set_warnings(FALSE);
2049       buf = next;
2050     } else if (__kmp_match_str("respect", buf, CCAST(const char **, &next))) {
2051       set_respect(TRUE);
2052       buf = next;
2053     } else if (__kmp_match_str("norespect", buf, CCAST(const char **, &next))) {
2054       set_respect(FALSE);
2055       buf = next;
2056     } else if (__kmp_match_str("duplicates", buf,
2057                                CCAST(const char **, &next)) ||
2058                __kmp_match_str("dups", buf, CCAST(const char **, &next))) {
2059       set_dups(TRUE);
2060       buf = next;
2061     } else if (__kmp_match_str("noduplicates", buf,
2062                                CCAST(const char **, &next)) ||
2063                __kmp_match_str("nodups", buf, CCAST(const char **, &next))) {
2064       set_dups(FALSE);
2065       buf = next;
2066     } else if (__kmp_match_str("granularity", buf,
2067                                CCAST(const char **, &next)) ||
2068                __kmp_match_str("gran", buf, CCAST(const char **, &next))) {
2069       SKIP_WS(next);
2070       if (*next != '=') {
2071         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2072         continue;
2073       }
2074       next++; // skip '='
2075       SKIP_WS(next);
2076 
2077       buf = next;
2078       if (__kmp_match_str("fine", buf, CCAST(const char **, &next))) {
2079         set_gran(affinity_gran_fine, -1);
2080         buf = next;
2081       } else if (__kmp_match_str("thread", buf, CCAST(const char **, &next))) {
2082         set_gran(affinity_gran_thread, -1);
2083         buf = next;
2084       } else if (__kmp_match_str("core", buf, CCAST(const char **, &next))) {
2085         set_gran(affinity_gran_core, -1);
2086         buf = next;
2087       } else if (__kmp_match_str("package", buf, CCAST(const char **, &next))) {
2088         set_gran(affinity_gran_package, -1);
2089         buf = next;
2090       } else if (__kmp_match_str("node", buf, CCAST(const char **, &next))) {
2091         set_gran(affinity_gran_node, -1);
2092         buf = next;
2093 #if KMP_GROUP_AFFINITY
2094       } else if (__kmp_match_str("group", buf, CCAST(const char **, &next))) {
2095         set_gran(affinity_gran_group, -1);
2096         buf = next;
2097 #endif /* KMP_GROUP AFFINITY */
2098       } else if ((*buf >= '0') && (*buf <= '9')) {
2099         int n;
2100         next = buf;
2101         SKIP_DIGITS(next);
2102         n = __kmp_str_to_int(buf, *next);
2103         KMP_ASSERT(n >= 0);
2104         buf = next;
2105         set_gran(affinity_gran_default, n);
2106       } else {
2107         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2108         continue;
2109       }
2110     } else if (__kmp_match_str("proclist", buf, CCAST(const char **, &next))) {
2111       char *temp_proclist;
2112 
2113       SKIP_WS(next);
2114       if (*next != '=') {
2115         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2116         continue;
2117       }
2118       next++; // skip '='
2119       SKIP_WS(next);
2120       if (*next != '[') {
2121         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2122         continue;
2123       }
2124       next++; // skip '['
2125       buf = next;
2126       if (!__kmp_parse_affinity_proc_id_list(
2127               name, buf, CCAST(const char **, &next), &temp_proclist)) {
2128         // warning already emitted.
2129         SKIP_TO(next, ']');
2130         if (*next == ']')
2131           next++;
2132         SKIP_TO(next, ',');
2133         if (*next == ',')
2134           next++;
2135         buf = next;
2136         continue;
2137       }
2138       if (*next != ']') {
2139         EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2140         continue;
2141       }
2142       next++; // skip ']'
2143       set_proclist(temp_proclist);
2144     } else if ((*buf >= '0') && (*buf <= '9')) {
2145       // Parse integer numbers -- permute and offset.
2146       int n;
2147       next = buf;
2148       SKIP_DIGITS(next);
2149       n = __kmp_str_to_int(buf, *next);
2150       KMP_ASSERT(n >= 0);
2151       buf = next;
2152       if (count < 2) {
2153         number[count] = n;
2154       } else {
2155         KMP_WARNING(AffManyParams, name, start);
2156       }
2157       ++count;
2158     } else {
2159       EMIT_WARN(TRUE, (AffInvalidParam, name, start));
2160       continue;
2161     }
2162 
2163     SKIP_WS(next);
2164     if (*next == ',') {
2165       next++;
2166       SKIP_WS(next);
2167     } else if (*next != '\0') {
2168       const char *temp = next;
2169       EMIT_WARN(TRUE, (ParseExtraCharsWarn, name, temp));
2170       continue;
2171     }
2172     buf = next;
2173   } // while
2174 
2175 #undef EMIT_WARN
2176 #undef _set_param
2177 #undef set_type
2178 #undef set_verbose
2179 #undef set_warnings
2180 #undef set_respect
2181 #undef set_granularity
2182 
2183   __kmp_str_free(&buffer);
2184 
2185   if (proclist) {
2186     if (!type) {
2187       KMP_WARNING(AffProcListNoType, name);
2188       *out_type = affinity_explicit;
2189 #if OMP_40_ENABLED
2190       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2191 #endif
2192     } else if (*out_type != affinity_explicit) {
2193       KMP_WARNING(AffProcListNotExplicit, name);
2194       KMP_ASSERT(*out_proclist != NULL);
2195       KMP_INTERNAL_FREE(*out_proclist);
2196       *out_proclist = NULL;
2197     }
2198   }
2199   switch (*out_type) {
2200   case affinity_logical:
2201   case affinity_physical: {
2202     if (count > 0) {
2203       *out_offset = number[0];
2204     }
2205     if (count > 1) {
2206       KMP_WARNING(AffManyParamsForLogic, name, number[1]);
2207     }
2208   } break;
2209   case affinity_balanced: {
2210     if (count > 0) {
2211       *out_compact = number[0];
2212     }
2213     if (count > 1) {
2214       *out_offset = number[1];
2215     }
2216 
2217     if (__kmp_affinity_gran == affinity_gran_default) {
2218 #if KMP_MIC_SUPPORTED
2219       if (__kmp_mic_type != non_mic) {
2220         if (__kmp_affinity_verbose || __kmp_affinity_warnings) {
2221           KMP_WARNING(AffGranUsing, "KMP_AFFINITY", "fine");
2222         }
2223         __kmp_affinity_gran = affinity_gran_fine;
2224       } else
2225 #endif
2226       {
2227         if (__kmp_affinity_verbose || __kmp_affinity_warnings) {
2228           KMP_WARNING(AffGranUsing, "KMP_AFFINITY", "core");
2229         }
2230         __kmp_affinity_gran = affinity_gran_core;
2231       }
2232     }
2233   } break;
2234   case affinity_scatter:
2235   case affinity_compact: {
2236     if (count > 0) {
2237       *out_compact = number[0];
2238     }
2239     if (count > 1) {
2240       *out_offset = number[1];
2241     }
2242   } break;
2243   case affinity_explicit: {
2244     if (*out_proclist == NULL) {
2245       KMP_WARNING(AffNoProcList, name);
2246       __kmp_affinity_type = affinity_none;
2247     }
2248     if (count > 0) {
2249       KMP_WARNING(AffNoParam, name, "explicit");
2250     }
2251   } break;
2252   case affinity_none: {
2253     if (count > 0) {
2254       KMP_WARNING(AffNoParam, name, "none");
2255     }
2256   } break;
2257   case affinity_disabled: {
2258     if (count > 0) {
2259       KMP_WARNING(AffNoParam, name, "disabled");
2260     }
2261   } break;
2262   case affinity_default: {
2263     if (count > 0) {
2264       KMP_WARNING(AffNoParam, name, "default");
2265     }
2266   } break;
2267   default: { KMP_ASSERT(0); }
2268   }
2269 } // __kmp_parse_affinity_env
2270 
2271 static void __kmp_stg_parse_affinity(char const *name, char const *value,
2272                                      void *data) {
2273   kmp_setting_t **rivals = (kmp_setting_t **)data;
2274   int rc;
2275 
2276   rc = __kmp_stg_check_rivals(name, value, rivals);
2277   if (rc) {
2278     return;
2279   }
2280 
2281   __kmp_parse_affinity_env(name, value, &__kmp_affinity_type,
2282                            &__kmp_affinity_proclist, &__kmp_affinity_verbose,
2283                            &__kmp_affinity_warnings,
2284                            &__kmp_affinity_respect_mask, &__kmp_affinity_gran,
2285                            &__kmp_affinity_gran_levels, &__kmp_affinity_dups,
2286                            &__kmp_affinity_compact, &__kmp_affinity_offset);
2287 
2288 } // __kmp_stg_parse_affinity
2289 
2290 static void __kmp_stg_print_affinity(kmp_str_buf_t *buffer, char const *name,
2291                                      void *data) {
2292   if (__kmp_env_format) {
2293     KMP_STR_BUF_PRINT_NAME_EX(name);
2294   } else {
2295     __kmp_str_buf_print(buffer, "   %s='", name);
2296   }
2297   if (__kmp_affinity_verbose) {
2298     __kmp_str_buf_print(buffer, "%s,", "verbose");
2299   } else {
2300     __kmp_str_buf_print(buffer, "%s,", "noverbose");
2301   }
2302   if (__kmp_affinity_warnings) {
2303     __kmp_str_buf_print(buffer, "%s,", "warnings");
2304   } else {
2305     __kmp_str_buf_print(buffer, "%s,", "nowarnings");
2306   }
2307   if (KMP_AFFINITY_CAPABLE()) {
2308     if (__kmp_affinity_respect_mask) {
2309       __kmp_str_buf_print(buffer, "%s,", "respect");
2310     } else {
2311       __kmp_str_buf_print(buffer, "%s,", "norespect");
2312     }
2313     switch (__kmp_affinity_gran) {
2314     case affinity_gran_default:
2315       __kmp_str_buf_print(buffer, "%s", "granularity=default,");
2316       break;
2317     case affinity_gran_fine:
2318       __kmp_str_buf_print(buffer, "%s", "granularity=fine,");
2319       break;
2320     case affinity_gran_thread:
2321       __kmp_str_buf_print(buffer, "%s", "granularity=thread,");
2322       break;
2323     case affinity_gran_core:
2324       __kmp_str_buf_print(buffer, "%s", "granularity=core,");
2325       break;
2326     case affinity_gran_package:
2327       __kmp_str_buf_print(buffer, "%s", "granularity=package,");
2328       break;
2329     case affinity_gran_node:
2330       __kmp_str_buf_print(buffer, "%s", "granularity=node,");
2331       break;
2332 #if KMP_GROUP_AFFINITY
2333     case affinity_gran_group:
2334       __kmp_str_buf_print(buffer, "%s", "granularity=group,");
2335       break;
2336 #endif /* KMP_GROUP_AFFINITY */
2337     }
2338   }
2339   if (!KMP_AFFINITY_CAPABLE()) {
2340     __kmp_str_buf_print(buffer, "%s", "disabled");
2341   } else
2342     switch (__kmp_affinity_type) {
2343     case affinity_none:
2344       __kmp_str_buf_print(buffer, "%s", "none");
2345       break;
2346     case affinity_physical:
2347       __kmp_str_buf_print(buffer, "%s,%d", "physical", __kmp_affinity_offset);
2348       break;
2349     case affinity_logical:
2350       __kmp_str_buf_print(buffer, "%s,%d", "logical", __kmp_affinity_offset);
2351       break;
2352     case affinity_compact:
2353       __kmp_str_buf_print(buffer, "%s,%d,%d", "compact", __kmp_affinity_compact,
2354                           __kmp_affinity_offset);
2355       break;
2356     case affinity_scatter:
2357       __kmp_str_buf_print(buffer, "%s,%d,%d", "scatter", __kmp_affinity_compact,
2358                           __kmp_affinity_offset);
2359       break;
2360     case affinity_explicit:
2361       __kmp_str_buf_print(buffer, "%s=[%s],%s", "proclist",
2362                           __kmp_affinity_proclist, "explicit");
2363       break;
2364     case affinity_balanced:
2365       __kmp_str_buf_print(buffer, "%s,%d,%d", "balanced",
2366                           __kmp_affinity_compact, __kmp_affinity_offset);
2367       break;
2368     case affinity_disabled:
2369       __kmp_str_buf_print(buffer, "%s", "disabled");
2370       break;
2371     case affinity_default:
2372       __kmp_str_buf_print(buffer, "%s", "default");
2373       break;
2374     default:
2375       __kmp_str_buf_print(buffer, "%s", "<unknown>");
2376       break;
2377     }
2378   __kmp_str_buf_print(buffer, "'\n");
2379 } //__kmp_stg_print_affinity
2380 
2381 #ifdef KMP_GOMP_COMPAT
2382 
2383 static void __kmp_stg_parse_gomp_cpu_affinity(char const *name,
2384                                               char const *value, void *data) {
2385   const char *next = NULL;
2386   char *temp_proclist;
2387   kmp_setting_t **rivals = (kmp_setting_t **)data;
2388   int rc;
2389 
2390   rc = __kmp_stg_check_rivals(name, value, rivals);
2391   if (rc) {
2392     return;
2393   }
2394 
2395   if (TCR_4(__kmp_init_middle)) {
2396     KMP_WARNING(EnvMiddleWarn, name);
2397     __kmp_env_toPrint(name, 0);
2398     return;
2399   }
2400 
2401   __kmp_env_toPrint(name, 1);
2402 
2403   if (__kmp_parse_affinity_proc_id_list(name, value, &next, &temp_proclist)) {
2404     SKIP_WS(next);
2405     if (*next == '\0') {
2406       // GOMP_CPU_AFFINITY => granularity=fine,explicit,proclist=...
2407       __kmp_affinity_proclist = temp_proclist;
2408       __kmp_affinity_type = affinity_explicit;
2409       __kmp_affinity_gran = affinity_gran_fine;
2410 #if OMP_40_ENABLED
2411       __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
2412 #endif
2413     } else {
2414       KMP_WARNING(AffSyntaxError, name);
2415       if (temp_proclist != NULL) {
2416         KMP_INTERNAL_FREE((void *)temp_proclist);
2417       }
2418     }
2419   } else {
2420     // Warning already emitted
2421     __kmp_affinity_type = affinity_none;
2422 #if OMP_40_ENABLED
2423     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
2424 #endif
2425   }
2426 } // __kmp_stg_parse_gomp_cpu_affinity
2427 
2428 #endif /* KMP_GOMP_COMPAT */
2429 
2430 #if OMP_40_ENABLED
2431 
2432 /*-----------------------------------------------------------------------------
2433 The OMP_PLACES proc id list parser. Here is the grammar:
2434 
2435 place_list := place
2436 place_list := place , place_list
2437 place := num
2438 place := place : num
2439 place := place : num : signed
2440 place := { subplacelist }
2441 place := ! place                  // (lowest priority)
2442 subplace_list := subplace
2443 subplace_list := subplace , subplace_list
2444 subplace := num
2445 subplace := num : num
2446 subplace := num : num : signed
2447 signed := num
2448 signed := + signed
2449 signed := - signed
2450 -----------------------------------------------------------------------------*/
2451 
2452 static int __kmp_parse_subplace_list(const char *var, const char **scan) {
2453   const char *next;
2454 
2455   for (;;) {
2456     int start, count, stride;
2457 
2458     //
2459     // Read in the starting proc id
2460     //
2461     SKIP_WS(*scan);
2462     if ((**scan < '0') || (**scan > '9')) {
2463       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2464       return FALSE;
2465     }
2466     next = *scan;
2467     SKIP_DIGITS(next);
2468     start = __kmp_str_to_int(*scan, *next);
2469     KMP_ASSERT(start >= 0);
2470     *scan = next;
2471 
2472     // valid follow sets are ',' ':' and '}'
2473     SKIP_WS(*scan);
2474     if (**scan == '}') {
2475       break;
2476     }
2477     if (**scan == ',') {
2478       (*scan)++; // skip ','
2479       continue;
2480     }
2481     if (**scan != ':') {
2482       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2483       return FALSE;
2484     }
2485     (*scan)++; // skip ':'
2486 
2487     // Read count parameter
2488     SKIP_WS(*scan);
2489     if ((**scan < '0') || (**scan > '9')) {
2490       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2491       return FALSE;
2492     }
2493     next = *scan;
2494     SKIP_DIGITS(next);
2495     count = __kmp_str_to_int(*scan, *next);
2496     KMP_ASSERT(count >= 0);
2497     *scan = next;
2498 
2499     // valid follow sets are ',' ':' and '}'
2500     SKIP_WS(*scan);
2501     if (**scan == '}') {
2502       break;
2503     }
2504     if (**scan == ',') {
2505       (*scan)++; // skip ','
2506       continue;
2507     }
2508     if (**scan != ':') {
2509       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2510       return FALSE;
2511     }
2512     (*scan)++; // skip ':'
2513 
2514     // Read stride parameter
2515     int sign = +1;
2516     for (;;) {
2517       SKIP_WS(*scan);
2518       if (**scan == '+') {
2519         (*scan)++; // skip '+'
2520         continue;
2521       }
2522       if (**scan == '-') {
2523         sign *= -1;
2524         (*scan)++; // skip '-'
2525         continue;
2526       }
2527       break;
2528     }
2529     SKIP_WS(*scan);
2530     if ((**scan < '0') || (**scan > '9')) {
2531       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2532       return FALSE;
2533     }
2534     next = *scan;
2535     SKIP_DIGITS(next);
2536     stride = __kmp_str_to_int(*scan, *next);
2537     KMP_ASSERT(stride >= 0);
2538     *scan = next;
2539     stride *= sign;
2540 
2541     // valid follow sets are ',' and '}'
2542     SKIP_WS(*scan);
2543     if (**scan == '}') {
2544       break;
2545     }
2546     if (**scan == ',') {
2547       (*scan)++; // skip ','
2548       continue;
2549     }
2550 
2551     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2552     return FALSE;
2553   }
2554   return TRUE;
2555 }
2556 
2557 static int __kmp_parse_place(const char *var, const char **scan) {
2558   const char *next;
2559 
2560   // valid follow sets are '{' '!' and num
2561   SKIP_WS(*scan);
2562   if (**scan == '{') {
2563     (*scan)++; // skip '{'
2564     if (!__kmp_parse_subplace_list(var, scan)) {
2565       return FALSE;
2566     }
2567     if (**scan != '}') {
2568       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2569       return FALSE;
2570     }
2571     (*scan)++; // skip '}'
2572   } else if (**scan == '!') {
2573     (*scan)++; // skip '!'
2574     return __kmp_parse_place(var, scan); //'!' has lower precedence than ':'
2575   } else if ((**scan >= '0') && (**scan <= '9')) {
2576     next = *scan;
2577     SKIP_DIGITS(next);
2578     int proc = __kmp_str_to_int(*scan, *next);
2579     KMP_ASSERT(proc >= 0);
2580     *scan = next;
2581   } else {
2582     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2583     return FALSE;
2584   }
2585   return TRUE;
2586 }
2587 
2588 static int __kmp_parse_place_list(const char *var, const char *env,
2589                                   char **place_list) {
2590   const char *scan = env;
2591   const char *next = scan;
2592 
2593   for (;;) {
2594     int start, count, stride;
2595 
2596     if (!__kmp_parse_place(var, &scan)) {
2597       return FALSE;
2598     }
2599 
2600     // valid follow sets are ',' ':' and EOL
2601     SKIP_WS(scan);
2602     if (*scan == '\0') {
2603       break;
2604     }
2605     if (*scan == ',') {
2606       scan++; // skip ','
2607       continue;
2608     }
2609     if (*scan != ':') {
2610       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2611       return FALSE;
2612     }
2613     scan++; // skip ':'
2614 
2615     // Read count parameter
2616     SKIP_WS(scan);
2617     if ((*scan < '0') || (*scan > '9')) {
2618       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2619       return FALSE;
2620     }
2621     next = scan;
2622     SKIP_DIGITS(next);
2623     count = __kmp_str_to_int(scan, *next);
2624     KMP_ASSERT(count >= 0);
2625     scan = next;
2626 
2627     // valid follow sets are ',' ':' and EOL
2628     SKIP_WS(scan);
2629     if (*scan == '\0') {
2630       break;
2631     }
2632     if (*scan == ',') {
2633       scan++; // skip ','
2634       continue;
2635     }
2636     if (*scan != ':') {
2637       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2638       return FALSE;
2639     }
2640     scan++; // skip ':'
2641 
2642     // Read stride parameter
2643     int sign = +1;
2644     for (;;) {
2645       SKIP_WS(scan);
2646       if (*scan == '+') {
2647         scan++; // skip '+'
2648         continue;
2649       }
2650       if (*scan == '-') {
2651         sign *= -1;
2652         scan++; // skip '-'
2653         continue;
2654       }
2655       break;
2656     }
2657     SKIP_WS(scan);
2658     if ((*scan < '0') || (*scan > '9')) {
2659       KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2660       return FALSE;
2661     }
2662     next = scan;
2663     SKIP_DIGITS(next);
2664     stride = __kmp_str_to_int(scan, *next);
2665     KMP_ASSERT(stride >= 0);
2666     scan = next;
2667     stride *= sign;
2668 
2669     // valid follow sets are ',' and EOL
2670     SKIP_WS(scan);
2671     if (*scan == '\0') {
2672       break;
2673     }
2674     if (*scan == ',') {
2675       scan++; // skip ','
2676       continue;
2677     }
2678 
2679     KMP_WARNING(SyntaxErrorUsing, var, "\"threads\"");
2680     return FALSE;
2681   }
2682 
2683   {
2684     int len = scan - env;
2685     char *retlist = (char *)__kmp_allocate((len + 1) * sizeof(char));
2686     KMP_MEMCPY_S(retlist, (len + 1) * sizeof(char), env, len * sizeof(char));
2687     retlist[len] = '\0';
2688     *place_list = retlist;
2689   }
2690   return TRUE;
2691 }
2692 
2693 static void __kmp_stg_parse_places(char const *name, char const *value,
2694                                    void *data) {
2695   int count;
2696   const char *scan = value;
2697   const char *next = scan;
2698   const char *kind = "\"threads\"";
2699   kmp_setting_t **rivals = (kmp_setting_t **)data;
2700   int rc;
2701 
2702   rc = __kmp_stg_check_rivals(name, value, rivals);
2703   if (rc) {
2704     return;
2705   }
2706 
2707   // If OMP_PROC_BIND is not specified but OMP_PLACES is,
2708   // then let OMP_PROC_BIND default to true.
2709   if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2710     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2711   }
2712 
2713   //__kmp_affinity_num_places = 0;
2714 
2715   if (__kmp_match_str("threads", scan, &next)) {
2716     scan = next;
2717     __kmp_affinity_type = affinity_compact;
2718     __kmp_affinity_gran = affinity_gran_thread;
2719     __kmp_affinity_dups = FALSE;
2720     kind = "\"threads\"";
2721   } else if (__kmp_match_str("cores", scan, &next)) {
2722     scan = next;
2723     __kmp_affinity_type = affinity_compact;
2724     __kmp_affinity_gran = affinity_gran_core;
2725     __kmp_affinity_dups = FALSE;
2726     kind = "\"cores\"";
2727   } else if (__kmp_match_str("sockets", scan, &next)) {
2728     scan = next;
2729     __kmp_affinity_type = affinity_compact;
2730     __kmp_affinity_gran = affinity_gran_package;
2731     __kmp_affinity_dups = FALSE;
2732     kind = "\"sockets\"";
2733   } else {
2734     if (__kmp_affinity_proclist != NULL) {
2735       KMP_INTERNAL_FREE((void *)__kmp_affinity_proclist);
2736       __kmp_affinity_proclist = NULL;
2737     }
2738     if (__kmp_parse_place_list(name, value, &__kmp_affinity_proclist)) {
2739       __kmp_affinity_type = affinity_explicit;
2740       __kmp_affinity_gran = affinity_gran_fine;
2741       __kmp_affinity_dups = FALSE;
2742       if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2743         __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2744       }
2745     }
2746     return;
2747   }
2748 
2749   if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default) {
2750     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
2751   }
2752 
2753   SKIP_WS(scan);
2754   if (*scan == '\0') {
2755     return;
2756   }
2757 
2758   // Parse option count parameter in parentheses
2759   if (*scan != '(') {
2760     KMP_WARNING(SyntaxErrorUsing, name, kind);
2761     return;
2762   }
2763   scan++; // skip '('
2764 
2765   SKIP_WS(scan);
2766   next = scan;
2767   SKIP_DIGITS(next);
2768   count = __kmp_str_to_int(scan, *next);
2769   KMP_ASSERT(count >= 0);
2770   scan = next;
2771 
2772   SKIP_WS(scan);
2773   if (*scan != ')') {
2774     KMP_WARNING(SyntaxErrorUsing, name, kind);
2775     return;
2776   }
2777   scan++; // skip ')'
2778 
2779   SKIP_WS(scan);
2780   if (*scan != '\0') {
2781     KMP_WARNING(ParseExtraCharsWarn, name, scan);
2782   }
2783   __kmp_affinity_num_places = count;
2784 }
2785 
2786 static void __kmp_stg_print_places(kmp_str_buf_t *buffer, char const *name,
2787                                    void *data) {
2788   if (__kmp_env_format) {
2789     KMP_STR_BUF_PRINT_NAME;
2790   } else {
2791     __kmp_str_buf_print(buffer, "   %s", name);
2792   }
2793   if ((__kmp_nested_proc_bind.used == 0) ||
2794       (__kmp_nested_proc_bind.bind_types == NULL) ||
2795       (__kmp_nested_proc_bind.bind_types[0] == proc_bind_false)) {
2796     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2797   } else if (__kmp_affinity_type == affinity_explicit) {
2798     if (__kmp_affinity_proclist != NULL) {
2799       __kmp_str_buf_print(buffer, "='%s'\n", __kmp_affinity_proclist);
2800     } else {
2801       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2802     }
2803   } else if (__kmp_affinity_type == affinity_compact) {
2804     int num;
2805     if (__kmp_affinity_num_masks > 0) {
2806       num = __kmp_affinity_num_masks;
2807     } else if (__kmp_affinity_num_places > 0) {
2808       num = __kmp_affinity_num_places;
2809     } else {
2810       num = 0;
2811     }
2812     if (__kmp_affinity_gran == affinity_gran_thread) {
2813       if (num > 0) {
2814         __kmp_str_buf_print(buffer, "='threads(%d)'\n", num);
2815       } else {
2816         __kmp_str_buf_print(buffer, "='threads'\n");
2817       }
2818     } else if (__kmp_affinity_gran == affinity_gran_core) {
2819       if (num > 0) {
2820         __kmp_str_buf_print(buffer, "='cores(%d)' \n", num);
2821       } else {
2822         __kmp_str_buf_print(buffer, "='cores'\n");
2823       }
2824     } else if (__kmp_affinity_gran == affinity_gran_package) {
2825       if (num > 0) {
2826         __kmp_str_buf_print(buffer, "='sockets(%d)'\n", num);
2827       } else {
2828         __kmp_str_buf_print(buffer, "='sockets'\n");
2829       }
2830     } else {
2831       __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2832     }
2833   } else {
2834     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
2835   }
2836 }
2837 
2838 #endif /* OMP_40_ENABLED */
2839 
2840 #if (!OMP_40_ENABLED)
2841 
2842 static void __kmp_stg_parse_proc_bind(char const *name, char const *value,
2843                                       void *data) {
2844   int enabled;
2845   kmp_setting_t **rivals = (kmp_setting_t **)data;
2846   int rc;
2847 
2848   rc = __kmp_stg_check_rivals(name, value, rivals);
2849   if (rc) {
2850     return;
2851   }
2852 
2853   // In OMP 3.1, OMP_PROC_BIND is strictly a boolean
2854   __kmp_stg_parse_bool(name, value, &enabled);
2855   if (enabled) {
2856     // OMP_PROC_BIND => granularity=fine,scatter on MIC
2857     // OMP_PROC_BIND => granularity=core,scatter elsewhere
2858     __kmp_affinity_type = affinity_scatter;
2859 #if KMP_MIC_SUPPORTED
2860     if (__kmp_mic_type != non_mic)
2861       __kmp_affinity_gran = affinity_gran_fine;
2862     else
2863 #endif
2864       __kmp_affinity_gran = affinity_gran_core;
2865   } else {
2866     __kmp_affinity_type = affinity_none;
2867   }
2868 } // __kmp_parse_proc_bind
2869 
2870 #endif /* if (! OMP_40_ENABLED) */
2871 
2872 static void __kmp_stg_parse_topology_method(char const *name, char const *value,
2873                                             void *data) {
2874   if (__kmp_str_match("all", 1, value)) {
2875     __kmp_affinity_top_method = affinity_top_method_all;
2876   }
2877 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
2878   else if (__kmp_str_match("x2apic id", 9, value) ||
2879            __kmp_str_match("x2apic_id", 9, value) ||
2880            __kmp_str_match("x2apic-id", 9, value) ||
2881            __kmp_str_match("x2apicid", 8, value) ||
2882            __kmp_str_match("cpuid leaf 11", 13, value) ||
2883            __kmp_str_match("cpuid_leaf_11", 13, value) ||
2884            __kmp_str_match("cpuid-leaf-11", 13, value) ||
2885            __kmp_str_match("cpuid leaf11", 12, value) ||
2886            __kmp_str_match("cpuid_leaf11", 12, value) ||
2887            __kmp_str_match("cpuid-leaf11", 12, value) ||
2888            __kmp_str_match("cpuidleaf 11", 12, value) ||
2889            __kmp_str_match("cpuidleaf_11", 12, value) ||
2890            __kmp_str_match("cpuidleaf-11", 12, value) ||
2891            __kmp_str_match("cpuidleaf11", 11, value) ||
2892            __kmp_str_match("cpuid 11", 8, value) ||
2893            __kmp_str_match("cpuid_11", 8, value) ||
2894            __kmp_str_match("cpuid-11", 8, value) ||
2895            __kmp_str_match("cpuid11", 7, value) ||
2896            __kmp_str_match("leaf 11", 7, value) ||
2897            __kmp_str_match("leaf_11", 7, value) ||
2898            __kmp_str_match("leaf-11", 7, value) ||
2899            __kmp_str_match("leaf11", 6, value)) {
2900     __kmp_affinity_top_method = affinity_top_method_x2apicid;
2901   } else if (__kmp_str_match("apic id", 7, value) ||
2902              __kmp_str_match("apic_id", 7, value) ||
2903              __kmp_str_match("apic-id", 7, value) ||
2904              __kmp_str_match("apicid", 6, value) ||
2905              __kmp_str_match("cpuid leaf 4", 12, value) ||
2906              __kmp_str_match("cpuid_leaf_4", 12, value) ||
2907              __kmp_str_match("cpuid-leaf-4", 12, value) ||
2908              __kmp_str_match("cpuid leaf4", 11, value) ||
2909              __kmp_str_match("cpuid_leaf4", 11, value) ||
2910              __kmp_str_match("cpuid-leaf4", 11, value) ||
2911              __kmp_str_match("cpuidleaf 4", 11, value) ||
2912              __kmp_str_match("cpuidleaf_4", 11, value) ||
2913              __kmp_str_match("cpuidleaf-4", 11, value) ||
2914              __kmp_str_match("cpuidleaf4", 10, value) ||
2915              __kmp_str_match("cpuid 4", 7, value) ||
2916              __kmp_str_match("cpuid_4", 7, value) ||
2917              __kmp_str_match("cpuid-4", 7, value) ||
2918              __kmp_str_match("cpuid4", 6, value) ||
2919              __kmp_str_match("leaf 4", 6, value) ||
2920              __kmp_str_match("leaf_4", 6, value) ||
2921              __kmp_str_match("leaf-4", 6, value) ||
2922              __kmp_str_match("leaf4", 5, value)) {
2923     __kmp_affinity_top_method = affinity_top_method_apicid;
2924   }
2925 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
2926   else if (__kmp_str_match("/proc/cpuinfo", 2, value) ||
2927            __kmp_str_match("cpuinfo", 5, value)) {
2928     __kmp_affinity_top_method = affinity_top_method_cpuinfo;
2929   }
2930 #if KMP_GROUP_AFFINITY
2931   else if (__kmp_str_match("group", 1, value)) {
2932     __kmp_affinity_top_method = affinity_top_method_group;
2933   }
2934 #endif /* KMP_GROUP_AFFINITY */
2935   else if (__kmp_str_match("flat", 1, value)) {
2936     __kmp_affinity_top_method = affinity_top_method_flat;
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   else {
2944     KMP_WARNING(StgInvalidValue, name, value);
2945   }
2946 } // __kmp_stg_parse_topology_method
2947 
2948 static void __kmp_stg_print_topology_method(kmp_str_buf_t *buffer,
2949                                             char const *name, void *data) {
2950   char const *value = NULL;
2951 
2952   switch (__kmp_affinity_top_method) {
2953   case affinity_top_method_default:
2954     value = "default";
2955     break;
2956 
2957   case affinity_top_method_all:
2958     value = "all";
2959     break;
2960 
2961 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
2962   case affinity_top_method_x2apicid:
2963     value = "x2APIC id";
2964     break;
2965 
2966   case affinity_top_method_apicid:
2967     value = "APIC id";
2968     break;
2969 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
2970 
2971 #if KMP_USE_HWLOC
2972   case affinity_top_method_hwloc:
2973     value = "hwloc";
2974     break;
2975 #endif
2976 
2977   case affinity_top_method_cpuinfo:
2978     value = "cpuinfo";
2979     break;
2980 
2981 #if KMP_GROUP_AFFINITY
2982   case affinity_top_method_group:
2983     value = "group";
2984     break;
2985 #endif /* KMP_GROUP_AFFINITY */
2986 
2987   case affinity_top_method_flat:
2988     value = "flat";
2989     break;
2990   }
2991 
2992   if (value != NULL) {
2993     __kmp_stg_print_str(buffer, name, value);
2994   }
2995 } // __kmp_stg_print_topology_method
2996 
2997 #endif /* KMP_AFFINITY_SUPPORTED */
2998 
2999 #if OMP_40_ENABLED
3000 
3001 // OMP_PROC_BIND / bind-var is functional on all 4.0 builds, including OS X*
3002 // OMP_PLACES / place-partition-var is not.
3003 static void __kmp_stg_parse_proc_bind(char const *name, char const *value,
3004                                       void *data) {
3005   kmp_setting_t **rivals = (kmp_setting_t **)data;
3006   int rc;
3007 
3008   rc = __kmp_stg_check_rivals(name, value, rivals);
3009   if (rc) {
3010     return;
3011   }
3012 
3013   // In OMP 4.0 OMP_PROC_BIND is a vector of proc_bind types.
3014   KMP_DEBUG_ASSERT((__kmp_nested_proc_bind.bind_types != NULL) &&
3015                    (__kmp_nested_proc_bind.used > 0));
3016 
3017   const char *buf = value;
3018   const char *next;
3019   int num;
3020   SKIP_WS(buf);
3021   if ((*buf >= '0') && (*buf <= '9')) {
3022     next = buf;
3023     SKIP_DIGITS(next);
3024     num = __kmp_str_to_int(buf, *next);
3025     KMP_ASSERT(num >= 0);
3026     buf = next;
3027     SKIP_WS(buf);
3028   } else {
3029     num = -1;
3030   }
3031 
3032   next = buf;
3033   if (__kmp_match_str("disabled", buf, &next)) {
3034     buf = next;
3035     SKIP_WS(buf);
3036 #if KMP_AFFINITY_SUPPORTED
3037     __kmp_affinity_type = affinity_disabled;
3038 #endif /* KMP_AFFINITY_SUPPORTED */
3039     __kmp_nested_proc_bind.used = 1;
3040     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3041   } else if ((num == (int)proc_bind_false) ||
3042              __kmp_match_str("false", buf, &next)) {
3043     buf = next;
3044     SKIP_WS(buf);
3045 #if KMP_AFFINITY_SUPPORTED
3046     __kmp_affinity_type = affinity_none;
3047 #endif /* KMP_AFFINITY_SUPPORTED */
3048     __kmp_nested_proc_bind.used = 1;
3049     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3050   } else if ((num == (int)proc_bind_true) ||
3051              __kmp_match_str("true", buf, &next)) {
3052     buf = next;
3053     SKIP_WS(buf);
3054     __kmp_nested_proc_bind.used = 1;
3055     __kmp_nested_proc_bind.bind_types[0] = proc_bind_true;
3056   } else {
3057     // Count the number of values in the env var string
3058     const char *scan;
3059     int nelem = 1;
3060     for (scan = buf; *scan != '\0'; scan++) {
3061       if (*scan == ',') {
3062         nelem++;
3063       }
3064     }
3065 
3066     // Create / expand the nested proc_bind array as needed
3067     if (__kmp_nested_proc_bind.size < nelem) {
3068       __kmp_nested_proc_bind.bind_types =
3069           (kmp_proc_bind_t *)KMP_INTERNAL_REALLOC(
3070               __kmp_nested_proc_bind.bind_types,
3071               sizeof(kmp_proc_bind_t) * nelem);
3072       if (__kmp_nested_proc_bind.bind_types == NULL) {
3073         KMP_FATAL(MemoryAllocFailed);
3074       }
3075       __kmp_nested_proc_bind.size = nelem;
3076     }
3077     __kmp_nested_proc_bind.used = nelem;
3078 
3079     // Save values in the nested proc_bind array
3080     int i = 0;
3081     for (;;) {
3082       enum kmp_proc_bind_t bind;
3083 
3084       if ((num == (int)proc_bind_master) ||
3085           __kmp_match_str("master", buf, &next)) {
3086         buf = next;
3087         SKIP_WS(buf);
3088         bind = proc_bind_master;
3089       } else if ((num == (int)proc_bind_close) ||
3090                  __kmp_match_str("close", buf, &next)) {
3091         buf = next;
3092         SKIP_WS(buf);
3093         bind = proc_bind_close;
3094       } else if ((num == (int)proc_bind_spread) ||
3095                  __kmp_match_str("spread", buf, &next)) {
3096         buf = next;
3097         SKIP_WS(buf);
3098         bind = proc_bind_spread;
3099       } else {
3100         KMP_WARNING(StgInvalidValue, name, value);
3101         __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
3102         __kmp_nested_proc_bind.used = 1;
3103         return;
3104       }
3105 
3106       __kmp_nested_proc_bind.bind_types[i++] = bind;
3107       if (i >= nelem) {
3108         break;
3109       }
3110       KMP_DEBUG_ASSERT(*buf == ',');
3111       buf++;
3112       SKIP_WS(buf);
3113 
3114       // Read next value if it was specified as an integer
3115       if ((*buf >= '0') && (*buf <= '9')) {
3116         next = buf;
3117         SKIP_DIGITS(next);
3118         num = __kmp_str_to_int(buf, *next);
3119         KMP_ASSERT(num >= 0);
3120         buf = next;
3121         SKIP_WS(buf);
3122       } else {
3123         num = -1;
3124       }
3125     }
3126     SKIP_WS(buf);
3127   }
3128   if (*buf != '\0') {
3129     KMP_WARNING(ParseExtraCharsWarn, name, buf);
3130   }
3131 }
3132 
3133 static void __kmp_stg_print_proc_bind(kmp_str_buf_t *buffer, char const *name,
3134                                       void *data) {
3135   int nelem = __kmp_nested_proc_bind.used;
3136   if (__kmp_env_format) {
3137     KMP_STR_BUF_PRINT_NAME;
3138   } else {
3139     __kmp_str_buf_print(buffer, "   %s", name);
3140   }
3141   if (nelem == 0) {
3142     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
3143   } else {
3144     int i;
3145     __kmp_str_buf_print(buffer, "='", name);
3146     for (i = 0; i < nelem; i++) {
3147       switch (__kmp_nested_proc_bind.bind_types[i]) {
3148       case proc_bind_false:
3149         __kmp_str_buf_print(buffer, "false");
3150         break;
3151 
3152       case proc_bind_true:
3153         __kmp_str_buf_print(buffer, "true");
3154         break;
3155 
3156       case proc_bind_master:
3157         __kmp_str_buf_print(buffer, "master");
3158         break;
3159 
3160       case proc_bind_close:
3161         __kmp_str_buf_print(buffer, "close");
3162         break;
3163 
3164       case proc_bind_spread:
3165         __kmp_str_buf_print(buffer, "spread");
3166         break;
3167 
3168       case proc_bind_intel:
3169         __kmp_str_buf_print(buffer, "intel");
3170         break;
3171 
3172       case proc_bind_default:
3173         __kmp_str_buf_print(buffer, "default");
3174         break;
3175       }
3176       if (i < nelem - 1) {
3177         __kmp_str_buf_print(buffer, ",");
3178       }
3179     }
3180     __kmp_str_buf_print(buffer, "'\n");
3181   }
3182 }
3183 
3184 #endif /* OMP_40_ENABLED */
3185 
3186 // -----------------------------------------------------------------------------
3187 // OMP_DYNAMIC
3188 
3189 static void __kmp_stg_parse_omp_dynamic(char const *name, char const *value,
3190                                         void *data) {
3191   __kmp_stg_parse_bool(name, value, &(__kmp_global.g.g_dynamic));
3192 } // __kmp_stg_parse_omp_dynamic
3193 
3194 static void __kmp_stg_print_omp_dynamic(kmp_str_buf_t *buffer, char const *name,
3195                                         void *data) {
3196   __kmp_stg_print_bool(buffer, name, __kmp_global.g.g_dynamic);
3197 } // __kmp_stg_print_omp_dynamic
3198 
3199 static void __kmp_stg_parse_kmp_dynamic_mode(char const *name,
3200                                              char const *value, void *data) {
3201   if (TCR_4(__kmp_init_parallel)) {
3202     KMP_WARNING(EnvParallelWarn, name);
3203     __kmp_env_toPrint(name, 0);
3204     return;
3205   }
3206 #ifdef USE_LOAD_BALANCE
3207   else if (__kmp_str_match("load balance", 2, value) ||
3208            __kmp_str_match("load_balance", 2, value) ||
3209            __kmp_str_match("load-balance", 2, value) ||
3210            __kmp_str_match("loadbalance", 2, value) ||
3211            __kmp_str_match("balance", 1, value)) {
3212     __kmp_global.g.g_dynamic_mode = dynamic_load_balance;
3213   }
3214 #endif /* USE_LOAD_BALANCE */
3215   else if (__kmp_str_match("thread limit", 1, value) ||
3216            __kmp_str_match("thread_limit", 1, value) ||
3217            __kmp_str_match("thread-limit", 1, value) ||
3218            __kmp_str_match("threadlimit", 1, value) ||
3219            __kmp_str_match("limit", 2, value)) {
3220     __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
3221   } else if (__kmp_str_match("random", 1, value)) {
3222     __kmp_global.g.g_dynamic_mode = dynamic_random;
3223   } else {
3224     KMP_WARNING(StgInvalidValue, name, value);
3225   }
3226 } //__kmp_stg_parse_kmp_dynamic_mode
3227 
3228 static void __kmp_stg_print_kmp_dynamic_mode(kmp_str_buf_t *buffer,
3229                                              char const *name, void *data) {
3230 #if KMP_DEBUG
3231   if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
3232     __kmp_str_buf_print(buffer, "   %s: %s \n", name, KMP_I18N_STR(NotDefined));
3233   }
3234 #ifdef USE_LOAD_BALANCE
3235   else if (__kmp_global.g.g_dynamic_mode == dynamic_load_balance) {
3236     __kmp_stg_print_str(buffer, name, "load balance");
3237   }
3238 #endif /* USE_LOAD_BALANCE */
3239   else if (__kmp_global.g.g_dynamic_mode == dynamic_thread_limit) {
3240     __kmp_stg_print_str(buffer, name, "thread limit");
3241   } else if (__kmp_global.g.g_dynamic_mode == dynamic_random) {
3242     __kmp_stg_print_str(buffer, name, "random");
3243   } else {
3244     KMP_ASSERT(0);
3245   }
3246 #endif /* KMP_DEBUG */
3247 } // __kmp_stg_print_kmp_dynamic_mode
3248 
3249 #ifdef USE_LOAD_BALANCE
3250 
3251 // -----------------------------------------------------------------------------
3252 // KMP_LOAD_BALANCE_INTERVAL
3253 
3254 static void __kmp_stg_parse_ld_balance_interval(char const *name,
3255                                                 char const *value, void *data) {
3256   double interval = __kmp_convert_to_double(value);
3257   if (interval >= 0) {
3258     __kmp_load_balance_interval = interval;
3259   } else {
3260     KMP_WARNING(StgInvalidValue, name, value);
3261   }
3262 } // __kmp_stg_parse_load_balance_interval
3263 
3264 static void __kmp_stg_print_ld_balance_interval(kmp_str_buf_t *buffer,
3265                                                 char const *name, void *data) {
3266 #if KMP_DEBUG
3267   __kmp_str_buf_print(buffer, "   %s=%8.6f\n", name,
3268                       __kmp_load_balance_interval);
3269 #endif /* KMP_DEBUG */
3270 } // __kmp_stg_print_load_balance_interval
3271 
3272 #endif /* USE_LOAD_BALANCE */
3273 
3274 // -----------------------------------------------------------------------------
3275 // KMP_INIT_AT_FORK
3276 
3277 static void __kmp_stg_parse_init_at_fork(char const *name, char const *value,
3278                                          void *data) {
3279   __kmp_stg_parse_bool(name, value, &__kmp_need_register_atfork);
3280   if (__kmp_need_register_atfork) {
3281     __kmp_need_register_atfork_specified = TRUE;
3282   }
3283 } // __kmp_stg_parse_init_at_fork
3284 
3285 static void __kmp_stg_print_init_at_fork(kmp_str_buf_t *buffer,
3286                                          char const *name, void *data) {
3287   __kmp_stg_print_bool(buffer, name, __kmp_need_register_atfork_specified);
3288 } // __kmp_stg_print_init_at_fork
3289 
3290 // -----------------------------------------------------------------------------
3291 // KMP_SCHEDULE
3292 
3293 static void __kmp_stg_parse_schedule(char const *name, char const *value,
3294                                      void *data) {
3295 
3296   if (value != NULL) {
3297     size_t length = KMP_STRLEN(value);
3298     if (length > INT_MAX) {
3299       KMP_WARNING(LongValue, name);
3300     } else {
3301       const char *semicolon;
3302       if (value[length - 1] == '"' || value[length - 1] == '\'')
3303         KMP_WARNING(UnbalancedQuotes, name);
3304       do {
3305         char sentinel;
3306 
3307         semicolon = strchr(value, ';');
3308         if (*value && semicolon != value) {
3309           const char *comma = strchr(value, ',');
3310 
3311           if (comma) {
3312             ++comma;
3313             sentinel = ',';
3314           } else
3315             sentinel = ';';
3316           if (!__kmp_strcasecmp_with_sentinel("static", value, sentinel)) {
3317             if (!__kmp_strcasecmp_with_sentinel("greedy", comma, ';')) {
3318               __kmp_static = kmp_sch_static_greedy;
3319               continue;
3320             } else if (!__kmp_strcasecmp_with_sentinel("balanced", comma,
3321                                                        ';')) {
3322               __kmp_static = kmp_sch_static_balanced;
3323               continue;
3324             }
3325           } else if (!__kmp_strcasecmp_with_sentinel("guided", value,
3326                                                      sentinel)) {
3327             if (!__kmp_strcasecmp_with_sentinel("iterative", comma, ';')) {
3328               __kmp_guided = kmp_sch_guided_iterative_chunked;
3329               continue;
3330             } else if (!__kmp_strcasecmp_with_sentinel("analytical", comma,
3331                                                        ';')) {
3332               /* analytical not allowed for too many threads */
3333               __kmp_guided = kmp_sch_guided_analytical_chunked;
3334               continue;
3335             }
3336           }
3337           KMP_WARNING(InvalidClause, name, value);
3338         } else
3339           KMP_WARNING(EmptyClause, name);
3340       } while ((value = semicolon ? semicolon + 1 : NULL));
3341     }
3342   }
3343 
3344 } // __kmp_stg_parse__schedule
3345 
3346 static void __kmp_stg_print_schedule(kmp_str_buf_t *buffer, char const *name,
3347                                      void *data) {
3348   if (__kmp_env_format) {
3349     KMP_STR_BUF_PRINT_NAME_EX(name);
3350   } else {
3351     __kmp_str_buf_print(buffer, "   %s='", name);
3352   }
3353   if (__kmp_static == kmp_sch_static_greedy) {
3354     __kmp_str_buf_print(buffer, "%s", "static,greedy");
3355   } else if (__kmp_static == kmp_sch_static_balanced) {
3356     __kmp_str_buf_print(buffer, "%s", "static,balanced");
3357   }
3358   if (__kmp_guided == kmp_sch_guided_iterative_chunked) {
3359     __kmp_str_buf_print(buffer, ";%s'\n", "guided,iterative");
3360   } else if (__kmp_guided == kmp_sch_guided_analytical_chunked) {
3361     __kmp_str_buf_print(buffer, ";%s'\n", "guided,analytical");
3362   }
3363 } // __kmp_stg_print_schedule
3364 
3365 // -----------------------------------------------------------------------------
3366 // OMP_SCHEDULE
3367 
3368 static void __kmp_stg_parse_omp_schedule(char const *name, char const *value,
3369                                          void *data) {
3370   size_t length;
3371   if (value) {
3372     length = KMP_STRLEN(value);
3373     if (length) {
3374       const char *comma = strchr(value, ',');
3375       if (value[length - 1] == '"' || value[length - 1] == '\'')
3376         KMP_WARNING(UnbalancedQuotes, name);
3377       /* get the specified scheduling style */
3378       if (!__kmp_strcasecmp_with_sentinel("dynamic", value, ',')) /* DYNAMIC */
3379         __kmp_sched = kmp_sch_dynamic_chunked;
3380       else if (!__kmp_strcasecmp_with_sentinel("guided", value,
3381                                                ',')) /* GUIDED */
3382         __kmp_sched = kmp_sch_guided_chunked;
3383       // AC: TODO: add AUTO schedule, and pprobably remove TRAPEZOIDAL (OMP 3.0
3384       // does not allow it)
3385       else if (!__kmp_strcasecmp_with_sentinel("auto", value, ',')) { /* AUTO */
3386         __kmp_sched = kmp_sch_auto;
3387         if (comma) {
3388           __kmp_msg(kmp_ms_warning, KMP_MSG(IgnoreChunk, name, comma),
3389                     __kmp_msg_null);
3390           comma = NULL;
3391         }
3392       } else if (!__kmp_strcasecmp_with_sentinel("trapezoidal", value,
3393                                                  ',')) /* TRAPEZOIDAL */
3394         __kmp_sched = kmp_sch_trapezoidal;
3395       else if (!__kmp_strcasecmp_with_sentinel("static", value,
3396                                                ',')) /* STATIC */
3397         __kmp_sched = kmp_sch_static;
3398 #if KMP_STATIC_STEAL_ENABLED
3399       else if (!__kmp_strcasecmp_with_sentinel("static_steal", value, ','))
3400         __kmp_sched = kmp_sch_static_steal;
3401 #endif
3402       else {
3403         KMP_WARNING(StgInvalidValue, name, value);
3404         value = NULL; /* skip processing of comma */
3405       }
3406       if (value && comma) {
3407         if (__kmp_sched == kmp_sch_static)
3408           __kmp_sched = kmp_sch_static_chunked;
3409         ++comma;
3410         __kmp_chunk = __kmp_str_to_int(comma, 0);
3411         if (__kmp_chunk < 1) {
3412           __kmp_chunk = KMP_DEFAULT_CHUNK;
3413           __kmp_msg(kmp_ms_warning, KMP_MSG(InvalidChunk, name, comma),
3414                     __kmp_msg_null);
3415           KMP_INFORM(Using_int_Value, name, __kmp_chunk);
3416           // AC: next block commented out until KMP_DEFAULT_CHUNK !=
3417           // KMP_MIN_CHUNK (to improve code coverage :)
3418           //     The default chunk size is 1 according to standard, thus making
3419           //     KMP_MIN_CHUNK not 1 we would introduce mess:
3420           //     wrong chunk becomes 1, but it will be impossible to explicitely
3421           //     set 1, because it becomes KMP_MIN_CHUNK...
3422           //                } else if ( __kmp_chunk < KMP_MIN_CHUNK ) {
3423           //                    __kmp_chunk = KMP_MIN_CHUNK;
3424         } else if (__kmp_chunk > KMP_MAX_CHUNK) {
3425           __kmp_chunk = KMP_MAX_CHUNK;
3426           __kmp_msg(kmp_ms_warning, KMP_MSG(LargeChunk, name, comma),
3427                     __kmp_msg_null);
3428           KMP_INFORM(Using_int_Value, name, __kmp_chunk);
3429         }
3430       }
3431     } else
3432       KMP_WARNING(EmptyString, name);
3433   }
3434   K_DIAG(1, ("__kmp_static == %d\n", __kmp_static))
3435   K_DIAG(1, ("__kmp_guided == %d\n", __kmp_guided))
3436   K_DIAG(1, ("__kmp_sched == %d\n", __kmp_sched))
3437   K_DIAG(1, ("__kmp_chunk == %d\n", __kmp_chunk))
3438 } // __kmp_stg_parse_omp_schedule
3439 
3440 static void __kmp_stg_print_omp_schedule(kmp_str_buf_t *buffer,
3441                                          char const *name, void *data) {
3442   if (__kmp_env_format) {
3443     KMP_STR_BUF_PRINT_NAME_EX(name);
3444   } else {
3445     __kmp_str_buf_print(buffer, "   %s='", name);
3446   }
3447   if (__kmp_chunk) {
3448     switch (__kmp_sched) {
3449     case kmp_sch_dynamic_chunked:
3450       __kmp_str_buf_print(buffer, "%s,%d'\n", "dynamic", __kmp_chunk);
3451       break;
3452     case kmp_sch_guided_iterative_chunked:
3453     case kmp_sch_guided_analytical_chunked:
3454       __kmp_str_buf_print(buffer, "%s,%d'\n", "guided", __kmp_chunk);
3455       break;
3456     case kmp_sch_trapezoidal:
3457       __kmp_str_buf_print(buffer, "%s,%d'\n", "trapezoidal", __kmp_chunk);
3458       break;
3459     case kmp_sch_static:
3460     case kmp_sch_static_chunked:
3461     case kmp_sch_static_balanced:
3462     case kmp_sch_static_greedy:
3463       __kmp_str_buf_print(buffer, "%s,%d'\n", "static", __kmp_chunk);
3464       break;
3465     case kmp_sch_static_steal:
3466       __kmp_str_buf_print(buffer, "%s,%d'\n", "static_steal", __kmp_chunk);
3467       break;
3468     case kmp_sch_auto:
3469       __kmp_str_buf_print(buffer, "%s,%d'\n", "auto", __kmp_chunk);
3470       break;
3471     }
3472   } else {
3473     switch (__kmp_sched) {
3474     case kmp_sch_dynamic_chunked:
3475       __kmp_str_buf_print(buffer, "%s'\n", "dynamic");
3476       break;
3477     case kmp_sch_guided_iterative_chunked:
3478     case kmp_sch_guided_analytical_chunked:
3479       __kmp_str_buf_print(buffer, "%s'\n", "guided");
3480       break;
3481     case kmp_sch_trapezoidal:
3482       __kmp_str_buf_print(buffer, "%s'\n", "trapezoidal");
3483       break;
3484     case kmp_sch_static:
3485     case kmp_sch_static_chunked:
3486     case kmp_sch_static_balanced:
3487     case kmp_sch_static_greedy:
3488       __kmp_str_buf_print(buffer, "%s'\n", "static");
3489       break;
3490     case kmp_sch_static_steal:
3491       __kmp_str_buf_print(buffer, "%s'\n", "static_steal");
3492       break;
3493     case kmp_sch_auto:
3494       __kmp_str_buf_print(buffer, "%s'\n", "auto");
3495       break;
3496     }
3497   }
3498 } // __kmp_stg_print_omp_schedule
3499 
3500 // -----------------------------------------------------------------------------
3501 // KMP_ATOMIC_MODE
3502 
3503 static void __kmp_stg_parse_atomic_mode(char const *name, char const *value,
3504                                         void *data) {
3505   // Modes: 0 -- do not change default; 1 -- Intel perf mode, 2 -- GOMP
3506   // compatibility mode.
3507   int mode = 0;
3508   int max = 1;
3509 #ifdef KMP_GOMP_COMPAT
3510   max = 2;
3511 #endif /* KMP_GOMP_COMPAT */
3512   __kmp_stg_parse_int(name, value, 0, max, &mode);
3513   // TODO; parse_int is not very suitable for this case. In case of overflow it
3514   // is better to use
3515   // 0 rather that max value.
3516   if (mode > 0) {
3517     __kmp_atomic_mode = mode;
3518   }
3519 } // __kmp_stg_parse_atomic_mode
3520 
3521 static void __kmp_stg_print_atomic_mode(kmp_str_buf_t *buffer, char const *name,
3522                                         void *data) {
3523   __kmp_stg_print_int(buffer, name, __kmp_atomic_mode);
3524 } // __kmp_stg_print_atomic_mode
3525 
3526 // -----------------------------------------------------------------------------
3527 // KMP_CONSISTENCY_CHECK
3528 
3529 static void __kmp_stg_parse_consistency_check(char const *name,
3530                                               char const *value, void *data) {
3531   if (!__kmp_strcasecmp_with_sentinel("all", value, 0)) {
3532     // Note, this will not work from kmp_set_defaults because th_cons stack was
3533     // not allocated
3534     // for existed thread(s) thus the first __kmp_push_<construct> will break
3535     // with assertion.
3536     // TODO: allocate th_cons if called from kmp_set_defaults.
3537     __kmp_env_consistency_check = TRUE;
3538   } else if (!__kmp_strcasecmp_with_sentinel("none", value, 0)) {
3539     __kmp_env_consistency_check = FALSE;
3540   } else {
3541     KMP_WARNING(StgInvalidValue, name, value);
3542   }
3543 } // __kmp_stg_parse_consistency_check
3544 
3545 static void __kmp_stg_print_consistency_check(kmp_str_buf_t *buffer,
3546                                               char const *name, void *data) {
3547 #if KMP_DEBUG
3548   const char *value = NULL;
3549 
3550   if (__kmp_env_consistency_check) {
3551     value = "all";
3552   } else {
3553     value = "none";
3554   }
3555 
3556   if (value != NULL) {
3557     __kmp_stg_print_str(buffer, name, value);
3558   }
3559 #endif /* KMP_DEBUG */
3560 } // __kmp_stg_print_consistency_check
3561 
3562 #if USE_ITT_BUILD
3563 // -----------------------------------------------------------------------------
3564 // KMP_ITT_PREPARE_DELAY
3565 
3566 #if USE_ITT_NOTIFY
3567 
3568 static void __kmp_stg_parse_itt_prepare_delay(char const *name,
3569                                               char const *value, void *data) {
3570   // Experimental code: KMP_ITT_PREPARE_DELAY specifies numbert of loop
3571   // iterations.
3572   int delay = 0;
3573   __kmp_stg_parse_int(name, value, 0, INT_MAX, &delay);
3574   __kmp_itt_prepare_delay = delay;
3575 } // __kmp_str_parse_itt_prepare_delay
3576 
3577 static void __kmp_stg_print_itt_prepare_delay(kmp_str_buf_t *buffer,
3578                                               char const *name, void *data) {
3579   __kmp_stg_print_uint64(buffer, name, __kmp_itt_prepare_delay);
3580 
3581 } // __kmp_str_print_itt_prepare_delay
3582 
3583 #endif // USE_ITT_NOTIFY
3584 #endif /* USE_ITT_BUILD */
3585 
3586 // -----------------------------------------------------------------------------
3587 // KMP_MALLOC_POOL_INCR
3588 
3589 static void __kmp_stg_parse_malloc_pool_incr(char const *name,
3590                                              char const *value, void *data) {
3591   __kmp_stg_parse_size(name, value, KMP_MIN_MALLOC_POOL_INCR,
3592                        KMP_MAX_MALLOC_POOL_INCR, NULL, &__kmp_malloc_pool_incr,
3593                        1);
3594 } // __kmp_stg_parse_malloc_pool_incr
3595 
3596 static void __kmp_stg_print_malloc_pool_incr(kmp_str_buf_t *buffer,
3597                                              char const *name, void *data) {
3598   __kmp_stg_print_size(buffer, name, __kmp_malloc_pool_incr);
3599 
3600 } // _kmp_stg_print_malloc_pool_incr
3601 
3602 #ifdef KMP_DEBUG
3603 
3604 // -----------------------------------------------------------------------------
3605 // KMP_PAR_RANGE
3606 
3607 static void __kmp_stg_parse_par_range_env(char const *name, char const *value,
3608                                           void *data) {
3609   __kmp_stg_parse_par_range(name, value, &__kmp_par_range,
3610                             __kmp_par_range_routine, __kmp_par_range_filename,
3611                             &__kmp_par_range_lb, &__kmp_par_range_ub);
3612 } // __kmp_stg_parse_par_range_env
3613 
3614 static void __kmp_stg_print_par_range_env(kmp_str_buf_t *buffer,
3615                                           char const *name, void *data) {
3616   if (__kmp_par_range != 0) {
3617     __kmp_stg_print_str(buffer, name, par_range_to_print);
3618   }
3619 } // __kmp_stg_print_par_range_env
3620 
3621 // -----------------------------------------------------------------------------
3622 // KMP_YIELD_CYCLE, KMP_YIELD_ON, KMP_YIELD_OFF
3623 
3624 static void __kmp_stg_parse_yield_cycle(char const *name, char const *value,
3625                                         void *data) {
3626   int flag = __kmp_yield_cycle;
3627   __kmp_stg_parse_bool(name, value, &flag);
3628   __kmp_yield_cycle = flag;
3629 } // __kmp_stg_parse_yield_cycle
3630 
3631 static void __kmp_stg_print_yield_cycle(kmp_str_buf_t *buffer, char const *name,
3632                                         void *data) {
3633   __kmp_stg_print_bool(buffer, name, __kmp_yield_cycle);
3634 } // __kmp_stg_print_yield_cycle
3635 
3636 static void __kmp_stg_parse_yield_on(char const *name, char const *value,
3637                                      void *data) {
3638   __kmp_stg_parse_int(name, value, 2, INT_MAX, &__kmp_yield_on_count);
3639 } // __kmp_stg_parse_yield_on
3640 
3641 static void __kmp_stg_print_yield_on(kmp_str_buf_t *buffer, char const *name,
3642                                      void *data) {
3643   __kmp_stg_print_int(buffer, name, __kmp_yield_on_count);
3644 } // __kmp_stg_print_yield_on
3645 
3646 static void __kmp_stg_parse_yield_off(char const *name, char const *value,
3647                                       void *data) {
3648   __kmp_stg_parse_int(name, value, 2, INT_MAX, &__kmp_yield_off_count);
3649 } // __kmp_stg_parse_yield_off
3650 
3651 static void __kmp_stg_print_yield_off(kmp_str_buf_t *buffer, char const *name,
3652                                       void *data) {
3653   __kmp_stg_print_int(buffer, name, __kmp_yield_off_count);
3654 } // __kmp_stg_print_yield_off
3655 
3656 #endif
3657 
3658 // -----------------------------------------------------------------------------
3659 // KMP_INIT_WAIT, KMP_NEXT_WAIT
3660 
3661 static void __kmp_stg_parse_init_wait(char const *name, char const *value,
3662                                       void *data) {
3663   int wait;
3664   KMP_ASSERT((__kmp_init_wait & 1) == 0);
3665   wait = __kmp_init_wait / 2;
3666   __kmp_stg_parse_int(name, value, KMP_MIN_INIT_WAIT, KMP_MAX_INIT_WAIT, &wait);
3667   __kmp_init_wait = wait * 2;
3668   KMP_ASSERT((__kmp_init_wait & 1) == 0);
3669   __kmp_yield_init = __kmp_init_wait;
3670 } // __kmp_stg_parse_init_wait
3671 
3672 static void __kmp_stg_print_init_wait(kmp_str_buf_t *buffer, char const *name,
3673                                       void *data) {
3674   __kmp_stg_print_int(buffer, name, __kmp_init_wait);
3675 } // __kmp_stg_print_init_wait
3676 
3677 static void __kmp_stg_parse_next_wait(char const *name, char const *value,
3678                                       void *data) {
3679   int wait;
3680   KMP_ASSERT((__kmp_next_wait & 1) == 0);
3681   wait = __kmp_next_wait / 2;
3682   __kmp_stg_parse_int(name, value, KMP_MIN_NEXT_WAIT, KMP_MAX_NEXT_WAIT, &wait);
3683   __kmp_next_wait = wait * 2;
3684   KMP_ASSERT((__kmp_next_wait & 1) == 0);
3685   __kmp_yield_next = __kmp_next_wait;
3686 } // __kmp_stg_parse_next_wait
3687 
3688 static void __kmp_stg_print_next_wait(kmp_str_buf_t *buffer, char const *name,
3689                                       void *data) {
3690   __kmp_stg_print_int(buffer, name, __kmp_next_wait);
3691 } //__kmp_stg_print_next_wait
3692 
3693 // -----------------------------------------------------------------------------
3694 // KMP_GTID_MODE
3695 
3696 static void __kmp_stg_parse_gtid_mode(char const *name, char const *value,
3697                                       void *data) {
3698   // Modes:
3699   //   0 -- do not change default
3700   //   1 -- sp search
3701   //   2 -- use "keyed" TLS var, i.e.
3702   //        pthread_getspecific(Linux* OS/OS X*) or TlsGetValue(Windows* OS)
3703   //   3 -- __declspec(thread) TLS var in tdata section
3704   int mode = 0;
3705   int max = 2;
3706 #ifdef KMP_TDATA_GTID
3707   max = 3;
3708 #endif /* KMP_TDATA_GTID */
3709   __kmp_stg_parse_int(name, value, 0, max, &mode);
3710   // TODO; parse_int is not very suitable for this case. In case of overflow it
3711   // is better to use 0 rather that max value.
3712   if (mode == 0) {
3713     __kmp_adjust_gtid_mode = TRUE;
3714   } else {
3715     __kmp_gtid_mode = mode;
3716     __kmp_adjust_gtid_mode = FALSE;
3717   }
3718 } // __kmp_str_parse_gtid_mode
3719 
3720 static void __kmp_stg_print_gtid_mode(kmp_str_buf_t *buffer, char const *name,
3721                                       void *data) {
3722   if (__kmp_adjust_gtid_mode) {
3723     __kmp_stg_print_int(buffer, name, 0);
3724   } else {
3725     __kmp_stg_print_int(buffer, name, __kmp_gtid_mode);
3726   }
3727 } // __kmp_stg_print_gtid_mode
3728 
3729 // -----------------------------------------------------------------------------
3730 // KMP_NUM_LOCKS_IN_BLOCK
3731 
3732 static void __kmp_stg_parse_lock_block(char const *name, char const *value,
3733                                        void *data) {
3734   __kmp_stg_parse_int(name, value, 0, KMP_INT_MAX, &__kmp_num_locks_in_block);
3735 } // __kmp_str_parse_lock_block
3736 
3737 static void __kmp_stg_print_lock_block(kmp_str_buf_t *buffer, char const *name,
3738                                        void *data) {
3739   __kmp_stg_print_int(buffer, name, __kmp_num_locks_in_block);
3740 } // __kmp_stg_print_lock_block
3741 
3742 // -----------------------------------------------------------------------------
3743 // KMP_LOCK_KIND
3744 
3745 #if KMP_USE_DYNAMIC_LOCK
3746 #define KMP_STORE_LOCK_SEQ(a) (__kmp_user_lock_seq = lockseq_##a)
3747 #else
3748 #define KMP_STORE_LOCK_SEQ(a)
3749 #endif
3750 
3751 static void __kmp_stg_parse_lock_kind(char const *name, char const *value,
3752                                       void *data) {
3753   if (__kmp_init_user_locks) {
3754     KMP_WARNING(EnvLockWarn, name);
3755     return;
3756   }
3757 
3758   if (__kmp_str_match("tas", 2, value) ||
3759       __kmp_str_match("test and set", 2, value) ||
3760       __kmp_str_match("test_and_set", 2, value) ||
3761       __kmp_str_match("test-and-set", 2, value) ||
3762       __kmp_str_match("test andset", 2, value) ||
3763       __kmp_str_match("test_andset", 2, value) ||
3764       __kmp_str_match("test-andset", 2, value) ||
3765       __kmp_str_match("testand set", 2, value) ||
3766       __kmp_str_match("testand_set", 2, value) ||
3767       __kmp_str_match("testand-set", 2, value) ||
3768       __kmp_str_match("testandset", 2, value)) {
3769     __kmp_user_lock_kind = lk_tas;
3770     KMP_STORE_LOCK_SEQ(tas);
3771   }
3772 #if KMP_USE_FUTEX
3773   else if (__kmp_str_match("futex", 1, value)) {
3774     if (__kmp_futex_determine_capable()) {
3775       __kmp_user_lock_kind = lk_futex;
3776       KMP_STORE_LOCK_SEQ(futex);
3777     } else {
3778       KMP_WARNING(FutexNotSupported, name, value);
3779     }
3780   }
3781 #endif
3782   else if (__kmp_str_match("ticket", 2, value)) {
3783     __kmp_user_lock_kind = lk_ticket;
3784     KMP_STORE_LOCK_SEQ(ticket);
3785   } else if (__kmp_str_match("queuing", 1, value) ||
3786              __kmp_str_match("queue", 1, value)) {
3787     __kmp_user_lock_kind = lk_queuing;
3788     KMP_STORE_LOCK_SEQ(queuing);
3789   } else if (__kmp_str_match("drdpa ticket", 1, value) ||
3790              __kmp_str_match("drdpa_ticket", 1, value) ||
3791              __kmp_str_match("drdpa-ticket", 1, value) ||
3792              __kmp_str_match("drdpaticket", 1, value) ||
3793              __kmp_str_match("drdpa", 1, value)) {
3794     __kmp_user_lock_kind = lk_drdpa;
3795     KMP_STORE_LOCK_SEQ(drdpa);
3796   }
3797 #if KMP_USE_ADAPTIVE_LOCKS
3798   else if (__kmp_str_match("adaptive", 1, value)) {
3799     if (__kmp_cpuinfo.rtm) { // ??? Is cpuinfo available here?
3800       __kmp_user_lock_kind = lk_adaptive;
3801       KMP_STORE_LOCK_SEQ(adaptive);
3802     } else {
3803       KMP_WARNING(AdaptiveNotSupported, name, value);
3804       __kmp_user_lock_kind = lk_queuing;
3805       KMP_STORE_LOCK_SEQ(queuing);
3806     }
3807   }
3808 #endif // KMP_USE_ADAPTIVE_LOCKS
3809 #if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
3810   else if (__kmp_str_match("rtm", 1, value)) {
3811     if (__kmp_cpuinfo.rtm) {
3812       __kmp_user_lock_kind = lk_rtm;
3813       KMP_STORE_LOCK_SEQ(rtm);
3814     } else {
3815       KMP_WARNING(AdaptiveNotSupported, name, value);
3816       __kmp_user_lock_kind = lk_queuing;
3817       KMP_STORE_LOCK_SEQ(queuing);
3818     }
3819   } else if (__kmp_str_match("hle", 1, value)) {
3820     __kmp_user_lock_kind = lk_hle;
3821     KMP_STORE_LOCK_SEQ(hle);
3822   }
3823 #endif
3824   else {
3825     KMP_WARNING(StgInvalidValue, name, value);
3826   }
3827 }
3828 
3829 static void __kmp_stg_print_lock_kind(kmp_str_buf_t *buffer, char const *name,
3830                                       void *data) {
3831   const char *value = NULL;
3832 
3833   switch (__kmp_user_lock_kind) {
3834   case lk_default:
3835     value = "default";
3836     break;
3837 
3838   case lk_tas:
3839     value = "tas";
3840     break;
3841 
3842 #if KMP_USE_FUTEX
3843   case lk_futex:
3844     value = "futex";
3845     break;
3846 #endif
3847 
3848 #if KMP_USE_DYNAMIC_LOCK && KMP_USE_TSX
3849   case lk_rtm:
3850     value = "rtm";
3851     break;
3852 
3853   case lk_hle:
3854     value = "hle";
3855     break;
3856 #endif
3857 
3858   case lk_ticket:
3859     value = "ticket";
3860     break;
3861 
3862   case lk_queuing:
3863     value = "queuing";
3864     break;
3865 
3866   case lk_drdpa:
3867     value = "drdpa";
3868     break;
3869 #if KMP_USE_ADAPTIVE_LOCKS
3870   case lk_adaptive:
3871     value = "adaptive";
3872     break;
3873 #endif
3874   }
3875 
3876   if (value != NULL) {
3877     __kmp_stg_print_str(buffer, name, value);
3878   }
3879 }
3880 
3881 // -----------------------------------------------------------------------------
3882 // KMP_SPIN_BACKOFF_PARAMS
3883 
3884 // KMP_SPIN_BACKOFF_PARAMS=max_backoff[,min_tick] (max backoff size, min tick
3885 // for machine pause)
3886 static void __kmp_stg_parse_spin_backoff_params(const char *name,
3887                                                 const char *value, void *data) {
3888   const char *next = value;
3889 
3890   int total = 0; // Count elements that were set. It'll be used as an array size
3891   int prev_comma = FALSE; // For correct processing sequential commas
3892   int i;
3893 
3894   kmp_uint32 max_backoff = __kmp_spin_backoff_params.max_backoff;
3895   kmp_uint32 min_tick = __kmp_spin_backoff_params.min_tick;
3896 
3897   // Run only 3 iterations because it is enough to read two values or find a
3898   // syntax error
3899   for (i = 0; i < 3; i++) {
3900     SKIP_WS(next);
3901 
3902     if (*next == '\0') {
3903       break;
3904     }
3905     // Next character is not an integer or not a comma OR number of values > 2
3906     // => end of list
3907     if (((*next < '0' || *next > '9') && *next != ',') || total > 2) {
3908       KMP_WARNING(EnvSyntaxError, name, value);
3909       return;
3910     }
3911     // The next character is ','
3912     if (*next == ',') {
3913       // ',' is the fisrt character
3914       if (total == 0 || prev_comma) {
3915         total++;
3916       }
3917       prev_comma = TRUE;
3918       next++; // skip ','
3919       SKIP_WS(next);
3920     }
3921     // Next character is a digit
3922     if (*next >= '0' && *next <= '9') {
3923       int num;
3924       const char *buf = next;
3925       char const *msg = NULL;
3926       prev_comma = FALSE;
3927       SKIP_DIGITS(next);
3928       total++;
3929 
3930       const char *tmp = next;
3931       SKIP_WS(tmp);
3932       if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
3933         KMP_WARNING(EnvSpacesNotAllowed, name, value);
3934         return;
3935       }
3936 
3937       num = __kmp_str_to_int(buf, *next);
3938       if (num <= 0) { // The number of retries should be > 0
3939         msg = KMP_I18N_STR(ValueTooSmall);
3940         num = 1;
3941       } else if (num > KMP_INT_MAX) {
3942         msg = KMP_I18N_STR(ValueTooLarge);
3943         num = KMP_INT_MAX;
3944       }
3945       if (msg != NULL) {
3946         // Message is not empty. Print warning.
3947         KMP_WARNING(ParseSizeIntWarn, name, value, msg);
3948         KMP_INFORM(Using_int_Value, name, num);
3949       }
3950       if (total == 1) {
3951         max_backoff = num;
3952       } else if (total == 2) {
3953         min_tick = num;
3954       }
3955     }
3956   }
3957   KMP_DEBUG_ASSERT(total > 0);
3958   if (total <= 0) {
3959     KMP_WARNING(EnvSyntaxError, name, value);
3960     return;
3961   }
3962   __kmp_spin_backoff_params.max_backoff = max_backoff;
3963   __kmp_spin_backoff_params.min_tick = min_tick;
3964 }
3965 
3966 static void __kmp_stg_print_spin_backoff_params(kmp_str_buf_t *buffer,
3967                                                 char const *name, void *data) {
3968   if (__kmp_env_format) {
3969     KMP_STR_BUF_PRINT_NAME_EX(name);
3970   } else {
3971     __kmp_str_buf_print(buffer, "   %s='", name);
3972   }
3973   __kmp_str_buf_print(buffer, "%d,%d'\n", __kmp_spin_backoff_params.max_backoff,
3974                       __kmp_spin_backoff_params.min_tick);
3975 }
3976 
3977 #if KMP_USE_ADAPTIVE_LOCKS
3978 
3979 // -----------------------------------------------------------------------------
3980 // KMP_ADAPTIVE_LOCK_PROPS, KMP_SPECULATIVE_STATSFILE
3981 
3982 // Parse out values for the tunable parameters from a string of the form
3983 // KMP_ADAPTIVE_LOCK_PROPS=max_soft_retries[,max_badness]
3984 static void __kmp_stg_parse_adaptive_lock_props(const char *name,
3985                                                 const char *value, void *data) {
3986   int max_retries = 0;
3987   int max_badness = 0;
3988 
3989   const char *next = value;
3990 
3991   int total = 0; // Count elements that were set. It'll be used as an array size
3992   int prev_comma = FALSE; // For correct processing sequential commas
3993   int i;
3994 
3995   // Save values in the structure __kmp_speculative_backoff_params
3996   // Run only 3 iterations because it is enough to read two values or find a
3997   // syntax error
3998   for (i = 0; i < 3; i++) {
3999     SKIP_WS(next);
4000 
4001     if (*next == '\0') {
4002       break;
4003     }
4004     // Next character is not an integer or not a comma OR number of values > 2
4005     // => end of list
4006     if (((*next < '0' || *next > '9') && *next != ',') || total > 2) {
4007       KMP_WARNING(EnvSyntaxError, name, value);
4008       return;
4009     }
4010     // The next character is ','
4011     if (*next == ',') {
4012       // ',' is the fisrt character
4013       if (total == 0 || prev_comma) {
4014         total++;
4015       }
4016       prev_comma = TRUE;
4017       next++; // skip ','
4018       SKIP_WS(next);
4019     }
4020     // Next character is a digit
4021     if (*next >= '0' && *next <= '9') {
4022       int num;
4023       const char *buf = next;
4024       char const *msg = NULL;
4025       prev_comma = FALSE;
4026       SKIP_DIGITS(next);
4027       total++;
4028 
4029       const char *tmp = next;
4030       SKIP_WS(tmp);
4031       if ((*next == ' ' || *next == '\t') && (*tmp >= '0' && *tmp <= '9')) {
4032         KMP_WARNING(EnvSpacesNotAllowed, name, value);
4033         return;
4034       }
4035 
4036       num = __kmp_str_to_int(buf, *next);
4037       if (num < 0) { // The number of retries should be >= 0
4038         msg = KMP_I18N_STR(ValueTooSmall);
4039         num = 1;
4040       } else if (num > KMP_INT_MAX) {
4041         msg = KMP_I18N_STR(ValueTooLarge);
4042         num = KMP_INT_MAX;
4043       }
4044       if (msg != NULL) {
4045         // Message is not empty. Print warning.
4046         KMP_WARNING(ParseSizeIntWarn, name, value, msg);
4047         KMP_INFORM(Using_int_Value, name, num);
4048       }
4049       if (total == 1) {
4050         max_retries = num;
4051       } else if (total == 2) {
4052         max_badness = num;
4053       }
4054     }
4055   }
4056   KMP_DEBUG_ASSERT(total > 0);
4057   if (total <= 0) {
4058     KMP_WARNING(EnvSyntaxError, name, value);
4059     return;
4060   }
4061   __kmp_adaptive_backoff_params.max_soft_retries = max_retries;
4062   __kmp_adaptive_backoff_params.max_badness = max_badness;
4063 }
4064 
4065 static void __kmp_stg_print_adaptive_lock_props(kmp_str_buf_t *buffer,
4066                                                 char const *name, void *data) {
4067   if (__kmp_env_format) {
4068     KMP_STR_BUF_PRINT_NAME_EX(name);
4069   } else {
4070     __kmp_str_buf_print(buffer, "   %s='", name);
4071   }
4072   __kmp_str_buf_print(buffer, "%d,%d'\n",
4073                       __kmp_adaptive_backoff_params.max_soft_retries,
4074                       __kmp_adaptive_backoff_params.max_badness);
4075 } // __kmp_stg_print_adaptive_lock_props
4076 
4077 #if KMP_DEBUG_ADAPTIVE_LOCKS
4078 
4079 static void __kmp_stg_parse_speculative_statsfile(char const *name,
4080                                                   char const *value,
4081                                                   void *data) {
4082   __kmp_stg_parse_file(name, value, "", &__kmp_speculative_statsfile);
4083 } // __kmp_stg_parse_speculative_statsfile
4084 
4085 static void __kmp_stg_print_speculative_statsfile(kmp_str_buf_t *buffer,
4086                                                   char const *name,
4087                                                   void *data) {
4088   if (__kmp_str_match("-", 0, __kmp_speculative_statsfile)) {
4089     __kmp_stg_print_str(buffer, name, "stdout");
4090   } else {
4091     __kmp_stg_print_str(buffer, name, __kmp_speculative_statsfile);
4092   }
4093 
4094 } // __kmp_stg_print_speculative_statsfile
4095 
4096 #endif // KMP_DEBUG_ADAPTIVE_LOCKS
4097 
4098 #endif // KMP_USE_ADAPTIVE_LOCKS
4099 
4100 // -----------------------------------------------------------------------------
4101 // KMP_HW_SUBSET (was KMP_PLACE_THREADS)
4102 
4103 // The longest observable sequense of items is
4104 // Socket-Node-Tile-Core-Thread
4105 // So, let's limit to 5 levels for now
4106 // The input string is usually short enough, let's use 512 limit for now
4107 #define MAX_T_LEVEL 5
4108 #define MAX_STR_LEN 512
4109 static void __kmp_stg_parse_hw_subset(char const *name, char const *value,
4110                                       void *data) {
4111   // Value example: 1s,5c@3,2T
4112   // Which means "use 1 socket, 5 cores with offset 3, 2 threads per core"
4113   kmp_setting_t **rivals = (kmp_setting_t **)data;
4114   if (strcmp(name, "KMP_PLACE_THREADS") == 0) {
4115     KMP_INFORM(EnvVarDeprecated, name, "KMP_HW_SUBSET");
4116   }
4117   if (__kmp_stg_check_rivals(name, value, rivals)) {
4118     return;
4119   }
4120 
4121   char *components[MAX_T_LEVEL];
4122   char const *digits = "0123456789";
4123   char input[MAX_STR_LEN];
4124   size_t len = 0, mlen = MAX_STR_LEN;
4125   int level = 0;
4126   // Canonize the string (remove spaces, unify delimiters, etc.)
4127   char *pos = CCAST(char *, value);
4128   while (*pos && mlen) {
4129     if (*pos != ' ') { // skip spaces
4130       if (len == 0 && *pos == ':') {
4131         __kmp_hws_abs_flag = 1; // if the first symbol is ":", skip it
4132       } else {
4133         input[len] = toupper(*pos);
4134         if (input[len] == 'X')
4135           input[len] = ','; // unify delimiters of levels
4136         if (input[len] == 'O' && strchr(digits, *(pos + 1)))
4137           input[len] = '@'; // unify delimiters of offset
4138         len++;
4139       }
4140     }
4141     mlen--;
4142     pos++;
4143   }
4144   if (len == 0 || mlen == 0)
4145     goto err; // contents is either empty or too long
4146   input[len] = '\0';
4147   __kmp_hws_requested = 1; // mark that subset requested
4148   // Split by delimiter
4149   pos = input;
4150   components[level++] = pos;
4151   while ((pos = strchr(pos, ','))) {
4152     *pos = '\0'; // modify input and avoid more copying
4153     components[level++] = ++pos; // expect something after ","
4154     if (level > MAX_T_LEVEL)
4155       goto err; // too many components provided
4156   }
4157   // Check each component
4158   for (int i = 0; i < level; ++i) {
4159     int offset = 0;
4160     int num = atoi(components[i]); // each component should start with a number
4161     if ((pos = strchr(components[i], '@'))) {
4162       offset = atoi(pos + 1); // save offset
4163       *pos = '\0'; // cut the offset from the component
4164     }
4165     pos = components[i] + strspn(components[i], digits);
4166     if (pos == components[i])
4167       goto err;
4168     // detect the component type
4169     switch (*pos) {
4170     case 'S': // Socket
4171       if (__kmp_hws_socket.num > 0)
4172         goto err; // duplicate is not allowed
4173       __kmp_hws_socket.num = num;
4174       __kmp_hws_socket.offset = offset;
4175       break;
4176     case 'N': // NUMA Node
4177       if (__kmp_hws_node.num > 0)
4178         goto err; // duplicate is not allowed
4179       __kmp_hws_node.num = num;
4180       __kmp_hws_node.offset = offset;
4181       break;
4182     case 'L': // Cache
4183       if (*(pos + 1) == '2') { // L2 - Tile
4184         if (__kmp_hws_tile.num > 0)
4185           goto err; // duplicate is not allowed
4186         __kmp_hws_tile.num = num;
4187         __kmp_hws_tile.offset = offset;
4188       } else if (*(pos + 1) == '3') { // L3 - Socket
4189         if (__kmp_hws_socket.num > 0)
4190           goto err; // duplicate is not allowed
4191         __kmp_hws_socket.num = num;
4192         __kmp_hws_socket.offset = offset;
4193       } else if (*(pos + 1) == '1') { // L1 - Core
4194         if (__kmp_hws_core.num > 0)
4195           goto err; // duplicate is not allowed
4196         __kmp_hws_core.num = num;
4197         __kmp_hws_core.offset = offset;
4198       }
4199       break;
4200     case 'C': // Core (or Cache?)
4201       if (*(pos + 1) != 'A') {
4202         if (__kmp_hws_core.num > 0)
4203           goto err; // duplicate is not allowed
4204         __kmp_hws_core.num = num;
4205         __kmp_hws_core.offset = offset;
4206       } else { // Cache
4207         char *d = pos + strcspn(pos, digits); // find digit
4208         if (*d == '2') { // L2 - Tile
4209           if (__kmp_hws_tile.num > 0)
4210             goto err; // duplicate is not allowed
4211           __kmp_hws_tile.num = num;
4212           __kmp_hws_tile.offset = offset;
4213         } else if (*d == '3') { // L3 - Socket
4214           if (__kmp_hws_socket.num > 0)
4215             goto err; // duplicate is not allowed
4216           __kmp_hws_socket.num = num;
4217           __kmp_hws_socket.offset = offset;
4218         } else if (*d == '1') { // L1 - Core
4219           if (__kmp_hws_core.num > 0)
4220             goto err; // duplicate is not allowed
4221           __kmp_hws_core.num = num;
4222           __kmp_hws_core.offset = offset;
4223         } else {
4224           goto err;
4225         }
4226       }
4227       break;
4228     case 'T': // Thread
4229       if (__kmp_hws_proc.num > 0)
4230         goto err; // duplicate is not allowed
4231       __kmp_hws_proc.num = num;
4232       __kmp_hws_proc.offset = offset;
4233       break;
4234     default:
4235       goto err;
4236     }
4237   }
4238   return;
4239 err:
4240   KMP_WARNING(AffHWSubsetInvalid, name, value);
4241   __kmp_hws_requested = 0; // mark that subset not requested
4242   return;
4243 }
4244 
4245 static void __kmp_stg_print_hw_subset(kmp_str_buf_t *buffer, char const *name,
4246                                       void *data) {
4247   if (__kmp_hws_requested) {
4248     int comma = 0;
4249     kmp_str_buf_t buf;
4250     __kmp_str_buf_init(&buf);
4251     if (__kmp_env_format)
4252       KMP_STR_BUF_PRINT_NAME_EX(name);
4253     else
4254       __kmp_str_buf_print(buffer, "   %s='", name);
4255     if (__kmp_hws_socket.num) {
4256       __kmp_str_buf_print(&buf, "%ds", __kmp_hws_socket.num);
4257       if (__kmp_hws_socket.offset)
4258         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_socket.offset);
4259       comma = 1;
4260     }
4261     if (__kmp_hws_node.num) {
4262       __kmp_str_buf_print(&buf, "%s%dn", comma ? "," : "", __kmp_hws_node.num);
4263       if (__kmp_hws_node.offset)
4264         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_node.offset);
4265       comma = 1;
4266     }
4267     if (__kmp_hws_tile.num) {
4268       __kmp_str_buf_print(&buf, "%s%dL2", comma ? "," : "", __kmp_hws_tile.num);
4269       if (__kmp_hws_tile.offset)
4270         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_tile.offset);
4271       comma = 1;
4272     }
4273     if (__kmp_hws_core.num) {
4274       __kmp_str_buf_print(&buf, "%s%dc", comma ? "," : "", __kmp_hws_core.num);
4275       if (__kmp_hws_core.offset)
4276         __kmp_str_buf_print(&buf, "@%d", __kmp_hws_core.offset);
4277       comma = 1;
4278     }
4279     if (__kmp_hws_proc.num)
4280       __kmp_str_buf_print(&buf, "%s%dt", comma ? "," : "", __kmp_hws_proc.num);
4281     __kmp_str_buf_print(buffer, "%s'\n", buf.str);
4282     __kmp_str_buf_free(&buf);
4283   }
4284 }
4285 
4286 #if USE_ITT_BUILD
4287 // -----------------------------------------------------------------------------
4288 // KMP_FORKJOIN_FRAMES
4289 
4290 static void __kmp_stg_parse_forkjoin_frames(char const *name, char const *value,
4291                                             void *data) {
4292   __kmp_stg_parse_bool(name, value, &__kmp_forkjoin_frames);
4293 } // __kmp_stg_parse_forkjoin_frames
4294 
4295 static void __kmp_stg_print_forkjoin_frames(kmp_str_buf_t *buffer,
4296                                             char const *name, void *data) {
4297   __kmp_stg_print_bool(buffer, name, __kmp_forkjoin_frames);
4298 } // __kmp_stg_print_forkjoin_frames
4299 
4300 // -----------------------------------------------------------------------------
4301 // KMP_FORKJOIN_FRAMES_MODE
4302 
4303 static void __kmp_stg_parse_forkjoin_frames_mode(char const *name,
4304                                                  char const *value,
4305                                                  void *data) {
4306   __kmp_stg_parse_int(name, value, 0, 3, &__kmp_forkjoin_frames_mode);
4307 } // __kmp_stg_parse_forkjoin_frames
4308 
4309 static void __kmp_stg_print_forkjoin_frames_mode(kmp_str_buf_t *buffer,
4310                                                  char const *name, void *data) {
4311   __kmp_stg_print_int(buffer, name, __kmp_forkjoin_frames_mode);
4312 } // __kmp_stg_print_forkjoin_frames
4313 #endif /* USE_ITT_BUILD */
4314 
4315 // -----------------------------------------------------------------------------
4316 // OMP_DISPLAY_ENV
4317 
4318 #if OMP_40_ENABLED
4319 
4320 static void __kmp_stg_parse_omp_display_env(char const *name, char const *value,
4321                                             void *data) {
4322   if (__kmp_str_match("VERBOSE", 1, value)) {
4323     __kmp_display_env_verbose = TRUE;
4324   } else {
4325     __kmp_stg_parse_bool(name, value, &__kmp_display_env);
4326   }
4327 
4328 } // __kmp_stg_parse_omp_display_env
4329 
4330 static void __kmp_stg_print_omp_display_env(kmp_str_buf_t *buffer,
4331                                             char const *name, void *data) {
4332   if (__kmp_display_env_verbose) {
4333     __kmp_stg_print_str(buffer, name, "VERBOSE");
4334   } else {
4335     __kmp_stg_print_bool(buffer, name, __kmp_display_env);
4336   }
4337 } // __kmp_stg_print_omp_display_env
4338 
4339 static void __kmp_stg_parse_omp_cancellation(char const *name,
4340                                              char const *value, void *data) {
4341   if (TCR_4(__kmp_init_parallel)) {
4342     KMP_WARNING(EnvParallelWarn, name);
4343     return;
4344   } // read value before first parallel only
4345   __kmp_stg_parse_bool(name, value, &__kmp_omp_cancellation);
4346 } // __kmp_stg_parse_omp_cancellation
4347 
4348 static void __kmp_stg_print_omp_cancellation(kmp_str_buf_t *buffer,
4349                                              char const *name, void *data) {
4350   __kmp_stg_print_bool(buffer, name, __kmp_omp_cancellation);
4351 } // __kmp_stg_print_omp_cancellation
4352 
4353 #endif
4354 
4355 #if OMP_50_ENABLED && OMPT_SUPPORT
4356 
4357 static char *__kmp_tool_libraries = NULL;
4358 
4359 static void __kmp_stg_parse_omp_tool_libraries(char const *name,
4360                                                char const *value, void *data) {
4361   __kmp_stg_parse_str(name, value, &__kmp_tool_libraries);
4362 } // __kmp_stg_parse_omp_tool_libraries
4363 
4364 static void __kmp_stg_print_omp_tool_libraries(kmp_str_buf_t *buffer,
4365                                                char const *name, void *data) {
4366   if (__kmp_tool_libraries)
4367     __kmp_stg_print_str(buffer, name, __kmp_tool_libraries);
4368   else {
4369     if (__kmp_env_format) {
4370       KMP_STR_BUF_PRINT_NAME;
4371     } else {
4372       __kmp_str_buf_print(buffer, "   %s", name);
4373     }
4374     __kmp_str_buf_print(buffer, ": %s\n", KMP_I18N_STR(NotDefined));
4375   }
4376 } // __kmp_stg_print_omp_tool_libraries
4377 
4378 #endif
4379 
4380 // Table.
4381 
4382 static kmp_setting_t __kmp_stg_table[] = {
4383 
4384     {"KMP_ALL_THREADS", __kmp_stg_parse_device_thread_limit, NULL, NULL, 0, 0},
4385     {"KMP_BLOCKTIME", __kmp_stg_parse_blocktime, __kmp_stg_print_blocktime,
4386      NULL, 0, 0},
4387     {"KMP_DUPLICATE_LIB_OK", __kmp_stg_parse_duplicate_lib_ok,
4388      __kmp_stg_print_duplicate_lib_ok, NULL, 0, 0},
4389     {"KMP_LIBRARY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy,
4390      NULL, 0, 0},
4391     {"KMP_DEVICE_THREAD_LIMIT", __kmp_stg_parse_device_thread_limit,
4392      __kmp_stg_print_device_thread_limit, NULL, 0, 0},
4393 #if KMP_USE_MONITOR
4394     {"KMP_MONITOR_STACKSIZE", __kmp_stg_parse_monitor_stacksize,
4395      __kmp_stg_print_monitor_stacksize, NULL, 0, 0},
4396 #endif
4397     {"KMP_SETTINGS", __kmp_stg_parse_settings, __kmp_stg_print_settings, NULL,
4398      0, 0},
4399     {"KMP_STACKOFFSET", __kmp_stg_parse_stackoffset,
4400      __kmp_stg_print_stackoffset, NULL, 0, 0},
4401     {"KMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize,
4402      NULL, 0, 0},
4403     {"KMP_STACKPAD", __kmp_stg_parse_stackpad, __kmp_stg_print_stackpad, NULL,
4404      0, 0},
4405     {"KMP_VERSION", __kmp_stg_parse_version, __kmp_stg_print_version, NULL, 0,
4406      0},
4407     {"KMP_WARNINGS", __kmp_stg_parse_warnings, __kmp_stg_print_warnings, NULL,
4408      0, 0},
4409 
4410     {"OMP_NESTED", __kmp_stg_parse_nested, __kmp_stg_print_nested, NULL, 0, 0},
4411     {"OMP_NUM_THREADS", __kmp_stg_parse_num_threads,
4412      __kmp_stg_print_num_threads, NULL, 0, 0},
4413     {"OMP_STACKSIZE", __kmp_stg_parse_stacksize, __kmp_stg_print_stacksize,
4414      NULL, 0, 0},
4415 
4416     {"KMP_TASKING", __kmp_stg_parse_tasking, __kmp_stg_print_tasking, NULL, 0,
4417      0},
4418     {"KMP_TASK_STEALING_CONSTRAINT", __kmp_stg_parse_task_stealing,
4419      __kmp_stg_print_task_stealing, NULL, 0, 0},
4420     {"OMP_MAX_ACTIVE_LEVELS", __kmp_stg_parse_max_active_levels,
4421      __kmp_stg_print_max_active_levels, NULL, 0, 0},
4422 #if OMP_40_ENABLED
4423     {"OMP_DEFAULT_DEVICE", __kmp_stg_parse_default_device,
4424      __kmp_stg_print_default_device, NULL, 0, 0},
4425 #endif
4426 #if OMP_45_ENABLED
4427     {"OMP_MAX_TASK_PRIORITY", __kmp_stg_parse_max_task_priority,
4428      __kmp_stg_print_max_task_priority, NULL, 0, 0},
4429     {"KMP_TASKLOOP_MIN_TASKS", __kmp_stg_parse_taskloop_min_tasks,
4430      __kmp_stg_print_taskloop_min_tasks, NULL, 0, 0},
4431 #endif
4432     {"OMP_THREAD_LIMIT", __kmp_stg_parse_thread_limit,
4433      __kmp_stg_print_thread_limit, NULL, 0, 0},
4434     {"KMP_TEAMS_THREAD_LIMIT", __kmp_stg_parse_teams_thread_limit,
4435      __kmp_stg_print_teams_thread_limit, NULL, 0, 0},
4436     {"OMP_WAIT_POLICY", __kmp_stg_parse_wait_policy,
4437      __kmp_stg_print_wait_policy, NULL, 0, 0},
4438     {"KMP_DISP_NUM_BUFFERS", __kmp_stg_parse_disp_buffers,
4439      __kmp_stg_print_disp_buffers, NULL, 0, 0},
4440 #if KMP_NESTED_HOT_TEAMS
4441     {"KMP_HOT_TEAMS_MAX_LEVEL", __kmp_stg_parse_hot_teams_level,
4442      __kmp_stg_print_hot_teams_level, NULL, 0, 0},
4443     {"KMP_HOT_TEAMS_MODE", __kmp_stg_parse_hot_teams_mode,
4444      __kmp_stg_print_hot_teams_mode, NULL, 0, 0},
4445 #endif // KMP_NESTED_HOT_TEAMS
4446 
4447 #if KMP_HANDLE_SIGNALS
4448     {"KMP_HANDLE_SIGNALS", __kmp_stg_parse_handle_signals,
4449      __kmp_stg_print_handle_signals, NULL, 0, 0},
4450 #endif
4451 
4452 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
4453     {"KMP_INHERIT_FP_CONTROL", __kmp_stg_parse_inherit_fp_control,
4454      __kmp_stg_print_inherit_fp_control, NULL, 0, 0},
4455 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
4456 
4457 #ifdef KMP_GOMP_COMPAT
4458     {"GOMP_STACKSIZE", __kmp_stg_parse_stacksize, NULL, NULL, 0, 0},
4459 #endif
4460 
4461 #ifdef KMP_DEBUG
4462     {"KMP_A_DEBUG", __kmp_stg_parse_a_debug, __kmp_stg_print_a_debug, NULL, 0,
4463      0},
4464     {"KMP_B_DEBUG", __kmp_stg_parse_b_debug, __kmp_stg_print_b_debug, NULL, 0,
4465      0},
4466     {"KMP_C_DEBUG", __kmp_stg_parse_c_debug, __kmp_stg_print_c_debug, NULL, 0,
4467      0},
4468     {"KMP_D_DEBUG", __kmp_stg_parse_d_debug, __kmp_stg_print_d_debug, NULL, 0,
4469      0},
4470     {"KMP_E_DEBUG", __kmp_stg_parse_e_debug, __kmp_stg_print_e_debug, NULL, 0,
4471      0},
4472     {"KMP_F_DEBUG", __kmp_stg_parse_f_debug, __kmp_stg_print_f_debug, NULL, 0,
4473      0},
4474     {"KMP_DEBUG", __kmp_stg_parse_debug, NULL, /* no print */ NULL, 0, 0},
4475     {"KMP_DEBUG_BUF", __kmp_stg_parse_debug_buf, __kmp_stg_print_debug_buf,
4476      NULL, 0, 0},
4477     {"KMP_DEBUG_BUF_ATOMIC", __kmp_stg_parse_debug_buf_atomic,
4478      __kmp_stg_print_debug_buf_atomic, NULL, 0, 0},
4479     {"KMP_DEBUG_BUF_CHARS", __kmp_stg_parse_debug_buf_chars,
4480      __kmp_stg_print_debug_buf_chars, NULL, 0, 0},
4481     {"KMP_DEBUG_BUF_LINES", __kmp_stg_parse_debug_buf_lines,
4482      __kmp_stg_print_debug_buf_lines, NULL, 0, 0},
4483     {"KMP_DIAG", __kmp_stg_parse_diag, __kmp_stg_print_diag, NULL, 0, 0},
4484 
4485     {"KMP_PAR_RANGE", __kmp_stg_parse_par_range_env,
4486      __kmp_stg_print_par_range_env, NULL, 0, 0},
4487     {"KMP_YIELD_CYCLE", __kmp_stg_parse_yield_cycle,
4488      __kmp_stg_print_yield_cycle, NULL, 0, 0},
4489     {"KMP_YIELD_ON", __kmp_stg_parse_yield_on, __kmp_stg_print_yield_on, NULL,
4490      0, 0},
4491     {"KMP_YIELD_OFF", __kmp_stg_parse_yield_off, __kmp_stg_print_yield_off,
4492      NULL, 0, 0},
4493 #endif // KMP_DEBUG
4494 
4495     {"KMP_ALIGN_ALLOC", __kmp_stg_parse_align_alloc,
4496      __kmp_stg_print_align_alloc, NULL, 0, 0},
4497 
4498     {"KMP_PLAIN_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4499      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4500     {"KMP_PLAIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4501      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4502     {"KMP_FORKJOIN_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4503      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4504     {"KMP_FORKJOIN_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4505      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4506 #if KMP_FAST_REDUCTION_BARRIER
4507     {"KMP_REDUCTION_BARRIER", __kmp_stg_parse_barrier_branch_bit,
4508      __kmp_stg_print_barrier_branch_bit, NULL, 0, 0},
4509     {"KMP_REDUCTION_BARRIER_PATTERN", __kmp_stg_parse_barrier_pattern,
4510      __kmp_stg_print_barrier_pattern, NULL, 0, 0},
4511 #endif
4512 
4513     {"KMP_ABORT_DELAY", __kmp_stg_parse_abort_delay,
4514      __kmp_stg_print_abort_delay, NULL, 0, 0},
4515     {"KMP_CPUINFO_FILE", __kmp_stg_parse_cpuinfo_file,
4516      __kmp_stg_print_cpuinfo_file, NULL, 0, 0},
4517     {"KMP_FORCE_REDUCTION", __kmp_stg_parse_force_reduction,
4518      __kmp_stg_print_force_reduction, NULL, 0, 0},
4519     {"KMP_DETERMINISTIC_REDUCTION", __kmp_stg_parse_force_reduction,
4520      __kmp_stg_print_force_reduction, NULL, 0, 0},
4521     {"KMP_STORAGE_MAP", __kmp_stg_parse_storage_map,
4522      __kmp_stg_print_storage_map, NULL, 0, 0},
4523     {"KMP_ALL_THREADPRIVATE", __kmp_stg_parse_all_threadprivate,
4524      __kmp_stg_print_all_threadprivate, NULL, 0, 0},
4525     {"KMP_FOREIGN_THREADS_THREADPRIVATE",
4526      __kmp_stg_parse_foreign_threads_threadprivate,
4527      __kmp_stg_print_foreign_threads_threadprivate, NULL, 0, 0},
4528 
4529 #if KMP_AFFINITY_SUPPORTED
4530     {"KMP_AFFINITY", __kmp_stg_parse_affinity, __kmp_stg_print_affinity, NULL,
4531      0, 0},
4532 #ifdef KMP_GOMP_COMPAT
4533     {"GOMP_CPU_AFFINITY", __kmp_stg_parse_gomp_cpu_affinity, NULL,
4534      /* no print */ NULL, 0, 0},
4535 #endif /* KMP_GOMP_COMPAT */
4536 #if OMP_40_ENABLED
4537     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind,
4538      NULL, 0, 0},
4539     {"OMP_PLACES", __kmp_stg_parse_places, __kmp_stg_print_places, NULL, 0, 0},
4540 #else
4541     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, NULL, /* no print */ NULL, 0,
4542      0},
4543 #endif /* OMP_40_ENABLED */
4544 
4545     {"KMP_TOPOLOGY_METHOD", __kmp_stg_parse_topology_method,
4546      __kmp_stg_print_topology_method, NULL, 0, 0},
4547 
4548 #else
4549 
4550 // KMP_AFFINITY is not supported on OS X*, nor is OMP_PLACES.
4551 // OMP_PROC_BIND and proc-bind-var are supported, however.
4552 #if OMP_40_ENABLED
4553     {"OMP_PROC_BIND", __kmp_stg_parse_proc_bind, __kmp_stg_print_proc_bind,
4554      NULL, 0, 0},
4555 #endif
4556 
4557 #endif // KMP_AFFINITY_SUPPORTED
4558 
4559     {"KMP_INIT_AT_FORK", __kmp_stg_parse_init_at_fork,
4560      __kmp_stg_print_init_at_fork, NULL, 0, 0},
4561     {"KMP_SCHEDULE", __kmp_stg_parse_schedule, __kmp_stg_print_schedule, NULL,
4562      0, 0},
4563     {"OMP_SCHEDULE", __kmp_stg_parse_omp_schedule, __kmp_stg_print_omp_schedule,
4564      NULL, 0, 0},
4565     {"KMP_ATOMIC_MODE", __kmp_stg_parse_atomic_mode,
4566      __kmp_stg_print_atomic_mode, NULL, 0, 0},
4567     {"KMP_CONSISTENCY_CHECK", __kmp_stg_parse_consistency_check,
4568      __kmp_stg_print_consistency_check, NULL, 0, 0},
4569 
4570 #if USE_ITT_BUILD && USE_ITT_NOTIFY
4571     {"KMP_ITT_PREPARE_DELAY", __kmp_stg_parse_itt_prepare_delay,
4572      __kmp_stg_print_itt_prepare_delay, NULL, 0, 0},
4573 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
4574     {"KMP_MALLOC_POOL_INCR", __kmp_stg_parse_malloc_pool_incr,
4575      __kmp_stg_print_malloc_pool_incr, NULL, 0, 0},
4576     {"KMP_INIT_WAIT", __kmp_stg_parse_init_wait, __kmp_stg_print_init_wait,
4577      NULL, 0, 0},
4578     {"KMP_NEXT_WAIT", __kmp_stg_parse_next_wait, __kmp_stg_print_next_wait,
4579      NULL, 0, 0},
4580     {"KMP_GTID_MODE", __kmp_stg_parse_gtid_mode, __kmp_stg_print_gtid_mode,
4581      NULL, 0, 0},
4582     {"OMP_DYNAMIC", __kmp_stg_parse_omp_dynamic, __kmp_stg_print_omp_dynamic,
4583      NULL, 0, 0},
4584     {"KMP_DYNAMIC_MODE", __kmp_stg_parse_kmp_dynamic_mode,
4585      __kmp_stg_print_kmp_dynamic_mode, NULL, 0, 0},
4586 
4587 #ifdef USE_LOAD_BALANCE
4588     {"KMP_LOAD_BALANCE_INTERVAL", __kmp_stg_parse_ld_balance_interval,
4589      __kmp_stg_print_ld_balance_interval, NULL, 0, 0},
4590 #endif
4591 
4592     {"KMP_NUM_LOCKS_IN_BLOCK", __kmp_stg_parse_lock_block,
4593      __kmp_stg_print_lock_block, NULL, 0, 0},
4594     {"KMP_LOCK_KIND", __kmp_stg_parse_lock_kind, __kmp_stg_print_lock_kind,
4595      NULL, 0, 0},
4596     {"KMP_SPIN_BACKOFF_PARAMS", __kmp_stg_parse_spin_backoff_params,
4597      __kmp_stg_print_spin_backoff_params, NULL, 0, 0},
4598 #if KMP_USE_ADAPTIVE_LOCKS
4599     {"KMP_ADAPTIVE_LOCK_PROPS", __kmp_stg_parse_adaptive_lock_props,
4600      __kmp_stg_print_adaptive_lock_props, NULL, 0, 0},
4601 #if KMP_DEBUG_ADAPTIVE_LOCKS
4602     {"KMP_SPECULATIVE_STATSFILE", __kmp_stg_parse_speculative_statsfile,
4603      __kmp_stg_print_speculative_statsfile, NULL, 0, 0},
4604 #endif
4605 #endif // KMP_USE_ADAPTIVE_LOCKS
4606     {"KMP_PLACE_THREADS", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset,
4607      NULL, 0, 0},
4608     {"KMP_HW_SUBSET", __kmp_stg_parse_hw_subset, __kmp_stg_print_hw_subset,
4609      NULL, 0, 0},
4610 #if USE_ITT_BUILD
4611     {"KMP_FORKJOIN_FRAMES", __kmp_stg_parse_forkjoin_frames,
4612      __kmp_stg_print_forkjoin_frames, NULL, 0, 0},
4613     {"KMP_FORKJOIN_FRAMES_MODE", __kmp_stg_parse_forkjoin_frames_mode,
4614      __kmp_stg_print_forkjoin_frames_mode, NULL, 0, 0},
4615 #endif
4616 
4617 #if OMP_40_ENABLED
4618     {"OMP_DISPLAY_ENV", __kmp_stg_parse_omp_display_env,
4619      __kmp_stg_print_omp_display_env, NULL, 0, 0},
4620     {"OMP_CANCELLATION", __kmp_stg_parse_omp_cancellation,
4621      __kmp_stg_print_omp_cancellation, NULL, 0, 0},
4622 #endif
4623 
4624 #if OMP_50_ENABLED && OMPT_SUPPORT
4625     {"OMP_TOOL_LIBRARIES", __kmp_stg_parse_omp_tool_libraries,
4626      __kmp_stg_print_omp_tool_libraries, NULL, 0, 0},
4627 #endif
4628 
4629     {"", NULL, NULL, NULL, 0, 0}}; // settings
4630 
4631 static int const __kmp_stg_count =
4632     sizeof(__kmp_stg_table) / sizeof(kmp_setting_t);
4633 
4634 static inline kmp_setting_t *__kmp_stg_find(char const *name) {
4635 
4636   int i;
4637   if (name != NULL) {
4638     for (i = 0; i < __kmp_stg_count; ++i) {
4639       if (strcmp(__kmp_stg_table[i].name, name) == 0) {
4640         return &__kmp_stg_table[i];
4641       }
4642     }
4643   }
4644   return NULL;
4645 
4646 } // __kmp_stg_find
4647 
4648 static int __kmp_stg_cmp(void const *_a, void const *_b) {
4649   const kmp_setting_t *a = RCAST(const kmp_setting_t *, _a);
4650   const kmp_setting_t *b = RCAST(const kmp_setting_t *, _b);
4651 
4652   // Process KMP_AFFINITY last.
4653   // It needs to come after OMP_PLACES and GOMP_CPU_AFFINITY.
4654   if (strcmp(a->name, "KMP_AFFINITY") == 0) {
4655     if (strcmp(b->name, "KMP_AFFINITY") == 0) {
4656       return 0;
4657     }
4658     return 1;
4659   } else if (strcmp(b->name, "KMP_AFFINITY") == 0) {
4660     return -1;
4661   }
4662   return strcmp(a->name, b->name);
4663 } // __kmp_stg_cmp
4664 
4665 static void __kmp_stg_init(void) {
4666 
4667   static int initialized = 0;
4668 
4669   if (!initialized) {
4670 
4671     // Sort table.
4672     qsort(__kmp_stg_table, __kmp_stg_count - 1, sizeof(kmp_setting_t),
4673           __kmp_stg_cmp);
4674 
4675     { // Initialize *_STACKSIZE data.
4676       kmp_setting_t *kmp_stacksize =
4677           __kmp_stg_find("KMP_STACKSIZE"); // 1st priority.
4678 #ifdef KMP_GOMP_COMPAT
4679       kmp_setting_t *gomp_stacksize =
4680           __kmp_stg_find("GOMP_STACKSIZE"); // 2nd priority.
4681 #endif
4682       kmp_setting_t *omp_stacksize =
4683           __kmp_stg_find("OMP_STACKSIZE"); // 3rd priority.
4684 
4685       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4686       // !!! Compiler does not understand rivals is used and optimizes out
4687       // assignments
4688       // !!!     rivals[ i ++ ] = ...;
4689       static kmp_setting_t *volatile rivals[4];
4690       static kmp_stg_ss_data_t kmp_data = {1, CCAST(kmp_setting_t **, rivals)};
4691 #ifdef KMP_GOMP_COMPAT
4692       static kmp_stg_ss_data_t gomp_data = {1024,
4693                                             CCAST(kmp_setting_t **, rivals)};
4694 #endif
4695       static kmp_stg_ss_data_t omp_data = {1024,
4696                                            CCAST(kmp_setting_t **, rivals)};
4697       int i = 0;
4698 
4699       rivals[i++] = kmp_stacksize;
4700 #ifdef KMP_GOMP_COMPAT
4701       if (gomp_stacksize != NULL) {
4702         rivals[i++] = gomp_stacksize;
4703       }
4704 #endif
4705       rivals[i++] = omp_stacksize;
4706       rivals[i++] = NULL;
4707 
4708       kmp_stacksize->data = &kmp_data;
4709 #ifdef KMP_GOMP_COMPAT
4710       if (gomp_stacksize != NULL) {
4711         gomp_stacksize->data = &gomp_data;
4712       }
4713 #endif
4714       omp_stacksize->data = &omp_data;
4715     }
4716 
4717     { // Initialize KMP_LIBRARY and OMP_WAIT_POLICY data.
4718       kmp_setting_t *kmp_library =
4719           __kmp_stg_find("KMP_LIBRARY"); // 1st priority.
4720       kmp_setting_t *omp_wait_policy =
4721           __kmp_stg_find("OMP_WAIT_POLICY"); // 2nd priority.
4722 
4723       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4724       static kmp_setting_t *volatile rivals[3];
4725       static kmp_stg_wp_data_t kmp_data = {0, CCAST(kmp_setting_t **, rivals)};
4726       static kmp_stg_wp_data_t omp_data = {1, CCAST(kmp_setting_t **, rivals)};
4727       int i = 0;
4728 
4729       rivals[i++] = kmp_library;
4730       if (omp_wait_policy != NULL) {
4731         rivals[i++] = omp_wait_policy;
4732       }
4733       rivals[i++] = NULL;
4734 
4735       kmp_library->data = &kmp_data;
4736       if (omp_wait_policy != NULL) {
4737         omp_wait_policy->data = &omp_data;
4738       }
4739     }
4740 
4741     { // Initialize KMP_DEVICE_THREAD_LIMIT and KMP_ALL_THREADS
4742       kmp_setting_t *kmp_device_thread_limit =
4743           __kmp_stg_find("KMP_DEVICE_THREAD_LIMIT"); // 1st priority.
4744       kmp_setting_t *kmp_all_threads =
4745           __kmp_stg_find("KMP_ALL_THREADS"); // 2nd priority.
4746 
4747       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4748       static kmp_setting_t *volatile rivals[3];
4749       int i = 0;
4750 
4751       rivals[i++] = kmp_device_thread_limit;
4752       rivals[i++] = kmp_all_threads;
4753       rivals[i++] = NULL;
4754 
4755       kmp_device_thread_limit->data = CCAST(kmp_setting_t **, rivals);
4756       kmp_all_threads->data = CCAST(kmp_setting_t **, rivals);
4757     }
4758 
4759     { // Initialize KMP_HW_SUBSET and KMP_PLACE_THREADS
4760       // 1st priority
4761       kmp_setting_t *kmp_hw_subset = __kmp_stg_find("KMP_HW_SUBSET");
4762       // 2nd priority
4763       kmp_setting_t *kmp_place_threads = __kmp_stg_find("KMP_PLACE_THREADS");
4764 
4765       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4766       static kmp_setting_t *volatile rivals[3];
4767       int i = 0;
4768 
4769       rivals[i++] = kmp_hw_subset;
4770       rivals[i++] = kmp_place_threads;
4771       rivals[i++] = NULL;
4772 
4773       kmp_hw_subset->data = CCAST(kmp_setting_t **, rivals);
4774       kmp_place_threads->data = CCAST(kmp_setting_t **, rivals);
4775     }
4776 
4777 #if KMP_AFFINITY_SUPPORTED
4778     { // Initialize KMP_AFFINITY, GOMP_CPU_AFFINITY, and OMP_PROC_BIND data.
4779       kmp_setting_t *kmp_affinity =
4780           __kmp_stg_find("KMP_AFFINITY"); // 1st priority.
4781       KMP_DEBUG_ASSERT(kmp_affinity != NULL);
4782 
4783 #ifdef KMP_GOMP_COMPAT
4784       kmp_setting_t *gomp_cpu_affinity =
4785           __kmp_stg_find("GOMP_CPU_AFFINITY"); // 2nd priority.
4786       KMP_DEBUG_ASSERT(gomp_cpu_affinity != NULL);
4787 #endif
4788 
4789       kmp_setting_t *omp_proc_bind =
4790           __kmp_stg_find("OMP_PROC_BIND"); // 3rd priority.
4791       KMP_DEBUG_ASSERT(omp_proc_bind != NULL);
4792 
4793       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4794       static kmp_setting_t *volatile rivals[4];
4795       int i = 0;
4796 
4797       rivals[i++] = kmp_affinity;
4798 
4799 #ifdef KMP_GOMP_COMPAT
4800       rivals[i++] = gomp_cpu_affinity;
4801       gomp_cpu_affinity->data = CCAST(kmp_setting_t **, rivals);
4802 #endif
4803 
4804       rivals[i++] = omp_proc_bind;
4805       omp_proc_bind->data = CCAST(kmp_setting_t **, rivals);
4806       rivals[i++] = NULL;
4807 
4808 #if OMP_40_ENABLED
4809       static kmp_setting_t *volatile places_rivals[4];
4810       i = 0;
4811 
4812       kmp_setting_t *omp_places = __kmp_stg_find("OMP_PLACES"); // 3rd priority.
4813       KMP_DEBUG_ASSERT(omp_places != NULL);
4814 
4815       places_rivals[i++] = kmp_affinity;
4816 #ifdef KMP_GOMP_COMPAT
4817       places_rivals[i++] = gomp_cpu_affinity;
4818 #endif
4819       places_rivals[i++] = omp_places;
4820       omp_places->data = CCAST(kmp_setting_t **, places_rivals);
4821       places_rivals[i++] = NULL;
4822 #endif
4823     }
4824 #else
4825 // KMP_AFFINITY not supported, so OMP_PROC_BIND has no rivals.
4826 // OMP_PLACES not supported yet.
4827 #endif // KMP_AFFINITY_SUPPORTED
4828 
4829     { // Initialize KMP_DETERMINISTIC_REDUCTION and KMP_FORCE_REDUCTION data.
4830       kmp_setting_t *kmp_force_red =
4831           __kmp_stg_find("KMP_FORCE_REDUCTION"); // 1st priority.
4832       kmp_setting_t *kmp_determ_red =
4833           __kmp_stg_find("KMP_DETERMINISTIC_REDUCTION"); // 2nd priority.
4834 
4835       // !!! volatile keyword is Intel (R) C Compiler bug CQ49908 workaround.
4836       static kmp_setting_t *volatile rivals[3];
4837       static kmp_stg_fr_data_t force_data = {1,
4838                                              CCAST(kmp_setting_t **, rivals)};
4839       static kmp_stg_fr_data_t determ_data = {0,
4840                                               CCAST(kmp_setting_t **, rivals)};
4841       int i = 0;
4842 
4843       rivals[i++] = kmp_force_red;
4844       if (kmp_determ_red != NULL) {
4845         rivals[i++] = kmp_determ_red;
4846       }
4847       rivals[i++] = NULL;
4848 
4849       kmp_force_red->data = &force_data;
4850       if (kmp_determ_red != NULL) {
4851         kmp_determ_red->data = &determ_data;
4852       }
4853     }
4854 
4855     initialized = 1;
4856   }
4857 
4858   // Reset flags.
4859   int i;
4860   for (i = 0; i < __kmp_stg_count; ++i) {
4861     __kmp_stg_table[i].set = 0;
4862   }
4863 
4864 } // __kmp_stg_init
4865 
4866 static void __kmp_stg_parse(char const *name, char const *value) {
4867   // On Windows* OS there are some nameless variables like "C:=C:\" (yeah,
4868   // really nameless, they are presented in environment block as
4869   // "=C:=C\\\x00=D:=D:\\\x00...", so let us skip them.
4870   if (name[0] == 0) {
4871     return;
4872   }
4873 
4874   if (value != NULL) {
4875     kmp_setting_t *setting = __kmp_stg_find(name);
4876     if (setting != NULL) {
4877       setting->parse(name, value, setting->data);
4878       setting->defined = 1;
4879     }
4880   }
4881 
4882 } // __kmp_stg_parse
4883 
4884 static int __kmp_stg_check_rivals( // 0 -- Ok, 1 -- errors found.
4885     char const *name, // Name of variable.
4886     char const *value, // Value of the variable.
4887     kmp_setting_t **rivals // List of rival settings (must include current one).
4888     ) {
4889 
4890   if (rivals == NULL) {
4891     return 0;
4892   }
4893 
4894   // Loop thru higher priority settings (listed before current).
4895   int i = 0;
4896   for (; strcmp(rivals[i]->name, name) != 0; i++) {
4897     KMP_DEBUG_ASSERT(rivals[i] != NULL);
4898 
4899 #if KMP_AFFINITY_SUPPORTED
4900     if (rivals[i] == __kmp_affinity_notype) {
4901       // If KMP_AFFINITY is specified without a type name,
4902       // it does not rival OMP_PROC_BIND or GOMP_CPU_AFFINITY.
4903       continue;
4904     }
4905 #endif
4906 
4907     if (rivals[i]->set) {
4908       KMP_WARNING(StgIgnored, name, rivals[i]->name);
4909       return 1;
4910     }
4911   }
4912 
4913   ++i; // Skip current setting.
4914   return 0;
4915 
4916 } // __kmp_stg_check_rivals
4917 
4918 static int __kmp_env_toPrint(char const *name, int flag) {
4919   int rc = 0;
4920   kmp_setting_t *setting = __kmp_stg_find(name);
4921   if (setting != NULL) {
4922     rc = setting->defined;
4923     if (flag >= 0) {
4924       setting->defined = flag;
4925     }
4926   }
4927   return rc;
4928 }
4929 
4930 static void __kmp_aux_env_initialize(kmp_env_blk_t *block) {
4931 
4932   char const *value;
4933 
4934   /* OMP_NUM_THREADS */
4935   value = __kmp_env_blk_var(block, "OMP_NUM_THREADS");
4936   if (value) {
4937     ompc_set_num_threads(__kmp_dflt_team_nth);
4938   }
4939 
4940   /* KMP_BLOCKTIME */
4941   value = __kmp_env_blk_var(block, "KMP_BLOCKTIME");
4942   if (value) {
4943     kmpc_set_blocktime(__kmp_dflt_blocktime);
4944   }
4945 
4946   /* OMP_NESTED */
4947   value = __kmp_env_blk_var(block, "OMP_NESTED");
4948   if (value) {
4949     ompc_set_nested(__kmp_dflt_nested);
4950   }
4951 
4952   /* OMP_DYNAMIC */
4953   value = __kmp_env_blk_var(block, "OMP_DYNAMIC");
4954   if (value) {
4955     ompc_set_dynamic(__kmp_global.g.g_dynamic);
4956   }
4957 }
4958 
4959 void __kmp_env_initialize(char const *string) {
4960 
4961   kmp_env_blk_t block;
4962   int i;
4963 
4964   __kmp_stg_init();
4965 
4966   // Hack!!!
4967   if (string == NULL) {
4968     // __kmp_max_nth = __kmp_sys_max_nth;
4969     __kmp_threads_capacity =
4970         __kmp_initial_threads_capacity(__kmp_dflt_team_nth_ub);
4971   }
4972   __kmp_env_blk_init(&block, string);
4973 
4974   // update the set flag on all entries that have an env var
4975   for (i = 0; i < block.count; ++i) {
4976     if ((block.vars[i].name == NULL) || (*block.vars[i].name == '\0')) {
4977       continue;
4978     }
4979     if (block.vars[i].value == NULL) {
4980       continue;
4981     }
4982     kmp_setting_t *setting = __kmp_stg_find(block.vars[i].name);
4983     if (setting != NULL) {
4984       setting->set = 1;
4985     }
4986   }
4987 
4988   // We need to know if blocktime was set when processing OMP_WAIT_POLICY
4989   blocktime_str = __kmp_env_blk_var(&block, "KMP_BLOCKTIME");
4990 
4991   // Special case. If we parse environment, not a string, process KMP_WARNINGS
4992   // first.
4993   if (string == NULL) {
4994     char const *name = "KMP_WARNINGS";
4995     char const *value = __kmp_env_blk_var(&block, name);
4996     __kmp_stg_parse(name, value);
4997   }
4998 
4999 #if KMP_AFFINITY_SUPPORTED
5000   // Special case. KMP_AFFINITY is not a rival to other affinity env vars
5001   // if no affinity type is specified.  We want to allow
5002   // KMP_AFFINITY=[no],verbose/[no]warnings/etc.  to be enabled when
5003   // specifying the affinity type via GOMP_CPU_AFFINITY or the OMP 4.0
5004   // affinity mechanism.
5005   __kmp_affinity_notype = NULL;
5006   char const *aff_str = __kmp_env_blk_var(&block, "KMP_AFFINITY");
5007   if (aff_str != NULL) {
5008 // Check if the KMP_AFFINITY type is specified in the string.
5009 // We just search the string for "compact", "scatter", etc.
5010 // without really parsing the string.  The syntax of the
5011 // KMP_AFFINITY env var is such that none of the affinity
5012 // type names can appear anywhere other that the type
5013 // specifier, even as substrings.
5014 //
5015 // I can't find a case-insensitive version of strstr on Windows* OS.
5016 // Use the case-sensitive version for now.
5017 
5018 #if KMP_OS_WINDOWS
5019 #define FIND strstr
5020 #else
5021 #define FIND strcasestr
5022 #endif
5023 
5024     if ((FIND(aff_str, "none") == NULL) &&
5025         (FIND(aff_str, "physical") == NULL) &&
5026         (FIND(aff_str, "logical") == NULL) &&
5027         (FIND(aff_str, "compact") == NULL) &&
5028         (FIND(aff_str, "scatter") == NULL) &&
5029         (FIND(aff_str, "explicit") == NULL) &&
5030         (FIND(aff_str, "balanced") == NULL) &&
5031         (FIND(aff_str, "disabled") == NULL)) {
5032       __kmp_affinity_notype = __kmp_stg_find("KMP_AFFINITY");
5033     } else {
5034       // A new affinity type is specified.
5035       // Reset the affinity flags to their default values,
5036       // in case this is called from kmp_set_defaults().
5037       __kmp_affinity_type = affinity_default;
5038       __kmp_affinity_gran = affinity_gran_default;
5039       __kmp_affinity_top_method = affinity_top_method_default;
5040       __kmp_affinity_respect_mask = affinity_respect_mask_default;
5041     }
5042 #undef FIND
5043 
5044 #if OMP_40_ENABLED
5045     // Also reset the affinity flags if OMP_PROC_BIND is specified.
5046     aff_str = __kmp_env_blk_var(&block, "OMP_PROC_BIND");
5047     if (aff_str != NULL) {
5048       __kmp_affinity_type = affinity_default;
5049       __kmp_affinity_gran = affinity_gran_default;
5050       __kmp_affinity_top_method = affinity_top_method_default;
5051       __kmp_affinity_respect_mask = affinity_respect_mask_default;
5052     }
5053 #endif /* OMP_40_ENABLED */
5054   }
5055 
5056 #endif /* KMP_AFFINITY_SUPPORTED */
5057 
5058 #if OMP_40_ENABLED
5059   // Set up the nested proc bind type vector.
5060   if (__kmp_nested_proc_bind.bind_types == NULL) {
5061     __kmp_nested_proc_bind.bind_types =
5062         (kmp_proc_bind_t *)KMP_INTERNAL_MALLOC(sizeof(kmp_proc_bind_t));
5063     if (__kmp_nested_proc_bind.bind_types == NULL) {
5064       KMP_FATAL(MemoryAllocFailed);
5065     }
5066     __kmp_nested_proc_bind.size = 1;
5067     __kmp_nested_proc_bind.used = 1;
5068 #if KMP_AFFINITY_SUPPORTED
5069     __kmp_nested_proc_bind.bind_types[0] = proc_bind_default;
5070 #else
5071     // default proc bind is false if affinity not supported
5072     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5073 #endif
5074   }
5075 #endif /* OMP_40_ENABLED */
5076 
5077   // Now process all of the settings.
5078   for (i = 0; i < block.count; ++i) {
5079     __kmp_stg_parse(block.vars[i].name, block.vars[i].value);
5080   }
5081 
5082   // If user locks have been allocated yet, don't reset the lock vptr table.
5083   if (!__kmp_init_user_locks) {
5084     if (__kmp_user_lock_kind == lk_default) {
5085       __kmp_user_lock_kind = lk_queuing;
5086     }
5087 #if KMP_USE_DYNAMIC_LOCK
5088     __kmp_init_dynamic_user_locks();
5089 #else
5090     __kmp_set_user_lock_vptrs(__kmp_user_lock_kind);
5091 #endif
5092   } else {
5093     KMP_DEBUG_ASSERT(string != NULL); // kmp_set_defaults() was called
5094     KMP_DEBUG_ASSERT(__kmp_user_lock_kind != lk_default);
5095 // Binds lock functions again to follow the transition between different
5096 // KMP_CONSISTENCY_CHECK values. Calling this again is harmless as long
5097 // as we do not allow lock kind changes after making a call to any
5098 // user lock functions (true).
5099 #if KMP_USE_DYNAMIC_LOCK
5100     __kmp_init_dynamic_user_locks();
5101 #else
5102     __kmp_set_user_lock_vptrs(__kmp_user_lock_kind);
5103 #endif
5104   }
5105 
5106 #if KMP_AFFINITY_SUPPORTED
5107 
5108   if (!TCR_4(__kmp_init_middle)) {
5109     // Determine if the machine/OS is actually capable of supporting
5110     // affinity.
5111     const char *var = "KMP_AFFINITY";
5112     KMPAffinity::pick_api();
5113 #if KMP_USE_HWLOC
5114     // If Hwloc topology discovery was requested but affinity was also disabled,
5115     // then tell user that Hwloc request is being ignored and use default
5116     // topology discovery method.
5117     if (__kmp_affinity_top_method == affinity_top_method_hwloc &&
5118         __kmp_affinity_dispatch->get_api_type() != KMPAffinity::HWLOC) {
5119       KMP_WARNING(AffIgnoringHwloc, var);
5120       __kmp_affinity_top_method = affinity_top_method_all;
5121     }
5122 #endif
5123     if (__kmp_affinity_type == affinity_disabled) {
5124       KMP_AFFINITY_DISABLE();
5125     } else if (!KMP_AFFINITY_CAPABLE()) {
5126       __kmp_affinity_dispatch->determine_capable(var);
5127       if (!KMP_AFFINITY_CAPABLE()) {
5128         if (__kmp_affinity_verbose ||
5129             (__kmp_affinity_warnings &&
5130              (__kmp_affinity_type != affinity_default) &&
5131              (__kmp_affinity_type != affinity_none) &&
5132              (__kmp_affinity_type != affinity_disabled))) {
5133           KMP_WARNING(AffNotSupported, var);
5134         }
5135         __kmp_affinity_type = affinity_disabled;
5136         __kmp_affinity_respect_mask = 0;
5137         __kmp_affinity_gran = affinity_gran_fine;
5138       }
5139     }
5140 
5141 #if OMP_40_ENABLED
5142     if (__kmp_affinity_type == affinity_disabled) {
5143       __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5144     } else if (__kmp_nested_proc_bind.bind_types[0] == proc_bind_true) {
5145       // OMP_PROC_BIND=true maps to OMP_PROC_BIND=spread.
5146       __kmp_nested_proc_bind.bind_types[0] = proc_bind_spread;
5147     }
5148 #endif /* OMP_40_ENABLED */
5149 
5150     if (KMP_AFFINITY_CAPABLE()) {
5151 
5152 #if KMP_GROUP_AFFINITY
5153       // This checks to see if the initial affinity mask is equal
5154       // to a single windows processor group.  If it is, then we do
5155       // not respect the initial affinity mask and instead, use the
5156       // entire machine.
5157       bool exactly_one_group = false;
5158       if (__kmp_num_proc_groups > 1) {
5159         int group;
5160         bool within_one_group;
5161         // Get the initial affinity mask and determine if it is
5162         // contained within a single group.
5163         kmp_affin_mask_t *init_mask;
5164         KMP_CPU_ALLOC(init_mask);
5165         __kmp_get_system_affinity(init_mask, TRUE);
5166         group = __kmp_get_proc_group(init_mask);
5167         within_one_group = (group >= 0);
5168         // If the initial affinity is within a single group,
5169         // then determine if it is equal to that single group.
5170         if (within_one_group) {
5171           DWORD num_bits_in_group = __kmp_GetActiveProcessorCount(group);
5172           int num_bits_in_mask = 0;
5173           for (int bit = init_mask->begin(); bit != init_mask->end();
5174                bit = init_mask->next(bit))
5175             num_bits_in_mask++;
5176           exactly_one_group = (num_bits_in_group == num_bits_in_mask);
5177         }
5178         KMP_CPU_FREE(init_mask);
5179       }
5180 
5181       // Handle the Win 64 group affinity stuff if there are multiple
5182       // processor groups, or if the user requested it, and OMP 4.0
5183       // affinity is not in effect.
5184       if (((__kmp_num_proc_groups > 1) &&
5185            (__kmp_affinity_type == affinity_default)
5186 #if OMP_40_ENABLED
5187            && (__kmp_nested_proc_bind.bind_types[0] == proc_bind_default))
5188 #endif
5189           || (__kmp_affinity_top_method == affinity_top_method_group)) {
5190         if (__kmp_affinity_respect_mask == affinity_respect_mask_default &&
5191             exactly_one_group) {
5192           __kmp_affinity_respect_mask = FALSE;
5193         }
5194         if (__kmp_affinity_type == affinity_default) {
5195           __kmp_affinity_type = affinity_compact;
5196 #if OMP_40_ENABLED
5197           __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
5198 #endif
5199         }
5200         if (__kmp_affinity_top_method == affinity_top_method_default) {
5201           if (__kmp_affinity_gran == affinity_gran_default) {
5202             __kmp_affinity_top_method = affinity_top_method_group;
5203             __kmp_affinity_gran = affinity_gran_group;
5204           } else if (__kmp_affinity_gran == affinity_gran_group) {
5205             __kmp_affinity_top_method = affinity_top_method_group;
5206           } else {
5207             __kmp_affinity_top_method = affinity_top_method_all;
5208           }
5209         } else if (__kmp_affinity_top_method == affinity_top_method_group) {
5210           if (__kmp_affinity_gran == affinity_gran_default) {
5211             __kmp_affinity_gran = affinity_gran_group;
5212           } else if ((__kmp_affinity_gran != affinity_gran_group) &&
5213                      (__kmp_affinity_gran != affinity_gran_fine) &&
5214                      (__kmp_affinity_gran != affinity_gran_thread)) {
5215             const char *str = NULL;
5216             switch (__kmp_affinity_gran) {
5217             case affinity_gran_core:
5218               str = "core";
5219               break;
5220             case affinity_gran_package:
5221               str = "package";
5222               break;
5223             case affinity_gran_node:
5224               str = "node";
5225               break;
5226             default:
5227               KMP_DEBUG_ASSERT(0);
5228             }
5229             KMP_WARNING(AffGranTopGroup, var, str);
5230             __kmp_affinity_gran = affinity_gran_fine;
5231           }
5232         } else {
5233           if (__kmp_affinity_gran == affinity_gran_default) {
5234             __kmp_affinity_gran = affinity_gran_core;
5235           } else if (__kmp_affinity_gran == affinity_gran_group) {
5236             const char *str = NULL;
5237             switch (__kmp_affinity_type) {
5238             case affinity_physical:
5239               str = "physical";
5240               break;
5241             case affinity_logical:
5242               str = "logical";
5243               break;
5244             case affinity_compact:
5245               str = "compact";
5246               break;
5247             case affinity_scatter:
5248               str = "scatter";
5249               break;
5250             case affinity_explicit:
5251               str = "explicit";
5252               break;
5253             // No MIC on windows, so no affinity_balanced case
5254             default:
5255               KMP_DEBUG_ASSERT(0);
5256             }
5257             KMP_WARNING(AffGranGroupType, var, str);
5258             __kmp_affinity_gran = affinity_gran_core;
5259           }
5260         }
5261       } else
5262 
5263 #endif /* KMP_GROUP_AFFINITY */
5264 
5265       {
5266         if (__kmp_affinity_respect_mask == affinity_respect_mask_default) {
5267 #if KMP_GROUP_AFFINITY
5268           if (__kmp_num_proc_groups > 1 && exactly_one_group) {
5269             __kmp_affinity_respect_mask = FALSE;
5270           } else
5271 #endif /* KMP_GROUP_AFFINITY */
5272           {
5273             __kmp_affinity_respect_mask = TRUE;
5274           }
5275         }
5276 #if OMP_40_ENABLED
5277         if ((__kmp_nested_proc_bind.bind_types[0] != proc_bind_intel) &&
5278             (__kmp_nested_proc_bind.bind_types[0] != proc_bind_default)) {
5279           if (__kmp_affinity_type == affinity_default) {
5280             __kmp_affinity_type = affinity_compact;
5281             __kmp_affinity_dups = FALSE;
5282           }
5283         } else
5284 #endif /* OMP_40_ENABLED */
5285             if (__kmp_affinity_type == affinity_default) {
5286 #if OMP_40_ENABLED
5287 #if KMP_MIC_SUPPORTED
5288           if (__kmp_mic_type != non_mic) {
5289             __kmp_nested_proc_bind.bind_types[0] = proc_bind_intel;
5290           } else
5291 #endif
5292           {
5293             __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
5294           }
5295 #endif /* OMP_40_ENABLED */
5296 #if KMP_MIC_SUPPORTED
5297           if (__kmp_mic_type != non_mic) {
5298             __kmp_affinity_type = affinity_scatter;
5299           } else
5300 #endif
5301           {
5302             __kmp_affinity_type = affinity_none;
5303           }
5304         }
5305         if ((__kmp_affinity_gran == affinity_gran_default) &&
5306             (__kmp_affinity_gran_levels < 0)) {
5307 #if KMP_MIC_SUPPORTED
5308           if (__kmp_mic_type != non_mic) {
5309             __kmp_affinity_gran = affinity_gran_fine;
5310           } else
5311 #endif
5312           {
5313             __kmp_affinity_gran = affinity_gran_core;
5314           }
5315         }
5316         if (__kmp_affinity_top_method == affinity_top_method_default) {
5317           __kmp_affinity_top_method = affinity_top_method_all;
5318         }
5319       }
5320     }
5321 
5322     K_DIAG(1, ("__kmp_affinity_type         == %d\n", __kmp_affinity_type));
5323     K_DIAG(1, ("__kmp_affinity_compact      == %d\n", __kmp_affinity_compact));
5324     K_DIAG(1, ("__kmp_affinity_offset       == %d\n", __kmp_affinity_offset));
5325     K_DIAG(1, ("__kmp_affinity_verbose      == %d\n", __kmp_affinity_verbose));
5326     K_DIAG(1, ("__kmp_affinity_warnings     == %d\n", __kmp_affinity_warnings));
5327     K_DIAG(1, ("__kmp_affinity_respect_mask == %d\n",
5328                __kmp_affinity_respect_mask));
5329     K_DIAG(1, ("__kmp_affinity_gran         == %d\n", __kmp_affinity_gran));
5330 
5331     KMP_DEBUG_ASSERT(__kmp_affinity_type != affinity_default);
5332 #if OMP_40_ENABLED
5333     KMP_DEBUG_ASSERT(__kmp_nested_proc_bind.bind_types[0] != proc_bind_default);
5334 #endif
5335   }
5336 
5337 #endif /* KMP_AFFINITY_SUPPORTED */
5338 
5339   if (__kmp_version) {
5340     __kmp_print_version_1();
5341   }
5342 
5343   // Post-initialization step: some env. vars need their value's further
5344   // processing
5345   if (string != NULL) { // kmp_set_defaults() was called
5346     __kmp_aux_env_initialize(&block);
5347   }
5348 
5349   __kmp_env_blk_free(&block);
5350 
5351   KMP_MB();
5352 
5353 } // __kmp_env_initialize
5354 
5355 void __kmp_env_print() {
5356 
5357   kmp_env_blk_t block;
5358   int i;
5359   kmp_str_buf_t buffer;
5360 
5361   __kmp_stg_init();
5362   __kmp_str_buf_init(&buffer);
5363 
5364   __kmp_env_blk_init(&block, NULL);
5365   __kmp_env_blk_sort(&block);
5366 
5367   // Print real environment values.
5368   __kmp_str_buf_print(&buffer, "\n%s\n\n", KMP_I18N_STR(UserSettings));
5369   for (i = 0; i < block.count; ++i) {
5370     char const *name = block.vars[i].name;
5371     char const *value = block.vars[i].value;
5372     if ((KMP_STRLEN(name) > 4 && strncmp(name, "KMP_", 4) == 0) ||
5373         strncmp(name, "OMP_", 4) == 0
5374 #ifdef KMP_GOMP_COMPAT
5375         || strncmp(name, "GOMP_", 5) == 0
5376 #endif // KMP_GOMP_COMPAT
5377         ) {
5378       __kmp_str_buf_print(&buffer, "   %s=%s\n", name, value);
5379     }
5380   }
5381   __kmp_str_buf_print(&buffer, "\n");
5382 
5383   // Print internal (effective) settings.
5384   __kmp_str_buf_print(&buffer, "%s\n\n", KMP_I18N_STR(EffectiveSettings));
5385   for (int i = 0; i < __kmp_stg_count; ++i) {
5386     if (__kmp_stg_table[i].print != NULL) {
5387       __kmp_stg_table[i].print(&buffer, __kmp_stg_table[i].name,
5388                                __kmp_stg_table[i].data);
5389     }
5390   }
5391 
5392   __kmp_printf("%s", buffer.str);
5393 
5394   __kmp_env_blk_free(&block);
5395   __kmp_str_buf_free(&buffer);
5396 
5397   __kmp_printf("\n");
5398 
5399 } // __kmp_env_print
5400 
5401 #if OMP_40_ENABLED
5402 void __kmp_env_print_2() {
5403 
5404   kmp_env_blk_t block;
5405   kmp_str_buf_t buffer;
5406 
5407   __kmp_env_format = 1;
5408 
5409   __kmp_stg_init();
5410   __kmp_str_buf_init(&buffer);
5411 
5412   __kmp_env_blk_init(&block, NULL);
5413   __kmp_env_blk_sort(&block);
5414 
5415   __kmp_str_buf_print(&buffer, "\n%s\n", KMP_I18N_STR(DisplayEnvBegin));
5416   __kmp_str_buf_print(&buffer, "   _OPENMP='%d'\n", __kmp_openmp_version);
5417 
5418   for (int i = 0; i < __kmp_stg_count; ++i) {
5419     if (__kmp_stg_table[i].print != NULL &&
5420         ((__kmp_display_env &&
5421           strncmp(__kmp_stg_table[i].name, "OMP_", 4) == 0) ||
5422          __kmp_display_env_verbose)) {
5423       __kmp_stg_table[i].print(&buffer, __kmp_stg_table[i].name,
5424                                __kmp_stg_table[i].data);
5425     }
5426   }
5427 
5428   __kmp_str_buf_print(&buffer, "%s\n", KMP_I18N_STR(DisplayEnvEnd));
5429   __kmp_str_buf_print(&buffer, "\n");
5430 
5431   __kmp_printf("%s", buffer.str);
5432 
5433   __kmp_env_blk_free(&block);
5434   __kmp_str_buf_free(&buffer);
5435 
5436   __kmp_printf("\n");
5437 
5438 } // __kmp_env_print_2
5439 #endif // OMP_40_ENABLED
5440 
5441 // end of file
5442