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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgomp/] [env.c] - Blame information for rev 834

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

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