1 /* Copyright (C) 2005-2025 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 (ompx_gnu_pinned_mem_alloc
, false)
1268 C (omp_default_mem_space
, true)
1269 C (omp_large_cap_mem_space
, true)
1270 C (omp_const_mem_space
, true)
1271 C (omp_high_bw_mem_space
, true)
1272 C (omp_low_lat_mem_space
, true)
1276 if (memspace
&& *val
== ':')
1279 const char *cp
= val
;
1286 traits
= gomp_alloca (ntraits
* sizeof (omp_alloctrait_t
));
1288 while (*val
!= '\0')
1291 else if (strncasecmp (val, #v "=", sizeof (#v)) == 0) \
1293 val += sizeof (#v); \
1294 traits[n].key = omp_atk_ ## v;
1296 else if (strncasecmp (val, #v, sizeof (#v) - 1) == 0) \
1298 val += sizeof (#v) - 1; \
1299 traits[n].value = omp_atv_ ## v; \
1316 traits
[n
].value
= strtol (val
, &end
, 10);
1317 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1334 traits
[n
].value
= strtol (val
, &end
, 10);
1335 if (errno
|| end
== val
|| traits
[n
].value
<= 0)
1349 /* Ignore fb_data, which expects an allocator handle. */
1383 case omp_default_mem_space
: *ret
= omp_default_mem_alloc
; break;
1384 case omp_large_cap_mem_space
: *ret
= omp_large_cap_mem_alloc
; break;
1385 case omp_const_mem_space
: *ret
= omp_const_mem_alloc
; break;
1386 case omp_high_bw_mem_space
: *ret
= omp_high_bw_mem_alloc
; break;
1387 case omp_low_lat_mem_space
: *ret
= omp_low_lat_mem_alloc
; break;
1388 default: __builtin_unreachable ();
1390 while (isspace ((unsigned char) *val
))
1396 *ret
= omp_init_allocator (*ret
, ntraits
, traits
);
1397 if (*ret
== omp_null_allocator
)
1399 gomp_error ("Allocator of environment variable %.*s cannot be "
1400 "created, using omp_default_mem_alloc instead",
1401 (int) (orig_val
- env
- 1), env
);
1402 *ret
= omp_default_mem_alloc
;
1405 gomp_def_allocator_envvar
= strdup (orig_val
);
1410 int len
= (orig_val
- env
- 1);
1412 gomp_error ("Missing value at the end of environment variable %s", env
);
1414 gomp_error ("Invalid value for environment variable %.*s when parsing: %s",
1416 *ret
= omp_default_mem_alloc
;
1421 parse_acc_device_type (void)
1423 const char *env
= getenv ("ACC_DEVICE_TYPE");
1425 if (env
&& *env
!= '\0')
1426 goacc_device_type
= strdup (env
);
1428 goacc_device_type
= NULL
;
1432 parse_gomp_openacc_dim (void)
1434 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1435 const char *var_name
= "GOMP_OPENACC_DIM";
1436 const char *env_var
= getenv (var_name
);
1437 const char *pos
= env_var
;
1443 for (i
= 0; *pos
&& i
!= GOMP_DIM_MAX
; i
++)
1448 if (i
&& *pos
++ != ':')
1455 val
= strtol (pos
, &eptr
, 10);
1456 if (errno
|| eptr
== pos
|| val
< 0 || (unsigned)val
!= val
)
1459 goacc_default_dims
[i
] = (int)val
;
1460 pos
= (const char *) eptr
;
1464 /* Helper function for omp_display_env which prints the values of run_sched_var.
1465 'device' can be 'host', 'dev', 'all' or a particular device number. */
1468 print_schedule (enum gomp_schedule_type run_sched_var
, int run_sched_chunk_size
,
1471 fprintf (stderr
, " [%s] OMP_SCHEDULE = '", device
);
1472 if ((run_sched_var
& GFS_MONOTONIC
))
1474 if (run_sched_var
!= (GFS_MONOTONIC
| GFS_STATIC
))
1475 fputs ("MONOTONIC:", stderr
);
1477 else if (run_sched_var
== GFS_STATIC
)
1478 fputs ("NONMONOTONIC:", stderr
);
1479 switch (run_sched_var
& ~GFS_MONOTONIC
)
1482 fputs ("RUNTIME", stderr
);
1483 if (run_sched_chunk_size
!= 1)
1484 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1487 fputs ("STATIC", stderr
);
1488 if (run_sched_chunk_size
!= 0)
1489 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1492 fputs ("DYNAMIC", stderr
);
1493 if (run_sched_chunk_size
!= 1)
1494 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1497 fputs ("GUIDED", stderr
);
1498 if (run_sched_chunk_size
!= 1)
1499 fprintf (stderr
, ",%d", run_sched_chunk_size
);
1502 fputs ("AUTO", stderr
);
1505 fputs ("'\n", stderr
);
1508 /* Helper function for omp_display_env which prints the values of proc_bind_var.
1509 'device' can be 'host', 'dev', 'all', or a particular device number. */
1512 print_proc_bind (char proc_bind_var
, unsigned long len
, char **list
,
1515 fprintf (stderr
, " [%s] OMP_PROC_BIND = '", device
);
1516 switch (proc_bind_var
)
1518 case omp_proc_bind_false
:
1519 fputs ("FALSE", stderr
);
1521 case omp_proc_bind_true
:
1522 fputs ("TRUE", stderr
);
1524 case omp_proc_bind_master
:
1525 fputs ("MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1527 case omp_proc_bind_close
:
1528 fputs ("CLOSE", stderr
);
1530 case omp_proc_bind_spread
:
1531 fputs ("SPREAD", stderr
);
1534 for (int i
= 1; i
< len
; i
++)
1537 case omp_proc_bind_master
:
1538 fputs (",MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1540 case omp_proc_bind_close
:
1541 fputs (",CLOSE", stderr
);
1543 case omp_proc_bind_spread
:
1544 fputs (",SPREAD", stderr
);
1547 fputs ("'\n", stderr
);
1550 enum gomp_parse_type
1561 /* The following table contains items that help parsing environment variables
1562 and fill corresponding ICVs with values. FLAG_VARS contain all ICVS which
1563 are affected by the environment variable. FLAGS determine what variant of
1564 environment variable is allowed. */
1566 #define ENTRY(NAME) NAME, sizeof (NAME) - 1
1567 static const struct envvar
1571 uint8_t flag_vars
[3];
1573 bool (*parse_func
) (const char *, const char *, void *const[]);
1575 { ENTRY ("SCHEDULE"),
1576 { GOMP_ICV_SCHEDULE
, GOMP_ICV_SCHEDULE_CHUNK_SIZE
},
1577 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1579 { ENTRY ("NUM_TEAMS"),
1580 { GOMP_ICV_NTEAMS
},
1581 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1583 { ENTRY ("DYNAMIC"),
1584 { GOMP_ICV_DYNAMIC
},
1585 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1587 { ENTRY ("TEAMS_THREAD_LIMIT"),
1588 { GOMP_ICV_TEAMS_THREAD_LIMIT
},
1589 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1591 { ENTRY ("THREAD_LIMIT"),
1592 { GOMP_ICV_THREAD_LIMIT
},
1593 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1594 &parse_unsigned_long
},
1595 { ENTRY ("NUM_THREADS"),
1596 { GOMP_ICV_NTHREADS
, GOMP_ICV_NTHREADS_LIST
, GOMP_ICV_NTHREADS_LIST_LEN
},
1597 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1598 &parse_unsigned_long_list
},
1599 { ENTRY ("PROC_BIND"),
1600 { GOMP_ICV_BIND
, GOMP_ICV_BIND_LIST
, GOMP_ICV_BIND_LIST_LEN
},
1601 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1603 { ENTRY ("MAX_ACTIVE_LEVELS"),
1604 { GOMP_ICV_MAX_ACTIVE_LEVELS
},
1605 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1606 &parse_unsigned_long
},
1607 { ENTRY ("WAIT_POLICY"),
1608 { GOMP_ICV_WAIT_POLICY
},
1609 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1610 &parse_wait_policy
},
1611 { ENTRY ("STACKSIZE"),
1612 { GOMP_ICV_STACKSIZE
},
1613 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1615 { ENTRY ("CANCELLATION"), { GOMP_ICV_CANCELLATION
}, 0, &parse_boolean
},
1616 { ENTRY ("DISPLAY_AFFINITY"), { GOMP_ICV_DISPLAY_AFFINITY
}, 0,
1618 { ENTRY ("TARGET_OFFLOAD"), { GOMP_ICV_TARGET_OFFLOAD
}, 0,
1619 &parse_target_offload
},
1620 { ENTRY ("MAX_TASK_PRIORITY"), { GOMP_ICV_MAX_TASK_PRIORITY
}, 0,
1622 { ENTRY ("ALLOCATOR"), { GOMP_ICV_ALLOCATOR
}, 0, &parse_allocator
},
1623 { ENTRY ("DEFAULT_DEVICE"), { GOMP_ICV_DEFAULT_DEVICE
},
1624 GOMP_ENV_SUFFIX_DEV
| GOMP_ENV_SUFFIX_ALL
| GOMP_ENV_SUFFIX_DEV_X
,
1628 #define OMP_VAR_CNT (sizeof (envvars) / sizeof (envvars[0]))
1630 /* The following table is used to apply the hierarchy of ICV variants for host
1631 variables, e.g. nteams_var is set to OMP_NUM_TEAMS_ALL if OMP_NUM_TEAMS is
1634 static const struct host_envvar
1636 unsigned char flag_var
;
1639 } host_envvars
[] = {
1640 { GOMP_ICV_NTEAMS
, { &gomp_nteams_var
}, PARSE_INT
},
1641 { GOMP_ICV_DYNAMIC
, { &gomp_global_icv
.dyn_var
}, PARSE_BOOL
},
1642 { GOMP_ICV_DEFAULT_DEVICE
, { &gomp_global_icv
.default_device_var
},
1644 { GOMP_ICV_TEAMS_THREAD_LIMIT
, { &gomp_teams_thread_limit_var
}, PARSE_INT
},
1645 { GOMP_ICV_SCHEDULE
,
1646 { &gomp_global_icv
.run_sched_var
, &gomp_global_icv
.run_sched_chunk_size
},
1648 { GOMP_ICV_THREAD_LIMIT
, { &gomp_global_icv
.thread_limit_var
}, PARSE_UINT
},
1649 { GOMP_ICV_NTHREADS
,
1650 { &gomp_global_icv
.nthreads_var
, &gomp_nthreads_var_list
,
1651 &gomp_nthreads_var_list_len
}, PARSE_ULONG
},
1653 { &gomp_global_icv
.bind_var
, &gomp_bind_var_list
, &gomp_bind_var_list_len
},
1655 { GOMP_ICV_MAX_ACTIVE_LEVELS
, { &gomp_global_icv
.max_active_levels_var
},
1658 #define OMP_HOST_VAR_CNT (sizeof (host_envvars) / sizeof (host_envvars[0]))
1660 #define INT_MAX_STR_LEN 10
1663 gomp_get_icv_flag (uint32_t value
, enum gomp_icvs icv
)
1665 return value
& (1 << (icv
- 1));
1669 gomp_set_icv_flag (uint32_t *value
, enum gomp_icvs icv
)
1671 *value
|= 1 << (icv
- 1);
1675 print_device_specific_icvs (int icv_code
)
1677 struct gomp_icv_list
*list
= gomp_initial_icv_list
;
1679 char dev_num
[INT_MAX_STR_LEN
+ 1];
1681 while (list
!= NULL
)
1683 if (list
->device_num
< 0)
1691 case GOMP_ICV_NTEAMS
:
1692 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTEAMS
))
1693 fprintf (stderr
, " [%d] OMP_NUM_TEAMS = '%d'\n",
1694 list
->device_num
, list
->icvs
.nteams_var
);
1696 case GOMP_ICV_DYNAMIC
:
1697 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_DYNAMIC
))
1698 fprintf (stderr
, " [%d] OMP_DYNAMIC = '%s'\n",
1699 list
->device_num
, list
->icvs
.dyn_var
? "TRUE" : "FALSE");
1701 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
1702 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_TEAMS_THREAD_LIMIT
))
1703 fprintf (stderr
, " [%d] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1704 list
->device_num
, list
->icvs
.teams_thread_limit_var
);
1706 case GOMP_ICV_SCHEDULE
:
1707 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_SCHEDULE
)))
1709 sprintf (dev_num
, "%d", list
->device_num
);
1710 print_schedule (list
->icvs
.run_sched_var
,
1711 list
->icvs
.run_sched_chunk_size
,
1714 case GOMP_ICV_THREAD_LIMIT
:
1715 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_THREAD_LIMIT
))
1716 fprintf (stderr
, " [%d] OMP_THREAD_LIMIT = '%d'\n",
1717 list
->device_num
, list
->icvs
.thread_limit_var
);
1719 case GOMP_ICV_NTHREADS
:
1720 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_NTHREADS
)))
1722 fprintf (stderr
, " [%d] OMP_NUM_THREADS = '%lu", list
->device_num
,
1723 list
->icvs
.nthreads_var
);
1724 for (i
= 1; i
< list
->icvs
.nthreads_var_list_len
; i
++)
1725 fprintf (stderr
, ",%lu", list
->icvs
.nthreads_var_list
[i
]);
1726 fputs ("'\n", stderr
);
1728 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
1729 fprintf (stderr
, " [%d] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1730 list
->device_num
, list
->icvs
.max_active_levels_var
);
1733 if (!(gomp_get_icv_flag (list
->flags
, GOMP_ICV_BIND
)))
1735 sprintf (dev_num
, "%d", list
->device_num
);
1736 print_proc_bind (list
->icvs
.bind_var
, list
->icvs
.bind_var_list_len
,
1737 &list
->icvs
.bind_var_list
, dev_num
);
1739 case GOMP_ICV_WAIT_POLICY
:
1740 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_WAIT_POLICY
))
1741 fprintf (stderr
, " [%d] OMP_WAIT_POLICY = '%s'\n",
1743 list
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1745 case GOMP_ICV_STACKSIZE
:
1746 if (gomp_get_icv_flag (list
->flags
, GOMP_ICV_STACKSIZE
))
1747 fprintf (stderr
, " [%d] OMP_STACKSIZE = '%lu'\n",
1748 list
->device_num
, list
->icvs
.stacksize
);
1756 omp_display_env (int verbose
)
1759 struct gomp_icv_list
*dev
1760 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_DEV
);
1761 struct gomp_icv_list
*all
1762 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
1763 struct gomp_icv_list
*none
1764 = gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
1766 if (none
->icvs
.default_device_var
== INT_MIN
)
1767 /* This implies OMP_TARGET_OFFLOAD=mandatory. */
1768 gomp_init_targets_once ();
1770 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr
);
1772 fputs (" _OPENMP = '201511'\n", stderr
);
1774 fprintf (stderr
, " [host] OMP_DYNAMIC = '%s'\n",
1775 none
->icvs
.dyn_var
? "TRUE" : "FALSE");
1776 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_DYNAMIC
))
1777 fprintf (stderr
, " [all] OMP_DYNAMIC = '%s'\n",
1778 all
->icvs
.dyn_var
? "TRUE" : "FALSE");
1779 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_DYNAMIC
))
1780 fprintf (stderr
, " [device] OMP_DYNAMIC = '%s'\n",
1781 dev
->icvs
.dyn_var
? "TRUE" : "FALSE");
1782 print_device_specific_icvs (GOMP_ICV_DYNAMIC
);
1784 /* The OMP_NESTED environment variable has been deprecated. */
1785 fprintf (stderr
, " [host] OMP_NESTED = '%s'\n",
1786 none
->icvs
.max_active_levels_var
> 1 ? "TRUE" : "FALSE");
1788 fprintf (stderr
, " [host] OMP_NUM_THREADS = '%lu",
1789 none
->icvs
.nthreads_var
);
1790 for (i
= 1; i
< none
->icvs
.nthreads_var_list_len
; i
++)
1791 fprintf (stderr
, ",%lu", none
->icvs
.nthreads_var_list
[i
]);
1792 fputs ("'\n", stderr
);
1793 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTHREADS
))
1795 fprintf (stderr
, " [all] OMP_NUM_THREADS = '%lu",
1796 all
->icvs
.nthreads_var
);
1797 for (i
= 1; i
< all
->icvs
.nthreads_var_list_len
; i
++)
1798 fprintf (stderr
, ",%lu", all
->icvs
.nthreads_var_list
[i
]);
1799 fputs ("'\n", stderr
);
1801 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTHREADS
))
1803 fprintf (stderr
, " [device] OMP_NUM_THREADS = '%lu",
1804 dev
->icvs
.nthreads_var
);
1805 for (i
= 1; i
< dev
->icvs
.nthreads_var_list_len
; i
++)
1806 fprintf (stderr
, ",%lu", dev
->icvs
.nthreads_var_list
[i
]);
1807 fputs ("'\n", stderr
);
1809 print_device_specific_icvs (GOMP_ICV_NTHREADS
);
1812 print_schedule (none
->icvs
.run_sched_var
,
1813 none
->icvs
.run_sched_chunk_size
, "host");
1814 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_SCHEDULE
))
1815 print_schedule (all
->icvs
.run_sched_var
,
1816 all
->icvs
.run_sched_chunk_size
, "all");
1817 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_SCHEDULE
))
1818 print_schedule (dev
->icvs
.run_sched_var
,
1819 dev
->icvs
.run_sched_chunk_size
, "device");
1820 print_device_specific_icvs (GOMP_ICV_SCHEDULE
);
1822 print_proc_bind (none
->icvs
.bind_var
,
1823 none
->icvs
.bind_var_list_len
,
1824 &none
->icvs
.bind_var_list
, "host");
1825 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
))
1826 print_proc_bind (all
->icvs
.bind_var
,
1827 all
->icvs
.bind_var_list_len
,
1828 &all
->icvs
.bind_var_list
, "all");
1829 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_BIND
))
1830 print_proc_bind (dev
->icvs
.bind_var
,
1831 dev
->icvs
.bind_var_list_len
,
1832 &dev
->icvs
.bind_var_list
, "device");
1833 print_device_specific_icvs (GOMP_ICV_BIND
);
1835 fputs (" [host] OMP_PLACES = '", stderr
);
1836 for (i
= 0; i
< gomp_places_list_len
; i
++)
1838 fputs ("{", stderr
);
1839 gomp_affinity_print_place (gomp_places_list
[i
]);
1840 fputs (i
+ 1 == gomp_places_list_len
? "}" : "},", stderr
);
1842 fputs ("'\n", stderr
);
1844 fprintf (stderr
, " [host] OMP_STACKSIZE = '%lu'\n",
1845 none
->icvs
.stacksize
);
1846 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
1847 fprintf (stderr
, " [all] OMP_STACKSIZE = '%lu'\n",
1848 all
->icvs
.stacksize
);
1849 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_STACKSIZE
))
1850 fprintf (stderr
, " [device] OMP_STACKSIZE = '%lu'\n",
1851 dev
->icvs
.stacksize
);
1852 print_device_specific_icvs (GOMP_ICV_STACKSIZE
);
1854 /* GOMP's default value is actually neither active nor passive. */
1855 fprintf (stderr
, " [host] OMP_WAIT_POLICY = '%s'\n",
1856 none
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1857 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
1858 fprintf (stderr
, " [all] OMP_WAIT_POLICY = '%s'\n",
1859 all
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1860 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_WAIT_POLICY
))
1861 fprintf (stderr
, " [device] OMP_WAIT_POLICY = '%s'\n",
1862 dev
->icvs
.wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1863 print_device_specific_icvs (GOMP_ICV_WAIT_POLICY
);
1865 fprintf (stderr
, " [host] OMP_THREAD_LIMIT = '%u'\n",
1866 none
->icvs
.thread_limit_var
);
1867 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_THREAD_LIMIT
))
1868 fprintf (stderr
, " [all] OMP_THREAD_LIMIT = '%d'\n",
1869 all
->icvs
.thread_limit_var
);
1870 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_THREAD_LIMIT
))
1871 fprintf (stderr
, " [device] OMP_THREAD_LIMIT = '%d'\n",
1872 dev
->icvs
.thread_limit_var
);
1873 print_device_specific_icvs (GOMP_ICV_THREAD_LIMIT
);
1875 fprintf (stderr
, " [host] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1876 none
->icvs
.max_active_levels_var
);
1877 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1878 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1879 fprintf (stderr
, " [all] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1880 all
->icvs
.max_active_levels_var
);
1881 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1882 GOMP_ICV_MAX_ACTIVE_LEVELS
))
1883 fprintf (stderr
, " [device] OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1884 dev
->icvs
.max_active_levels_var
);
1885 print_device_specific_icvs (GOMP_ICV_MAX_ACTIVE_LEVELS
);
1888 fprintf (stderr
, " [host] OMP_NUM_TEAMS = '%d'\n",
1889 none
->icvs
.nteams_var
);
1890 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_NTEAMS
))
1891 fprintf (stderr
, " [all] OMP_NUM_TEAMS = '%d'\n",
1892 all
->icvs
.nteams_var
);
1893 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
, GOMP_ICV_NTEAMS
))
1894 fprintf (stderr
, " [device] OMP_NUM_TEAMS = '%d'\n",
1895 dev
->icvs
.nteams_var
);
1896 print_device_specific_icvs (GOMP_ICV_NTEAMS
);
1898 fprintf (stderr
, " [host] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1899 none
->icvs
.teams_thread_limit_var
);
1900 if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
,
1901 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1902 fprintf (stderr
, " [all] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1903 all
->icvs
.teams_thread_limit_var
);
1904 if (dev
!= NULL
&& gomp_get_icv_flag (dev
->flags
,
1905 GOMP_ICV_TEAMS_THREAD_LIMIT
))
1906 fprintf (stderr
, " [device] OMP_TEAMS_THREAD_LIMIT = '%u'\n",
1907 dev
->icvs
.teams_thread_limit_var
);
1908 print_device_specific_icvs (GOMP_ICV_TEAMS_THREAD_LIMIT
);
1910 fprintf (stderr
, " [all] OMP_CANCELLATION = '%s'\n",
1911 gomp_cancel_var
? "TRUE" : "FALSE");
1913 fprintf (stderr
, " [all] OMP_DEFAULT_DEVICE = '%d'\n",
1914 none
->icvs
.default_device_var
);
1916 fprintf (stderr
, " [all] OMP_MAX_TASK_PRIORITY = '%d'\n",
1917 gomp_max_task_priority_var
);
1918 fprintf (stderr
, " [all] OMP_DISPLAY_AFFINITY = '%s'\n",
1919 gomp_display_affinity_var
? "TRUE" : "FALSE");
1920 fprintf (stderr
, " [host] OMP_AFFINITY_FORMAT = '%s'\n",
1921 gomp_affinity_format_var
);
1922 fprintf (stderr
, " [host] OMP_ALLOCATOR = '");
1923 switch (gomp_def_allocator
)
1925 #define C(v) case v: fputs (#v, stderr); break;
1926 C (omp_default_mem_alloc
)
1927 C (omp_large_cap_mem_alloc
)
1928 C (omp_const_mem_alloc
)
1929 C (omp_high_bw_mem_alloc
)
1930 C (omp_low_lat_mem_alloc
)
1931 C (omp_cgroup_mem_alloc
)
1932 C (omp_pteam_mem_alloc
)
1933 C (omp_thread_mem_alloc
)
1935 /* For an OMP_ALLOCATOR with traits, '' will be output. */
1937 if (gomp_def_allocator_envvar
)
1938 fputs (gomp_def_allocator_envvar
, stderr
);
1941 fputs ("'\n", stderr
);
1943 fputs (" [all] OMP_TARGET_OFFLOAD = '", stderr
);
1944 switch (gomp_target_offload_var
)
1946 case GOMP_TARGET_OFFLOAD_DEFAULT
:
1947 fputs ("DEFAULT", stderr
);
1949 case GOMP_TARGET_OFFLOAD_MANDATORY
:
1950 fputs ("MANDATORY", stderr
);
1952 case GOMP_TARGET_OFFLOAD_DISABLED
:
1953 fputs ("DISABLED", stderr
);
1956 fputs ("'\n", stderr
);
1960 fputs (" [host] GOMP_CPU_AFFINITY = ''\n", stderr
);
1961 fprintf (stderr
, " [host] GOMP_STACKSIZE = '%lu'\n", stacksize
);
1962 #ifdef HAVE_INTTYPES_H
1963 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%"PRIu64
"'\n",
1964 (uint64_t) gomp_spin_count_var
);
1966 fprintf (stderr
, " [host] GOMP_SPINCOUNT = '%lu'\n",
1967 (unsigned long) gomp_spin_count_var
);
1971 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr
);
1973 ialias (omp_display_env
)
1976 handle_omp_display_env (void)
1979 bool display
= false;
1980 bool verbose
= false;
1982 env
= getenv ("OMP_DISPLAY_ENV");
1986 while (isspace ((unsigned char) *env
))
1988 if (strncasecmp (env
, "true", 4) == 0)
1993 else if (strncasecmp (env
, "false", 5) == 0)
1998 else if (strncasecmp (env
, "verbose", 7) == 0)
2006 while (isspace ((unsigned char) *env
))
2009 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
2012 ialias_call (omp_display_env
) (verbose
);
2015 /* Helper function for initialize_env. Extracts the device number from
2016 an environment variable name. ENV is the complete environment variable.
2017 DEV_NUM_PTR points to the start of the device number in the environment
2018 variable string. DEV_NUM_LEN is the returned length of the device num
2022 get_device_num (char *env
, char *dev_num_ptr
, int *dev_num
, int *dev_num_len
)
2025 unsigned long val
= strtoul (dev_num_ptr
, &end
, 10);
2028 || (dev_num_ptr
[0] == '0' && end
!= dev_num_ptr
+ 1)
2029 || (dev_num_ptr
[0] < '0' || dev_num_ptr
[0] > '9'))
2031 gomp_error ("Invalid device number in %s", env
);
2035 *dev_num_len
= end
- dev_num_ptr
;
2040 get_icv_member_addr (struct gomp_initial_icvs
*icvs
, int icv_code
,
2043 if (icv_code
== 0 || icv_addr
== NULL
)
2046 icv_addr
[0] = icv_addr
[1] = icv_addr
[2] = NULL
;
2050 case GOMP_ICV_NTEAMS
:
2051 icv_addr
[0] = &icvs
->nteams_var
;
2052 /* icv_addr[1] = (void *) false; */
2054 case GOMP_ICV_DYNAMIC
:
2055 icv_addr
[0] = &(*icvs
).dyn_var
;
2057 case GOMP_ICV_TEAMS_THREAD_LIMIT
:
2058 icv_addr
[0] = &icvs
->teams_thread_limit_var
;
2059 /* icv_addr[1] = (void *) false; */
2061 case GOMP_ICV_SCHEDULE
:
2062 icv_addr
[0] = &icvs
->run_sched_var
;
2063 icv_addr
[1] = &icvs
->run_sched_chunk_size
;
2065 case GOMP_ICV_THREAD_LIMIT
:
2066 icv_addr
[0] = &icvs
->thread_limit_var
;
2067 /* icv_addr[1] = (void *) false; */
2068 icv_addr
[2] = (void *) UINT_MAX
;
2070 case GOMP_ICV_NTHREADS
:
2071 icv_addr
[0] = &icvs
->nthreads_var
;
2072 icv_addr
[1] = &icvs
->nthreads_var_list
;
2073 icv_addr
[2] = &icvs
->nthreads_var_list_len
;
2075 case GOMP_ICV_MAX_ACTIVE_LEVELS
:
2076 icv_addr
[0] = &icvs
->max_active_levels_var
;
2077 icv_addr
[1] = (void *) true;
2078 icv_addr
[2] = (void *) gomp_supported_active_levels
;
2081 icv_addr
[0] = &icvs
->bind_var
;
2082 icv_addr
[1] = &icvs
->bind_var_list
;
2083 icv_addr
[2] = &icvs
->bind_var_list_len
;
2085 case GOMP_ICV_WAIT_POLICY
:
2086 icv_addr
[0] = &icvs
->wait_policy
;
2088 case GOMP_ICV_STACKSIZE
:
2089 icv_addr
[0] = &icvs
->stacksize
;
2091 case GOMP_ICV_CANCELLATION
:
2092 icv_addr
[0] = &gomp_cancel_var
;
2094 case GOMP_ICV_DISPLAY_AFFINITY
:
2095 icv_addr
[0] = &gomp_display_affinity_var
;
2097 case GOMP_ICV_TARGET_OFFLOAD
:
2098 icv_addr
[0] = &gomp_target_offload_var
;
2100 case GOMP_ICV_MAX_TASK_PRIORITY
:
2101 icv_addr
[0] = &gomp_max_task_priority_var
;
2103 case GOMP_ICV_ALLOCATOR
:
2104 icv_addr
[0] = &gomp_def_allocator
;
2106 case GOMP_ICV_DEFAULT_DEVICE
:
2107 icv_addr
[0] = &icvs
->default_device_var
;
2108 icv_addr
[1] = (void *) true;
2113 struct gomp_icv_list
*
2114 gomp_get_initial_icv_item (int dev_num
)
2116 struct gomp_icv_list
*l
= gomp_initial_icv_list
;
2117 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2124 initialize_icvs (struct gomp_initial_icvs
*icvs
)
2126 icvs
->nthreads_var_list
= NULL
;
2127 icvs
->bind_var_list
= NULL
;
2128 icvs
->nthreads_var
= gomp_default_icv_values
.nthreads_var
;
2129 icvs
->nthreads_var_list_len
= 0;
2130 icvs
->bind_var_list_len
= 0;
2131 icvs
->stacksize
= 0;
2132 icvs
->thread_limit_var
= gomp_default_icv_values
.thread_limit_var
;
2133 icvs
->run_sched_var
= gomp_default_icv_values
.run_sched_var
;
2134 icvs
->run_sched_chunk_size
= gomp_default_icv_values
.run_sched_chunk_size
;
2135 icvs
->default_device_var
= gomp_default_icv_values
.default_device_var
;
2136 icvs
->dyn_var
= gomp_default_icv_values
.dyn_var
;
2137 icvs
->max_active_levels_var
= gomp_default_icv_values
.max_active_levels_var
;
2138 icvs
->bind_var
= gomp_default_icv_values
.bind_var
;
2139 icvs
->nteams_var
= gomp_default_icv_values
.nteams_var
;
2140 icvs
->teams_thread_limit_var
= gomp_default_icv_values
.teams_thread_limit_var
;
2141 icvs
->wait_policy
= -1;
2144 /* Helper function for initialize_env to add a device specific ICV value
2145 to gomp_initial_icv_list. */
2148 add_initial_icv_to_list (int dev_num
, int icv_code
, void *icv_addr
[3])
2150 struct gomp_icv_list
*last
= NULL
, *l
= gomp_initial_icv_list
;
2151 while (l
!= NULL
&& l
->device_num
!= dev_num
)
2159 l
= ((struct gomp_icv_list
*)
2160 gomp_malloc_cleared (sizeof (struct gomp_icv_list
)));
2161 l
->device_num
= dev_num
;
2162 initialize_icvs (&l
->icvs
);
2165 l
->next
= gomp_initial_icv_list
;
2166 gomp_initial_icv_list
= l
;
2172 gomp_initial_icv_list
= l
;
2178 get_icv_member_addr (&l
->icvs
, icv_code
, icv_addr
);
2183 /* Return true if STR string starts with PREFIX. */
2186 startswith (const char *str
, const char *prefix
)
2188 return strncmp (str
, prefix
, strlen (prefix
)) == 0;
2191 static void __attribute__((destructor
))
2194 if (gomp_def_allocator_envvar
!= NULL
)
2196 free (gomp_def_allocator_envvar
);
2197 omp_destroy_allocator (gomp_def_allocator
);
2201 static void __attribute__((constructor
))
2202 initialize_env (void)
2205 int omp_var
, dev_num
= 0, dev_num_len
= 0, i
;
2206 bool ignore
= false;
2209 uint32_t *flag_var_addr
= NULL
;
2211 struct gomp_icv_list
*all
, *none
;
2213 /* Do a compile time check that mkomp_h.pl did good job. */
2214 omp_check_defines ();
2216 #ifndef HAVE_SYNC_BUILTINS
2217 gomp_mutex_init (&gomp_managed_threads_lock
);
2219 gomp_init_num_threads ();
2220 gomp_available_cpus
= gomp_global_icv
.nthreads_var
;
2222 /* Initial values for host environment variables should always exist even if
2223 there is no explicitly set host environment variable. Moreover, they are
2224 set to the initial global values. */
2225 add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
, 0, NULL
);
2226 none
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
);
2227 initialize_icvs (&none
->icvs
);
2230 for (env
= environ
; *env
!= 0; env
++)
2232 if (!startswith (*env
, "OMP_"))
2235 /* Name of the environment variable without suffix "OMP_". */
2236 char *name
= *env
+ sizeof ("OMP_") - 1;
2237 for (omp_var
= 0; omp_var
< OMP_VAR_CNT
; omp_var
++)
2239 if (startswith (name
, envvars
[omp_var
].name
))
2241 pos
= envvars
[omp_var
].name_len
;
2242 if (name
[pos
] == '=')
2246 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_NO_SUFFIX
,
2247 envvars
[omp_var
].flag_vars
[0],
2250 else if (startswith (&name
[pos
], "_DEV=")
2251 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV
)
2255 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_DEV
,
2256 envvars
[omp_var
].flag_vars
[0],
2259 else if (startswith (&name
[pos
], "_ALL=")
2260 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_ALL
)
2264 = add_initial_icv_to_list (GOMP_DEVICE_NUM_FOR_ALL
,
2265 envvars
[omp_var
].flag_vars
[0],
2268 else if (startswith (&name
[pos
], "_DEV_")
2269 && envvars
[omp_var
].flag
& GOMP_ENV_SUFFIX_DEV_X
)
2272 if (!get_device_num (*env
, &name
[pos
], &dev_num
,
2276 pos
+= dev_num_len
+ 1;
2278 = add_initial_icv_to_list (dev_num
,
2279 envvars
[omp_var
].flag_vars
[0],
2284 gomp_error ("Invalid environment variable in %s", *env
);
2287 env_val
= &name
[pos
];
2289 if (envvars
[omp_var
].parse_func (*env
, env_val
, params
))
2291 for (i
= 0; i
< 3; ++i
)
2292 if (envvars
[omp_var
].flag_vars
[i
])
2293 gomp_set_icv_flag (flag_var_addr
,
2294 envvars
[omp_var
].flag_vars
[i
]);
2304 all
= gomp_get_initial_icv_item (GOMP_DEVICE_NUM_FOR_ALL
);
2305 for (omp_var
= 0; omp_var
< OMP_HOST_VAR_CNT
; omp_var
++)
2308 && gomp_get_icv_flag (none
->flags
, host_envvars
[omp_var
].flag_var
))
2309 get_icv_member_addr (&none
->icvs
,
2310 host_envvars
[omp_var
].flag_var
, params
);
2311 else if (all
!= NULL
2312 && gomp_get_icv_flag (all
->flags
,
2313 host_envvars
[omp_var
].flag_var
))
2314 get_icv_member_addr (&all
->icvs
, host_envvars
[omp_var
].flag_var
,
2319 switch (host_envvars
[omp_var
].type_code
)
2322 for (i
= 0; i
< 3; ++i
)
2323 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2324 *(int *) (host_envvars
[omp_var
].dest
[i
]) = *(int *) params
[i
];
2327 for (i
= 0; i
< 3; ++i
)
2328 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2329 *(bool *) (host_envvars
[omp_var
].dest
[i
]) = *(bool *) params
[i
];
2332 for (i
= 0; i
< 3; ++i
)
2333 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2334 *(unsigned int *) (host_envvars
[omp_var
].dest
[i
])
2335 = *(unsigned int *) params
[i
];
2338 for (i
= 0; i
< 3; ++i
)
2339 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2340 *(unsigned long *) (host_envvars
[omp_var
].dest
[i
])
2341 = *(unsigned long *) params
[i
];
2344 for (i
= 0; i
< 3; ++i
)
2345 if (host_envvars
[omp_var
].dest
[i
] != NULL
&& params
[i
] != NULL
)
2346 *(unsigned char *) (host_envvars
[omp_var
].dest
[i
])
2347 = *(unsigned char *) params
[i
];
2349 case PARSE_SCHEDULE
:
2350 *(enum gomp_schedule_type
*) (host_envvars
[omp_var
].dest
[0])
2351 = *(enum gomp_schedule_type
*) params
[0];
2352 *(int *) (host_envvars
[omp_var
].dest
[1]) = *(int *) params
[1];
2355 *(char *) (host_envvars
[omp_var
].dest
[0]) = *(char *) params
[0];
2356 *(char **) (host_envvars
[omp_var
].dest
[1]) = *(char **) params
[1];
2357 *(unsigned long *) (host_envvars
[omp_var
].dest
[2])
2358 = *(unsigned long *) params
[2];
2363 if (((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_BIND
))
2364 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_BIND
)))
2365 && gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2369 && gomp_get_icv_flag (none
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))
2371 && gomp_get_icv_flag (all
->flags
, GOMP_ICV_MAX_ACTIVE_LEVELS
))))
2374 const char *env
= getenv ("OMP_NESTED");
2376 /* OMP_NESTED is deprecated in OpenMP 5.0. */
2377 if (parse_boolean ("OMP_NESTED", env
, (void *[]) {&nested
}))
2378 gomp_global_icv
.max_active_levels_var
2379 = nested
? gomp_supported_active_levels
: 1;
2380 else if (gomp_nthreads_var_list_len
> 1 || gomp_bind_var_list_len
> 1)
2381 gomp_global_icv
.max_active_levels_var
= gomp_supported_active_levels
;
2384 if (gomp_global_icv
.default_device_var
== INT_MIN
2385 && gomp_target_offload_var
!= GOMP_TARGET_OFFLOAD_MANDATORY
)
2386 none
->icvs
.default_device_var
= gomp_global_icv
.default_device_var
= 0;
2388 /* Process GOMP_* variables and dependencies between parsed ICVs. */
2389 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var
, true);
2391 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
2392 parsed if present in the environment. If OMP_PROC_BIND was set
2393 explicitly to false, don't populate places list though. If places
2394 list was successfully set from OMP_PLACES, only parse but don't process
2395 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
2396 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
2397 was successfully parsed into a places list, otherwise to
2398 OMP_PROC_BIND=false. */
2399 if (parse_places_var ("OMP_PLACES", ignore
))
2401 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2402 gomp_global_icv
.bind_var
= true;
2405 if (parse_affinity (ignore
))
2407 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
2408 gomp_global_icv
.bind_var
= true;
2411 if (gomp_global_icv
.bind_var
!= omp_proc_bind_false
)
2412 gomp_init_affinity ();
2415 const char *env
= getenv ("OMP_AFFINITY_FORMAT");
2417 gomp_set_affinity_format (env
, strlen (env
));
2420 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_WAIT_POLICY
))
2421 wait_policy
= none
->icvs
.wait_policy
;
2422 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_WAIT_POLICY
))
2423 wait_policy
= all
->icvs
.wait_policy
;
2425 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var
))
2427 /* Using a rough estimation of 100000 spins per msec,
2428 use 5 min blocking for OMP_WAIT_POLICY=active,
2429 3 msec blocking when OMP_WAIT_POLICY is not specificed
2430 and 0 when OMP_WAIT_POLICY=passive.
2431 Depending on the CPU speed, this can be e.g. 5 times longer
2432 or 5 times shorter. */
2433 if (wait_policy
> 0)
2434 gomp_spin_count_var
= 30000000000LL;
2435 else if (wait_policy
< 0)
2437 gomp_spin_count_var
= 300000LL;
2438 do_adjust_default_spincount ();
2441 /* gomp_throttled_spin_count_var is used when there are more libgomp
2442 managed threads than available CPUs. Use very short spinning. */
2443 if (wait_policy
> 0)
2444 gomp_throttled_spin_count_var
= 1000LL;
2445 else if (wait_policy
< 0)
2446 gomp_throttled_spin_count_var
= 100LL;
2447 if (gomp_throttled_spin_count_var
> gomp_spin_count_var
)
2448 gomp_throttled_spin_count_var
= gomp_spin_count_var
;
2450 /* Not strictly environment related, but ordering constructors is tricky. */
2451 pthread_attr_init (&gomp_thread_attr
);
2453 if (!(none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
)))
2455 const char *env
= getenv ("GOMP_STACKSIZE");
2457 && parse_stacksize ("GOMP_STACKSIZE", env
,
2458 (void *[3]) {&none
->icvs
.stacksize
}))
2459 gomp_set_icv_flag (&none
->flags
, GOMP_ICV_STACKSIZE
);
2461 if (none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2462 stacksize
= none
->icvs
.stacksize
;
2463 else if (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2464 stacksize
= all
->icvs
.stacksize
;
2466 if ((none
!= NULL
&& gomp_get_icv_flag (none
->flags
, GOMP_ICV_STACKSIZE
))
2467 || (all
!= NULL
&& gomp_get_icv_flag (all
->flags
, GOMP_ICV_STACKSIZE
))
2468 || GOMP_DEFAULT_STACKSIZE
)
2472 err
= pthread_attr_setstacksize (&gomp_thread_attr
, stacksize
);
2474 #ifdef PTHREAD_STACK_MIN
2477 if (stacksize
< PTHREAD_STACK_MIN
)
2478 gomp_error ("Stack size less than minimum of %luk",
2479 PTHREAD_STACK_MIN
/ 1024ul
2480 + (PTHREAD_STACK_MIN
% 1024 != 0));
2482 gomp_error ("Stack size larger than system limit");
2487 gomp_error ("Stack size change failed: %s", strerror (err
));
2490 handle_omp_display_env ();
2494 if (!parse_int ("ACC_DEVICE_NUM", getenv ("ACC_DEVICE_NUM"),
2495 (void *[]) {&goacc_device_num
, (void *) true}))
2496 goacc_device_num
= 0;
2498 parse_acc_device_type ();
2499 parse_gomp_openacc_dim ();
2501 goacc_runtime_initialize ();
2503 goacc_profiling_initialize ();
2505 #endif /* LIBGOMP_OFFLOADED_ONLY */