OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libgomp/] [env.c] - Blame information for rev 861

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 273 jeremybenn
/* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
2
   Free Software Foundation, Inc.
3
   Contributed by Richard Henderson <rth@redhat.com>.
4
 
5
   This file is part of the GNU OpenMP Library (libgomp).
6
 
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)
10
   any later version.
11
 
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
15
   more details.
16
 
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.
20
 
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/>.  */
25
 
26
/* This file defines the OpenMP internal control variables, and arranges
27
   for them to be initialized from environment variables at startup.  */
28
 
29
#include "libgomp.h"
30
#include "libgomp_f.h"
31
#include <ctype.h>
32
#include <stdlib.h>
33
#ifdef STRING_WITH_STRINGS
34
# include <string.h>
35
# include <strings.h>
36
#else
37
# ifdef HAVE_STRING_H
38
#  include <string.h>
39
# else
40
#  ifdef HAVE_STRINGS_H
41
#   include <strings.h>
42
#  endif
43
# endif
44
#endif
45
#include <limits.h>
46
#include <errno.h>
47
 
48
#ifndef HAVE_STRTOULL
49
# define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
50
#endif
51
 
52
struct gomp_task_icv gomp_global_icv = {
53
  .nthreads_var = 1,
54
  .run_sched_var = GFS_DYNAMIC,
55
  .run_sched_modifier = 1,
56
  .dyn_var = false,
57
  .nest_var = false
58
};
59
 
60
unsigned short *gomp_cpu_affinity;
61
size_t gomp_cpu_affinity_len;
62
unsigned long gomp_max_active_levels_var = INT_MAX;
63
unsigned long gomp_thread_limit_var = ULONG_MAX;
64
unsigned long gomp_remaining_threads_count;
65
#ifndef HAVE_SYNC_BUILTINS
66
gomp_mutex_t gomp_remaining_threads_lock;
67
#endif
68
unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
69
unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
70
 
71
/* Parse the OMP_SCHEDULE environment variable.  */
72
 
73
static void
74
parse_schedule (void)
75
{
76
  char *env, *end;
77
  unsigned long value;
78
 
79
  env = getenv ("OMP_SCHEDULE");
80
  if (env == NULL)
81
    return;
82
 
83
  while (isspace ((unsigned char) *env))
84
    ++env;
85
  if (strncasecmp (env, "static", 6) == 0)
86
    {
87
      gomp_global_icv.run_sched_var = GFS_STATIC;
88
      env += 6;
89
    }
90
  else if (strncasecmp (env, "dynamic", 7) == 0)
91
    {
92
      gomp_global_icv.run_sched_var = GFS_DYNAMIC;
93
      env += 7;
94
    }
95
  else if (strncasecmp (env, "guided", 6) == 0)
96
    {
97
      gomp_global_icv.run_sched_var = GFS_GUIDED;
98
      env += 6;
99
    }
100
  else if (strncasecmp (env, "auto", 4) == 0)
101
    {
102
      gomp_global_icv.run_sched_var = GFS_AUTO;
103
      env += 4;
104
    }
105
  else
106
    goto unknown;
107
 
108
  while (isspace ((unsigned char) *env))
109
    ++env;
110
  if (*env == '\0')
111
    return;
112
  if (*env++ != ',')
113
    goto unknown;
114
  while (isspace ((unsigned char) *env))
115
    ++env;
116
  if (*env == '\0')
117
    goto invalid;
118
 
119
  errno = 0;
120
  value = strtoul (env, &end, 10);
121
  if (errno)
122
    goto invalid;
123
 
124
  while (isspace ((unsigned char) *end))
125
    ++end;
126
  if (*end != '\0')
127
    goto invalid;
128
 
129
  if ((int)value != value)
130
    goto invalid;
131
 
132
  gomp_global_icv.run_sched_modifier = value;
133
  return;
134
 
135
 unknown:
136
  gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
137
  return;
138
 
139
 invalid:
140
  gomp_error ("Invalid value for chunk size in "
141
              "environment variable OMP_SCHEDULE");
142
  return;
143
}
144
 
145
/* Parse an unsigned long environment variable.  Return true if one was
146
   present and it was successfully parsed.  */
147
 
148
static bool
149
parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
150
{
151
  char *env, *end;
152
  unsigned long value;
153
 
154
  env = getenv (name);
155
  if (env == NULL)
156
    return false;
157
 
158
  while (isspace ((unsigned char) *env))
159
    ++env;
160
  if (*env == '\0')
161
    goto invalid;
162
 
163
  errno = 0;
164
  value = strtoul (env, &end, 10);
165
  if (errno || (long) value <= 0 - allow_zero)
166
    goto invalid;
167
 
168
  while (isspace ((unsigned char) *end))
169
    ++end;
170
  if (*end != '\0')
171
    goto invalid;
172
 
173
  *pvalue = value;
174
  return true;
175
 
176
 invalid:
177
  gomp_error ("Invalid value for environment variable %s", name);
178
  return false;
179
}
180
 
181
/* Parse the OMP_STACKSIZE environment varible.  Return true if one was
182
   present and it was successfully parsed.  */
183
 
184
static bool
185
parse_stacksize (const char *name, unsigned long *pvalue)
186
{
187
  char *env, *end;
188
  unsigned long value, shift = 10;
189
 
190
  env = getenv (name);
191
  if (env == NULL)
192
    return false;
193
 
194
  while (isspace ((unsigned char) *env))
195
    ++env;
196
  if (*env == '\0')
197
    goto invalid;
198
 
199
  errno = 0;
200
  value = strtoul (env, &end, 10);
201
  if (errno)
202
    goto invalid;
203
 
204
  while (isspace ((unsigned char) *end))
205
    ++end;
206
  if (*end != '\0')
207
    {
208
      switch (tolower ((unsigned char) *end))
209
        {
210
        case 'b':
211
          shift = 0;
212
          break;
213
        case 'k':
214
          break;
215
        case 'm':
216
          shift = 20;
217
          break;
218
        case 'g':
219
          shift = 30;
220
          break;
221
        default:
222
          goto invalid;
223
        }
224
      ++end;
225
      while (isspace ((unsigned char) *end))
226
        ++end;
227
      if (*end != '\0')
228
        goto invalid;
229
    }
230
 
231
  if (((value << shift) >> shift) != value)
232
    goto invalid;
233
 
234
  *pvalue = value << shift;
235
  return true;
236
 
237
 invalid:
238
  gomp_error ("Invalid value for environment variable %s", name);
239
  return false;
240
}
241
 
242
/* Parse the GOMP_SPINCOUNT environment varible.  Return true if one was
243
   present and it was successfully parsed.  */
244
 
245
static bool
246
parse_spincount (const char *name, unsigned long long *pvalue)
247
{
248
  char *env, *end;
249
  unsigned long long value, mult = 1;
250
 
251
  env = getenv (name);
252
  if (env == NULL)
253
    return false;
254
 
255
  while (isspace ((unsigned char) *env))
256
    ++env;
257
  if (*env == '\0')
258
    goto invalid;
259
 
260
  if (strncasecmp (env, "infinite", 8) == 0
261
      || strncasecmp (env, "infinity", 8) == 0)
262
    {
263
      value = ~0ULL;
264
      end = env + 8;
265
      goto check_tail;
266
    }
267
 
268
  errno = 0;
269
  value = strtoull (env, &end, 10);
270
  if (errno)
271
    goto invalid;
272
 
273
  while (isspace ((unsigned char) *end))
274
    ++end;
275
  if (*end != '\0')
276
    {
277
      switch (tolower ((unsigned char) *end))
278
        {
279
        case 'k':
280
          mult = 1000LL;
281
          break;
282
        case 'm':
283
          mult = 1000LL * 1000LL;
284
          break;
285
        case 'g':
286
          mult = 1000LL * 1000LL * 1000LL;
287
          break;
288
        case 't':
289
          mult = 1000LL * 1000LL * 1000LL * 1000LL;
290
          break;
291
        default:
292
          goto invalid;
293
        }
294
      ++end;
295
     check_tail:
296
      while (isspace ((unsigned char) *end))
297
        ++end;
298
      if (*end != '\0')
299
        goto invalid;
300
    }
301
 
302
  if (value > ~0ULL / mult)
303
    value = ~0ULL;
304
  else
305
    value *= mult;
306
 
307
  *pvalue = value;
308
  return true;
309
 
310
 invalid:
311
  gomp_error ("Invalid value for environment variable %s", name);
312
  return false;
313
}
314
 
315
/* Parse a boolean value for environment variable NAME and store the
316
   result in VALUE.  */
317
 
318
static void
319
parse_boolean (const char *name, bool *value)
320
{
321
  const char *env;
322
 
323
  env = getenv (name);
324
  if (env == NULL)
325
    return;
326
 
327
  while (isspace ((unsigned char) *env))
328
    ++env;
329
  if (strncasecmp (env, "true", 4) == 0)
330
    {
331
      *value = true;
332
      env += 4;
333
    }
334
  else if (strncasecmp (env, "false", 5) == 0)
335
    {
336
      *value = false;
337
      env += 5;
338
    }
339
  else
340
    env = "X";
341
  while (isspace ((unsigned char) *env))
342
    ++env;
343
  if (*env != '\0')
344
    gomp_error ("Invalid value for environment variable %s", name);
345
}
346
 
347
/* Parse the OMP_WAIT_POLICY environment variable and store the
348
   result in gomp_active_wait_policy.  */
349
 
350
static int
351
parse_wait_policy (void)
352
{
353
  const char *env;
354
  int ret = -1;
355
 
356
  env = getenv ("OMP_WAIT_POLICY");
357
  if (env == NULL)
358
    return -1;
359
 
360
  while (isspace ((unsigned char) *env))
361
    ++env;
362
  if (strncasecmp (env, "active", 6) == 0)
363
    {
364
      ret = 1;
365
      env += 6;
366
    }
367
  else if (strncasecmp (env, "passive", 7) == 0)
368
    {
369
      ret = 0;
370
      env += 7;
371
    }
372
  else
373
    env = "X";
374
  while (isspace ((unsigned char) *env))
375
    ++env;
376
  if (*env == '\0')
377
    return ret;
378
  gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
379
  return -1;
380
}
381
 
382
/* Parse the GOMP_CPU_AFFINITY environment varible.  Return true if one was
383
   present and it was successfully parsed.  */
384
 
385
static bool
386
parse_affinity (void)
387
{
388
  char *env, *end;
389
  unsigned long cpu_beg, cpu_end, cpu_stride;
390
  unsigned short *cpus = NULL;
391
  size_t allocated = 0, used = 0, needed;
392
 
393
  env = getenv ("GOMP_CPU_AFFINITY");
394
  if (env == NULL)
395
    return false;
396
 
397
  do
398
    {
399
      while (*env == ' ' || *env == '\t')
400
        env++;
401
 
402
      cpu_beg = strtoul (env, &end, 0);
403
      cpu_end = cpu_beg;
404
      cpu_stride = 1;
405
      if (env == end || cpu_beg >= 65536)
406
        goto invalid;
407
 
408
      env = end;
409
      if (*env == '-')
410
        {
411
          cpu_end = strtoul (++env, &end, 0);
412
          if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
413
            goto invalid;
414
 
415
          env = end;
416
          if (*env == ':')
417
            {
418
              cpu_stride = strtoul (++env, &end, 0);
419
              if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
420
                goto invalid;
421
 
422
              env = end;
423
            }
424
        }
425
 
426
      needed = (cpu_end - cpu_beg) / cpu_stride + 1;
427
      if (used + needed >= allocated)
428
        {
429
          unsigned short *new_cpus;
430
 
431
          if (allocated < 64)
432
            allocated = 64;
433
          if (allocated > needed)
434
            allocated <<= 1;
435
          else
436
            allocated += 2 * needed;
437
          new_cpus = realloc (cpus, allocated * sizeof (unsigned short));
438
          if (new_cpus == NULL)
439
            {
440
              free (cpus);
441
              gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
442
              return false;
443
            }
444
 
445
          cpus = new_cpus;
446
        }
447
 
448
      while (needed--)
449
        {
450
          cpus[used++] = cpu_beg;
451
          cpu_beg += cpu_stride;
452
        }
453
 
454
      while (*env == ' ' || *env == '\t')
455
        env++;
456
 
457
      if (*env == ',')
458
        env++;
459
      else if (*env == '\0')
460
        break;
461
    }
462
  while (1);
463
 
464
  gomp_cpu_affinity = cpus;
465
  gomp_cpu_affinity_len = used;
466
  return true;
467
 
468
 invalid:
469
  gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
470
  return false;
471
}
472
 
473
static void __attribute__((constructor))
474
initialize_env (void)
475
{
476
  unsigned long stacksize;
477
  int wait_policy;
478
 
479
  /* Do a compile time check that mkomp_h.pl did good job.  */
480
  omp_check_defines ();
481
 
482
  parse_schedule ();
483
  parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
484
  parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
485
  parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
486
                       true);
487
  parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
488
  if (gomp_thread_limit_var != ULONG_MAX)
489
    gomp_remaining_threads_count = gomp_thread_limit_var - 1;
490
#ifndef HAVE_SYNC_BUILTINS
491
  gomp_mutex_init (&gomp_remaining_threads_lock);
492
#endif
493
  gomp_init_num_threads ();
494
  gomp_available_cpus = gomp_global_icv.nthreads_var;
495
  if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_global_icv.nthreads_var,
496
                            false))
497
    gomp_global_icv.nthreads_var = gomp_available_cpus;
498
  if (parse_affinity ())
499
    gomp_init_affinity ();
500
  wait_policy = parse_wait_policy ();
501
  if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
502
    {
503
      /* Using a rough estimation of 100000 spins per msec,
504
         use 5 min blocking for OMP_WAIT_POLICY=active,
505
         200 msec blocking when OMP_WAIT_POLICY is not specificed
506
         and 0 when OMP_WAIT_POLICY=passive.
507
         Depending on the CPU speed, this can be e.g. 5 times longer
508
         or 5 times shorter.  */
509
      if (wait_policy > 0)
510
        gomp_spin_count_var = 30000000000LL;
511
      else if (wait_policy < 0)
512
        gomp_spin_count_var = 20000000LL;
513
    }
514
  /* gomp_throttled_spin_count_var is used when there are more libgomp
515
     managed threads than available CPUs.  Use very short spinning.  */
516
  if (wait_policy > 0)
517
    gomp_throttled_spin_count_var = 1000LL;
518
  else if (wait_policy < 0)
519
    gomp_throttled_spin_count_var = 100LL;
520
  if (gomp_throttled_spin_count_var > gomp_spin_count_var)
521
    gomp_throttled_spin_count_var = gomp_spin_count_var;
522
 
523
  /* Not strictly environment related, but ordering constructors is tricky.  */
524
  pthread_attr_init (&gomp_thread_attr);
525
  pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
526
 
527
  if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
528
      || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
529
    {
530
      int err;
531
 
532
      err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
533
 
534
#ifdef PTHREAD_STACK_MIN
535
      if (err == EINVAL)
536
        {
537
          if (stacksize < PTHREAD_STACK_MIN)
538
            gomp_error ("Stack size less than minimum of %luk",
539
                        PTHREAD_STACK_MIN / 1024ul
540
                        + (PTHREAD_STACK_MIN % 1024 != 0));
541
          else
542
            gomp_error ("Stack size larger than system limit");
543
        }
544
      else
545
#endif
546
      if (err != 0)
547
        gomp_error ("Stack size change failed: %s", strerror (err));
548
    }
549
}
550
 
551
 
552
/* The public OpenMP API routines that access these variables.  */
553
 
554
void
555
omp_set_num_threads (int n)
556
{
557
  struct gomp_task_icv *icv = gomp_icv (true);
558
  icv->nthreads_var = (n > 0 ? n : 1);
559
}
560
 
561
void
562
omp_set_dynamic (int val)
563
{
564
  struct gomp_task_icv *icv = gomp_icv (true);
565
  icv->dyn_var = val;
566
}
567
 
568
int
569
omp_get_dynamic (void)
570
{
571
  struct gomp_task_icv *icv = gomp_icv (false);
572
  return icv->dyn_var;
573
}
574
 
575
void
576
omp_set_nested (int val)
577
{
578
  struct gomp_task_icv *icv = gomp_icv (true);
579
  icv->nest_var = val;
580
}
581
 
582
int
583
omp_get_nested (void)
584
{
585
  struct gomp_task_icv *icv = gomp_icv (false);
586
  return icv->nest_var;
587
}
588
 
589
void
590
omp_set_schedule (omp_sched_t kind, int modifier)
591
{
592
  struct gomp_task_icv *icv = gomp_icv (true);
593
  switch (kind)
594
    {
595
    case omp_sched_static:
596
      if (modifier < 1)
597
        modifier = 0;
598
      icv->run_sched_modifier = modifier;
599
      break;
600
    case omp_sched_dynamic:
601
    case omp_sched_guided:
602
      if (modifier < 1)
603
        modifier = 1;
604
      icv->run_sched_modifier = modifier;
605
      break;
606
    case omp_sched_auto:
607
      break;
608
    default:
609
      return;
610
    }
611
  icv->run_sched_var = kind;
612
}
613
 
614
void
615
omp_get_schedule (omp_sched_t *kind, int *modifier)
616
{
617
  struct gomp_task_icv *icv = gomp_icv (false);
618
  *kind = icv->run_sched_var;
619
  *modifier = icv->run_sched_modifier;
620
}
621
 
622
int
623
omp_get_max_threads (void)
624
{
625
  struct gomp_task_icv *icv = gomp_icv (false);
626
  return icv->nthreads_var;
627
}
628
 
629
int
630
omp_get_thread_limit (void)
631
{
632
  return gomp_thread_limit_var > INT_MAX ? INT_MAX : gomp_thread_limit_var;
633
}
634
 
635
void
636
omp_set_max_active_levels (int max_levels)
637
{
638
  if (max_levels >= 0)
639
    gomp_max_active_levels_var = max_levels;
640
}
641
 
642
int
643
omp_get_max_active_levels (void)
644
{
645
  return gomp_max_active_levels_var;
646
}
647
 
648
ialias (omp_set_dynamic)
649
ialias (omp_set_nested)
650
ialias (omp_set_num_threads)
651
ialias (omp_get_dynamic)
652
ialias (omp_get_nested)
653
ialias (omp_set_schedule)
654
ialias (omp_get_schedule)
655
ialias (omp_get_max_threads)
656
ialias (omp_get_thread_limit)
657
ialias (omp_set_max_active_levels)
658
ialias (omp_get_max_active_levels)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.