]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgomp/env.c
i386.md (*indirect_jump): Macroize using P mode iterator.
[thirdparty/gcc.git] / libgomp / env.c
CommitLineData
a0884cf0 1/* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
953ff289
DN
2 Contributed by Richard Henderson <rth@redhat.com>.
3
4 This file is part of the GNU OpenMP Library (libgomp).
5
6 Libgomp is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with libgomp; see the file COPYING.LIB. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21/* As a special exception, if you link this library with other files, some
22 of which are compiled with GCC, to produce an executable, this library
23 does not by itself cause the resulting executable to be covered by the
24 GNU General Public License. This exception does not however invalidate
25 any other reasons why the executable file might be covered by the GNU
26 General Public License. */
27
28/* This file defines the OpenMP internal control variables, and arranges
29 for them to be initialized from environment variables at startup. */
30
31#include "libgomp.h"
32#include "libgomp_f.h"
89b3e3cd 33#include <ctype.h>
953ff289 34#include <stdlib.h>
a1b25e49
PG
35#ifdef STRING_WITH_STRINGS
36# include <string.h>
37# include <strings.h>
38#else
39# ifdef HAVE_STRING_H
40# include <string.h>
41# else
42# ifdef HAVE_STRINGS_H
43# include <strings.h>
44# endif
45# endif
46#endif
d0d1b24d
RH
47#include <limits.h>
48#include <errno.h>
953ff289
DN
49
50
d0d1b24d 51unsigned long gomp_nthreads_var = 1;
953ff289
DN
52bool gomp_dyn_var = false;
53bool gomp_nest_var = false;
54enum gomp_schedule_type gomp_run_sched_var = GFS_DYNAMIC;
d0d1b24d 55unsigned long gomp_run_sched_chunk = 1;
a0884cf0
JJ
56unsigned short *gomp_cpu_affinity;
57size_t gomp_cpu_affinity_len;
953ff289
DN
58
59/* Parse the OMP_SCHEDULE environment variable. */
60
61static void
62parse_schedule (void)
63{
64 char *env, *end;
6acf0b38 65 unsigned long value;
953ff289
DN
66
67 env = getenv ("OMP_SCHEDULE");
68 if (env == NULL)
69 return;
70
89b3e3cd
JJ
71 while (isspace ((unsigned char) *env))
72 ++env;
73 if (strncasecmp (env, "static", 6) == 0)
953ff289
DN
74 {
75 gomp_run_sched_var = GFS_STATIC;
76 env += 6;
77 }
89b3e3cd 78 else if (strncasecmp (env, "dynamic", 7) == 0)
953ff289
DN
79 {
80 gomp_run_sched_var = GFS_DYNAMIC;
81 env += 7;
82 }
89b3e3cd 83 else if (strncasecmp (env, "guided", 6) == 0)
953ff289
DN
84 {
85 gomp_run_sched_var = GFS_GUIDED;
86 env += 6;
87 }
88 else
89 goto unknown;
90
89b3e3cd
JJ
91 while (isspace ((unsigned char) *env))
92 ++env;
953ff289
DN
93 if (*env == '\0')
94 return;
89b3e3cd 95 if (*env++ != ',')
953ff289 96 goto unknown;
89b3e3cd
JJ
97 while (isspace ((unsigned char) *env))
98 ++env;
953ff289 99 if (*env == '\0')
953ff289
DN
100 goto invalid;
101
6acf0b38
UB
102 errno = 0;
103 value = strtoul (env, &end, 10);
104 if (errno)
105 goto invalid;
106
89b3e3cd
JJ
107 while (isspace ((unsigned char) *end))
108 ++end;
953ff289
DN
109 if (*end != '\0')
110 goto invalid;
6acf0b38
UB
111
112 gomp_run_sched_chunk = value;
953ff289
DN
113 return;
114
115 unknown:
116 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
117 return;
118
119 invalid:
120 gomp_error ("Invalid value for chunk size in "
121 "environment variable OMP_SCHEDULE");
953ff289
DN
122 return;
123}
124
d0d1b24d 125/* Parse an unsigned long environment varible. Return true if one was
953ff289
DN
126 present and it was successfully parsed. */
127
128static bool
d0d1b24d 129parse_unsigned_long (const char *name, unsigned long *pvalue)
953ff289
DN
130{
131 char *env, *end;
d0d1b24d 132 unsigned long value;
953ff289 133
d0d1b24d 134 env = getenv (name);
953ff289
DN
135 if (env == NULL)
136 return false;
137
89b3e3cd
JJ
138 while (isspace ((unsigned char) *env))
139 ++env;
953ff289
DN
140 if (*env == '\0')
141 goto invalid;
142
6acf0b38 143 errno = 0;
d0d1b24d 144 value = strtoul (env, &end, 10);
6acf0b38
UB
145 if (errno || (long) value <= 0)
146 goto invalid;
147
89b3e3cd
JJ
148 while (isspace ((unsigned char) *end))
149 ++end;
953ff289
DN
150 if (*end != '\0')
151 goto invalid;
d0d1b24d
RH
152
153 *pvalue = value;
953ff289
DN
154 return true;
155
156 invalid:
d0d1b24d 157 gomp_error ("Invalid value for environment variable %s", name);
953ff289
DN
158 return false;
159}
160
d0d1b24d 161/* Parse a boolean value for environment variable NAME and store the
953ff289
DN
162 result in VALUE. */
163
164static void
165parse_boolean (const char *name, bool *value)
166{
167 const char *env;
168
169 env = getenv (name);
170 if (env == NULL)
171 return;
172
89b3e3cd
JJ
173 while (isspace ((unsigned char) *env))
174 ++env;
175 if (strncasecmp (env, "true", 4) == 0)
176 {
177 *value = true;
178 env += 4;
179 }
180 else if (strncasecmp (env, "false", 5) == 0)
181 {
182 *value = false;
183 env += 5;
184 }
953ff289 185 else
89b3e3cd
JJ
186 env = "X";
187 while (isspace ((unsigned char) *env))
188 ++env;
189 if (*env != '\0')
d0d1b24d 190 gomp_error ("Invalid value for environment variable %s", name);
953ff289
DN
191}
192
a0884cf0
JJ
193/* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
194 present and it was successfully parsed. */
195
196static bool
197parse_affinity (void)
198{
199 char *env, *end;
200 unsigned long cpu_beg, cpu_end, cpu_stride;
201 unsigned short *cpus = NULL;
202 size_t allocated = 0, used = 0, needed;
203
204 env = getenv ("GOMP_CPU_AFFINITY");
205 if (env == NULL)
206 return false;
207
208 do
209 {
210 while (*env == ' ' || *env == '\t')
211 env++;
212
213 cpu_beg = strtoul (env, &end, 0);
214 cpu_end = cpu_beg;
215 cpu_stride = 1;
216 if (env == end || cpu_beg >= 65536)
217 goto invalid;
218
219 env = end;
220 if (*env == '-')
221 {
222 cpu_end = strtoul (++env, &end, 0);
223 if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
224 goto invalid;
225
226 env = end;
227 if (*env == ':')
228 {
229 cpu_stride = strtoul (++env, &end, 0);
230 if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
231 goto invalid;
232
233 env = end;
234 }
235 }
236
237 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
238 if (used + needed >= allocated)
239 {
240 unsigned short *new_cpus;
241
242 if (allocated < 64)
243 allocated = 64;
244 if (allocated > needed)
245 allocated <<= 1;
246 else
247 allocated += 2 * needed;
248 new_cpus = realloc (cpus, allocated * sizeof (unsigned short));
249 if (new_cpus == NULL)
250 {
251 free (cpus);
252 gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
253 return false;
254 }
255
256 cpus = new_cpus;
257 }
258
259 while (needed--)
260 {
261 cpus[used++] = cpu_beg;
262 cpu_beg += cpu_stride;
263 }
264
265 while (*env == ' ' || *env == '\t')
266 env++;
267
268 if (*env == ',')
269 env++;
270 else if (*env == '\0')
271 break;
272 }
273 while (1);
274
275 gomp_cpu_affinity = cpus;
276 gomp_cpu_affinity_len = used;
277 return true;
278
279 invalid:
280 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
281 return false;
282}
283
953ff289
DN
284static void __attribute__((constructor))
285initialize_env (void)
286{
d0d1b24d
RH
287 unsigned long stacksize;
288
953ff289
DN
289 /* Do a compile time check that mkomp_h.pl did good job. */
290 omp_check_defines ();
291
292 parse_schedule ();
293 parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var);
294 parse_boolean ("OMP_NESTED", &gomp_nest_var);
d0d1b24d 295 if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var))
953ff289 296 gomp_init_num_threads ();
a0884cf0
JJ
297 if (parse_affinity ())
298 gomp_init_affinity ();
d0d1b24d
RH
299
300 /* Not strictly environment related, but ordering constructors is tricky. */
301 pthread_attr_init (&gomp_thread_attr);
302 pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
303
c3b11a40 304 if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize))
d0d1b24d 305 {
c3b11a40
RH
306 int err;
307
d0d1b24d 308 stacksize *= 1024;
c3b11a40
RH
309 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
310
311#ifdef PTHREAD_STACK_MIN
312 if (err == EINVAL)
d0d1b24d 313 {
c3b11a40
RH
314 if (stacksize < PTHREAD_STACK_MIN)
315 gomp_error ("Stack size less than minimum of %luk",
316 PTHREAD_STACK_MIN / 1024ul
317 + (PTHREAD_STACK_MIN % 1024 != 0));
318 else
d0d1b24d 319 gomp_error ("Stack size larger than system limit");
d0d1b24d 320 }
c3b11a40
RH
321 else
322#endif
323 if (err != 0)
324 gomp_error ("Stack size change failed: %s", strerror (err));
d0d1b24d 325 }
953ff289
DN
326}
327
328\f
329/* The public OpenMP API routines that access these variables. */
330
331void
332omp_set_num_threads (int n)
333{
62bd6216 334 gomp_nthreads_var = (n > 0 ? n : 1);
953ff289
DN
335}
336
337void
338omp_set_dynamic (int val)
339{
340 gomp_dyn_var = val;
341}
342
343int
344omp_get_dynamic (void)
345{
346 return gomp_dyn_var;
347}
348
349void
350omp_set_nested (int val)
351{
352 gomp_nest_var = val;
353}
354
355int
356omp_get_nested (void)
357{
358 return gomp_nest_var;
359}
360
361ialias (omp_set_dynamic)
362ialias (omp_set_nested)
363ialias (omp_set_num_threads)
364ialias (omp_get_dynamic)
365ialias (omp_get_nested)