1 /* Copyright (C) 2005-2021 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 struct gomp_task_icv gomp_global_icv
= {
66 .thread_limit_var
= UINT_MAX
,
67 .run_sched_var
= GFS_DYNAMIC
,
68 .run_sched_chunk_size
= 1,
69 .default_device_var
= 0,
71 .max_active_levels_var
= 1,
72 .bind_var
= omp_proc_bind_false
,
76 bool gomp_cancel_var
= false;
77 enum gomp_target_offload_t gomp_target_offload_var
78 = GOMP_TARGET_OFFLOAD_DEFAULT
;
79 int gomp_max_task_priority_var
= 0;
80 #ifndef HAVE_SYNC_BUILTINS
81 gomp_mutex_t gomp_managed_threads_lock
;
83 unsigned long gomp_available_cpus
= 1, gomp_managed_threads
= 1;
84 unsigned long long gomp_spin_count_var
, gomp_throttled_spin_count_var
;
85 unsigned long *gomp_nthreads_var_list
, gomp_nthreads_var_list_len
;
86 char *gomp_bind_var_list
;
87 unsigned long gomp_bind_var_list_len
;
88 void **gomp_places_list
;
89 unsigned long gomp_places_list_len
;
90 uintptr_t gomp_def_allocator
= omp_default_mem_alloc
;
92 unsigned int gomp_num_teams_var
;
93 bool gomp_display_affinity_var
;
94 char *gomp_affinity_format_var
= "level %L thread %i affinity %A";
95 size_t gomp_affinity_format_len
;
96 char *goacc_device_type
;
98 int goacc_default_dims
[GOMP_DIM_MAX
];
100 #ifndef LIBGOMP_OFFLOADED_ONLY
102 static int wait_policy
;
103 static unsigned long stacksize
= GOMP_DEFAULT_STACKSIZE
;
105 /* Parse the OMP_SCHEDULE environment variable. */
108 parse_schedule (void)
114 env
= getenv ("OMP_SCHEDULE");
118 while (isspace ((unsigned char) *env
))
120 if (strncasecmp (env
, "monotonic", 9) == 0)
125 else if (strncasecmp (env
, "nonmonotonic", 12) == 0)
132 while (isspace ((unsigned char) *env
))
137 while (isspace ((unsigned char) *env
))
140 if (strncasecmp (env
, "static", 6) == 0)
142 gomp_global_icv
.run_sched_var
= GFS_STATIC
;
145 else if (strncasecmp (env
, "dynamic", 7) == 0)
147 gomp_global_icv
.run_sched_var
= GFS_DYNAMIC
;
150 else if (strncasecmp (env
, "guided", 6) == 0)
152 gomp_global_icv
.run_sched_var
= GFS_GUIDED
;
155 else if (strncasecmp (env
, "auto", 4) == 0)
157 gomp_global_icv
.run_sched_var
= GFS_AUTO
;
164 || (monotonic
== 0 && gomp_global_icv
.run_sched_var
== GFS_STATIC
))
165 gomp_global_icv
.run_sched_var
|= GFS_MONOTONIC
;
167 while (isspace ((unsigned char) *env
))
171 gomp_global_icv
.run_sched_chunk_size
172 = (gomp_global_icv
.run_sched_var
& ~GFS_MONOTONIC
) != GFS_STATIC
;
177 while (isspace ((unsigned char) *env
))
183 value
= strtoul (env
, &end
, 10);
187 while (isspace ((unsigned char) *end
))
192 if ((int)value
!= value
)
196 && (gomp_global_icv
.run_sched_var
& ~GFS_MONOTONIC
) != GFS_STATIC
)
198 gomp_global_icv
.run_sched_chunk_size
= value
;
202 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
206 gomp_error ("Invalid value for chunk size in "
207 "environment variable OMP_SCHEDULE");
211 /* Parse an unsigned long environment variable. Return true if one was
212 present and it was successfully parsed. If SECURE, use secure_getenv to the
213 environment variable. */
216 parse_unsigned_long_1 (const char *name
, unsigned long *pvalue
, bool allow_zero
,
222 env
= (secure
? secure_getenv (name
) : getenv (name
));
226 while (isspace ((unsigned char) *env
))
232 value
= strtoul (env
, &end
, 10);
233 if (errno
|| (long) value
<= 0 - allow_zero
)
236 while (isspace ((unsigned char) *end
))
245 gomp_error ("Invalid value for environment variable %s", name
);
249 /* As parse_unsigned_long_1, but always use getenv. */
252 parse_unsigned_long (const char *name
, unsigned long *pvalue
, bool allow_zero
)
254 return parse_unsigned_long_1 (name
, pvalue
, allow_zero
, false);
257 /* Parse a positive int environment variable. Return true if one was
258 present and it was successfully parsed. If SECURE, use secure_getenv to the
259 environment variable. */
262 parse_int_1 (const char *name
, int *pvalue
, bool allow_zero
, bool secure
)
265 if (!parse_unsigned_long_1 (name
, &value
, allow_zero
, secure
))
269 gomp_error ("Invalid value for environment variable %s", name
);
272 *pvalue
= (int) value
;
276 /* As parse_int_1, but use getenv. */
279 parse_int (const char *name
, int *pvalue
, bool allow_zero
)
281 return parse_int_1 (name
, pvalue
, allow_zero
, false);
284 /* As parse_int_1, but use getenv_secure. */
287 parse_int_secure (const char *name
, int *pvalue
, bool allow_zero
)
289 return parse_int_1 (name
, pvalue
, allow_zero
, true);
292 /* Parse an unsigned long list environment variable. Return true if one was
293 present and it was successfully parsed. */
296 parse_unsigned_long_list (const char *name
, unsigned long *p1stvalue
,
297 unsigned long **pvalues
,
298 unsigned long *pnvalues
)
301 unsigned long value
, *values
= NULL
;
307 while (isspace ((unsigned char) *env
))
313 value
= strtoul (env
, &end
, 10);
314 if (errno
|| (long) value
<= 0)
317 while (isspace ((unsigned char) *end
))
323 unsigned long nvalues
= 0, nalloced
= 0;
328 if (nvalues
== nalloced
)
331 nalloced
= nalloced
? nalloced
* 2 : 16;
332 n
= realloc (values
, nalloced
* sizeof (unsigned long));
336 gomp_error ("Out of memory while trying to parse"
337 " environment variable %s", name
);
342 values
[nvalues
++] = value
;
345 while (isspace ((unsigned char) *env
))
351 value
= strtoul (env
, &end
, 10);
352 if (errno
|| (long) value
<= 0)
355 values
[nvalues
++] = value
;
356 while (isspace ((unsigned char) *end
))
364 *p1stvalue
= values
[0];
377 gomp_error ("Invalid value for environment variable %s", name
);
382 parse_target_offload (const char *name
, enum gomp_target_offload_t
*offload
)
385 int new_offload
= -1;
391 while (isspace ((unsigned char) *env
))
393 if (strncasecmp (env
, "default", 7) == 0)
396 new_offload
= GOMP_TARGET_OFFLOAD_DEFAULT
;
398 else if (strncasecmp (env
, "mandatory", 9) == 0)
401 new_offload
= GOMP_TARGET_OFFLOAD_MANDATORY
;
403 else if (strncasecmp (env
, "disabled", 8) == 0)
406 new_offload
= GOMP_TARGET_OFFLOAD_DISABLED
;
408 while (isspace ((unsigned char) *env
))
410 if (new_offload
!= -1 && *env
== '\0')
412 *offload
= new_offload
;
416 gomp_error ("Invalid value for environment variable OMP_TARGET_OFFLOAD");
419 /* Parse environment variable set to a boolean or list of omp_proc_bind_t
420 enum values. Return true if one was present and it was successfully
424 parse_bind_var (const char *name
, char *p1stvalue
,
425 char **pvalues
, unsigned long *pnvalues
)
428 char value
= omp_proc_bind_false
, *values
= NULL
;
430 static struct proc_bind_kinds
434 omp_proc_bind_t kind
;
437 { "false", 5, omp_proc_bind_false
},
438 { "true", 4, omp_proc_bind_true
},
439 { "master", 6, omp_proc_bind_master
},
440 { "primary", 7, omp_proc_bind_primary
},
441 { "close", 5, omp_proc_bind_close
},
442 { "spread", 6, omp_proc_bind_spread
}
449 while (isspace ((unsigned char) *env
))
454 for (i
= 0; i
< 6; i
++)
455 if (strncasecmp (env
, kinds
[i
].name
, kinds
[i
].len
) == 0)
457 value
= kinds
[i
].kind
;
464 while (isspace ((unsigned char) *env
))
470 unsigned long nvalues
= 0, nalloced
= 0;
472 if (value
== omp_proc_bind_false
473 || value
== omp_proc_bind_true
)
479 if (nvalues
== nalloced
)
482 nalloced
= nalloced
? nalloced
* 2 : 16;
483 n
= realloc (values
, nalloced
);
487 gomp_error ("Out of memory while trying to parse"
488 " environment variable %s", name
);
493 values
[nvalues
++] = value
;
496 while (isspace ((unsigned char) *env
))
501 for (i
= 2; i
< 6; i
++)
502 if (strncasecmp (env
, kinds
[i
].name
, kinds
[i
].len
) == 0)
504 value
= kinds
[i
].kind
;
511 values
[nvalues
++] = value
;
512 while (isspace ((unsigned char) *env
))
520 *p1stvalue
= values
[0];
533 gomp_error ("Invalid value for environment variable %s", name
);
538 parse_one_place (char **envp
, bool *negatep
, unsigned long *lenp
,
541 char *env
= *envp
, *start
;
542 void *p
= gomp_places_list
? gomp_places_list
[gomp_places_list_len
] : NULL
;
543 unsigned long len
= 1;
546 bool any_negate
= false;
548 while (isspace ((unsigned char) *env
))
554 while (isspace ((unsigned char) *env
))
560 while (isspace ((unsigned char) *env
))
563 for (pass
= 0; pass
< (any_negate
? 2 : 1); pass
++)
568 unsigned long this_num
, this_len
= 1;
569 long this_stride
= 1;
570 bool this_negate
= (*env
== '!');
573 if (gomp_places_list
)
576 while (isspace ((unsigned char) *env
))
581 this_num
= strtoul (env
, &env
, 10);
584 while (isspace ((unsigned char) *env
))
589 while (isspace ((unsigned char) *env
))
592 this_len
= strtoul (env
, &env
, 10);
593 if (errno
|| this_len
== 0)
595 while (isspace ((unsigned char) *env
))
600 while (isspace ((unsigned char) *env
))
603 this_stride
= strtol (env
, &env
, 10);
606 while (isspace ((unsigned char) *env
))
610 if (this_negate
&& this_len
!= 1)
612 if (gomp_places_list
&& pass
== this_negate
)
616 if (!gomp_affinity_remove_cpu (p
, this_num
))
619 else if (!gomp_affinity_add_cpus (p
, this_num
, this_len
,
633 while (isspace ((unsigned char) *env
))
638 while (isspace ((unsigned char) *env
))
641 len
= strtoul (env
, &env
, 10);
642 if (errno
|| len
== 0 || len
>= 65536)
644 while (isspace ((unsigned char) *env
))
649 while (isspace ((unsigned char) *env
))
652 stride
= strtol (env
, &env
, 10);
655 while (isspace ((unsigned char) *env
))
659 if (*negatep
&& len
!= 1)
668 parse_places_var (const char *name
, bool ignore
)
670 char *env
= getenv (name
), *end
;
671 bool any_negate
= false;
673 unsigned long count
= 0;
677 while (isspace ((unsigned char) *env
))
682 if (strncasecmp (env
, "threads", 7) == 0)
687 else if (strncasecmp (env
, "cores", 5) == 0)
692 else if (strncasecmp (env
, "sockets", 7) == 0)
700 while (isspace ((unsigned char) *env
))
706 while (isspace ((unsigned char) *env
))
710 count
= strtoul (env
, &end
, 10);
714 while (isspace ((unsigned char) *env
))
719 while (isspace ((unsigned char) *env
))
728 return gomp_affinity_init_level (level
, count
, false);
738 if (!parse_one_place (&end
, &negate
, &len
, &stride
))
761 gomp_places_list_len
= 0;
762 gomp_places_list
= gomp_affinity_alloc (count
, false);
763 if (gomp_places_list
== NULL
)
771 gomp_affinity_init_place (gomp_places_list
[gomp_places_list_len
]);
772 if (!parse_one_place (&env
, &negate
, &len
, &stride
))
777 for (count
= 0; count
< gomp_places_list_len
; count
++)
778 if (gomp_affinity_same_place
779 (gomp_places_list
[count
],
780 gomp_places_list
[gomp_places_list_len
]))
782 if (count
== gomp_places_list_len
)
784 gomp_error ("Trying to remove a non-existing place from list "
788 p
= gomp_places_list
[count
];
789 memmove (&gomp_places_list
[count
],
790 &gomp_places_list
[count
+ 1],
791 (gomp_places_list_len
- count
- 1) * sizeof (void *));
792 --gomp_places_list_len
;
793 gomp_places_list
[gomp_places_list_len
] = p
;
796 ++gomp_places_list_len
;
799 for (count
= 0; count
< len
- 1; count
++)
800 if (!gomp_affinity_copy_place
801 (gomp_places_list
[gomp_places_list_len
+ count
+ 1],
802 gomp_places_list
[gomp_places_list_len
+ count
],
805 gomp_places_list_len
+= len
;
813 if (gomp_places_list_len
== 0)
815 gomp_error ("All places have been removed");
818 if (!gomp_affinity_finalize_place_list (false))
823 free (gomp_places_list
);
824 gomp_places_list
= NULL
;
825 gomp_places_list_len
= 0;
826 gomp_error ("Invalid value for environment variable %s", name
);
830 /* Parse the OMP_STACKSIZE environment varible. Return true if one was
831 present and it was successfully parsed. */
834 parse_stacksize (const char *name
, unsigned long *pvalue
)
837 unsigned long value
, shift
= 10;
843 while (isspace ((unsigned char) *env
))
849 value
= strtoul (env
, &end
, 10);
853 while (isspace ((unsigned char) *end
))
857 switch (tolower ((unsigned char) *end
))
874 while (isspace ((unsigned char) *end
))
880 if (((value
<< shift
) >> shift
) != value
)
883 *pvalue
= value
<< shift
;
887 gomp_error ("Invalid value for environment variable %s", name
);
891 /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
892 present and it was successfully parsed. */
895 parse_spincount (const char *name
, unsigned long long *pvalue
)
898 unsigned long long value
, mult
= 1;
904 while (isspace ((unsigned char) *env
))
909 if (strncasecmp (env
, "infinite", 8) == 0
910 || strncasecmp (env
, "infinity", 8) == 0)
918 value
= strtoull (env
, &end
, 10);
922 while (isspace ((unsigned char) *end
))
926 switch (tolower ((unsigned char) *end
))
932 mult
= 1000LL * 1000LL;
935 mult
= 1000LL * 1000LL * 1000LL;
938 mult
= 1000LL * 1000LL * 1000LL * 1000LL;
945 while (isspace ((unsigned char) *end
))
951 if (value
> ~0ULL / mult
)
960 gomp_error ("Invalid value for environment variable %s", name
);
964 /* Parse a boolean value for environment variable NAME and store the
965 result in VALUE. Return true if one was present and it was
966 successfully parsed. */
969 parse_boolean (const char *name
, bool *value
)
977 while (isspace ((unsigned char) *env
))
979 if (strncasecmp (env
, "true", 4) == 0)
984 else if (strncasecmp (env
, "false", 5) == 0)
991 while (isspace ((unsigned char) *env
))
995 gomp_error ("Invalid value for environment variable %s", name
);
1001 /* Parse the OMP_WAIT_POLICY environment variable and return the value. */
1004 parse_wait_policy (void)
1009 env
= getenv ("OMP_WAIT_POLICY");
1013 while (isspace ((unsigned char) *env
))
1015 if (strncasecmp (env
, "active", 6) == 0)
1020 else if (strncasecmp (env
, "passive", 7) == 0)
1027 while (isspace ((unsigned char) *env
))
1031 gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
1035 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
1036 present and it was successfully parsed. */
1039 parse_affinity (bool ignore
)
1041 char *env
, *end
, *start
;
1043 unsigned long cpu_beg
, cpu_end
, cpu_stride
;
1044 size_t count
= 0, needed
;
1046 env
= getenv ("GOMP_CPU_AFFINITY");
1051 for (pass
= 0; pass
< 2; pass
++)
1059 gomp_places_list_len
= 0;
1060 gomp_places_list
= gomp_affinity_alloc (count
, true);
1061 if (gomp_places_list
== NULL
)
1066 while (isspace ((unsigned char) *env
))
1070 cpu_beg
= strtoul (env
, &end
, 0);
1071 if (errno
|| cpu_beg
>= 65536)
1080 cpu_end
= strtoul (++env
, &end
, 0);
1081 if (errno
|| cpu_end
>= 65536 || cpu_end
< cpu_beg
)
1088 cpu_stride
= strtoul (++env
, &end
, 0);
1089 if (errno
|| cpu_stride
== 0 || cpu_stride
>= 65536)
1096 needed
= (cpu_end
- cpu_beg
) / cpu_stride
+ 1;
1103 void *p
= gomp_places_list
[gomp_places_list_len
];
1104 gomp_affinity_init_place (p
);
1105 if (gomp_affinity_add_cpus (p
, cpu_beg
, 1, 0, true))
1106 ++gomp_places_list_len
;
1107 cpu_beg
+= cpu_stride
;
1111 while (isspace ((unsigned char) *env
))
1116 else if (*env
== '\0')
1122 if (gomp_places_list_len
== 0)
1124 free (gomp_places_list
);
1125 gomp_places_list
= NULL
;
1131 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
1135 /* Parse the OMP_ALLOCATOR environment variable and return the value. */
1138 parse_allocator (void)
1141 uintptr_t ret
= omp_default_mem_alloc
;
1143 env
= getenv ("OMP_ALLOCATOR");
1147 while (isspace ((unsigned char) *env
))
1152 else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
1155 env += sizeof (#v) - 1; \
1157 C (omp_default_mem_alloc
)
1158 C (omp_large_cap_mem_alloc
)
1159 C (omp_const_mem_alloc
)
1160 C (omp_high_bw_mem_alloc
)
1161 C (omp_low_lat_mem_alloc
)
1162 C (omp_cgroup_mem_alloc
)
1163 C (omp_pteam_mem_alloc
)
1164 C (omp_thread_mem_alloc
)
1168 while (isspace ((unsigned char) *env
))
1172 gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
1173 return omp_default_mem_alloc
;
1177 parse_acc_device_type (void)
1179 const char *env
= getenv ("ACC_DEVICE_TYPE");
1181 if (env
&& *env
!= '\0')
1182 goacc_device_type
= strdup (env
);
1184 goacc_device_type
= NULL
;
1188 parse_gomp_openacc_dim (void)
1190 /* The syntax is the same as for the -fopenacc-dim compilation option. */
1191 const char *var_name
= "GOMP_OPENACC_DIM";
1192 const char *env_var
= getenv (var_name
);
1196 const char *pos
= env_var
;
1198 for (i
= 0; *pos
&& i
!= GOMP_DIM_MAX
; i
++)
1200 if (i
&& *pos
++ != ':')
1208 long val
= strtol (pos
, (char **)&eptr
, 10);
1209 if (errno
|| val
< 0 || (unsigned)val
!= val
)
1212 goacc_default_dims
[i
] = (int)val
;
1218 omp_display_env (int verbose
)
1222 fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr
);
1224 fputs (" _OPENMP = '201511'\n", stderr
);
1225 fprintf (stderr
, " OMP_DYNAMIC = '%s'\n",
1226 gomp_global_icv
.dyn_var
? "TRUE" : "FALSE");
1227 fprintf (stderr
, " OMP_NESTED = '%s'\n",
1228 gomp_global_icv
.max_active_levels_var
> 1 ? "TRUE" : "FALSE");
1230 fprintf (stderr
, " OMP_NUM_THREADS = '%lu", gomp_global_icv
.nthreads_var
);
1231 for (i
= 1; i
< gomp_nthreads_var_list_len
; i
++)
1232 fprintf (stderr
, ",%lu", gomp_nthreads_var_list
[i
]);
1233 fputs ("'\n", stderr
);
1235 fprintf (stderr
, " OMP_SCHEDULE = '");
1236 if ((gomp_global_icv
.run_sched_var
& GFS_MONOTONIC
))
1238 if (gomp_global_icv
.run_sched_var
!= (GFS_MONOTONIC
| GFS_STATIC
))
1239 fputs ("MONOTONIC:", stderr
);
1241 else if (gomp_global_icv
.run_sched_var
== GFS_STATIC
)
1242 fputs ("NONMONOTONIC:", stderr
);
1243 switch (gomp_global_icv
.run_sched_var
& ~GFS_MONOTONIC
)
1246 fputs ("RUNTIME", stderr
);
1247 if (gomp_global_icv
.run_sched_chunk_size
!= 1)
1248 fprintf (stderr
, ",%d", gomp_global_icv
.run_sched_chunk_size
);
1251 fputs ("STATIC", stderr
);
1252 if (gomp_global_icv
.run_sched_chunk_size
!= 0)
1253 fprintf (stderr
, ",%d", gomp_global_icv
.run_sched_chunk_size
);
1256 fputs ("DYNAMIC", stderr
);
1257 if (gomp_global_icv
.run_sched_chunk_size
!= 1)
1258 fprintf (stderr
, ",%d", gomp_global_icv
.run_sched_chunk_size
);
1261 fputs ("GUIDED", stderr
);
1262 if (gomp_global_icv
.run_sched_chunk_size
!= 1)
1263 fprintf (stderr
, ",%d", gomp_global_icv
.run_sched_chunk_size
);
1266 fputs ("AUTO", stderr
);
1269 fputs ("'\n", stderr
);
1271 fputs (" OMP_PROC_BIND = '", stderr
);
1272 switch (gomp_global_icv
.bind_var
)
1274 case omp_proc_bind_false
:
1275 fputs ("FALSE", stderr
);
1277 case omp_proc_bind_true
:
1278 fputs ("TRUE", stderr
);
1280 case omp_proc_bind_master
:
1281 fputs ("MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1283 case omp_proc_bind_close
:
1284 fputs ("CLOSE", stderr
);
1286 case omp_proc_bind_spread
:
1287 fputs ("SPREAD", stderr
);
1290 for (i
= 1; i
< gomp_bind_var_list_len
; i
++)
1291 switch (gomp_bind_var_list
[i
])
1293 case omp_proc_bind_master
:
1294 fputs (",MASTER", stderr
); /* TODO: Change to PRIMARY for OpenMP 5.1. */
1296 case omp_proc_bind_close
:
1297 fputs (",CLOSE", stderr
);
1299 case omp_proc_bind_spread
:
1300 fputs (",SPREAD", stderr
);
1303 fputs ("'\n", stderr
);
1304 fputs (" OMP_PLACES = '", stderr
);
1305 for (i
= 0; i
< gomp_places_list_len
; i
++)
1307 fputs ("{", stderr
);
1308 gomp_affinity_print_place (gomp_places_list
[i
]);
1309 fputs (i
+ 1 == gomp_places_list_len
? "}" : "},", stderr
);
1311 fputs ("'\n", stderr
);
1313 fprintf (stderr
, " OMP_STACKSIZE = '%lu'\n", stacksize
);
1315 /* GOMP's default value is actually neither active nor passive. */
1316 fprintf (stderr
, " OMP_WAIT_POLICY = '%s'\n",
1317 wait_policy
> 0 ? "ACTIVE" : "PASSIVE");
1318 fprintf (stderr
, " OMP_THREAD_LIMIT = '%u'\n",
1319 gomp_global_icv
.thread_limit_var
);
1320 fprintf (stderr
, " OMP_MAX_ACTIVE_LEVELS = '%u'\n",
1321 gomp_global_icv
.max_active_levels_var
);
1323 fprintf (stderr
, " OMP_CANCELLATION = '%s'\n",
1324 gomp_cancel_var
? "TRUE" : "FALSE");
1325 fprintf (stderr
, " OMP_DEFAULT_DEVICE = '%d'\n",
1326 gomp_global_icv
.default_device_var
);
1327 fprintf (stderr
, " OMP_MAX_TASK_PRIORITY = '%d'\n",
1328 gomp_max_task_priority_var
);
1329 fprintf (stderr
, " OMP_DISPLAY_AFFINITY = '%s'\n",
1330 gomp_display_affinity_var
? "TRUE" : "FALSE");
1331 fprintf (stderr
, " OMP_AFFINITY_FORMAT = '%s'\n",
1332 gomp_affinity_format_var
);
1333 fprintf (stderr
, " OMP_ALLOCATOR = '");
1334 switch (gomp_def_allocator
)
1336 #define C(v) case v: fputs (#v, stderr); break;
1337 C (omp_default_mem_alloc
)
1338 C (omp_large_cap_mem_alloc
)
1339 C (omp_const_mem_alloc
)
1340 C (omp_high_bw_mem_alloc
)
1341 C (omp_low_lat_mem_alloc
)
1342 C (omp_cgroup_mem_alloc
)
1343 C (omp_pteam_mem_alloc
)
1344 C (omp_thread_mem_alloc
)
1348 fputs ("'\n", stderr
);
1350 fputs (" OMP_TARGET_OFFLOAD = '", stderr
);
1351 switch (gomp_target_offload_var
)
1353 case GOMP_TARGET_OFFLOAD_DEFAULT
:
1354 fputs ("DEFAULT", stderr
);
1356 case GOMP_TARGET_OFFLOAD_MANDATORY
:
1357 fputs ("MANDATORY", stderr
);
1359 case GOMP_TARGET_OFFLOAD_DISABLED
:
1360 fputs ("DISABLED", stderr
);
1363 fputs ("'\n", stderr
);
1367 fputs (" GOMP_CPU_AFFINITY = ''\n", stderr
);
1368 fprintf (stderr
, " GOMP_STACKSIZE = '%lu'\n", stacksize
);
1369 #ifdef HAVE_INTTYPES_H
1370 fprintf (stderr
, " GOMP_SPINCOUNT = '%"PRIu64
"'\n",
1371 (uint64_t) gomp_spin_count_var
);
1373 fprintf (stderr
, " GOMP_SPINCOUNT = '%lu'\n",
1374 (unsigned long) gomp_spin_count_var
);
1378 fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr
);
1380 ialias (omp_display_env
)
1383 handle_omp_display_env (void)
1386 bool display
= false;
1387 bool verbose
= false;
1389 env
= getenv ("OMP_DISPLAY_ENV");
1393 while (isspace ((unsigned char) *env
))
1395 if (strncasecmp (env
, "true", 4) == 0)
1400 else if (strncasecmp (env
, "false", 5) == 0)
1405 else if (strncasecmp (env
, "verbose", 7) == 0)
1413 while (isspace ((unsigned char) *env
))
1416 gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
1419 omp_display_env (verbose
);
1423 static void __attribute__((constructor
))
1424 initialize_env (void)
1426 unsigned long thread_limit_var
;
1427 unsigned long max_active_levels_var
;
1429 /* Do a compile time check that mkomp_h.pl did good job. */
1430 omp_check_defines ();
1433 parse_boolean ("OMP_DYNAMIC", &gomp_global_icv
.dyn_var
);
1434 parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var
);
1435 parse_boolean ("OMP_DISPLAY_AFFINITY", &gomp_display_affinity_var
);
1436 parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv
.default_device_var
, true);
1437 parse_target_offload ("OMP_TARGET_OFFLOAD", &gomp_target_offload_var
);
1438 parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var
, true);
1439 gomp_def_allocator
= parse_allocator ();
1440 if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var
, false))
1442 gomp_global_icv
.thread_limit_var
1443 = thread_limit_var
> INT_MAX
? UINT_MAX
: thread_limit_var
;
1445 parse_int_secure ("GOMP_DEBUG", &gomp_debug_var
, true);
1446 #ifndef HAVE_SYNC_BUILTINS
1447 gomp_mutex_init (&gomp_managed_threads_lock
);
1449 gomp_init_num_threads ();
1450 gomp_available_cpus
= gomp_global_icv
.nthreads_var
;
1451 if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
1452 &gomp_global_icv
.nthreads_var
,
1453 &gomp_nthreads_var_list
,
1454 &gomp_nthreads_var_list_len
))
1455 gomp_global_icv
.nthreads_var
= gomp_available_cpus
;
1456 bool ignore
= false;
1457 if (parse_bind_var ("OMP_PROC_BIND",
1458 &gomp_global_icv
.bind_var
,
1459 &gomp_bind_var_list
,
1460 &gomp_bind_var_list_len
)
1461 && gomp_global_icv
.bind_var
== omp_proc_bind_false
)
1463 if (parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS",
1464 &max_active_levels_var
, true))
1465 gomp_global_icv
.max_active_levels_var
1466 = (max_active_levels_var
> gomp_supported_active_levels
)
1467 ? gomp_supported_active_levels
: max_active_levels_var
;
1472 /* OMP_NESTED is deprecated in OpenMP 5.0. */
1473 if (parse_boolean ("OMP_NESTED", &nested
))
1474 gomp_global_icv
.max_active_levels_var
1475 = nested
? gomp_supported_active_levels
: 1;
1476 else if (gomp_nthreads_var_list_len
> 1 || gomp_bind_var_list_len
> 1)
1477 gomp_global_icv
.max_active_levels_var
= gomp_supported_active_levels
;
1479 /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
1480 parsed if present in the environment. If OMP_PROC_BIND was set
1481 explicitly to false, don't populate places list though. If places
1482 list was successfully set from OMP_PLACES, only parse but don't process
1483 GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
1484 default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
1485 was successfully parsed into a places list, otherwise to
1486 OMP_PROC_BIND=false. */
1487 if (parse_places_var ("OMP_PLACES", ignore
))
1489 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
1490 gomp_global_icv
.bind_var
= true;
1493 if (parse_affinity (ignore
))
1495 if (gomp_global_icv
.bind_var
== omp_proc_bind_false
)
1496 gomp_global_icv
.bind_var
= true;
1499 if (gomp_global_icv
.bind_var
!= omp_proc_bind_false
)
1500 gomp_init_affinity ();
1503 const char *env
= getenv ("OMP_AFFINITY_FORMAT");
1505 gomp_set_affinity_format (env
, strlen (env
));
1508 wait_policy
= parse_wait_policy ();
1509 if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var
))
1511 /* Using a rough estimation of 100000 spins per msec,
1512 use 5 min blocking for OMP_WAIT_POLICY=active,
1513 3 msec blocking when OMP_WAIT_POLICY is not specificed
1514 and 0 when OMP_WAIT_POLICY=passive.
1515 Depending on the CPU speed, this can be e.g. 5 times longer
1516 or 5 times shorter. */
1517 if (wait_policy
> 0)
1518 gomp_spin_count_var
= 30000000000LL;
1519 else if (wait_policy
< 0)
1520 gomp_spin_count_var
= 300000LL;
1522 /* gomp_throttled_spin_count_var is used when there are more libgomp
1523 managed threads than available CPUs. Use very short spinning. */
1524 if (wait_policy
> 0)
1525 gomp_throttled_spin_count_var
= 1000LL;
1526 else if (wait_policy
< 0)
1527 gomp_throttled_spin_count_var
= 100LL;
1528 if (gomp_throttled_spin_count_var
> gomp_spin_count_var
)
1529 gomp_throttled_spin_count_var
= gomp_spin_count_var
;
1531 /* Not strictly environment related, but ordering constructors is tricky. */
1532 pthread_attr_init (&gomp_thread_attr
);
1534 if (parse_stacksize ("OMP_STACKSIZE", &stacksize
)
1535 || parse_stacksize ("GOMP_STACKSIZE", &stacksize
)
1536 || GOMP_DEFAULT_STACKSIZE
)
1540 err
= pthread_attr_setstacksize (&gomp_thread_attr
, stacksize
);
1542 #ifdef PTHREAD_STACK_MIN
1545 if (stacksize
< PTHREAD_STACK_MIN
)
1546 gomp_error ("Stack size less than minimum of %luk",
1547 PTHREAD_STACK_MIN
/ 1024ul
1548 + (PTHREAD_STACK_MIN
% 1024 != 0));
1550 gomp_error ("Stack size larger than system limit");
1555 gomp_error ("Stack size change failed: %s", strerror (err
));
1558 handle_omp_display_env ();
1562 if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num
, true))
1563 goacc_device_num
= 0;
1565 parse_acc_device_type ();
1566 parse_gomp_openacc_dim ();
1568 goacc_runtime_initialize ();
1570 goacc_profiling_initialize ();
1572 #endif /* LIBGOMP_OFFLOADED_ONLY */