2008-06-03 Kai Tietz <kai.tietz@onevision.com>
[official-gcc.git] / libgomp / env.c
blob6c6a35228eb555bc09c37bac6f878b7e4095f956
1 /* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU OpenMP Library (libgomp).
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.
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.
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. */
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. */
28 /* This file defines the OpenMP internal control variables, and arranges
29 for them to be initialized from environment variables at startup. */
31 #include "libgomp.h"
32 #include "libgomp_f.h"
33 #include <ctype.h>
34 #include <stdlib.h>
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
47 #include <limits.h>
48 #include <errno.h>
51 unsigned long gomp_nthreads_var = 1;
52 bool gomp_dyn_var = false;
53 bool gomp_nest_var = false;
54 enum gomp_schedule_type gomp_run_sched_var = GFS_DYNAMIC;
55 unsigned long gomp_run_sched_chunk = 1;
56 unsigned short *gomp_cpu_affinity;
57 size_t gomp_cpu_affinity_len;
59 /* Parse the OMP_SCHEDULE environment variable. */
61 static void
62 parse_schedule (void)
64 char *env, *end;
65 unsigned long value;
67 env = getenv ("OMP_SCHEDULE");
68 if (env == NULL)
69 return;
71 while (isspace ((unsigned char) *env))
72 ++env;
73 if (strncasecmp (env, "static", 6) == 0)
75 gomp_run_sched_var = GFS_STATIC;
76 env += 6;
78 else if (strncasecmp (env, "dynamic", 7) == 0)
80 gomp_run_sched_var = GFS_DYNAMIC;
81 env += 7;
83 else if (strncasecmp (env, "guided", 6) == 0)
85 gomp_run_sched_var = GFS_GUIDED;
86 env += 6;
88 else
89 goto unknown;
91 while (isspace ((unsigned char) *env))
92 ++env;
93 if (*env == '\0')
94 return;
95 if (*env++ != ',')
96 goto unknown;
97 while (isspace ((unsigned char) *env))
98 ++env;
99 if (*env == '\0')
100 goto invalid;
102 errno = 0;
103 value = strtoul (env, &end, 10);
104 if (errno)
105 goto invalid;
107 while (isspace ((unsigned char) *end))
108 ++end;
109 if (*end != '\0')
110 goto invalid;
112 gomp_run_sched_chunk = value;
113 return;
115 unknown:
116 gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
117 return;
119 invalid:
120 gomp_error ("Invalid value for chunk size in "
121 "environment variable OMP_SCHEDULE");
122 return;
125 /* Parse an unsigned long environment varible. Return true if one was
126 present and it was successfully parsed. */
128 static bool
129 parse_unsigned_long (const char *name, unsigned long *pvalue)
131 char *env, *end;
132 unsigned long value;
134 env = getenv (name);
135 if (env == NULL)
136 return false;
138 while (isspace ((unsigned char) *env))
139 ++env;
140 if (*env == '\0')
141 goto invalid;
143 errno = 0;
144 value = strtoul (env, &end, 10);
145 if (errno || (long) value <= 0)
146 goto invalid;
148 while (isspace ((unsigned char) *end))
149 ++end;
150 if (*end != '\0')
151 goto invalid;
153 *pvalue = value;
154 return true;
156 invalid:
157 gomp_error ("Invalid value for environment variable %s", name);
158 return false;
161 /* Parse a boolean value for environment variable NAME and store the
162 result in VALUE. */
164 static void
165 parse_boolean (const char *name, bool *value)
167 const char *env;
169 env = getenv (name);
170 if (env == NULL)
171 return;
173 while (isspace ((unsigned char) *env))
174 ++env;
175 if (strncasecmp (env, "true", 4) == 0)
177 *value = true;
178 env += 4;
180 else if (strncasecmp (env, "false", 5) == 0)
182 *value = false;
183 env += 5;
185 else
186 env = "X";
187 while (isspace ((unsigned char) *env))
188 ++env;
189 if (*env != '\0')
190 gomp_error ("Invalid value for environment variable %s", name);
193 /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
194 present and it was successfully parsed. */
196 static bool
197 parse_affinity (void)
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;
204 env = getenv ("GOMP_CPU_AFFINITY");
205 if (env == NULL)
206 return false;
210 while (*env == ' ' || *env == '\t')
211 env++;
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;
219 env = end;
220 if (*env == '-')
222 cpu_end = strtoul (++env, &end, 0);
223 if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
224 goto invalid;
226 env = end;
227 if (*env == ':')
229 cpu_stride = strtoul (++env, &end, 0);
230 if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
231 goto invalid;
233 env = end;
237 needed = (cpu_end - cpu_beg) / cpu_stride + 1;
238 if (used + needed >= allocated)
240 unsigned short *new_cpus;
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)
251 free (cpus);
252 gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
253 return false;
256 cpus = new_cpus;
259 while (needed--)
261 cpus[used++] = cpu_beg;
262 cpu_beg += cpu_stride;
265 while (*env == ' ' || *env == '\t')
266 env++;
268 if (*env == ',')
269 env++;
270 else if (*env == '\0')
271 break;
273 while (1);
275 gomp_cpu_affinity = cpus;
276 gomp_cpu_affinity_len = used;
277 return true;
279 invalid:
280 gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
281 return false;
284 static void __attribute__((constructor))
285 initialize_env (void)
287 unsigned long stacksize;
289 /* Do a compile time check that mkomp_h.pl did good job. */
290 omp_check_defines ();
292 parse_schedule ();
293 parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var);
294 parse_boolean ("OMP_NESTED", &gomp_nest_var);
295 if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var))
296 gomp_init_num_threads ();
297 if (parse_affinity ())
298 gomp_init_affinity ();
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);
304 if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize))
306 int err;
308 stacksize *= 1024;
309 err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
311 #ifdef PTHREAD_STACK_MIN
312 if (err == EINVAL)
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
319 gomp_error ("Stack size larger than system limit");
321 else
322 #endif
323 if (err != 0)
324 gomp_error ("Stack size change failed: %s", strerror (err));
329 /* The public OpenMP API routines that access these variables. */
331 void
332 omp_set_num_threads (int n)
334 gomp_nthreads_var = (n > 0 ? n : 1);
337 void
338 omp_set_dynamic (int val)
340 gomp_dyn_var = val;
344 omp_get_dynamic (void)
346 return gomp_dyn_var;
349 void
350 omp_set_nested (int val)
352 gomp_nest_var = val;
356 omp_get_nested (void)
358 return gomp_nest_var;
361 ialias (omp_set_dynamic)
362 ialias (omp_set_nested)
363 ialias (omp_set_num_threads)
364 ialias (omp_get_dynamic)
365 ialias (omp_get_nested)