1 /* Copyright (C) 2005-2024 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"
64 #include "spincount.h"
66 /* Default values of ICVs according to the OpenMP standard,
67 except for default-device-var. */
68 const struct gomp_default_icv gomp_default_icv_values
= {
70 .thread_limit_var
= UINT_MAX
,
71 .run_sched_var
= GFS_DYNAMIC
,
72 .run_sched_chunk_size
= 1,
73 .default_device_var
= INT_MIN
,
74 .max_active_levels_var
= 1,
75 .bind_var
= omp_proc_bind_false
,
77 .teams_thread_limit_var
= 0,
81 struct gomp_task_icv gomp_global_icv
= {
82 .nthreads_var
= gomp_default_icv_values
.nthreads_var
,
83 .thread_limit_var
= gomp_default_icv_values
.thread_limit_var
,
84 .run_sched_var
= gomp_default_icv_values
.run_sched_var
,
85 .run_sched_chunk_size
= gomp_default_icv_values
.run_sched_chunk_size
,
86 .default_device_var
= gomp_default_icv_values
.default_device_var
,
87 .dyn_var
= gomp_default_icv_values
.dyn_var
,
88 .max_active_levels_var
= gomp_default_icv_values
.max_active_levels_var
,
89 .bind_var
= gomp_default_icv_values
.bind_var
,
93 /* List for initial "_DEV", "_ALL", and "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV,
94 OMP_NUM_TEAMS_ALL, or OMP_NUM_TEAMS_DEV_42. */
95 struct gomp_icv_list
*gomp_initial_icv_list
= NULL
;
97 /* List for "_DEV_X" ICVs like OMP_NUM_TEAMS_DEV_42. This list contains all
98 device-specific ICVs that are copied from host to device and back. */
99 struct gomp_offload_icv_list
*gomp_offload_icv_list
= NULL
;
101 bool gomp_cancel_var
= false;
102 enum gomp_target_offload_t gomp_target_offload_var
103 = GOMP_TARGET_OFFLOAD_DEFAULT
;
104 int gomp_max_task_priority_var
= 0;
105 #ifndef HAVE_SYNC_BUILTINS
106 gomp_mutex_t gomp_managed_threads_lock
;
108 unsigned long gomp_available_cpus
= 1, gomp_managed_threads
= 1;
109 unsigned long long gomp_spin_count_var
, gomp_throttled_spin_count_var
;
110 unsigned long *gomp_nthreads_var_list
, gomp_nthreads_var_list_len
;
111 char *gomp_bind_var_list
;
112 unsigned long gomp_bind_var_list_len
;
113 void **gomp_places_list
;
114 unsigned long gomp_places_list_len
;
115 uintptr_t gomp_def_allocator
= omp_default_mem_alloc
;
116 char *gomp_def_allocator_envvar
= NULL
;
118 unsigned int gomp_num_teams_var
;
120 int gomp_teams_thread_limit_var
;
121 bool gomp_display_affinity_var
;
122 char *gomp_affinity_format_var
= "level %L thread %i affinity %A";
123 size_t gomp_affinity_format_len
;
124 char *goacc_device_type
;
125 int goacc_device_num
;
126 int goacc_default_dims
[GOMP_DIM_MAX
];
128 #ifndef LIBGOMP_OFFLOADED_ONLY
130 static int wait_policy
= -1;
131 static unsigned long stacksize
= GOMP_DEFAULT_STACKSIZE
;
134 print_env_var_error (const char *env
, const char *val
)
136 gomp_error ("Invalid value for environment variable %.*s: %s",
137 (int) (val
- env
- 1), env
, val
);
140 /* Parse the OMP_SCHEDULE environment variable. */
142 parse_schedule (const char *env
, const char *val
, void *const params
[])
144 enum gomp_schedule_type
*schedule
= (enum gomp_schedule_type
*) params
[0];
145 int *chunk_size
= (int *) params
[1];
153 while (isspace ((unsigned char) *val
))
155 if (strncasecmp (val
, "monotonic", 9) == 0)
160 else if (strncasecmp (val
, "nonmonotonic", 12) == 0)
167 while (isspace ((unsigned char) *val
))
172 while (isspace ((unsigned char) *val
))
175 if (strncasecmp (val
, "static", 6) == 0)
177 *schedule
= GFS_STATIC
;
180 else if (strncasecmp (val
, "dynamic", 7) == 0)
182 *schedule
= GFS_DYNAMIC
;
185 else if (strncasecmp (val
, "guided", 6) == 0)
187 *schedule
= GFS_GUIDED
;
190 else if (strncasecmp (val
, "auto", 4) == 0)
192 *schedule
= GFS_AUTO
;
199 || (monotonic
== 0 && *schedule
== GFS_STATIC
))
200 *schedule
|= GFS_MONOTONIC
;
202 while (isspace ((unsigned char) *val
))
206 *chunk_size
= (*schedule
& ~GFS_MONOTONIC
) != GFS_STATIC
;
211 while (isspace ((unsigned char) *val
))
217 value
= strtoul (val
, &end
, 10);
218 if (errno
|| end
== val
)
221 while (isspace ((unsigned char) *end
))
226 if ((int)value
!= value
)
229 if (value
== 0 && (*schedule
& ~GFS_MONOTONIC
) != GFS_STATIC
)
235 print_env_var_error (env
, val
);
239 char name
[val
- env
];
240 memcpy (name
, env
, val
- env
- 1);
241 name
[val
- env
- 1] = '\0';
242 gomp_error ("Invalid value for chunk size in "
243 "environment variable %s: %s", name
, val
);
247 /* Parse an unsigned long environment variable. Return true if one was
248 present and it was successfully parsed. If SECURE, use secure_getenv to the
249 environment variable. */
252 parse_unsigned_long_1 (const char *env
, const char *val
, unsigned long *pvalue
,
261 while (isspace ((unsigned char) *val
))
267 value
= strtoul (val
, &end
, 10);
268 if (errno
|| end
== val
|| (long) value
<= 0 - allow_zero
)
271 while (isspace ((unsigned char) *end
))
280 print_env_var_error (env
, val
);
284 /* As parse_unsigned_long_1, but always use getenv. */
287 parse_unsigned_long (const char *env
, const char *val
, void *const params
[])
289 unsigned long upper
= (uintptr_t) params
[2];
290 unsigned long pvalue
= 0;
291 bool ret
= parse_unsigned_long_1 (env
, val
, &pvalue
, (bool) params
[1]);
296 *(unsigned long *) params
[0] = pvalue
;
301 if (upper
<= UCHAR_MAX
)
302 *(unsigned char *) params
[0] = pvalue
;
303 else if (upper
<= UINT_MAX
)
304 *(unsigned int *) params
[0] = pvalue
;
306 *(unsigned long *) params
[0] = pvalue
;
312 /* Parse a positive int environment variable. Return true if one was
313 present and it was successfully parsed. If SECURE, use secure_getenv to the
314 environment variable. */
317 parse_int_1 (const char *env
, const char *val
, int *pvalue
, bool allow_zero
)
320 if (!parse_unsigned_long_1 (env
, val
, &value
, allow_zero
))
324 print_env_var_error (env
, val
);
327 *pvalue
= (int) value
;
332 parse_int (const char *env
, const char *val
, void *const params
[])
334 return parse_int_1 (env
, val
, (int *) params
[0], (bool) params
[1]);
337 /* As parse_int_1, but use getenv_secure. */
340 parse_int_secure (const char *env
, int *pvalue
, bool allow_zero
)
342 return parse_int_1 (env
, secure_getenv (env
), pvalue
, allow_zero
);
345 /* Parse an unsigned long list environment variable. Return true if one was
346 present and it was successfully parsed. */
349 parse_unsigned_long_list (const char *env
, const char *val
,
350 void *const params
[])
352 unsigned long *p1stvalue
= (unsigned long *) params
[0];
353 unsigned long **pvalues
= (unsigned long **) params
[1];
354 unsigned long *pnvalues
= (unsigned long *) params
[2];
356 unsigned long value
, *values
= NULL
;
361 while (isspace ((unsigned char) *val
))
367 value
= strtoul (val
, &end
, 10);
368 if (errno
|| (long) value
<= 0)
371 while (isspace ((unsigned char) *end
))
377 unsigned long nvalues
= 0, nalloced
= 0;
382 if (nvalues
== nalloced
)
385 nalloced
= nalloced
? nalloced
* 2 : 16;
386 n
= realloc (values
, nalloced
* sizeof (unsigned long));
390 char name
[val
- env
];
391 memcpy (name
, env
, val
- env
- 1);
392 name
[val
- env
- 1] = '\0';
393 gomp_error ("Out of memory while trying to parse"
394 " environment variable %s", name
);
399 values
[nvalues
++] = value
;
402 while (isspace ((unsigned char) *val
))
408 value
= strtoul (val
, &end
, 10);
409 if (errno
|| (long) value
<= 0)
412 values
[nvalues
++] = value
;
413 while (isspace ((unsigned char) *end
))
421 *p1stvalue
= values
[0];
439 print_env_var_error (env
, val
);
444 parse_target_offload (const char *env
, const char *val
, void *const params
[])
446 int new_offload
= -1;
451 while (isspace ((unsigned char) *val
))
453 if (strncasecmp (val
, "default", 7) == 0)
456 new_offload
= GOMP_TARGET_OFFLOAD_DEFAULT
;
458 else if (strncasecmp (val
, "mandatory", 9) == 0)
461 new_offload
= GOMP_TARGET_OFFLOAD_MANDATORY
;
463 else if (strncasecmp (val
, "disabled", 8) == 0)
466 new_offload
= GOMP_TARGET_OFFLOAD_DISABLED
;
468 while (isspace ((unsigned char) *val
))
470 if (new_offload
!= -1 && *val
== '\0')
472 *(enum gomp_target_offload_t
*) params
[0] = new_offload
;
476 print_env_var_error (env
, val
);
480 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
481 enum values. Return true if one was present and it was successfully
485 parse_bind_var (const char *env
, const char *val
, void *const params
[])
487 char *p1stvalue
= (char *) params
[0];
488 char **pvalues
= (char **) params
[1];
489 unsigned long *pnvalues
= (unsigned long *) params
[2];
490 char value
= omp_proc_bind_false
, *values
= NULL
;
492 static struct proc_bind_kinds
496 omp_proc_bind_t kind
;
499 { "false", 5, omp_proc_bind_false
},
500 { "true", 4, omp_proc_bind_true
},
501 { "master", 6, omp_proc_bind_master
},
502 { "primary", 7, omp_proc_bind_primary
},
503 { "close", 5, omp_proc_bind_close
},
504 { "spread", 6, omp_proc_bind_spread
}
510 while (isspace ((unsigned char) *val
))
515 for (i
= 0; i
< 6; i
++)
516 if (strncasecmp (val
, kinds
[i
].name
, kinds
[i
].len
) == 0)
518 value
= kinds
[i
].kind
;
525 while (isspace ((unsigned char) *val
))
531 unsigned long nvalues
= 0, nalloced
= 0;
533 if (value
== omp_proc_bind_false
534 || value
== omp_proc_bind_true
)
540 if (nvalues
== nalloced
)
543 nalloced
= nalloced
? nalloced
* 2 : 16;
544 n
= realloc (values
, nalloced
);
548 char name
[val
- env
];
549 memcpy (name
, env
, val
- env
- 1);
550 name
[val
- env
- 1] = '\0';
551 gomp_error ("Out of memory while trying to parse"
552 " environment variable %s", name
);
557 values
[nvalues
++] = value
;
560 while (isspace ((unsigned char) *val
))
565 for (i
= 2; i
< 6; i
++)
566 if (strncasecmp (val
, kinds
[i
].name
, kinds
[i
].len
) == 0)
568 value
= kinds
[i
].kind
;
575 values
[nvalues
++] = value
;
576 while (isspace ((unsigned char) *val
))
584 *p1stvalue
= values
[0];
597 print_env_var_error (env
, val
);
602 parse_one_place (char **envp
, bool *negatep
, unsigned long *lenp
,
605 char *env
= *envp
, *start
;
606 void *p
= gomp_places_list
? gomp_places_list
[gomp_places_list_len
] : NULL
;
607 unsigned long len
= 1;
610 bool any_negate
= false;
611 bool has_braces
= true;
613 while (isspace ((unsigned char) *env
))
619 while (isspace ((unsigned char) *env
))
625 unsigned long this_num
;
628 this_num
= strtoul (env
, &end
, 10);
629 if (errno
|| end
== env
)
634 && !gomp_affinity_add_cpus (p
, this_num
, 1, 1, false))
640 while (isspace ((unsigned char) *env
))
644 for (pass
= 0; pass
< (any_negate
? 2 : has_braces
); pass
++)
649 unsigned long this_num
, this_len
= 1;
650 long this_stride
= 1;
651 bool this_negate
= (*env
== '!');
655 if (gomp_places_list
)
658 while (isspace ((unsigned char) *env
))
663 this_num
= strtoul (env
, &end
, 10);
664 if (errno
|| end
== env
)
667 while (isspace ((unsigned char) *env
))
674 while (isspace ((unsigned char) *env
))
677 this_len
= strtoul (env
, &env
, 10);
678 if (errno
|| this_len
== 0)
680 while (isspace ((unsigned char) *env
))
685 while (isspace ((unsigned char) *env
))
688 this_stride
= strtol (env
, &end
, 10);
689 if (errno
|| end
== env
)
692 while (isspace ((unsigned char) *env
))
696 if (gomp_places_list
&& pass
== this_negate
)
700 if (!gomp_affinity_remove_cpu (p
, this_num
))
703 else if (!gomp_affinity_add_cpus (p
, this_num
, this_len
,
717 while (isspace ((unsigned char) *env
))
725 while (isspace ((unsigned char) *env
))
728 len
= strtoul (env
, &env
, 10);
729 if (errno
|| len
== 0 || len
>= 65536)
731 while (isspace ((unsigned char) *env
))
736 while (isspace ((unsigned char) *env
))
739 stride
= strtol (env
, &end
, 10);
740 if (errno
|| end
== env
)
743 while (isspace ((unsigned char) *env
))
754 parse_places_var (const char *name
, bool ignore
)
756 char *env
= getenv (name
), *end
;
757 bool any_negate
= false;
759 unsigned long count
= 0;
763 while (isspace ((unsigned char) *env
))
768 if (strncasecmp (env
, "threads", 7) == 0)
773 else if (strncasecmp (env
, "cores", 5) == 0)
778 else if (strncasecmp (env
, "sockets", 7) == 0)
783 else if (strncasecmp (env
, "ll_caches", 9) == 0)
788 else if (strncasecmp (env
, "numa_domains", 12) == 0)
796 while (isspace ((unsigned char) *env
))
802 while (isspace ((unsigned char) *env
))
806 count
= strtoul (env
, &end
, 10);
807 if (errno
|| end
== env
)
810 while (isspace ((unsigned char) *env
))
815 while (isspace ((unsigned char) *env
))
824 return gomp_affinity_init_level (level
, count
, false);
834 if (!parse_one_place (&end
, &negate
, &len
, &stride
))
857 gomp_places_list_len
= 0;
858 gomp_places_list
= gomp_affinity_alloc (count
, false);
859 if (gomp_places_list
== NULL
)
867 gomp_affinity_init_place (gomp_places_list
[gomp_places_list_len
]);
868 if (!parse_one_place (&env
, &negate
, &len
, &stride
))
873 for (count
= 0; count
< gomp_places_list_len
; count
++)
874 if (gomp_affinity_same_place
875 (gomp_places_list
[count
],
876 gomp_places_list
[gomp_places_list_len
]))
878 if (count
== gomp_places_list_len
)
880 gomp_error ("Trying to remove a non-existing place from list "
884 p
= gomp_places_list
[count
];
885 memmove (&gomp_places_list
[count
],
886 &gomp_places_list
[count
+ 1],
887 (gomp_places_list_len
- count
- 1) * sizeof (void *));
888 --gomp_places_list_len
;
889 gomp_places_list
[gomp_places_list_len
] = p
;
892 ++gomp_places_list_len
;
895 for (count
= 0; count
< len
- 1; count
++)
896 if (!gomp_affinity_copy_place
897 (gomp_places_list
[gomp_places_list_len
+ count
+ 1],
898 gomp_places_list
[gomp_places_list_len
+ count
],
901 gomp_places_list_len
+= len
;
909 if (gomp_places_list_len
== 0)
911 gomp_error ("All places have been removed");
914 if (!gomp_affinity_finalize_place_list (false))
919 free (gomp_places_list
);
920 gomp_places_list
= NULL
;
921 gomp_places_list_len
= 0;
922 gomp_error ("Invalid value for environment variable %s", name
);
926 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
927 present and it was successfully parsed. */
930 parse_stacksize (const char *env
, const char *val
, void *const params
[])
933 unsigned long value
, shift
= 10;
938 while (isspace ((unsigned char) *val
))
944 value
= strtoul (val
, &end
, 10);
945 if (errno
|| end
== val
)
948 while (isspace ((unsigned char) *end
))
952 switch (tolower ((unsigned char) *end
))
969 while (isspace ((unsigned char) *end
))
975 if (((value
<< shift
) >> shift
) != value
)
978 *(unsigned long *) params
[0] = value
<< shift
;
982 print_env_var_error (env
, val
);
986 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
987 present and it was successfully parsed. */
990 parse_spincount (const char *name
, unsigned long long *pvalue
)
993 unsigned long long value
, mult
= 1;
999 while (isspace ((unsigned char) *env
))
1004 if (strncasecmp (env
, "infinite", 8) == 0
1005 || strncasecmp (env
, "infinity", 8) == 0)
1013 value
= strtoull (env
, &end
, 10);
1014 if (errno
|| end
== env
)
1017 while (isspace ((unsigned char) *end
))
1021 switch (tolower ((unsigned char) *end
))
1027 mult
= 1000LL * 1000LL;
1030 mult
= 1000LL * 1000LL * 1000LL;
1033 mult
= 1000LL * 1000LL * 1000LL * 1000LL;
1040 while (isspace ((unsigned char) *end
))
1046 if (value
> ~0ULL / mult
)
1055 gomp_error ("Invalid value for environment variable %s", name
);
1059 /* Parse a boolean value for environment variable NAME and store the
1060 result in VALUE. Return true if one was present and it was
1061 successfully parsed. */
1063 parse_boolean (const char *env
, const char *val
, void *const params
[])
1065 bool *value
= (bool *) params
[0];
1070 while (isspace ((unsigned char) *val
))
1072 if (strncasecmp (val
, "true", 4) == 0)
1077 else if (strncasecmp (val
, "false", 5) == 0)
1084 while (isspace ((unsigned char) *val
))
1088 print_env_var_error (env
, val
);
1094 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1097 parse_wait_policy (const char *env
, const char *val
, void *const params
[])
1099 int *pvalue
= (int *) params
[0];
1108 while (isspace ((unsigned char) *val
))
1110 if (strncasecmp (val
, "active", 6) == 0)
1115 else if (strncasecmp (val
, "passive", 7) == 0)
1122 while (isspace ((unsigned char) *val
))
1129 print_env_var_error (env
, val
);
1134 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1135 present and it was successfully parsed. */
1138 parse_affinity (bool ignore
)
1140 char *env
, *end
, *start
;
1142 unsigned long cpu_beg
, cpu_end
, cpu_stride
;
1143 size_t count
= 0, needed
;
1145 env
= getenv ("GOMP_CPU_AFFINITY");
1150 for (pass
= 0; pass
< 2; pass
++)
1158 gomp_places_list_len
= 0;
1159 gomp_places_list
= gomp_affinity_alloc (count
, true);
1160 if (gomp_places_list
== NULL
)
1165 while (isspace ((unsigned char) *env
))
1169 cpu_beg
= strtoul (env
, &end
, 0);
1170 if (errno
|| end
== env
|| cpu_beg
>= 65536)
1179 cpu_end
= strtoul (++env
, &end
, 0);
1180 if (errno
|| end
== env
|| cpu_end
>= 65536 || cpu_end
< cpu_beg
)
1187 cpu_stride
= strtoul (++env
, &end
, 0);
1188 if (errno
|| cpu_stride
== 0 || cpu_stride
>= 65536)
1195 needed
= (cpu_end
- cpu_beg
) / cpu_stride
+ 1;
1202 void *p
= gomp_places_list
[gomp_places_list_len
];
1203 gomp_affinity_init_place (p
);
1204 if (gomp_affinity_add_cpus (p
, cpu_beg
, 1, 0, true))
1205 ++gomp_places_list_len
;
1206 cpu_beg
+= cpu_stride
;
1210 while (isspace ((unsigned char) *env
))
1215 else if (*env
== '\0')
1221 if (gomp_places_list_len
== 0)
1223 free (gomp_places_list
);
1224 gomp_places_list
= NULL
;
1230 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1234 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1236 parse_allocator (const char *env
, const char *val
, void *const params
[])
1238 const char *orig_val
= val
;
1239 uintptr_t *ret
= (uintptr_t *) params
[0];
1240 *ret
= omp_default_mem_alloc
;
1241 bool memspace
= false;
1243 omp_alloctrait_t
*traits
;
1248 while (isspace ((unsigned char) *val
))
1253 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1256 val += sizeof (#v) - 1; \
1259 C (omp_default_mem_alloc
, false)
1260 C (omp_large_cap_mem_alloc
, false)
1261 C (omp_const_mem_alloc
, false)
1262 C (omp_high_bw_mem_alloc
, false)
1263 C (omp_low_lat_mem_alloc
, false)
1264 C (omp_cgroup_mem_alloc
, false)
1265 C (omp_pteam_mem_alloc
, false)
1266 C (omp_thread_mem_alloc
, false)
1267 C (omp_default_mem_space
, true)
1268 C (omp_large_cap_mem_space
, true)
1269 C (omp_const_mem_space
, true)
1270 C (omp_high_bw_mem_space
, true)
1271 C (omp_low_lat_mem_space
, true)
1275 if (memspace
&& *val
== ':')
1278 const char *cp
= val
;
1285 traits
= gomp_alloca (ntraits
* sizeof (omp_alloctrait_t
));
1287 while (*val
!= '\0')
1290 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1292 val += sizeof (#v); \
1293 traits[n].key = omp_atk_ ## v;
1295 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1297 val += sizeof (#v) - 1; \
1298 traits[n].value = omp_atv_ ## v; \
1315 traits
[n
].value
= strtol (val
, &end
, 10);
1316 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1333 traits
[n
].value
= strtol (val
, &end
, 10);
1334 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1348 /* Ignore fb_data, which expects an allocator handle. */
1382 case omp_default_mem_space
: *ret
= omp_default_mem_alloc
; break;
1383 case omp_large_cap_mem_space
: *ret
= omp_large_cap_mem_alloc
; break;
1384 case omp_const_mem_space
: *ret
= omp_const_mem_alloc
; break;
1385 case omp_high_bw_mem_space
: *ret
= omp_high_bw_mem_alloc
; break;
1386 case omp_low_lat_mem_space
: *ret
= omp_low_lat_mem_alloc
; break;
1387 default: __builtin_unreachable ();
1389 while (isspace ((unsigned char) *val
))
1395 *ret
= omp_init_allocator (*ret
, ntraits
, traits
);
1396 if (*ret
== omp_null_allocator
)
1398 gomp_error ("Allocator of environment variable %.*s cannot be "
1399 "created, using omp_default_mem_alloc instead",
1400 (int) (orig_val
- env
- 1), env
);
1401 *ret
= omp_default_mem_alloc
;
1404 gomp_def_allocator_envvar
= strdup (orig_val
);
1409 int len
= (orig_val
- env
- 1);
1411 gomp_error ("Missing value at the end of environment variable %s", env
);
1413 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1415 *ret
= omp_default_mem_alloc
;
1420 parse_acc_device_type (void)
1422 const char *env
= getenv ("ACC_DEVICE_TYPE");
1424 if (env
&& *env
!= '\0')
1425 goacc_device_type
= strdup (env
);
1427 goacc_device_type
= NULL
;
1431 parse_gomp_openacc_dim (void)
1433 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1434 const char *var_name
= "GOMP_OPENACC_DIM";
1435 const char *env_var
= getenv (var_name
);
1436 const char *pos
= env_var
;
1442 for (i
= 0; *pos
&& i
!= GOMP_DIM_MAX
; i
++)
1447 if (i
&& *pos
++ != ':')
1454 val
= strtol (pos
, &eptr
, 10);
1455 if (errno
|| eptr
== pos
|| val
< 0 || (unsigned)val
!= val
)
1458 goacc_default_dims
[i
] = (int)val
;
1459 pos
= (const char *) eptr
;
1463 /* Helper function for omp_display_env which prints the values of run_sched_var.
1464 'device' can be 'host', 'dev', 'all' or a particular device number. */
1467 print_schedule (enum gomp_schedule_type run_sched_var
, int run_sched_chunk_size
,
1470 fprintf (stderr
, " [%s] OMP_SCHEDULE = '", device
);
1471 if ((run_sched_var
& GFS_MONOTONIC
))
1473 if (run_sched_var
!= (GFS_MONOTONIC
| GFS_STATIC
))
1474 fputs ("MONOTONIC:", stderr
);
1476 else if (run_sched_var
== GFS_STATIC
)
1477 fputs ("NONMONOTONIC:", stderr
);
1478 switch (run_sched_var
& ~GFS_MONOTONIC
)
1481 fputs ("RUNTIME", stderr
);
1482 if (run_sched_chunk_size
!= 1)
1483 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1486 fputs ("STATIC", stderr
);
1487 if (run_sched_chunk_size
!= 0)
1488 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1491 fputs ("DYNAMIC", stderr
);
1492 if (run_sched_chunk_size
!= 1)
1493 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1496 fputs ("GUIDED", stderr
);
1497 if (run_sched_chunk_size
!= 1)
1498 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1501 fputs ("AUTO", stderr
);
1504 fputs ("'\n", stderr
);
1507 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1508 'device' can be 'host', 'dev', 'all', or a particular device number. */
1511 print_proc_bind (char proc_bind_var
, unsigned long len
, char **list
,
1514 fprintf (stderr
, " [%s] OMP_PROC_BIND = '", device
);
1515 switch (proc_bind_var
)
1517 case omp_proc_bind_false
:
1518 fputs ("FALSE", stderr
);
1520 case omp_proc_bind_true
:
1521 fputs ("TRUE", stderr
);
1523 case omp_proc_bind_master
:
1524 fputs ("MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1526 case omp_proc_bind_close
:
1527 fputs ("CLOSE", stderr
);
1529 case omp_proc_bind_spread
:
1530 fputs ("SPREAD", stderr
);
1533 for (int i
= 1; i
< len
; i
++)
1536 case omp_proc_bind_master
:
1537 fputs (",MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1539 case omp_proc_bind_close
:
1540 fputs (",CLOSE", stderr
);
1542 case omp_proc_bind_spread
:
1543 fputs (",SPREAD", stderr
);
1546 fputs ("'\n", stderr
);
1549 enum gomp_parse_type
1560 /* The following table contains items that help parsing environment variables
1561 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1562 are affected by the environment variable. FLAGS determine what variant of
1563 environment variable is allowed. */
1565 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1566 static const struct envvar
1570 uint8_t flag_vars
[3];
1572 bool (*parse_func
) (const char *, const char *, void *const[]);
1574 { ENTRY ("SCHEDULE"),
1575 { GOMP_ICV_SCHEDULE
, GOMP_ICV_SCHEDULE_CHUNK_SIZE
},
1576 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1578 { ENTRY ("NUM_TEAMS"),
1579 { GOMP_ICV_NTEAMS
},
1580 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1582 { ENTRY ("DYNAMIC"),
1583 { GOMP_ICV_DYNAMIC
},
1584 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1586 { ENTRY ("TEAMS_THREAD_LIMIT"),
1587 { GOMP_ICV_TEAMS_THREAD_LIMIT
},
1588 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1590 { ENTRY ("THREAD_LIMIT"),
1591 { GOMP_ICV_THREAD_LIMIT
},
1592 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1593 &parse_unsigned_long
},
1594 { ENTRY ("NUM_THREADS"),
1595 { GOMP_ICV_NTHREADS
, GOMP_ICV_NTHREADS_LIST
, GOMP_ICV_NTHREADS_LIST_LEN
},
1596 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1597 &parse_unsigned_long_list
},
1598 { ENTRY ("PROC_BIND"),
1599 { GOMP_ICV_BIND
, GOMP_ICV_BIND_LIST
, GOMP_ICV_BIND_LIST_LEN
},
1600 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1602 { ENTRY ("MAX_ACTIVE_LEVELS"),
1603 { GOMP_ICV_MAX_ACTIVE_LEVELS
},
1604 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1605 &parse_unsigned_long
},
1606 { ENTRY ("WAIT_POLICY"),
1607 { GOMP_ICV_WAIT_POLICY
},
1608 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1609 &parse_wait_policy
},
1610 { ENTRY ("STACKSIZE"),
1611 { GOMP_ICV_STACKSIZE
},
1612 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1614 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION
}, 0, &parse_boolean
},
1615 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY
}, 0,
1617 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD
}, 0,
1618 &parse_target_offload
},
1619 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY
}, 0,
1621 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR
}, 0, &parse_allocator
},
1622 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE
},
1623 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1627 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1629 /* The following table is used to apply the hierarchy of ICV variants for host
1630 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1633 static const struct host_envvar
1635 unsigned char flag_var
;
1638 } host_envvars
[] = {
1639 { GOMP_ICV_NTEAMS
, { &gomp_nteams_var
}, PARSE_INT
},
1640 { GOMP_ICV_DYNAMIC
, { &gomp_global_icv
.dyn_var
}, PARSE_BOOL
},
1641 { GOMP_ICV_DEFAULT_DEVICE
, { &gomp_global_icv
.default_device_var
},
1643 { GOMP_ICV_TEAMS_THREAD_LIMIT
, { &gomp_teams_thread_limit_var
}, PARSE_INT
},
1644 { GOMP_ICV_SCHEDULE
,
1645 { &gomp_global_icv
.run_sched_var
, &gomp_global_icv
.run_sched_chunk_size
},
1647 { GOMP_ICV_THREAD_LIMIT
, { &gomp_global_icv
.thread_limit_var
}, PARSE_UINT
},
1648 { GOMP_ICV_NTHREADS
,
1649 { &gomp_global_icv
.nthreads_var
, &gomp_nthreads_var_list
,
1650 &gomp_nthreads_var_list_len
}, PARSE_ULONG
},
1652 { &gomp_global_icv
.bind_var
, &gomp_bind_var_list
, &gomp_bind_var_list_len
},
1654 { GOMP_ICV_MAX_ACTIVE_LEVELS
, { &gomp_global_icv
.max_active_levels_var
},
1657 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1659 #define INT_MAX_STR_LEN 10
1662 gomp_get_icv_flag (uint32_t value
, enum gomp_icvs icv
)
1664 return value
& (1 << (icv
- 1));
1668 gomp_set_icv_flag (uint32_t *value
, enum gomp_icvs icv
)
1670 *value
|= 1 << (icv
- 1);
1674 print_device_specific_icvs (int icv_code
)
1676 struct gomp_icv_list
*list
= gomp_initial_icv_list
;
1678 char dev_num
[INT_MAX_STR_LEN
+ 1];
1680 while (list
!= NULL
)
1682 if (list
->device_num
< 0)
1690 case GOMP_ICV_NTEAMS
:
1691 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTEAMS
))
1692 fprintf (stderr
, " [%d] OMP_NUM_TEAMS = '%d'\n",
1693 list
->device_num
, list
->icvs
.nteams_var
);
1695 case GOMP_ICV_DYNAMIC
:
1696 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_DYNAMIC
))
1697 fprintf (stderr
, " [%d] OMP_DYNAMIC = '%s'\n",
1698 list
->device_num
, list
->icvs
.dyn_var
? "TRUE" : "FALSE");
1700 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
1701 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_TEAMS_THREAD_LIMIT
))
1702 fprintf (stderr
, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1703 list
->device_num
, list
->icvs
.teams_thread_limit_var
);
1705 case GOMP_ICV_SCHEDULE
:
1706 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_SCHEDULE
)))
1708 sprintf (dev_num
, "%d", list
->device_num
);
1709 print_schedule (list
->icvs
.run_sched_var
,
1710 list
->icvs
.run_sched_chunk_size
,
1713 case GOMP_ICV_THREAD_LIMIT
:
1714 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_THREAD_LIMIT
))
1715 fprintf (stderr
, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1716 list
->device_num
, list
->icvs
.thread_limit_var
);
1718 case GOMP_ICV_NTHREADS
:
1719 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTHREADS
)))
1721 fprintf (stderr
, " [%d] OMP_NUM_THREADS = '%lu", list
->device_num
,
1722 list
->icvs
.nthreads_var
);
1723 for (i
= 1; i
< list
->icvs
.nthreads_var_list_len
; i
++)
1724 fprintf (stderr
, ",%lu", list
->icvs
.nthreads_var_list
[i
]);
1725 fputs ("'\n", stderr
);
1727 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
1728 fprintf (stderr
, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1729 list
->device_num
, list
->icvs
.max_active_levels_var
);
1732 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_BIND
)))
1734 sprintf (dev_num
, "%d", list
->device_num
);
1735 print_proc_bind (list
->icvs
.bind_var
, list
->icvs
.bind_var_list_len
,
1736 &list
->icvs
.bind_var_list
, dev_num
);
1738 case GOMP_ICV_WAIT_POLICY
:
1739 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_WAIT_POLICY
))
1740 fprintf (stderr
, " [%d] OMP_WAIT_POLICY = '%s'\n",
1742 list
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1744 case GOMP_ICV_STACKSIZE
:
1745 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_STACKSIZE
))
1746 fprintf (stderr
, " [%d] OMP_STACKSIZE = '%lu'\n",
1747 list
->device_num
, list
->icvs
.stacksize
);
1755 omp_display_env (int verbose
)
1758 struct gomp_icv_list
*dev
1759 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV
);
1760 struct gomp_icv_list
*all
1761 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
1762 struct gomp_icv_list
*none
1763 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
1765 if (none
->icvs
.default_device_var
== INT_MIN
)
1766 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1767 gomp_init_targets_once ();
1769 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr
);
1771 fputs (" _OPENMP = '201511'\n", stderr
);
1773 fprintf (stderr
, " [host] OMP_DYNAMIC = '%s'\n",
1774 none
->icvs
.dyn_var
? "TRUE" : "FALSE");
1775 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_DYNAMIC
))
1776 fprintf (stderr
, " [all] OMP_DYNAMIC = '%s'\n",
1777 all
->icvs
.dyn_var
? "TRUE" : "FALSE");
1778 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_DYNAMIC
))
1779 fprintf (stderr
, " [device] OMP_DYNAMIC = '%s'\n",
1780 dev
->icvs
.dyn_var
? "TRUE" : "FALSE");
1781 print_device_specific_icvs (GOMP_ICV_DYNAMIC
);
1783 /* The OMP_NESTED environment variable has been deprecated. */
1784 fprintf (stderr
, " [host] OMP_NESTED = '%s'\n",
1785 none
->icvs
.max_active_levels_var
> 1 ? "TRUE" : "FALSE");
1787 fprintf (stderr
, " [host] OMP_NUM_THREADS = '%lu",
1788 none
->icvs
.nthreads_var
);
1789 for (i
= 1; i
< none
->icvs
.nthreads_var_list_len
; i
++)
1790 fprintf (stderr
, ",%lu", none
->icvs
.nthreads_var_list
[i
]);
1791 fputs ("'\n", stderr
);
1792 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTHREADS
))
1794 fprintf (stderr
, " [all] OMP_NUM_THREADS = '%lu",
1795 all
->icvs
.nthreads_var
);
1796 for (i
= 1; i
< all
->icvs
.nthreads_var_list_len
; i
++)
1797 fprintf (stderr
, ",%lu", all
->icvs
.nthreads_var_list
[i
]);
1798 fputs ("'\n", stderr
);
1800 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTHREADS
))
1802 fprintf (stderr
, " [device] OMP_NUM_THREADS = '%lu",
1803 dev
->icvs
.nthreads_var
);
1804 for (i
= 1; i
< dev
->icvs
.nthreads_var_list_len
; i
++)
1805 fprintf (stderr
, ",%lu", dev
->icvs
.nthreads_var_list
[i
]);
1806 fputs ("'\n", stderr
);
1808 print_device_specific_icvs (GOMP_ICV_NTHREADS
);
1811 print_schedule (none
->icvs
.run_sched_var
,
1812 none
->icvs
.run_sched_chunk_size
, "host");
1813 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_SCHEDULE
))
1814 print_schedule (all
->icvs
.run_sched_var
,
1815 all
->icvs
.run_sched_chunk_size
, "all");
1816 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_SCHEDULE
))
1817 print_schedule (dev
->icvs
.run_sched_var
,
1818 dev
->icvs
.run_sched_chunk_size
, "device");
1819 print_device_specific_icvs (GOMP_ICV_SCHEDULE
);
1821 print_proc_bind (none
->icvs
.bind_var
,
1822 none
->icvs
.bind_var_list_len
,
1823 &none
->icvs
.bind_var_list
, "host");
1824 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
))
1825 print_proc_bind (all
->icvs
.bind_var
,
1826 all
->icvs
.bind_var_list_len
,
1827 &all
->icvs
.bind_var_list
, "all");
1828 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_BIND
))
1829 print_proc_bind (dev
->icvs
.bind_var
,
1830 dev
->icvs
.bind_var_list_len
,
1831 &dev
->icvs
.bind_var_list
, "device");
1832 print_device_specific_icvs (GOMP_ICV_BIND
);
1834 fputs (" [host] OMP_PLACES = '", stderr
);
1835 for (i
= 0; i
< gomp_places_list_len
; i
++)
1837 fputs ("{", stderr
);
1838 gomp_affinity_print_place (gomp_places_list
[i
]);
1839 fputs (i
+ 1 == gomp_places_list_len
? "}" : "},", stderr
);
1841 fputs ("'\n", stderr
);
1843 fprintf (stderr
, " [host] OMP_STACKSIZE = '%lu'\n",
1844 none
->icvs
.stacksize
);
1845 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
1846 fprintf (stderr
, " [all] OMP_STACKSIZE = '%lu'\n",
1847 all
->icvs
.stacksize
);
1848 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_STACKSIZE
))
1849 fprintf (stderr
, " [device] OMP_STACKSIZE = '%lu'\n",
1850 dev
->icvs
.stacksize
);
1851 print_device_specific_icvs (GOMP_ICV_STACKSIZE
);
1853 /* GOMP's default value is actually neither active nor passive. */
1854 fprintf (stderr
, " [host] OMP_WAIT_POLICY = '%s'\n",
1855 none
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1856 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
1857 fprintf (stderr
, " [all] OMP_WAIT_POLICY = '%s'\n",
1858 all
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1859 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_WAIT_POLICY
))
1860 fprintf (stderr
, " [device] OMP_WAIT_POLICY = '%s'\n",
1861 dev
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1862 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY
);
1864 fprintf (stderr
, " [host] OMP_THREAD_LIMIT = '%u'\n",
1865 none
->icvs
.thread_limit_var
);
1866 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_THREAD_LIMIT
))
1867 fprintf (stderr
, " [all] OMP_THREAD_LIMIT = '%d'\n",
1868 all
->icvs
.thread_limit_var
);
1869 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_THREAD_LIMIT
))
1870 fprintf (stderr
, " [device] OMP_THREAD_LIMIT = '%d'\n",
1871 dev
->icvs
.thread_limit_var
);
1872 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT
);
1874 fprintf (stderr
, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1875 none
->icvs
.max_active_levels_var
);
1876 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1877 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1878 fprintf (stderr
, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1879 all
->icvs
.max_active_levels_var
);
1880 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1881 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1882 fprintf (stderr
, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1883 dev
->icvs
.max_active_levels_var
);
1884 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS
);
1887 fprintf (stderr
, " [host] OMP_NUM_TEAMS = '%d'\n",
1888 none
->icvs
.nteams_var
);
1889 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTEAMS
))
1890 fprintf (stderr
, " [all] OMP_NUM_TEAMS = '%d'\n",
1891 all
->icvs
.nteams_var
);
1892 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTEAMS
))
1893 fprintf (stderr
, " [device] OMP_NUM_TEAMS = '%d'\n",
1894 dev
->icvs
.nteams_var
);
1895 print_device_specific_icvs (GOMP_ICV_NTEAMS
);
1897 fprintf (stderr
, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1898 none
->icvs
.teams_thread_limit_var
);
1899 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1900 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1901 fprintf (stderr
, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1902 all
->icvs
.teams_thread_limit_var
);
1903 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1904 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1905 fprintf (stderr
, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1906 dev
->icvs
.teams_thread_limit_var
);
1907 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT
);
1909 fprintf (stderr
, " [all] OMP_CANCELLATION = '%s'\n",
1910 gomp_cancel_var
? "TRUE" : "FALSE");
1912 fprintf (stderr
, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1913 none
->icvs
.default_device_var
);
1915 fprintf (stderr
, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1916 gomp_max_task_priority_var
);
1917 fprintf (stderr
, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1918 gomp_display_affinity_var
? "TRUE" : "FALSE");
1919 fprintf (stderr
, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1920 gomp_affinity_format_var
);
1921 fprintf (stderr
, " [host] OMP_ALLOCATOR = '");
1922 switch (gomp_def_allocator
)
1924 #define C(v) case v: fputs (#v, stderr); break;
1925 C (omp_default_mem_alloc
)
1926 C (omp_large_cap_mem_alloc
)
1927 C (omp_const_mem_alloc
)
1928 C (omp_high_bw_mem_alloc
)
1929 C (omp_low_lat_mem_alloc
)
1930 C (omp_cgroup_mem_alloc
)
1931 C (omp_pteam_mem_alloc
)
1932 C (omp_thread_mem_alloc
)
1934 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1936 if (gomp_def_allocator_envvar
)
1937 fputs (gomp_def_allocator_envvar
, stderr
);
1940 fputs ("'\n", stderr
);
1942 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr
);
1943 switch (gomp_target_offload_var
)
1945 case GOMP_TARGET_OFFLOAD_DEFAULT
:
1946 fputs ("DEFAULT", stderr
);
1948 case GOMP_TARGET_OFFLOAD_MANDATORY
:
1949 fputs ("MANDATORY", stderr
);
1951 case GOMP_TARGET_OFFLOAD_DISABLED
:
1952 fputs ("DISABLED", stderr
);
1955 fputs ("'\n", stderr
);
1959 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr
);
1960 fprintf (stderr
, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize
);
1961 #ifdef HAVE_INTTYPES_H
1962 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%"PRIu64
"'\n",
1963 (uint64_t) gomp_spin_count_var
);
1965 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%lu'\n",
1966 (unsigned long) gomp_spin_count_var
);
1970 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr
);
1972 ialias (omp_display_env
)
1975 handle_omp_display_env (void)
1978 bool display
= false;
1979 bool verbose
= false;
1981 env
= getenv ("OMP_DISPLAY_ENV");
1985 while (isspace ((unsigned char) *env
))
1987 if (strncasecmp (env
, "true", 4) == 0)
1992 else if (strncasecmp (env
, "false", 5) == 0)
1997 else if (strncasecmp (env
, "verbose", 7) == 0)
2005 while (isspace ((unsigned char) *env
))
2008 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2011 ialias_call (omp_display_env
) (verbose
);
2014 /* Helper function for initialize_env. Extracts the device number from
2015 an environment variable name. ENV is the complete environment variable.
2016 DEV_NUM_PTR points to the start of the device number in the environment
2017 variable string. DEV_NUM_LEN is the returned length of the device num
2021 get_device_num (char *env
, char *dev_num_ptr
, int *dev_num
, int *dev_num_len
)
2024 unsigned long val
= strtoul (dev_num_ptr
, &end
, 10);
2027 || (dev_num_ptr
[0] == '0' && end
!= dev_num_ptr
+ 1)
2028 || (dev_num_ptr
[0] < '0' || dev_num_ptr
[0] > '9'))
2030 gomp_error ("Invalid device number in %s", env
);
2034 *dev_num_len
= end
- dev_num_ptr
;
2039 get_icv_member_addr (struct gomp_initial_icvs
*icvs
, int icv_code
,
2042 if (icv_code
== 0 || icv_addr
== NULL
)
2045 icv_addr
[0] = icv_addr
[1] = icv_addr
[2] = NULL
;
2049 case GOMP_ICV_NTEAMS
:
2050 icv_addr
[0] = &icvs
->nteams_var
;
2051 /* icv_addr[1] = (void *) false; */
2053 case GOMP_ICV_DYNAMIC
:
2054 icv_addr
[0] = &(*icvs
).dyn_var
;
2056 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
2057 icv_addr
[0] = &icvs
->teams_thread_limit_var
;
2058 /* icv_addr[1] = (void *) false; */
2060 case GOMP_ICV_SCHEDULE
:
2061 icv_addr
[0] = &icvs
->run_sched_var
;
2062 icv_addr
[1] = &icvs
->run_sched_chunk_size
;
2064 case GOMP_ICV_THREAD_LIMIT
:
2065 icv_addr
[0] = &icvs
->thread_limit_var
;
2066 /* icv_addr[1] = (void *) false; */
2067 icv_addr
[2] = (void *) UINT_MAX
;
2069 case GOMP_ICV_NTHREADS
:
2070 icv_addr
[0] = &icvs
->nthreads_var
;
2071 icv_addr
[1] = &icvs
->nthreads_var_list
;
2072 icv_addr
[2] = &icvs
->nthreads_var_list_len
;
2074 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
2075 icv_addr
[0] = &icvs
->max_active_levels_var
;
2076 icv_addr
[1] = (void *) true;
2077 icv_addr
[2] = (void *) gomp_supported_active_levels
;
2080 icv_addr
[0] = &icvs
->bind_var
;
2081 icv_addr
[1] = &icvs
->bind_var_list
;
2082 icv_addr
[2] = &icvs
->bind_var_list_len
;
2084 case GOMP_ICV_WAIT_POLICY
:
2085 icv_addr
[0] = &icvs
->wait_policy
;
2087 case GOMP_ICV_STACKSIZE
:
2088 icv_addr
[0] = &icvs
->stacksize
;
2090 case GOMP_ICV_CANCELLATION
:
2091 icv_addr
[0] = &gomp_cancel_var
;
2093 case GOMP_ICV_DISPLAY_AFFINITY
:
2094 icv_addr
[0] = &gomp_display_affinity_var
;
2096 case GOMP_ICV_TARGET_OFFLOAD
:
2097 icv_addr
[0] = &gomp_target_offload_var
;
2099 case GOMP_ICV_MAX_TASK_PRIORITY
:
2100 icv_addr
[0] = &gomp_max_task_priority_var
;
2102 case GOMP_ICV_ALLOCATOR
:
2103 icv_addr
[0] = &gomp_def_allocator
;
2105 case GOMP_ICV_DEFAULT_DEVICE
:
2106 icv_addr
[0] = &icvs
->default_device_var
;
2107 icv_addr
[1] = (void *) true;
2112 struct gomp_icv_list
*
2113 gomp_get_initial_icv_item (int dev_num
)
2115 struct gomp_icv_list
*l
= gomp_initial_icv_list
;
2116 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2123 initialize_icvs (struct gomp_initial_icvs
*icvs
)
2125 icvs
->nthreads_var_list
= NULL
;
2126 icvs
->bind_var_list
= NULL
;
2127 icvs
->nthreads_var
= gomp_default_icv_values
.nthreads_var
;
2128 icvs
->nthreads_var_list_len
= 0;
2129 icvs
->bind_var_list_len
= 0;
2130 icvs
->stacksize
= 0;
2131 icvs
->thread_limit_var
= gomp_default_icv_values
.thread_limit_var
;
2132 icvs
->run_sched_var
= gomp_default_icv_values
.run_sched_var
;
2133 icvs
->run_sched_chunk_size
= gomp_default_icv_values
.run_sched_chunk_size
;
2134 icvs
->default_device_var
= gomp_default_icv_values
.default_device_var
;
2135 icvs
->dyn_var
= gomp_default_icv_values
.dyn_var
;
2136 icvs
->max_active_levels_var
= gomp_default_icv_values
.max_active_levels_var
;
2137 icvs
->bind_var
= gomp_default_icv_values
.bind_var
;
2138 icvs
->nteams_var
= gomp_default_icv_values
.nteams_var
;
2139 icvs
->teams_thread_limit_var
= gomp_default_icv_values
.teams_thread_limit_var
;
2140 icvs
->wait_policy
= -1;
2143 /* Helper function for initialize_env to add a device specific ICV value
2144 to gomp_initial_icv_list. */
2147 add_initial_icv_to_list (int dev_num
, int icv_code
, void *icv_addr
[3])
2149 struct gomp_icv_list
*last
= NULL
, *l
= gomp_initial_icv_list
;
2150 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2158 l
= ((struct gomp_icv_list
*)
2159 gomp_malloc_cleared (sizeof (struct gomp_icv_list
)));
2160 l
->device_num
= dev_num
;
2161 initialize_icvs (&l
->icvs
);
2164 l
->next
= gomp_initial_icv_list
;
2165 gomp_initial_icv_list
= l
;
2171 gomp_initial_icv_list
= l
;
2177 get_icv_member_addr (&l
->icvs
, icv_code
, icv_addr
);
2182 /* Return true if STR string starts with PREFIX. */
2185 startswith (const char *str
, const char *prefix
)
2187 return strncmp (str
, prefix
, strlen (prefix
)) == 0;
2190 static void __attribute__((destructor
))
2193 if (gomp_def_allocator_envvar
!= NULL
)
2195 free (gomp_def_allocator_envvar
);
2196 omp_destroy_allocator (gomp_def_allocator
);
2200 static void __attribute__((constructor
))
2201 initialize_env (void)
2204 int omp_var
, dev_num
= 0, dev_num_len
= 0, i
;
2205 bool ignore
= false;
2208 uint32_t *flag_var_addr
= NULL
;
2210 struct gomp_icv_list
*all
, *none
;
2212 /* Do a compile time check that mkomp_h.pl did good job. */
2213 omp_check_defines ();
2215 #ifndef HAVE_SYNC_BUILTINS
2216 gomp_mutex_init (&gomp_managed_threads_lock
);
2218 gomp_init_num_threads ();
2219 gomp_available_cpus
= gomp_global_icv
.nthreads_var
;
2221 /* Initial values for host environment variables should always exist even if
2222 there is no explicitly set host environment variable. Moreover, they are
2223 set to the initial global values. */
2224 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
, 0, NULL
);
2225 none
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
2226 initialize_icvs (&none
->icvs
);
2229 for (env
= environ
; *env
!= 0; env
++)
2231 if (!startswith (*env
, "OMP_"))
2234 /* Name of the environment variable without suffix "OMP_". */
2235 char *name
= *env
+ sizeof ("OMP_") - 1;
2236 for (omp_var
= 0; omp_var
< OMP_VAR_CNT
; omp_var
++)
2238 if (startswith (name
, envvars
[omp_var
].name
))
2240 pos
= envvars
[omp_var
].name_len
;
2241 if (name
[pos
] == '=')
2245 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
,
2246 envvars
[omp_var
].flag_vars
[0],
2249 else if (startswith (&name
[pos
], "_DEV=")
2250 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV
)
2254 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV
,
2255 envvars
[omp_var
].flag_vars
[0],
2258 else if (startswith (&name
[pos
], "_ALL=")
2259 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_ALL
)
2263 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL
,
2264 envvars
[omp_var
].flag_vars
[0],
2267 else if (startswith (&name
[pos
], "_DEV_")
2268 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV_X
)
2271 if (!get_device_num (*env
, &name
[pos
], &dev_num
,
2275 pos
+= dev_num_len
+ 1;
2277 = add_initial_icv_to_list (dev_num
,
2278 envvars
[omp_var
].flag_vars
[0],
2283 gomp_error ("Invalid environment variable in %s", *env
);
2286 env_val
= &name
[pos
];
2288 if (envvars
[omp_var
].parse_func (*env
, env_val
, params
))
2290 for (i
= 0; i
< 3; ++i
)
2291 if (envvars
[omp_var
].flag_vars
[i
])
2292 gomp_set_icv_flag (flag_var_addr
,
2293 envvars
[omp_var
].flag_vars
[i
]);
2303 all
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
2304 for (omp_var
= 0; omp_var
< OMP_HOST_VAR_CNT
; omp_var
++)
2307 && gomp_get_icv_flag (none
->flags
, host_envvars
[omp_var
].flag_var
))
2308 get_icv_member_addr (&none
->icvs
,
2309 host_envvars
[omp_var
].flag_var
, params
);
2310 else if (all
!= NULL
2311 && gomp_get_icv_flag (all
->flags
,
2312 host_envvars
[omp_var
].flag_var
))
2313 get_icv_member_addr (&all
->icvs
, host_envvars
[omp_var
].flag_var
,
2318 switch (host_envvars
[omp_var
].type_code
)
2321 for (i
= 0; i
< 3; ++i
)
2322 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2323 *(int *) (host_envvars
[omp_var
].dest
[i
]) = *(int *) params
[i
];
2326 for (i
= 0; i
< 3; ++i
)
2327 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2328 *(bool *) (host_envvars
[omp_var
].dest
[i
]) = *(bool *) params
[i
];
2331 for (i
= 0; i
< 3; ++i
)
2332 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2333 *(unsigned int *) (host_envvars
[omp_var
].dest
[i
])
2334 = *(unsigned int *) params
[i
];
2337 for (i
= 0; i
< 3; ++i
)
2338 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2339 *(unsigned long *) (host_envvars
[omp_var
].dest
[i
])
2340 = *(unsigned long *) params
[i
];
2343 for (i
= 0; i
< 3; ++i
)
2344 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2345 *(unsigned char *) (host_envvars
[omp_var
].dest
[i
])
2346 = *(unsigned char *) params
[i
];
2348 case PARSE_SCHEDULE
:
2349 *(enum gomp_schedule_type
*) (host_envvars
[omp_var
].dest
[0])
2350 = *(enum gomp_schedule_type
*) params
[0];
2351 *(int *) (host_envvars
[omp_var
].dest
[1]) = *(int *) params
[1];
2354 *(char *) (host_envvars
[omp_var
].dest
[0]) = *(char *) params
[0];
2355 *(char **) (host_envvars
[omp_var
].dest
[1]) = *(char **) params
[1];
2356 *(unsigned long *) (host_envvars
[omp_var
].dest
[2])
2357 = *(unsigned long *) params
[2];
2362 if (((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_BIND
))
2363 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
)))
2364 && gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2368 && gomp_get_icv_flag (none
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))
2370 && gomp_get_icv_flag (all
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))))
2373 const char *env
= getenv ("OMP_NESTED");
2375 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2376 if (parse_boolean ("OMP_NESTED", env
, (void *[]) {&nested
}))
2377 gomp_global_icv
.max_active_levels_var
2378 = nested
? gomp_supported_active_levels
: 1;
2379 else if (gomp_nthreads_var_list_len
> 1 || gomp_bind_var_list_len
> 1)
2380 gomp_global_icv
.max_active_levels_var
= gomp_supported_active_levels
;
2383 if (gomp_global_icv
.default_device_var
== INT_MIN
2384 && gomp_target_offload_var
!= GOMP_TARGET_OFFLOAD_MANDATORY
)
2385 none
->icvs
.default_device_var
= gomp_global_icv
.default_device_var
= 0;
2387 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2388 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var
, true);
2390 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2391 parsed if present in the environment. If OMP_PROC_BIND was set
2392 explicitly to false, don't populate places list though. If places
2393 list was successfully set from OMP_PLACES, only parse but don't process
2394 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2395 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2396 was successfully parsed into a places list, otherwise to
2397 OMP_PROC_BIND=false. */
2398 if (parse_places_var ("OMP_PLACES", ignore
))
2400 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2401 gomp_global_icv
.bind_var
= true;
2404 if (parse_affinity (ignore
))
2406 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2407 gomp_global_icv
.bind_var
= true;
2410 if (gomp_global_icv
.bind_var
!= omp_proc_bind_false
)
2411 gomp_init_affinity ();
2414 const char *env
= getenv ("OMP_AFFINITY_FORMAT");
2416 gomp_set_affinity_format (env
, strlen (env
));
2419 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_WAIT_POLICY
))
2420 wait_policy
= none
->icvs
.wait_policy
;
2421 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
2422 wait_policy
= all
->icvs
.wait_policy
;
2424 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var
))
2426 /* Using a rough estimation of 100000 spins per msec,
2427 use 5 min blocking for OMP_WAIT_POLICY=active,
2428 3 msec blocking when OMP_WAIT_POLICY is not specificed
2429 and 0 when OMP_WAIT_POLICY=passive.
2430 Depending on the CPU speed, this can be e.g. 5 times longer
2431 or 5 times shorter. */
2432 if (wait_policy
> 0)
2433 gomp_spin_count_var
= 30000000000LL;
2434 else if (wait_policy
< 0)
2436 gomp_spin_count_var
= 300000LL;
2437 do_adjust_default_spincount ();
2440 /* gomp_throttled_spin_count_var is used when there are more libgomp
2441 managed threads than available CPUs. Use very short spinning. */
2442 if (wait_policy
> 0)
2443 gomp_throttled_spin_count_var
= 1000LL;
2444 else if (wait_policy
< 0)
2445 gomp_throttled_spin_count_var
= 100LL;
2446 if (gomp_throttled_spin_count_var
> gomp_spin_count_var
)
2447 gomp_throttled_spin_count_var
= gomp_spin_count_var
;
2449 /* Not strictly environment related, but ordering constructors is tricky. */
2450 pthread_attr_init (&gomp_thread_attr
);
2452 if (!(none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
)))
2454 const char *env
= getenv ("GOMP_STACKSIZE");
2456 && parse_stacksize ("GOMP_STACKSIZE", env
,
2457 (void *[3]) {&none
->icvs
.stacksize
}))
2458 gomp_set_icv_flag (&none
->flags
, GOMP_ICV_STACKSIZE
);
2460 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2461 stacksize
= none
->icvs
.stacksize
;
2462 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2463 stacksize
= all
->icvs
.stacksize
;
2465 if ((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2466 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2467 || GOMP_DEFAULT_STACKSIZE
)
2471 err
= pthread_attr_setstacksize (&gomp_thread_attr
, stacksize
);
2473 #ifdef PTHREAD_STACK_MIN
2476 if (stacksize
< PTHREAD_STACK_MIN
)
2477 gomp_error ("Stack size less than minimum of %luk",
2478 PTHREAD_STACK_MIN
/ 1024ul
2479 + (PTHREAD_STACK_MIN
% 1024 != 0));
2481 gomp_error ("Stack size larger than system limit");
2486 gomp_error ("Stack size change failed: %s", strerror (err
));
2489 handle_omp_display_env ();
2493 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2494 (void *[]) {&goacc_device_num
, (void *) true}))
2495 goacc_device_num
= 0;
2497 parse_acc_device_type ();
2498 parse_gomp_openacc_dim ();
2500 goacc_runtime_initialize ();
2502 goacc_profiling_initialize ();
2504 #endif /* LIBGOMP_OFFLOADED_ONLY */