OSDN Git Service

PR libgomp/29949
[pf3gnuchains/gcc-fork.git] / libgomp / env.c
1 /* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
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"
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <limits.h>
37 #include <errno.h>
38
39
40 unsigned long gomp_nthreads_var = 1;
41 bool gomp_dyn_var = false;
42 bool gomp_nest_var = false;
43 enum gomp_schedule_type gomp_run_sched_var = GFS_DYNAMIC;
44 unsigned long gomp_run_sched_chunk = 1;
45
46 /* Parse the OMP_SCHEDULE environment variable.  */
47
48 static void
49 parse_schedule (void)
50 {
51   char *env, *end;
52   unsigned long value;
53
54   env = getenv ("OMP_SCHEDULE");
55   if (env == NULL)
56     return;
57
58   while (isspace ((unsigned char) *env))
59     ++env;
60   if (strncasecmp (env, "static", 6) == 0)
61     {
62       gomp_run_sched_var = GFS_STATIC;
63       env += 6;
64     }
65   else if (strncasecmp (env, "dynamic", 7) == 0)
66     {
67       gomp_run_sched_var = GFS_DYNAMIC;
68       env += 7;
69     }
70   else if (strncasecmp (env, "guided", 6) == 0)
71     {
72       gomp_run_sched_var = GFS_GUIDED;
73       env += 6;
74     }
75   else
76     goto unknown;
77
78   while (isspace ((unsigned char) *env))
79     ++env;
80   if (*env == '\0')
81     return;
82   if (*env++ != ',')
83     goto unknown;
84   while (isspace ((unsigned char) *env))
85     ++env;
86   if (*env == '\0')
87     goto invalid;
88
89   errno = 0;
90   value = strtoul (env, &end, 10);
91   if (errno)
92     goto invalid;
93
94   while (isspace ((unsigned char) *end))
95     ++end;
96   if (*end != '\0')
97     goto invalid;
98
99   gomp_run_sched_chunk = value;
100   return;
101
102  unknown:
103   gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
104   return;
105
106  invalid:
107   gomp_error ("Invalid value for chunk size in "
108               "environment variable OMP_SCHEDULE");
109   return;
110 }
111
112 /* Parse an unsigned long environment varible.  Return true if one was
113    present and it was successfully parsed.  */
114
115 static bool
116 parse_unsigned_long (const char *name, unsigned long *pvalue)
117 {
118   char *env, *end;
119   unsigned long value;
120
121   env = getenv (name);
122   if (env == NULL)
123     return false;
124
125   while (isspace ((unsigned char) *env))
126     ++env;
127   if (*env == '\0')
128     goto invalid;
129
130   errno = 0;
131   value = strtoul (env, &end, 10);
132   if (errno || (long) value <= 0)
133     goto invalid;
134
135   while (isspace ((unsigned char) *end))
136     ++end;
137   if (*end != '\0')
138     goto invalid;
139
140   *pvalue = value;
141   return true;
142
143  invalid:
144   gomp_error ("Invalid value for environment variable %s", name);
145   return false;
146 }
147
148 /* Parse a boolean value for environment variable NAME and store the 
149    result in VALUE.  */
150
151 static void
152 parse_boolean (const char *name, bool *value)
153 {
154   const char *env;
155
156   env = getenv (name);
157   if (env == NULL)
158     return;
159
160   while (isspace ((unsigned char) *env))
161     ++env;
162   if (strncasecmp (env, "true", 4) == 0)
163     {
164       *value = true;
165       env += 4;
166     }
167   else if (strncasecmp (env, "false", 5) == 0)
168     {
169       *value = false;
170       env += 5;
171     }
172   else
173     env = "X";
174   while (isspace ((unsigned char) *env))
175     ++env;
176   if (*env != '\0')
177     gomp_error ("Invalid value for environment variable %s", name);
178 }
179
180 static void __attribute__((constructor))
181 initialize_env (void)
182 {
183   unsigned long stacksize;
184
185   /* Do a compile time check that mkomp_h.pl did good job.  */
186   omp_check_defines ();
187
188   parse_schedule ();
189   parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var);
190   parse_boolean ("OMP_NESTED", &gomp_nest_var);
191   if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var))
192     gomp_init_num_threads ();
193
194   /* Not strictly environment related, but ordering constructors is tricky.  */
195   pthread_attr_init (&gomp_thread_attr);
196   pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
197
198   if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize))
199     {
200       int err;
201
202       stacksize *= 1024;
203       err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
204
205 #ifdef PTHREAD_STACK_MIN
206       if (err == EINVAL)
207         {
208           if (stacksize < PTHREAD_STACK_MIN)
209             gomp_error ("Stack size less than minimum of %luk",
210                         PTHREAD_STACK_MIN / 1024ul
211                         + (PTHREAD_STACK_MIN % 1024 != 0));
212           else
213             gomp_error ("Stack size larger than system limit");
214         }
215       else
216 #endif
217       if (err != 0)
218         gomp_error ("Stack size change failed: %s", strerror (err));
219     }
220 }
221
222 \f
223 /* The public OpenMP API routines that access these variables.  */
224
225 void
226 omp_set_num_threads (int n)
227 {
228   gomp_nthreads_var = (n > 0 ? n : 1);
229 }
230
231 void
232 omp_set_dynamic (int val)
233 {
234   gomp_dyn_var = val;
235 }
236
237 int
238 omp_get_dynamic (void)
239 {
240   return gomp_dyn_var;
241 }
242
243 void
244 omp_set_nested (int val)
245 {
246   gomp_nest_var = val;
247 }
248
249 int
250 omp_get_nested (void)
251 {
252   return gomp_nest_var;
253 }
254
255 ialias (omp_set_dynamic)
256 ialias (omp_set_nested)
257 ialias (omp_set_num_threads)
258 ialias (omp_get_dynamic)
259 ialias (omp_get_nested)