1 /* Copyright (C) 2005-2023 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This file defines the OpenMP internal control variables and arranges
27 for them to be initialized from environment variables at startup. */
31 #include "gomp-constants.h"
33 #ifndef LIBGOMP_OFFLOADED_ONLY
34 #include "libgomp_f.h"
39 #ifdef HAVE_INTTYPES_H
40 # include <inttypes.h> /* For PRIu64. */
42 #ifdef STRING_WITH_STRINGS
49 # ifdef HAVE_STRINGS_H
55 #include "thread-stacksize.h"
58 # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
60 #endif /* LIBGOMP_OFFLOADED_ONLY */
62 #include "secure_getenv.h"
65 /* Default values of ICVs according to the OpenMP standard,
66 except for default-device-var. */
67 const struct gomp_default_icv gomp_default_icv_values
= {
69 .thread_limit_var
= UINT_MAX
,
70 .run_sched_var
= GFS_DYNAMIC
,
71 .run_sched_chunk_size
= 1,
72 .default_device_var
= INT_MIN
,
73 .max_active_levels_var
= 1,
74 .bind_var
= omp_proc_bind_false
,
76 .teams_thread_limit_var
= 0,
80 struct gomp_task_icv gomp_global_icv
= {
81 .nthreads_var
= gomp_default_icv_values
.nthreads_var
,
82 .thread_limit_var
= gomp_default_icv_values
.thread_limit_var
,
83 .run_sched_var
= gomp_default_icv_values
.run_sched_var
,
84 .run_sched_chunk_size
= gomp_default_icv_values
.run_sched_chunk_size
,
85 .default_device_var
= gomp_default_icv_values
.default_device_var
,
86 .dyn_var
= gomp_default_icv_values
.dyn_var
,
87 .max_active_levels_var
= gomp_default_icv_values
.max_active_levels_var
,
88 .bind_var
= gomp_default_icv_values
.bind_var
,
92 /* List for initial "_DEV", "_ALL", and "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV,
93 OMP_NUM_TEAMS_ALL, or OMP_NUM_TEAMS_DEV_42. */
94 struct gomp_icv_list
*gomp_initial_icv_list
= NULL
;
96 /* List for "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV_42. This list contains all
97 device-specific ICVs that are copied from host to device and back. */
98 struct gomp_offload_icv_list
*gomp_offload_icv_list
= NULL
;
100 bool gomp_cancel_var
= false;
101 enum gomp_target_offload_t gomp_target_offload_var
102 = GOMP_TARGET_OFFLOAD_DEFAULT
;
103 int gomp_max_task_priority_var
= 0;
104 #ifndef HAVE_SYNC_BUILTINS
105 gomp_mutex_t gomp_managed_threads_lock
;
107 unsigned long gomp_available_cpus
= 1, gomp_managed_threads
= 1;
108 unsigned long long gomp_spin_count_var
, gomp_throttled_spin_count_var
;
109 unsigned long *gomp_nthreads_var_list
, gomp_nthreads_var_list_len
;
110 char *gomp_bind_var_list
;
111 unsigned long gomp_bind_var_list_len
;
112 void **gomp_places_list
;
113 unsigned long gomp_places_list_len
;
114 uintptr_t gomp_def_allocator
= omp_default_mem_alloc
;
115 char *gomp_def_allocator_envvar
= NULL
;
117 unsigned int gomp_num_teams_var
;
119 int gomp_teams_thread_limit_var
;
120 bool gomp_display_affinity_var
;
121 char *gomp_affinity_format_var
= "level %L thread %i affinity %A";
122 size_t gomp_affinity_format_len
;
123 char *goacc_device_type
;
124 int goacc_device_num
;
125 int goacc_default_dims
[GOMP_DIM_MAX
];
127 #ifndef LIBGOMP_OFFLOADED_ONLY
129 static int wait_policy
= -1;
130 static unsigned long stacksize
= GOMP_DEFAULT_STACKSIZE
;
133 print_env_var_error (const char *env
, const char *val
)
135 gomp_error ("Invalid value for environment variable %.*s: %s",
136 (int) (val
- env
- 1), env
, val
);
139 /* Parse the OMP_SCHEDULE environment variable. */
141 parse_schedule (const char *env
, const char *val
, void *const params
[])
143 enum gomp_schedule_type
*schedule
= (enum gomp_schedule_type
*) params
[0];
144 int *chunk_size
= (int *) params
[1];
152 while (isspace ((unsigned char) *val
))
154 if (strncasecmp (val
, "monotonic", 9) == 0)
159 else if (strncasecmp (val
, "nonmonotonic", 12) == 0)
166 while (isspace ((unsigned char) *val
))
171 while (isspace ((unsigned char) *val
))
174 if (strncasecmp (val
, "static", 6) == 0)
176 *schedule
= GFS_STATIC
;
179 else if (strncasecmp (val
, "dynamic", 7) == 0)
181 *schedule
= GFS_DYNAMIC
;
184 else if (strncasecmp (val
, "guided", 6) == 0)
186 *schedule
= GFS_GUIDED
;
189 else if (strncasecmp (val
, "auto", 4) == 0)
191 *schedule
= GFS_AUTO
;
198 || (monotonic
== 0 && *schedule
== GFS_STATIC
))
199 *schedule
|= GFS_MONOTONIC
;
201 while (isspace ((unsigned char) *val
))
205 *chunk_size
= (*schedule
& ~GFS_MONOTONIC
) != GFS_STATIC
;
210 while (isspace ((unsigned char) *val
))
216 value
= strtoul (val
, &end
, 10);
217 if (errno
|| end
== val
)
220 while (isspace ((unsigned char) *end
))
225 if ((int)value
!= value
)
228 if (value
== 0 && (*schedule
& ~GFS_MONOTONIC
) != GFS_STATIC
)
234 print_env_var_error (env
, val
);
238 char name
[val
- env
];
239 memcpy (name
, env
, val
- env
- 1);
240 name
[val
- env
- 1] = '\0';
241 gomp_error ("Invalid value for chunk size in "
242 "environment variable %s: %s", name
, val
);
246 /* Parse an unsigned long environment variable. Return true if one was
247 present and it was successfully parsed. If SECURE, use secure_getenv to the
248 environment variable. */
251 parse_unsigned_long_1 (const char *env
, const char *val
, unsigned long *pvalue
,
260 while (isspace ((unsigned char) *val
))
266 value
= strtoul (val
, &end
, 10);
267 if (errno
|| end
== val
|| (long) value
<= 0 - allow_zero
)
270 while (isspace ((unsigned char) *end
))
279 print_env_var_error (env
, val
);
283 /* As parse_unsigned_long_1, but always use getenv. */
286 parse_unsigned_long (const char *env
, const char *val
, void *const params
[])
288 unsigned long upper
= (uintptr_t) params
[2];
289 unsigned long pvalue
= 0;
290 bool ret
= parse_unsigned_long_1 (env
, val
, &pvalue
, (bool) params
[1]);
295 *(unsigned long *) params
[0] = pvalue
;
300 if (upper
<= UCHAR_MAX
)
301 *(unsigned char *) params
[0] = pvalue
;
302 else if (upper
<= UINT_MAX
)
303 *(unsigned int *) params
[0] = pvalue
;
305 *(unsigned long *) params
[0] = pvalue
;
311 /* Parse a positive int environment variable. Return true if one was
312 present and it was successfully parsed. If SECURE, use secure_getenv to the
313 environment variable. */
316 parse_int_1 (const char *env
, const char *val
, int *pvalue
, bool allow_zero
)
319 if (!parse_unsigned_long_1 (env
, val
, &value
, allow_zero
))
323 print_env_var_error (env
, val
);
326 *pvalue
= (int) value
;
331 parse_int (const char *env
, const char *val
, void *const params
[])
333 return parse_int_1 (env
, val
, (int *) params
[0], (bool) params
[1]);
336 /* As parse_int_1, but use getenv_secure. */
339 parse_int_secure (const char *env
, int *pvalue
, bool allow_zero
)
341 return parse_int_1 (env
, secure_getenv (env
), pvalue
, allow_zero
);
344 /* Parse an unsigned long list environment variable. Return true if one was
345 present and it was successfully parsed. */
348 parse_unsigned_long_list (const char *env
, const char *val
,
349 void *const params
[])
351 unsigned long *p1stvalue
= (unsigned long *) params
[0];
352 unsigned long **pvalues
= (unsigned long **) params
[1];
353 unsigned long *pnvalues
= (unsigned long *) params
[2];
355 unsigned long value
, *values
= NULL
;
360 while (isspace ((unsigned char) *val
))
366 value
= strtoul (val
, &end
, 10);
367 if (errno
|| (long) value
<= 0)
370 while (isspace ((unsigned char) *end
))
376 unsigned long nvalues
= 0, nalloced
= 0;
381 if (nvalues
== nalloced
)
384 nalloced
= nalloced
? nalloced
* 2 : 16;
385 n
= realloc (values
, nalloced
* sizeof (unsigned long));
389 char name
[val
- env
];
390 memcpy (name
, env
, val
- env
- 1);
391 name
[val
- env
- 1] = '\0';
392 gomp_error ("Out of memory while trying to parse"
393 " environment variable %s", name
);
398 values
[nvalues
++] = value
;
401 while (isspace ((unsigned char) *val
))
407 value
= strtoul (val
, &end
, 10);
408 if (errno
|| (long) value
<= 0)
411 values
[nvalues
++] = value
;
412 while (isspace ((unsigned char) *end
))
420 *p1stvalue
= values
[0];
438 print_env_var_error (env
, val
);
443 parse_target_offload (const char *env
, const char *val
, void *const params
[])
445 int new_offload
= -1;
450 while (isspace ((unsigned char) *val
))
452 if (strncasecmp (val
, "default", 7) == 0)
455 new_offload
= GOMP_TARGET_OFFLOAD_DEFAULT
;
457 else if (strncasecmp (val
, "mandatory", 9) == 0)
460 new_offload
= GOMP_TARGET_OFFLOAD_MANDATORY
;
462 else if (strncasecmp (val
, "disabled", 8) == 0)
465 new_offload
= GOMP_TARGET_OFFLOAD_DISABLED
;
467 while (isspace ((unsigned char) *val
))
469 if (new_offload
!= -1 && *val
== '\0')
471 *(enum gomp_target_offload_t
*) params
[0] = new_offload
;
475 print_env_var_error (env
, val
);
479 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
480 enum values. Return true if one was present and it was successfully
484 parse_bind_var (const char *env
, const char *val
, void *const params
[])
486 char *p1stvalue
= (char *) params
[0];
487 char **pvalues
= (char **) params
[1];
488 unsigned long *pnvalues
= (unsigned long *) params
[2];
489 char value
= omp_proc_bind_false
, *values
= NULL
;
491 static struct proc_bind_kinds
495 omp_proc_bind_t kind
;
498 { "false", 5, omp_proc_bind_false
},
499 { "true", 4, omp_proc_bind_true
},
500 { "master", 6, omp_proc_bind_master
},
501 { "primary", 7, omp_proc_bind_primary
},
502 { "close", 5, omp_proc_bind_close
},
503 { "spread", 6, omp_proc_bind_spread
}
509 while (isspace ((unsigned char) *val
))
514 for (i
= 0; i
< 6; i
++)
515 if (strncasecmp (val
, kinds
[i
].name
, kinds
[i
].len
) == 0)
517 value
= kinds
[i
].kind
;
524 while (isspace ((unsigned char) *val
))
530 unsigned long nvalues
= 0, nalloced
= 0;
532 if (value
== omp_proc_bind_false
533 || value
== omp_proc_bind_true
)
539 if (nvalues
== nalloced
)
542 nalloced
= nalloced
? nalloced
* 2 : 16;
543 n
= realloc (values
, nalloced
);
547 char name
[val
- env
];
548 memcpy (name
, env
, val
- env
- 1);
549 name
[val
- env
- 1] = '\0';
550 gomp_error ("Out of memory while trying to parse"
551 " environment variable %s", name
);
556 values
[nvalues
++] = value
;
559 while (isspace ((unsigned char) *val
))
564 for (i
= 2; i
< 6; i
++)
565 if (strncasecmp (val
, kinds
[i
].name
, kinds
[i
].len
) == 0)
567 value
= kinds
[i
].kind
;
574 values
[nvalues
++] = value
;
575 while (isspace ((unsigned char) *val
))
583 *p1stvalue
= values
[0];
596 print_env_var_error (env
, val
);
601 parse_one_place (char **envp
, bool *negatep
, unsigned long *lenp
,
604 char *env
= *envp
, *start
;
605 void *p
= gomp_places_list
? gomp_places_list
[gomp_places_list_len
] : NULL
;
606 unsigned long len
= 1;
609 bool any_negate
= false;
610 bool has_braces
= true;
612 while (isspace ((unsigned char) *env
))
618 while (isspace ((unsigned char) *env
))
624 unsigned long this_num
;
627 this_num
= strtoul (env
, &end
, 10);
628 if (errno
|| end
== env
)
633 && !gomp_affinity_add_cpus (p
, this_num
, 1, 1, false))
639 while (isspace ((unsigned char) *env
))
643 for (pass
= 0; pass
< (any_negate
? 2 : has_braces
); pass
++)
648 unsigned long this_num
, this_len
= 1;
649 long this_stride
= 1;
650 bool this_negate
= (*env
== '!');
654 if (gomp_places_list
)
657 while (isspace ((unsigned char) *env
))
662 this_num
= strtoul (env
, &end
, 10);
663 if (errno
|| end
== env
)
666 while (isspace ((unsigned char) *env
))
673 while (isspace ((unsigned char) *env
))
676 this_len
= strtoul (env
, &env
, 10);
677 if (errno
|| this_len
== 0)
679 while (isspace ((unsigned char) *env
))
684 while (isspace ((unsigned char) *env
))
687 this_stride
= strtol (env
, &end
, 10);
688 if (errno
|| end
== env
)
691 while (isspace ((unsigned char) *env
))
695 if (gomp_places_list
&& pass
== this_negate
)
699 if (!gomp_affinity_remove_cpu (p
, this_num
))
702 else if (!gomp_affinity_add_cpus (p
, this_num
, this_len
,
716 while (isspace ((unsigned char) *env
))
724 while (isspace ((unsigned char) *env
))
727 len
= strtoul (env
, &env
, 10);
728 if (errno
|| len
== 0 || len
>= 65536)
730 while (isspace ((unsigned char) *env
))
735 while (isspace ((unsigned char) *env
))
738 stride
= strtol (env
, &end
, 10);
739 if (errno
|| end
== env
)
742 while (isspace ((unsigned char) *env
))
753 parse_places_var (const char *name
, bool ignore
)
755 char *env
= getenv (name
), *end
;
756 bool any_negate
= false;
758 unsigned long count
= 0;
762 while (isspace ((unsigned char) *env
))
767 if (strncasecmp (env
, "threads", 7) == 0)
772 else if (strncasecmp (env
, "cores", 5) == 0)
777 else if (strncasecmp (env
, "sockets", 7) == 0)
782 else if (strncasecmp (env
, "ll_caches", 9) == 0)
787 else if (strncasecmp (env
, "numa_domains", 12) == 0)
795 while (isspace ((unsigned char) *env
))
801 while (isspace ((unsigned char) *env
))
805 count
= strtoul (env
, &end
, 10);
806 if (errno
|| end
== env
)
809 while (isspace ((unsigned char) *env
))
814 while (isspace ((unsigned char) *env
))
823 return gomp_affinity_init_level (level
, count
, false);
833 if (!parse_one_place (&end
, &negate
, &len
, &stride
))
856 gomp_places_list_len
= 0;
857 gomp_places_list
= gomp_affinity_alloc (count
, false);
858 if (gomp_places_list
== NULL
)
866 gomp_affinity_init_place (gomp_places_list
[gomp_places_list_len
]);
867 if (!parse_one_place (&env
, &negate
, &len
, &stride
))
872 for (count
= 0; count
< gomp_places_list_len
; count
++)
873 if (gomp_affinity_same_place
874 (gomp_places_list
[count
],
875 gomp_places_list
[gomp_places_list_len
]))
877 if (count
== gomp_places_list_len
)
879 gomp_error ("Trying to remove a non-existing place from list "
883 p
= gomp_places_list
[count
];
884 memmove (&gomp_places_list
[count
],
885 &gomp_places_list
[count
+ 1],
886 (gomp_places_list_len
- count
- 1) * sizeof (void *));
887 --gomp_places_list_len
;
888 gomp_places_list
[gomp_places_list_len
] = p
;
891 ++gomp_places_list_len
;
894 for (count
= 0; count
< len
- 1; count
++)
895 if (!gomp_affinity_copy_place
896 (gomp_places_list
[gomp_places_list_len
+ count
+ 1],
897 gomp_places_list
[gomp_places_list_len
+ count
],
900 gomp_places_list_len
+= len
;
908 if (gomp_places_list_len
== 0)
910 gomp_error ("All places have been removed");
913 if (!gomp_affinity_finalize_place_list (false))
918 free (gomp_places_list
);
919 gomp_places_list
= NULL
;
920 gomp_places_list_len
= 0;
921 gomp_error ("Invalid value for environment variable %s", name
);
925 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
926 present and it was successfully parsed. */
929 parse_stacksize (const char *env
, const char *val
, void *const params
[])
932 unsigned long value
, shift
= 10;
937 while (isspace ((unsigned char) *val
))
943 value
= strtoul (val
, &end
, 10);
944 if (errno
|| end
== val
)
947 while (isspace ((unsigned char) *end
))
951 switch (tolower ((unsigned char) *end
))
968 while (isspace ((unsigned char) *end
))
974 if (((value
<< shift
) >> shift
) != value
)
977 *(unsigned long *) params
[0] = value
<< shift
;
981 print_env_var_error (env
, val
);
985 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
986 present and it was successfully parsed. */
989 parse_spincount (const char *name
, unsigned long long *pvalue
)
992 unsigned long long value
, mult
= 1;
998 while (isspace ((unsigned char) *env
))
1003 if (strncasecmp (env
, "infinite", 8) == 0
1004 || strncasecmp (env
, "infinity", 8) == 0)
1012 value
= strtoull (env
, &end
, 10);
1013 if (errno
|| end
== env
)
1016 while (isspace ((unsigned char) *end
))
1020 switch (tolower ((unsigned char) *end
))
1026 mult
= 1000LL * 1000LL;
1029 mult
= 1000LL * 1000LL * 1000LL;
1032 mult
= 1000LL * 1000LL * 1000LL * 1000LL;
1039 while (isspace ((unsigned char) *end
))
1045 if (value
> ~0ULL / mult
)
1054 gomp_error ("Invalid value for environment variable %s", name
);
1058 /* Parse a boolean value for environment variable NAME and store the
1059 result in VALUE. Return true if one was present and it was
1060 successfully parsed. */
1062 parse_boolean (const char *env
, const char *val
, void *const params
[])
1064 bool *value
= (bool *) params
[0];
1069 while (isspace ((unsigned char) *val
))
1071 if (strncasecmp (val
, "true", 4) == 0)
1076 else if (strncasecmp (val
, "false", 5) == 0)
1083 while (isspace ((unsigned char) *val
))
1087 print_env_var_error (env
, val
);
1093 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1096 parse_wait_policy (const char *env
, const char *val
, void *const params
[])
1098 int *pvalue
= (int *) params
[0];
1107 while (isspace ((unsigned char) *val
))
1109 if (strncasecmp (val
, "active", 6) == 0)
1114 else if (strncasecmp (val
, "passive", 7) == 0)
1121 while (isspace ((unsigned char) *val
))
1128 print_env_var_error (env
, val
);
1133 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1134 present and it was successfully parsed. */
1137 parse_affinity (bool ignore
)
1139 char *env
, *end
, *start
;
1141 unsigned long cpu_beg
, cpu_end
, cpu_stride
;
1142 size_t count
= 0, needed
;
1144 env
= getenv ("GOMP_CPU_AFFINITY");
1149 for (pass
= 0; pass
< 2; pass
++)
1157 gomp_places_list_len
= 0;
1158 gomp_places_list
= gomp_affinity_alloc (count
, true);
1159 if (gomp_places_list
== NULL
)
1164 while (isspace ((unsigned char) *env
))
1168 cpu_beg
= strtoul (env
, &end
, 0);
1169 if (errno
|| end
== env
|| cpu_beg
>= 65536)
1178 cpu_end
= strtoul (++env
, &end
, 0);
1179 if (errno
|| end
== env
|| cpu_end
>= 65536 || cpu_end
< cpu_beg
)
1186 cpu_stride
= strtoul (++env
, &end
, 0);
1187 if (errno
|| cpu_stride
== 0 || cpu_stride
>= 65536)
1194 needed
= (cpu_end
- cpu_beg
) / cpu_stride
+ 1;
1201 void *p
= gomp_places_list
[gomp_places_list_len
];
1202 gomp_affinity_init_place (p
);
1203 if (gomp_affinity_add_cpus (p
, cpu_beg
, 1, 0, true))
1204 ++gomp_places_list_len
;
1205 cpu_beg
+= cpu_stride
;
1209 while (isspace ((unsigned char) *env
))
1214 else if (*env
== '\0')
1220 if (gomp_places_list_len
== 0)
1222 free (gomp_places_list
);
1223 gomp_places_list
= NULL
;
1229 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1233 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1235 parse_allocator (const char *env
, const char *val
, void *const params
[])
1237 const char *orig_val
= val
;
1238 uintptr_t *ret
= (uintptr_t *) params
[0];
1239 *ret
= omp_default_mem_alloc
;
1240 bool memspace
= false;
1242 omp_alloctrait_t
*traits
;
1247 while (isspace ((unsigned char) *val
))
1252 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1255 val += sizeof (#v) - 1; \
1258 C (omp_default_mem_alloc
, false)
1259 C (omp_large_cap_mem_alloc
, false)
1260 C (omp_const_mem_alloc
, false)
1261 C (omp_high_bw_mem_alloc
, false)
1262 C (omp_low_lat_mem_alloc
, false)
1263 C (omp_cgroup_mem_alloc
, false)
1264 C (omp_pteam_mem_alloc
, false)
1265 C (omp_thread_mem_alloc
, false)
1266 C (omp_default_mem_space
, true)
1267 C (omp_large_cap_mem_space
, true)
1268 C (omp_const_mem_space
, true)
1269 C (omp_high_bw_mem_space
, true)
1270 C (omp_low_lat_mem_space
, true)
1274 if (memspace
&& *val
== ':')
1277 const char *cp
= val
;
1284 traits
= gomp_alloca (ntraits
* sizeof (omp_alloctrait_t
));
1286 while (*val
!= '\0')
1289 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1291 val += sizeof (#v); \
1292 traits[n].key = omp_atk_ ## v;
1294 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1296 val += sizeof (#v) - 1; \
1297 traits[n].value = omp_atv_ ## v; \
1314 traits
[n
].value
= strtol (val
, &end
, 10);
1315 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1332 traits
[n
].value
= strtol (val
, &end
, 10);
1333 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1347 /* Ignore fb_data, which expects an allocator handle. */
1381 case omp_default_mem_space
: *ret
= omp_default_mem_alloc
; break;
1382 case omp_large_cap_mem_space
: *ret
= omp_large_cap_mem_alloc
; break;
1383 case omp_const_mem_space
: *ret
= omp_const_mem_alloc
; break;
1384 case omp_high_bw_mem_space
: *ret
= omp_high_bw_mem_alloc
; break;
1385 case omp_low_lat_mem_space
: *ret
= omp_low_lat_mem_alloc
; break;
1386 default: __builtin_unreachable ();
1388 while (isspace ((unsigned char) *val
))
1394 *ret
= omp_init_allocator (*ret
, ntraits
, traits
);
1395 if (*ret
== omp_null_allocator
)
1397 gomp_error ("Allocator of environment variable %.*s cannot be "
1398 "created, using omp_default_mem_alloc instead",
1399 (int) (orig_val
- env
- 1), env
);
1400 *ret
= omp_default_mem_alloc
;
1403 gomp_def_allocator_envvar
= strdup (orig_val
);
1408 int len
= (orig_val
- env
- 1);
1410 gomp_error ("Missing value at the end of environment variable %s", env
);
1412 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1414 *ret
= omp_default_mem_alloc
;
1419 parse_acc_device_type (void)
1421 const char *env
= getenv ("ACC_DEVICE_TYPE");
1423 if (env
&& *env
!= '\0')
1424 goacc_device_type
= strdup (env
);
1426 goacc_device_type
= NULL
;
1430 parse_gomp_openacc_dim (void)
1432 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1433 const char *var_name
= "GOMP_OPENACC_DIM";
1434 const char *env_var
= getenv (var_name
);
1435 const char *pos
= env_var
;
1441 for (i
= 0; *pos
&& i
!= GOMP_DIM_MAX
; i
++)
1446 if (i
&& *pos
++ != ':')
1453 val
= strtol (pos
, &eptr
, 10);
1454 if (errno
|| eptr
== pos
|| val
< 0 || (unsigned)val
!= val
)
1457 goacc_default_dims
[i
] = (int)val
;
1458 pos
= (const char *) eptr
;
1462 /* Helper function for omp_display_env which prints the values of run_sched_var.
1463 'device' can be 'host', 'dev', 'all' or a particular device number. */
1466 print_schedule (enum gomp_schedule_type run_sched_var
, int run_sched_chunk_size
,
1469 fprintf (stderr
, " [%s] OMP_SCHEDULE = '", device
);
1470 if ((run_sched_var
& GFS_MONOTONIC
))
1472 if (run_sched_var
!= (GFS_MONOTONIC
| GFS_STATIC
))
1473 fputs ("MONOTONIC:", stderr
);
1475 else if (run_sched_var
== GFS_STATIC
)
1476 fputs ("NONMONOTONIC:", stderr
);
1477 switch (run_sched_var
& ~GFS_MONOTONIC
)
1480 fputs ("RUNTIME", stderr
);
1481 if (run_sched_chunk_size
!= 1)
1482 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1485 fputs ("STATIC", stderr
);
1486 if (run_sched_chunk_size
!= 0)
1487 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1490 fputs ("DYNAMIC", stderr
);
1491 if (run_sched_chunk_size
!= 1)
1492 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1495 fputs ("GUIDED", stderr
);
1496 if (run_sched_chunk_size
!= 1)
1497 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1500 fputs ("AUTO", stderr
);
1503 fputs ("'\n", stderr
);
1506 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1507 'device' can be 'host', 'dev', 'all', or a particular device number. */
1510 print_proc_bind (char proc_bind_var
, unsigned long len
, char **list
,
1513 fprintf (stderr
, " [%s] OMP_PROC_BIND = '", device
);
1514 switch (proc_bind_var
)
1516 case omp_proc_bind_false
:
1517 fputs ("FALSE", stderr
);
1519 case omp_proc_bind_true
:
1520 fputs ("TRUE", stderr
);
1522 case omp_proc_bind_master
:
1523 fputs ("MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1525 case omp_proc_bind_close
:
1526 fputs ("CLOSE", stderr
);
1528 case omp_proc_bind_spread
:
1529 fputs ("SPREAD", stderr
);
1532 for (int i
= 1; i
< len
; i
++)
1535 case omp_proc_bind_master
:
1536 fputs (",MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1538 case omp_proc_bind_close
:
1539 fputs (",CLOSE", stderr
);
1541 case omp_proc_bind_spread
:
1542 fputs (",SPREAD", stderr
);
1545 fputs ("'\n", stderr
);
1548 enum gomp_parse_type
1559 /* The following table contains items that help parsing environment variables
1560 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1561 are affected by the environment variable. FLAGS determine what variant of
1562 environment variable is allowed. */
1564 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1565 static const struct envvar
1569 uint8_t flag_vars
[3];
1571 bool (*parse_func
) (const char *, const char *, void *const[]);
1573 { ENTRY ("SCHEDULE"),
1574 { GOMP_ICV_SCHEDULE
, GOMP_ICV_SCHEDULE_CHUNK_SIZE
},
1575 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1577 { ENTRY ("NUM_TEAMS"),
1578 { GOMP_ICV_NTEAMS
},
1579 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1581 { ENTRY ("DYNAMIC"),
1582 { GOMP_ICV_DYNAMIC
},
1583 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1585 { ENTRY ("TEAMS_THREAD_LIMIT"),
1586 { GOMP_ICV_TEAMS_THREAD_LIMIT
},
1587 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1589 { ENTRY ("THREAD_LIMIT"),
1590 { GOMP_ICV_THREAD_LIMIT
},
1591 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1592 &parse_unsigned_long
},
1593 { ENTRY ("NUM_THREADS"),
1594 { GOMP_ICV_NTHREADS
, GOMP_ICV_NTHREADS_LIST
, GOMP_ICV_NTHREADS_LIST_LEN
},
1595 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1596 &parse_unsigned_long_list
},
1597 { ENTRY ("PROC_BIND"),
1598 { GOMP_ICV_BIND
, GOMP_ICV_BIND_LIST
, GOMP_ICV_BIND_LIST_LEN
},
1599 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1601 { ENTRY ("MAX_ACTIVE_LEVELS"),
1602 { GOMP_ICV_MAX_ACTIVE_LEVELS
},
1603 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1604 &parse_unsigned_long
},
1605 { ENTRY ("WAIT_POLICY"),
1606 { GOMP_ICV_WAIT_POLICY
},
1607 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1608 &parse_wait_policy
},
1609 { ENTRY ("STACKSIZE"),
1610 { GOMP_ICV_STACKSIZE
},
1611 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1613 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION
}, 0, &parse_boolean
},
1614 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY
}, 0,
1616 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD
}, 0,
1617 &parse_target_offload
},
1618 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY
}, 0,
1620 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR
}, 0, &parse_allocator
},
1621 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE
},
1622 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1626 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1628 /* The following table is used to apply the hierarchy of ICV variants for host
1629 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1632 static const struct host_envvar
1634 unsigned char flag_var
;
1637 } host_envvars
[] = {
1638 { GOMP_ICV_NTEAMS
, { &gomp_nteams_var
}, PARSE_INT
},
1639 { GOMP_ICV_DYNAMIC
, { &gomp_global_icv
.dyn_var
}, PARSE_BOOL
},
1640 { GOMP_ICV_DEFAULT_DEVICE
, { &gomp_global_icv
.default_device_var
},
1642 { GOMP_ICV_TEAMS_THREAD_LIMIT
, { &gomp_teams_thread_limit_var
}, PARSE_INT
},
1643 { GOMP_ICV_SCHEDULE
,
1644 { &gomp_global_icv
.run_sched_var
, &gomp_global_icv
.run_sched_chunk_size
},
1646 { GOMP_ICV_THREAD_LIMIT
, { &gomp_global_icv
.thread_limit_var
}, PARSE_UINT
},
1647 { GOMP_ICV_NTHREADS
,
1648 { &gomp_global_icv
.nthreads_var
, &gomp_nthreads_var_list
,
1649 &gomp_nthreads_var_list_len
}, PARSE_ULONG
},
1651 { &gomp_global_icv
.bind_var
, &gomp_bind_var_list
, &gomp_bind_var_list_len
},
1653 { GOMP_ICV_MAX_ACTIVE_LEVELS
, { &gomp_global_icv
.max_active_levels_var
},
1656 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1658 #define INT_MAX_STR_LEN 10
1661 gomp_get_icv_flag (uint32_t value
, enum gomp_icvs icv
)
1663 return value
& (1 << (icv
- 1));
1667 gomp_set_icv_flag (uint32_t *value
, enum gomp_icvs icv
)
1669 *value
|= 1 << (icv
- 1);
1673 print_device_specific_icvs (int icv_code
)
1675 struct gomp_icv_list
*list
= gomp_initial_icv_list
;
1677 char dev_num
[INT_MAX_STR_LEN
+ 1];
1679 while (list
!= NULL
)
1681 if (list
->device_num
< 0)
1689 case GOMP_ICV_NTEAMS
:
1690 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTEAMS
))
1691 fprintf (stderr
, " [%d] OMP_NUM_TEAMS = '%d'\n",
1692 list
->device_num
, list
->icvs
.nteams_var
);
1694 case GOMP_ICV_DYNAMIC
:
1695 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_DYNAMIC
))
1696 fprintf (stderr
, " [%d] OMP_DYNAMIC = '%s'\n",
1697 list
->device_num
, list
->icvs
.dyn_var
? "TRUE" : "FALSE");
1699 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
1700 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_TEAMS_THREAD_LIMIT
))
1701 fprintf (stderr
, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1702 list
->device_num
, list
->icvs
.teams_thread_limit_var
);
1704 case GOMP_ICV_SCHEDULE
:
1705 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_SCHEDULE
)))
1707 sprintf (dev_num
, "%d", list
->device_num
);
1708 print_schedule (list
->icvs
.run_sched_var
,
1709 list
->icvs
.run_sched_chunk_size
,
1712 case GOMP_ICV_THREAD_LIMIT
:
1713 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_THREAD_LIMIT
))
1714 fprintf (stderr
, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1715 list
->device_num
, list
->icvs
.thread_limit_var
);
1717 case GOMP_ICV_NTHREADS
:
1718 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTHREADS
)))
1720 fprintf (stderr
, " [%d] OMP_NUM_THREADS = '%lu", list
->device_num
,
1721 list
->icvs
.nthreads_var
);
1722 for (i
= 1; i
< list
->icvs
.nthreads_var_list_len
; i
++)
1723 fprintf (stderr
, ",%lu", list
->icvs
.nthreads_var_list
[i
]);
1724 fputs ("'\n", stderr
);
1726 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
1727 fprintf (stderr
, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1728 list
->device_num
, list
->icvs
.max_active_levels_var
);
1731 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_BIND
)))
1733 sprintf (dev_num
, "%d", list
->device_num
);
1734 print_proc_bind (list
->icvs
.bind_var
, list
->icvs
.bind_var_list_len
,
1735 &list
->icvs
.bind_var_list
, dev_num
);
1737 case GOMP_ICV_WAIT_POLICY
:
1738 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_WAIT_POLICY
))
1739 fprintf (stderr
, " [%d] OMP_WAIT_POLICY = '%s'\n",
1741 list
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1743 case GOMP_ICV_STACKSIZE
:
1744 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_STACKSIZE
))
1745 fprintf (stderr
, " [%d] OMP_STACKSIZE = '%lu'\n",
1746 list
->device_num
, list
->icvs
.stacksize
);
1754 omp_display_env (int verbose
)
1757 struct gomp_icv_list
*dev
1758 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV
);
1759 struct gomp_icv_list
*all
1760 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
1761 struct gomp_icv_list
*none
1762 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
1764 if (none
->icvs
.default_device_var
== INT_MIN
)
1765 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1766 gomp_init_targets_once ();
1768 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr
);
1770 fputs (" _OPENMP = '201511'\n", stderr
);
1772 fprintf (stderr
, " [host] OMP_DYNAMIC = '%s'\n",
1773 none
->icvs
.dyn_var
? "TRUE" : "FALSE");
1774 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_DYNAMIC
))
1775 fprintf (stderr
, " [all] OMP_DYNAMIC = '%s'\n",
1776 all
->icvs
.dyn_var
? "TRUE" : "FALSE");
1777 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_DYNAMIC
))
1778 fprintf (stderr
, " [device] OMP_DYNAMIC = '%s'\n",
1779 dev
->icvs
.dyn_var
? "TRUE" : "FALSE");
1780 print_device_specific_icvs (GOMP_ICV_DYNAMIC
);
1782 /* The OMP_NESTED environment variable has been deprecated. */
1783 fprintf (stderr
, " [host] OMP_NESTED = '%s'\n",
1784 none
->icvs
.max_active_levels_var
> 1 ? "TRUE" : "FALSE");
1786 fprintf (stderr
, " [host] OMP_NUM_THREADS = '%lu",
1787 none
->icvs
.nthreads_var
);
1788 for (i
= 1; i
< none
->icvs
.nthreads_var_list_len
; i
++)
1789 fprintf (stderr
, ",%lu", none
->icvs
.nthreads_var_list
[i
]);
1790 fputs ("'\n", stderr
);
1791 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTHREADS
))
1793 fprintf (stderr
, " [all] OMP_NUM_THREADS = '%lu",
1794 all
->icvs
.nthreads_var
);
1795 for (i
= 1; i
< all
->icvs
.nthreads_var_list_len
; i
++)
1796 fprintf (stderr
, ",%lu", all
->icvs
.nthreads_var_list
[i
]);
1797 fputs ("'\n", stderr
);
1799 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTHREADS
))
1801 fprintf (stderr
, " [device] OMP_NUM_THREADS = '%lu",
1802 dev
->icvs
.nthreads_var
);
1803 for (i
= 1; i
< dev
->icvs
.nthreads_var_list_len
; i
++)
1804 fprintf (stderr
, ",%lu", dev
->icvs
.nthreads_var_list
[i
]);
1805 fputs ("'\n", stderr
);
1807 print_device_specific_icvs (GOMP_ICV_NTHREADS
);
1810 print_schedule (none
->icvs
.run_sched_var
,
1811 none
->icvs
.run_sched_chunk_size
, "host");
1812 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_SCHEDULE
))
1813 print_schedule (all
->icvs
.run_sched_var
,
1814 all
->icvs
.run_sched_chunk_size
, "all");
1815 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_SCHEDULE
))
1816 print_schedule (dev
->icvs
.run_sched_var
,
1817 dev
->icvs
.run_sched_chunk_size
, "device");
1818 print_device_specific_icvs (GOMP_ICV_SCHEDULE
);
1820 print_proc_bind (none
->icvs
.bind_var
,
1821 none
->icvs
.bind_var_list_len
,
1822 &none
->icvs
.bind_var_list
, "host");
1823 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
))
1824 print_proc_bind (all
->icvs
.bind_var
,
1825 all
->icvs
.bind_var_list_len
,
1826 &all
->icvs
.bind_var_list
, "all");
1827 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_BIND
))
1828 print_proc_bind (dev
->icvs
.bind_var
,
1829 dev
->icvs
.bind_var_list_len
,
1830 &dev
->icvs
.bind_var_list
, "device");
1831 print_device_specific_icvs (GOMP_ICV_BIND
);
1833 fputs (" [host] OMP_PLACES = '", stderr
);
1834 for (i
= 0; i
< gomp_places_list_len
; i
++)
1836 fputs ("{", stderr
);
1837 gomp_affinity_print_place (gomp_places_list
[i
]);
1838 fputs (i
+ 1 == gomp_places_list_len
? "}" : "},", stderr
);
1840 fputs ("'\n", stderr
);
1842 fprintf (stderr
, " [host] OMP_STACKSIZE = '%lu'\n",
1843 none
->icvs
.stacksize
);
1844 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
1845 fprintf (stderr
, " [all] OMP_STACKSIZE = '%lu'\n",
1846 all
->icvs
.stacksize
);
1847 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_STACKSIZE
))
1848 fprintf (stderr
, " [device] OMP_STACKSIZE = '%lu'\n",
1849 dev
->icvs
.stacksize
);
1850 print_device_specific_icvs (GOMP_ICV_STACKSIZE
);
1852 /* GOMP's default value is actually neither active nor passive. */
1853 fprintf (stderr
, " [host] OMP_WAIT_POLICY = '%s'\n",
1854 none
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1855 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
1856 fprintf (stderr
, " [all] OMP_WAIT_POLICY = '%s'\n",
1857 all
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1858 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_WAIT_POLICY
))
1859 fprintf (stderr
, " [device] OMP_WAIT_POLICY = '%s'\n",
1860 dev
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1861 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY
);
1863 fprintf (stderr
, " [host] OMP_THREAD_LIMIT = '%u'\n",
1864 none
->icvs
.thread_limit_var
);
1865 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_THREAD_LIMIT
))
1866 fprintf (stderr
, " [all] OMP_THREAD_LIMIT = '%d'\n",
1867 all
->icvs
.thread_limit_var
);
1868 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_THREAD_LIMIT
))
1869 fprintf (stderr
, " [device] OMP_THREAD_LIMIT = '%d'\n",
1870 dev
->icvs
.thread_limit_var
);
1871 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT
);
1873 fprintf (stderr
, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1874 none
->icvs
.max_active_levels_var
);
1875 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1876 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1877 fprintf (stderr
, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1878 all
->icvs
.max_active_levels_var
);
1879 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1880 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1881 fprintf (stderr
, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1882 dev
->icvs
.max_active_levels_var
);
1883 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS
);
1886 fprintf (stderr
, " [host] OMP_NUM_TEAMS = '%d'\n",
1887 none
->icvs
.nteams_var
);
1888 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTEAMS
))
1889 fprintf (stderr
, " [all] OMP_NUM_TEAMS = '%d'\n",
1890 all
->icvs
.nteams_var
);
1891 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTEAMS
))
1892 fprintf (stderr
, " [device] OMP_NUM_TEAMS = '%d'\n",
1893 dev
->icvs
.nteams_var
);
1894 print_device_specific_icvs (GOMP_ICV_NTEAMS
);
1896 fprintf (stderr
, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1897 none
->icvs
.teams_thread_limit_var
);
1898 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1899 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1900 fprintf (stderr
, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1901 all
->icvs
.teams_thread_limit_var
);
1902 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1903 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1904 fprintf (stderr
, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1905 dev
->icvs
.teams_thread_limit_var
);
1906 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT
);
1908 fprintf (stderr
, " [all] OMP_CANCELLATION = '%s'\n",
1909 gomp_cancel_var
? "TRUE" : "FALSE");
1911 fprintf (stderr
, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1912 none
->icvs
.default_device_var
);
1914 fprintf (stderr
, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1915 gomp_max_task_priority_var
);
1916 fprintf (stderr
, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1917 gomp_display_affinity_var
? "TRUE" : "FALSE");
1918 fprintf (stderr
, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1919 gomp_affinity_format_var
);
1920 fprintf (stderr
, " [host] OMP_ALLOCATOR = '");
1921 switch (gomp_def_allocator
)
1923 #define C(v) case v: fputs (#v, stderr); break;
1924 C (omp_default_mem_alloc
)
1925 C (omp_large_cap_mem_alloc
)
1926 C (omp_const_mem_alloc
)
1927 C (omp_high_bw_mem_alloc
)
1928 C (omp_low_lat_mem_alloc
)
1929 C (omp_cgroup_mem_alloc
)
1930 C (omp_pteam_mem_alloc
)
1931 C (omp_thread_mem_alloc
)
1933 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1935 if (gomp_def_allocator_envvar
)
1936 fputs (gomp_def_allocator_envvar
, stderr
);
1939 fputs ("'\n", stderr
);
1941 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr
);
1942 switch (gomp_target_offload_var
)
1944 case GOMP_TARGET_OFFLOAD_DEFAULT
:
1945 fputs ("DEFAULT", stderr
);
1947 case GOMP_TARGET_OFFLOAD_MANDATORY
:
1948 fputs ("MANDATORY", stderr
);
1950 case GOMP_TARGET_OFFLOAD_DISABLED
:
1951 fputs ("DISABLED", stderr
);
1954 fputs ("'\n", stderr
);
1958 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr
);
1959 fprintf (stderr
, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize
);
1960 #ifdef HAVE_INTTYPES_H
1961 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%"PRIu64
"'\n",
1962 (uint64_t) gomp_spin_count_var
);
1964 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%lu'\n",
1965 (unsigned long) gomp_spin_count_var
);
1969 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr
);
1971 ialias (omp_display_env
)
1974 handle_omp_display_env (void)
1977 bool display
= false;
1978 bool verbose
= false;
1980 env
= getenv ("OMP_DISPLAY_ENV");
1984 while (isspace ((unsigned char) *env
))
1986 if (strncasecmp (env
, "true", 4) == 0)
1991 else if (strncasecmp (env
, "false", 5) == 0)
1996 else if (strncasecmp (env
, "verbose", 7) == 0)
2004 while (isspace ((unsigned char) *env
))
2007 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2010 ialias_call (omp_display_env
) (verbose
);
2013 /* Helper function for initialize_env. Extracts the device number from
2014 an environment variable name. ENV is the complete environment variable.
2015 DEV_NUM_PTR points to the start of the device number in the environment
2016 variable string. DEV_NUM_LEN is the returned length of the device num
2020 get_device_num (char *env
, char *dev_num_ptr
, int *dev_num
, int *dev_num_len
)
2023 unsigned long val
= strtoul (dev_num_ptr
, &end
, 10);
2026 || (dev_num_ptr
[0] == '0' && end
!= dev_num_ptr
+ 1)
2027 || (dev_num_ptr
[0] < '0' || dev_num_ptr
[0] > '9'))
2029 gomp_error ("Invalid device number in %s", env
);
2033 *dev_num_len
= end
- dev_num_ptr
;
2038 get_icv_member_addr (struct gomp_initial_icvs
*icvs
, int icv_code
,
2041 if (icv_code
== 0 || icv_addr
== NULL
)
2044 icv_addr
[0] = icv_addr
[1] = icv_addr
[2] = NULL
;
2048 case GOMP_ICV_NTEAMS
:
2049 icv_addr
[0] = &icvs
->nteams_var
;
2050 /* icv_addr[1] = (void *) false; */
2052 case GOMP_ICV_DYNAMIC
:
2053 icv_addr
[0] = &(*icvs
).dyn_var
;
2055 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
2056 icv_addr
[0] = &icvs
->teams_thread_limit_var
;
2057 /* icv_addr[1] = (void *) false; */
2059 case GOMP_ICV_SCHEDULE
:
2060 icv_addr
[0] = &icvs
->run_sched_var
;
2061 icv_addr
[1] = &icvs
->run_sched_chunk_size
;
2063 case GOMP_ICV_THREAD_LIMIT
:
2064 icv_addr
[0] = &icvs
->thread_limit_var
;
2065 /* icv_addr[1] = (void *) false; */
2066 icv_addr
[2] = (void *) UINT_MAX
;
2068 case GOMP_ICV_NTHREADS
:
2069 icv_addr
[0] = &icvs
->nthreads_var
;
2070 icv_addr
[1] = &icvs
->nthreads_var_list
;
2071 icv_addr
[2] = &icvs
->nthreads_var_list_len
;
2073 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
2074 icv_addr
[0] = &icvs
->max_active_levels_var
;
2075 icv_addr
[1] = (void *) true;
2076 icv_addr
[2] = (void *) gomp_supported_active_levels
;
2079 icv_addr
[0] = &icvs
->bind_var
;
2080 icv_addr
[1] = &icvs
->bind_var_list
;
2081 icv_addr
[2] = &icvs
->bind_var_list_len
;
2083 case GOMP_ICV_WAIT_POLICY
:
2084 icv_addr
[0] = &icvs
->wait_policy
;
2086 case GOMP_ICV_STACKSIZE
:
2087 icv_addr
[0] = &icvs
->stacksize
;
2089 case GOMP_ICV_CANCELLATION
:
2090 icv_addr
[0] = &gomp_cancel_var
;
2092 case GOMP_ICV_DISPLAY_AFFINITY
:
2093 icv_addr
[0] = &gomp_display_affinity_var
;
2095 case GOMP_ICV_TARGET_OFFLOAD
:
2096 icv_addr
[0] = &gomp_target_offload_var
;
2098 case GOMP_ICV_MAX_TASK_PRIORITY
:
2099 icv_addr
[0] = &gomp_max_task_priority_var
;
2101 case GOMP_ICV_ALLOCATOR
:
2102 icv_addr
[0] = &gomp_def_allocator
;
2104 case GOMP_ICV_DEFAULT_DEVICE
:
2105 icv_addr
[0] = &icvs
->default_device_var
;
2106 icv_addr
[1] = (void *) true;
2111 struct gomp_icv_list
*
2112 gomp_get_initial_icv_item (int dev_num
)
2114 struct gomp_icv_list
*l
= gomp_initial_icv_list
;
2115 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2122 initialize_icvs (struct gomp_initial_icvs
*icvs
)
2124 icvs
->nthreads_var_list
= NULL
;
2125 icvs
->bind_var_list
= NULL
;
2126 icvs
->nthreads_var
= gomp_default_icv_values
.nthreads_var
;
2127 icvs
->nthreads_var_list_len
= 0;
2128 icvs
->bind_var_list_len
= 0;
2129 icvs
->stacksize
= 0;
2130 icvs
->thread_limit_var
= gomp_default_icv_values
.thread_limit_var
;
2131 icvs
->run_sched_var
= gomp_default_icv_values
.run_sched_var
;
2132 icvs
->run_sched_chunk_size
= gomp_default_icv_values
.run_sched_chunk_size
;
2133 icvs
->default_device_var
= gomp_default_icv_values
.default_device_var
;
2134 icvs
->dyn_var
= gomp_default_icv_values
.dyn_var
;
2135 icvs
->max_active_levels_var
= gomp_default_icv_values
.max_active_levels_var
;
2136 icvs
->bind_var
= gomp_default_icv_values
.bind_var
;
2137 icvs
->nteams_var
= gomp_default_icv_values
.nteams_var
;
2138 icvs
->teams_thread_limit_var
= gomp_default_icv_values
.teams_thread_limit_var
;
2139 icvs
->wait_policy
= -1;
2142 /* Helper function for initialize_env to add a device specific ICV value
2143 to gomp_initial_icv_list. */
2146 add_initial_icv_to_list (int dev_num
, int icv_code
, void *icv_addr
[3])
2148 struct gomp_icv_list
*last
= NULL
, *l
= gomp_initial_icv_list
;
2149 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2157 l
= ((struct gomp_icv_list
*)
2158 gomp_malloc_cleared (sizeof (struct gomp_icv_list
)));
2159 l
->device_num
= dev_num
;
2160 initialize_icvs (&l
->icvs
);
2163 l
->next
= gomp_initial_icv_list
;
2164 gomp_initial_icv_list
= l
;
2170 gomp_initial_icv_list
= l
;
2176 get_icv_member_addr (&l
->icvs
, icv_code
, icv_addr
);
2181 /* Return true if STR string starts with PREFIX. */
2184 startswith (const char *str
, const char *prefix
)
2186 return strncmp (str
, prefix
, strlen (prefix
)) == 0;
2189 static void __attribute__((destructor
))
2192 if (gomp_def_allocator_envvar
!= NULL
)
2194 free (gomp_def_allocator_envvar
);
2195 omp_destroy_allocator (gomp_def_allocator
);
2199 static void __attribute__((constructor
))
2200 initialize_env (void)
2203 int omp_var
, dev_num
= 0, dev_num_len
= 0, i
;
2204 bool ignore
= false;
2207 uint32_t *flag_var_addr
= NULL
;
2209 struct gomp_icv_list
*all
, *none
;
2211 /* Do a compile time check that mkomp_h.pl did good job. */
2212 omp_check_defines ();
2214 #ifndef HAVE_SYNC_BUILTINS
2215 gomp_mutex_init (&gomp_managed_threads_lock
);
2217 gomp_init_num_threads ();
2218 gomp_available_cpus
= gomp_global_icv
.nthreads_var
;
2220 /* Initial values for host environment variables should always exist even if
2221 there is no explicitly set host environment variable. Moreover, they are
2222 set to the initial global values. */
2223 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
, 0, NULL
);
2224 none
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
2225 initialize_icvs (&none
->icvs
);
2227 for (env
= environ
; *env
!= 0; env
++)
2229 if (!startswith (*env
, "OMP_"))
2232 /* Name of the environment variable without suffix "OMP_". */
2233 char *name
= *env
+ sizeof ("OMP_") - 1;
2234 for (omp_var
= 0; omp_var
< OMP_VAR_CNT
; omp_var
++)
2236 if (startswith (name
, envvars
[omp_var
].name
))
2238 pos
= envvars
[omp_var
].name_len
;
2239 if (name
[pos
] == '=')
2243 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
,
2244 envvars
[omp_var
].flag_vars
[0],
2247 else if (startswith (&name
[pos
], "_DEV=")
2248 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV
)
2252 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV
,
2253 envvars
[omp_var
].flag_vars
[0],
2256 else if (startswith (&name
[pos
], "_ALL=")
2257 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_ALL
)
2261 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL
,
2262 envvars
[omp_var
].flag_vars
[0],
2265 else if (startswith (&name
[pos
], "_DEV_")
2266 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV_X
)
2269 if (!get_device_num (*env
, &name
[pos
], &dev_num
,
2273 pos
+= dev_num_len
+ 1;
2275 = add_initial_icv_to_list (dev_num
,
2276 envvars
[omp_var
].flag_vars
[0],
2281 gomp_error ("Invalid environment variable in %s", *env
);
2284 env_val
= &name
[pos
];
2286 if (envvars
[omp_var
].parse_func (*env
, env_val
, params
))
2288 for (i
= 0; i
< 3; ++i
)
2289 if (envvars
[omp_var
].flag_vars
[i
])
2290 gomp_set_icv_flag (flag_var_addr
,
2291 envvars
[omp_var
].flag_vars
[i
]);
2301 all
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
2302 for (omp_var
= 0; omp_var
< OMP_HOST_VAR_CNT
; omp_var
++)
2305 && gomp_get_icv_flag (none
->flags
, host_envvars
[omp_var
].flag_var
))
2306 get_icv_member_addr (&none
->icvs
,
2307 host_envvars
[omp_var
].flag_var
, params
);
2308 else if (all
!= NULL
2309 && gomp_get_icv_flag (all
->flags
,
2310 host_envvars
[omp_var
].flag_var
))
2311 get_icv_member_addr (&all
->icvs
, host_envvars
[omp_var
].flag_var
,
2316 switch (host_envvars
[omp_var
].type_code
)
2319 for (i
= 0; i
< 3; ++i
)
2320 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2321 *(int *) (host_envvars
[omp_var
].dest
[i
]) = *(int *) params
[i
];
2324 for (i
= 0; i
< 3; ++i
)
2325 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2326 *(bool *) (host_envvars
[omp_var
].dest
[i
]) = *(bool *) params
[i
];
2329 for (i
= 0; i
< 3; ++i
)
2330 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2331 *(unsigned int *) (host_envvars
[omp_var
].dest
[i
])
2332 = *(unsigned int *) params
[i
];
2335 for (i
= 0; i
< 3; ++i
)
2336 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2337 *(unsigned long *) (host_envvars
[omp_var
].dest
[i
])
2338 = *(unsigned long *) params
[i
];
2341 for (i
= 0; i
< 3; ++i
)
2342 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2343 *(unsigned char *) (host_envvars
[omp_var
].dest
[i
])
2344 = *(unsigned char *) params
[i
];
2346 case PARSE_SCHEDULE
:
2347 *(enum gomp_schedule_type
*) (host_envvars
[omp_var
].dest
[0])
2348 = *(enum gomp_schedule_type
*) params
[0];
2349 *(int *) (host_envvars
[omp_var
].dest
[1]) = *(int *) params
[1];
2352 *(char *) (host_envvars
[omp_var
].dest
[0]) = *(char *) params
[0];
2353 *(char **) (host_envvars
[omp_var
].dest
[1]) = *(char **) params
[1];
2354 *(unsigned long *) (host_envvars
[omp_var
].dest
[2])
2355 = *(unsigned long *) params
[2];
2360 if (((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_BIND
))
2361 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
)))
2362 && gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2366 && gomp_get_icv_flag (none
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))
2368 && gomp_get_icv_flag (all
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))))
2371 const char *env
= getenv ("OMP_NESTED");
2373 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2374 if (parse_boolean ("OMP_NESTED", env
, (void *[]) {&nested
}))
2375 gomp_global_icv
.max_active_levels_var
2376 = nested
? gomp_supported_active_levels
: 1;
2377 else if (gomp_nthreads_var_list_len
> 1 || gomp_bind_var_list_len
> 1)
2378 gomp_global_icv
.max_active_levels_var
= gomp_supported_active_levels
;
2381 if (gomp_global_icv
.default_device_var
== INT_MIN
2382 && gomp_target_offload_var
!= GOMP_TARGET_OFFLOAD_MANDATORY
)
2383 none
->icvs
.default_device_var
= gomp_global_icv
.default_device_var
= 0;
2385 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2386 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var
, true);
2388 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2389 parsed if present in the environment. If OMP_PROC_BIND was set
2390 explicitly to false, don't populate places list though. If places
2391 list was successfully set from OMP_PLACES, only parse but don't process
2392 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2393 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2394 was successfully parsed into a places list, otherwise to
2395 OMP_PROC_BIND=false. */
2396 if (parse_places_var ("OMP_PLACES", ignore
))
2398 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2399 gomp_global_icv
.bind_var
= true;
2402 if (parse_affinity (ignore
))
2404 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2405 gomp_global_icv
.bind_var
= true;
2408 if (gomp_global_icv
.bind_var
!= omp_proc_bind_false
)
2409 gomp_init_affinity ();
2412 const char *env
= getenv ("OMP_AFFINITY_FORMAT");
2414 gomp_set_affinity_format (env
, strlen (env
));
2417 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_WAIT_POLICY
))
2418 wait_policy
= none
->icvs
.wait_policy
;
2419 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
2420 wait_policy
= all
->icvs
.wait_policy
;
2422 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var
))
2424 /* Using a rough estimation of 100000 spins per msec,
2425 use 5 min blocking for OMP_WAIT_POLICY=active,
2426 3 msec blocking when OMP_WAIT_POLICY is not specificed
2427 and 0 when OMP_WAIT_POLICY=passive.
2428 Depending on the CPU speed, this can be e.g. 5 times longer
2429 or 5 times shorter. */
2430 if (wait_policy
> 0)
2431 gomp_spin_count_var
= 30000000000LL;
2432 else if (wait_policy
< 0)
2433 gomp_spin_count_var
= 300000LL;
2435 /* gomp_throttled_spin_count_var is used when there are more libgomp
2436 managed threads than available CPUs. Use very short spinning. */
2437 if (wait_policy
> 0)
2438 gomp_throttled_spin_count_var
= 1000LL;
2439 else if (wait_policy
< 0)
2440 gomp_throttled_spin_count_var
= 100LL;
2441 if (gomp_throttled_spin_count_var
> gomp_spin_count_var
)
2442 gomp_throttled_spin_count_var
= gomp_spin_count_var
;
2444 /* Not strictly environment related, but ordering constructors is tricky. */
2445 pthread_attr_init (&gomp_thread_attr
);
2447 if (!(none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
)))
2449 const char *env
= getenv ("GOMP_STACKSIZE");
2451 && parse_stacksize ("GOMP_STACKSIZE", env
,
2452 (void *[3]) {&none
->icvs
.stacksize
}))
2453 gomp_set_icv_flag (&none
->flags
, GOMP_ICV_STACKSIZE
);
2455 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2456 stacksize
= none
->icvs
.stacksize
;
2457 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2458 stacksize
= all
->icvs
.stacksize
;
2460 if ((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2461 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2462 || GOMP_DEFAULT_STACKSIZE
)
2466 err
= pthread_attr_setstacksize (&gomp_thread_attr
, stacksize
);
2468 #ifdef PTHREAD_STACK_MIN
2471 if (stacksize
< PTHREAD_STACK_MIN
)
2472 gomp_error ("Stack size less than minimum of %luk",
2473 PTHREAD_STACK_MIN
/ 1024ul
2474 + (PTHREAD_STACK_MIN
% 1024 != 0));
2476 gomp_error ("Stack size larger than system limit");
2481 gomp_error ("Stack size change failed: %s", strerror (err
));
2484 handle_omp_display_env ();
2488 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2489 (void *[]) {&goacc_device_num
, (void *) true}))
2490 goacc_device_num
= 0;
2492 parse_acc_device_type ();
2493 parse_gomp_openacc_dim ();
2495 goacc_runtime_initialize ();
2497 goacc_profiling_initialize ();
2499 #endif /* LIBGOMP_OFFLOADED_ONLY */