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