1169695Skan/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. 2169695Skan Contributed by Richard Henderson <rth@redhat.com>. 3169695Skan 4169695Skan This file is part of the GNU OpenMP Library (libgomp). 5169695Skan 6169695Skan Libgomp is free software; you can redistribute it and/or modify it 7169695Skan under the terms of the GNU Lesser General Public License as published by 8169695Skan the Free Software Foundation; either version 2.1 of the License, or 9169695Skan (at your option) any later version. 10169695Skan 11169695Skan Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY 12169695Skan WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13169695Skan FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 14169695Skan more details. 15169695Skan 16169695Skan You should have received a copy of the GNU Lesser General Public License 17169695Skan along with libgomp; see the file COPYING.LIB. If not, write to the 18169695Skan Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19169695Skan MA 02110-1301, USA. */ 20169695Skan 21169695Skan/* As a special exception, if you link this library with other files, some 22169695Skan of which are compiled with GCC, to produce an executable, this library 23169695Skan does not by itself cause the resulting executable to be covered by the 24169695Skan GNU General Public License. This exception does not however invalidate 25169695Skan any other reasons why the executable file might be covered by the GNU 26169695Skan General Public License. */ 27169695Skan 28169695Skan/* This file defines the OpenMP internal control variables, and arranges 29169695Skan for them to be initialized from environment variables at startup. */ 30169695Skan 31169695Skan#include "libgomp.h" 32169695Skan#include "libgomp_f.h" 33169695Skan#include <ctype.h> 34169695Skan#include <stdlib.h> 35169695Skan#include <string.h> 36169695Skan#include <limits.h> 37169695Skan#include <errno.h> 38169695Skan 39169695Skan 40169695Skanunsigned long gomp_nthreads_var = 1; 41169695Skanbool gomp_dyn_var = false; 42169695Skanbool gomp_nest_var = false; 43169695Skanenum gomp_schedule_type gomp_run_sched_var = GFS_DYNAMIC; 44169695Skanunsigned long gomp_run_sched_chunk = 1; 45169695Skan 46169695Skan/* Parse the OMP_SCHEDULE environment variable. */ 47169695Skan 48169695Skanstatic void 49169695Skanparse_schedule (void) 50169695Skan{ 51169695Skan char *env, *end; 52169695Skan unsigned long value; 53169695Skan 54169695Skan env = getenv ("OMP_SCHEDULE"); 55169695Skan if (env == NULL) 56169695Skan return; 57169695Skan 58169695Skan while (isspace ((unsigned char) *env)) 59169695Skan ++env; 60169695Skan if (strncasecmp (env, "static", 6) == 0) 61169695Skan { 62169695Skan gomp_run_sched_var = GFS_STATIC; 63169695Skan env += 6; 64169695Skan } 65169695Skan else if (strncasecmp (env, "dynamic", 7) == 0) 66169695Skan { 67169695Skan gomp_run_sched_var = GFS_DYNAMIC; 68169695Skan env += 7; 69169695Skan } 70169695Skan else if (strncasecmp (env, "guided", 6) == 0) 71169695Skan { 72169695Skan gomp_run_sched_var = GFS_GUIDED; 73169695Skan env += 6; 74169695Skan } 75169695Skan else 76169695Skan goto unknown; 77169695Skan 78169695Skan while (isspace ((unsigned char) *env)) 79169695Skan ++env; 80169695Skan if (*env == '\0') 81169695Skan return; 82169695Skan if (*env++ != ',') 83169695Skan goto unknown; 84169695Skan while (isspace ((unsigned char) *env)) 85169695Skan ++env; 86169695Skan if (*env == '\0') 87169695Skan goto invalid; 88169695Skan 89169695Skan errno = 0; 90169695Skan value = strtoul (env, &end, 10); 91169695Skan if (errno) 92169695Skan goto invalid; 93169695Skan 94169695Skan while (isspace ((unsigned char) *end)) 95169695Skan ++end; 96169695Skan if (*end != '\0') 97169695Skan goto invalid; 98169695Skan 99169695Skan gomp_run_sched_chunk = value; 100169695Skan return; 101169695Skan 102169695Skan unknown: 103169695Skan gomp_error ("Unknown value for environment variable OMP_SCHEDULE"); 104169695Skan return; 105169695Skan 106169695Skan invalid: 107169695Skan gomp_error ("Invalid value for chunk size in " 108169695Skan "environment variable OMP_SCHEDULE"); 109169695Skan return; 110169695Skan} 111169695Skan 112169695Skan/* Parse an unsigned long environment varible. Return true if one was 113169695Skan present and it was successfully parsed. */ 114169695Skan 115169695Skanstatic bool 116169695Skanparse_unsigned_long (const char *name, unsigned long *pvalue) 117169695Skan{ 118169695Skan char *env, *end; 119169695Skan unsigned long value; 120169695Skan 121169695Skan env = getenv (name); 122169695Skan if (env == NULL) 123169695Skan return false; 124169695Skan 125169695Skan while (isspace ((unsigned char) *env)) 126169695Skan ++env; 127169695Skan if (*env == '\0') 128169695Skan goto invalid; 129169695Skan 130169695Skan errno = 0; 131169695Skan value = strtoul (env, &end, 10); 132169695Skan if (errno || (long) value <= 0) 133169695Skan goto invalid; 134169695Skan 135169695Skan while (isspace ((unsigned char) *end)) 136169695Skan ++end; 137169695Skan if (*end != '\0') 138169695Skan goto invalid; 139169695Skan 140169695Skan *pvalue = value; 141169695Skan return true; 142169695Skan 143169695Skan invalid: 144169695Skan gomp_error ("Invalid value for environment variable %s", name); 145169695Skan return false; 146169695Skan} 147169695Skan 148169695Skan/* Parse a boolean value for environment variable NAME and store the 149169695Skan result in VALUE. */ 150169695Skan 151169695Skanstatic void 152169695Skanparse_boolean (const char *name, bool *value) 153169695Skan{ 154169695Skan const char *env; 155169695Skan 156169695Skan env = getenv (name); 157169695Skan if (env == NULL) 158169695Skan return; 159169695Skan 160169695Skan while (isspace ((unsigned char) *env)) 161169695Skan ++env; 162169695Skan if (strncasecmp (env, "true", 4) == 0) 163169695Skan { 164169695Skan *value = true; 165169695Skan env += 4; 166169695Skan } 167169695Skan else if (strncasecmp (env, "false", 5) == 0) 168169695Skan { 169169695Skan *value = false; 170169695Skan env += 5; 171169695Skan } 172169695Skan else 173169695Skan env = "X"; 174169695Skan while (isspace ((unsigned char) *env)) 175169695Skan ++env; 176169695Skan if (*env != '\0') 177169695Skan gomp_error ("Invalid value for environment variable %s", name); 178169695Skan} 179169695Skan 180169695Skanstatic void __attribute__((constructor)) 181169695Skaninitialize_env (void) 182169695Skan{ 183169695Skan unsigned long stacksize; 184169695Skan 185169695Skan /* Do a compile time check that mkomp_h.pl did good job. */ 186169695Skan omp_check_defines (); 187169695Skan 188169695Skan parse_schedule (); 189169695Skan parse_boolean ("OMP_DYNAMIC", &gomp_dyn_var); 190169695Skan parse_boolean ("OMP_NESTED", &gomp_nest_var); 191169695Skan if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_nthreads_var)) 192169695Skan gomp_init_num_threads (); 193169695Skan 194169695Skan /* Not strictly environment related, but ordering constructors is tricky. */ 195169695Skan pthread_attr_init (&gomp_thread_attr); 196169695Skan pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED); 197169695Skan 198169695Skan if (parse_unsigned_long ("GOMP_STACKSIZE", &stacksize)) 199169695Skan { 200169695Skan int err; 201169695Skan 202169695Skan stacksize *= 1024; 203169695Skan err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize); 204169695Skan 205169695Skan#ifdef PTHREAD_STACK_MIN 206169695Skan if (err == EINVAL) 207169695Skan { 208169695Skan if (stacksize < PTHREAD_STACK_MIN) 209169695Skan gomp_error ("Stack size less than minimum of %luk", 210169695Skan PTHREAD_STACK_MIN / 1024ul 211169695Skan + (PTHREAD_STACK_MIN % 1024 != 0)); 212169695Skan else 213169695Skan gomp_error ("Stack size larger than system limit"); 214169695Skan } 215169695Skan else 216169695Skan#endif 217169695Skan if (err != 0) 218169695Skan gomp_error ("Stack size change failed: %s", strerror (err)); 219169695Skan } 220169695Skan} 221169695Skan 222169695Skan 223169695Skan/* The public OpenMP API routines that access these variables. */ 224169695Skan 225169695Skanvoid 226169695Skanomp_set_num_threads (int n) 227169695Skan{ 228169695Skan gomp_nthreads_var = (n > 0 ? n : 1); 229169695Skan} 230169695Skan 231169695Skanvoid 232169695Skanomp_set_dynamic (int val) 233169695Skan{ 234169695Skan gomp_dyn_var = val; 235169695Skan} 236169695Skan 237169695Skanint 238169695Skanomp_get_dynamic (void) 239169695Skan{ 240169695Skan return gomp_dyn_var; 241169695Skan} 242169695Skan 243169695Skanvoid 244169695Skanomp_set_nested (int val) 245169695Skan{ 246169695Skan gomp_nest_var = val; 247169695Skan} 248169695Skan 249169695Skanint 250169695Skanomp_get_nested (void) 251169695Skan{ 252169695Skan return gomp_nest_var; 253169695Skan} 254169695Skan 255169695Skanialias (omp_set_dynamic) 256169695Skanialias (omp_set_nested) 257169695Skanialias (omp_set_num_threads) 258169695Skanialias (omp_get_dynamic) 259169695Skanialias (omp_get_nested) 260