env.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. /* Copyright (C) 2005-2015 Free Software Foundation, Inc.
  2. Contributed by Richard Henderson <rth@redhat.com>.
  3. This file is part of the GNU Offloading and Multi Processing Library
  4. (libgomp).
  5. Libgomp is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. /* This file defines the OpenMP internal control variables, and arranges
  21. for them to be initialized from environment variables at startup. */
  22. #include "libgomp.h"
  23. #include "libgomp_f.h"
  24. #include "oacc-int.h"
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #ifdef HAVE_INTTYPES_H
  29. # include <inttypes.h> /* For PRIu64. */
  30. #endif
  31. #ifdef STRING_WITH_STRINGS
  32. # include <string.h>
  33. # include <strings.h>
  34. #else
  35. # ifdef HAVE_STRING_H
  36. # include <string.h>
  37. # else
  38. # ifdef HAVE_STRINGS_H
  39. # include <strings.h>
  40. # endif
  41. # endif
  42. #endif
  43. #include <limits.h>
  44. #include <errno.h>
  45. #ifndef HAVE_STRTOULL
  46. # define strtoull(ptr, eptr, base) strtoul (ptr, eptr, base)
  47. #endif
  48. struct gomp_task_icv gomp_global_icv = {
  49. .nthreads_var = 1,
  50. .thread_limit_var = UINT_MAX,
  51. .run_sched_var = GFS_DYNAMIC,
  52. .run_sched_modifier = 1,
  53. .default_device_var = 0,
  54. .dyn_var = false,
  55. .nest_var = false,
  56. .bind_var = omp_proc_bind_false,
  57. .target_data = NULL
  58. };
  59. unsigned long gomp_max_active_levels_var = INT_MAX;
  60. bool gomp_cancel_var = false;
  61. #ifndef HAVE_SYNC_BUILTINS
  62. gomp_mutex_t gomp_managed_threads_lock;
  63. #endif
  64. unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
  65. unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
  66. unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
  67. char *gomp_bind_var_list;
  68. unsigned long gomp_bind_var_list_len;
  69. void **gomp_places_list;
  70. unsigned long gomp_places_list_len;
  71. int gomp_debug_var;
  72. char *goacc_device_type;
  73. int goacc_device_num;
  74. /* Parse the OMP_SCHEDULE environment variable. */
  75. static void
  76. parse_schedule (void)
  77. {
  78. char *env, *end;
  79. unsigned long value;
  80. env = getenv ("OMP_SCHEDULE");
  81. if (env == NULL)
  82. return;
  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. while (isspace ((unsigned char) *env))
  108. ++env;
  109. if (*env == '\0')
  110. {
  111. gomp_global_icv.run_sched_modifier
  112. = gomp_global_icv.run_sched_var != GFS_STATIC;
  113. return;
  114. }
  115. if (*env++ != ',')
  116. goto unknown;
  117. while (isspace ((unsigned char) *env))
  118. ++env;
  119. if (*env == '\0')
  120. goto invalid;
  121. errno = 0;
  122. value = strtoul (env, &end, 10);
  123. if (errno)
  124. goto invalid;
  125. while (isspace ((unsigned char) *end))
  126. ++end;
  127. if (*end != '\0')
  128. goto invalid;
  129. if ((int)value != value)
  130. goto invalid;
  131. if (value == 0 && gomp_global_icv.run_sched_var != GFS_STATIC)
  132. value = 1;
  133. gomp_global_icv.run_sched_modifier = value;
  134. return;
  135. unknown:
  136. gomp_error ("Unknown value for environment variable OMP_SCHEDULE");
  137. return;
  138. invalid:
  139. gomp_error ("Invalid value for chunk size in "
  140. "environment variable OMP_SCHEDULE");
  141. return;
  142. }
  143. /* Parse an unsigned long environment variable. Return true if one was
  144. present and it was successfully parsed. */
  145. static bool
  146. parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
  147. {
  148. char *env, *end;
  149. unsigned long value;
  150. env = getenv (name);
  151. if (env == NULL)
  152. return false;
  153. while (isspace ((unsigned char) *env))
  154. ++env;
  155. if (*env == '\0')
  156. goto invalid;
  157. errno = 0;
  158. value = strtoul (env, &end, 10);
  159. if (errno || (long) value <= 0 - allow_zero)
  160. goto invalid;
  161. while (isspace ((unsigned char) *end))
  162. ++end;
  163. if (*end != '\0')
  164. goto invalid;
  165. *pvalue = value;
  166. return true;
  167. invalid:
  168. gomp_error ("Invalid value for environment variable %s", name);
  169. return false;
  170. }
  171. /* Parse a positive int environment variable. Return true if one was
  172. present and it was successfully parsed. */
  173. static bool
  174. parse_int (const char *name, int *pvalue, bool allow_zero)
  175. {
  176. unsigned long value;
  177. if (!parse_unsigned_long (name, &value, allow_zero))
  178. return false;
  179. if (value > INT_MAX)
  180. {
  181. gomp_error ("Invalid value for environment variable %s", name);
  182. return false;
  183. }
  184. *pvalue = (int) value;
  185. return true;
  186. }
  187. /* Parse an unsigned long list environment variable. Return true if one was
  188. present and it was successfully parsed. */
  189. static bool
  190. parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
  191. unsigned long **pvalues,
  192. unsigned long *pnvalues)
  193. {
  194. char *env, *end;
  195. unsigned long value, *values = NULL;
  196. env = getenv (name);
  197. if (env == NULL)
  198. return false;
  199. while (isspace ((unsigned char) *env))
  200. ++env;
  201. if (*env == '\0')
  202. goto invalid;
  203. errno = 0;
  204. value = strtoul (env, &end, 10);
  205. if (errno || (long) value <= 0)
  206. goto invalid;
  207. while (isspace ((unsigned char) *end))
  208. ++end;
  209. if (*end != '\0')
  210. {
  211. if (*end == ',')
  212. {
  213. unsigned long nvalues = 0, nalloced = 0;
  214. do
  215. {
  216. env = end + 1;
  217. if (nvalues == nalloced)
  218. {
  219. unsigned long *n;
  220. nalloced = nalloced ? nalloced * 2 : 16;
  221. n = realloc (values, nalloced * sizeof (unsigned long));
  222. if (n == NULL)
  223. {
  224. free (values);
  225. gomp_error ("Out of memory while trying to parse"
  226. " environment variable %s", name);
  227. return false;
  228. }
  229. values = n;
  230. if (nvalues == 0)
  231. values[nvalues++] = value;
  232. }
  233. while (isspace ((unsigned char) *env))
  234. ++env;
  235. if (*env == '\0')
  236. goto invalid;
  237. errno = 0;
  238. value = strtoul (env, &end, 10);
  239. if (errno || (long) value <= 0)
  240. goto invalid;
  241. values[nvalues++] = value;
  242. while (isspace ((unsigned char) *end))
  243. ++end;
  244. if (*end == '\0')
  245. break;
  246. if (*end != ',')
  247. goto invalid;
  248. }
  249. while (1);
  250. *p1stvalue = values[0];
  251. *pvalues = values;
  252. *pnvalues = nvalues;
  253. return true;
  254. }
  255. goto invalid;
  256. }
  257. *p1stvalue = value;
  258. return true;
  259. invalid:
  260. free (values);
  261. gomp_error ("Invalid value for environment variable %s", name);
  262. return false;
  263. }
  264. /* Parse environment variable set to a boolean or list of omp_proc_bind_t
  265. enum values. Return true if one was present and it was successfully
  266. parsed. */
  267. static bool
  268. parse_bind_var (const char *name, char *p1stvalue,
  269. char **pvalues, unsigned long *pnvalues)
  270. {
  271. char *env;
  272. char value = omp_proc_bind_false, *values = NULL;
  273. int i;
  274. static struct proc_bind_kinds
  275. {
  276. const char name[7];
  277. const char len;
  278. omp_proc_bind_t kind;
  279. } kinds[] =
  280. {
  281. { "false", 5, omp_proc_bind_false },
  282. { "true", 4, omp_proc_bind_true },
  283. { "master", 6, omp_proc_bind_master },
  284. { "close", 5, omp_proc_bind_close },
  285. { "spread", 6, omp_proc_bind_spread }
  286. };
  287. env = getenv (name);
  288. if (env == NULL)
  289. return false;
  290. while (isspace ((unsigned char) *env))
  291. ++env;
  292. if (*env == '\0')
  293. goto invalid;
  294. for (i = 0; i < 5; i++)
  295. if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
  296. {
  297. value = kinds[i].kind;
  298. env += kinds[i].len;
  299. break;
  300. }
  301. if (i == 5)
  302. goto invalid;
  303. while (isspace ((unsigned char) *env))
  304. ++env;
  305. if (*env != '\0')
  306. {
  307. if (*env == ',')
  308. {
  309. unsigned long nvalues = 0, nalloced = 0;
  310. if (value == omp_proc_bind_false
  311. || value == omp_proc_bind_true)
  312. goto invalid;
  313. do
  314. {
  315. env++;
  316. if (nvalues == nalloced)
  317. {
  318. char *n;
  319. nalloced = nalloced ? nalloced * 2 : 16;
  320. n = realloc (values, nalloced);
  321. if (n == NULL)
  322. {
  323. free (values);
  324. gomp_error ("Out of memory while trying to parse"
  325. " environment variable %s", name);
  326. return false;
  327. }
  328. values = n;
  329. if (nvalues == 0)
  330. values[nvalues++] = value;
  331. }
  332. while (isspace ((unsigned char) *env))
  333. ++env;
  334. if (*env == '\0')
  335. goto invalid;
  336. for (i = 2; i < 5; i++)
  337. if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
  338. {
  339. value = kinds[i].kind;
  340. env += kinds[i].len;
  341. break;
  342. }
  343. if (i == 5)
  344. goto invalid;
  345. values[nvalues++] = value;
  346. while (isspace ((unsigned char) *env))
  347. ++env;
  348. if (*env == '\0')
  349. break;
  350. if (*env != ',')
  351. goto invalid;
  352. }
  353. while (1);
  354. *p1stvalue = values[0];
  355. *pvalues = values;
  356. *pnvalues = nvalues;
  357. return true;
  358. }
  359. goto invalid;
  360. }
  361. *p1stvalue = value;
  362. return true;
  363. invalid:
  364. free (values);
  365. gomp_error ("Invalid value for environment variable %s", name);
  366. return false;
  367. }
  368. static bool
  369. parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
  370. long *stridep)
  371. {
  372. char *env = *envp, *start;
  373. void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
  374. unsigned long len = 1;
  375. long stride = 1;
  376. int pass;
  377. bool any_negate = false;
  378. *negatep = false;
  379. while (isspace ((unsigned char) *env))
  380. ++env;
  381. if (*env == '!')
  382. {
  383. *negatep = true;
  384. ++env;
  385. while (isspace ((unsigned char) *env))
  386. ++env;
  387. }
  388. if (*env != '{')
  389. return false;
  390. ++env;
  391. while (isspace ((unsigned char) *env))
  392. ++env;
  393. start = env;
  394. for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
  395. {
  396. env = start;
  397. do
  398. {
  399. unsigned long this_num, this_len = 1;
  400. long this_stride = 1;
  401. bool this_negate = (*env == '!');
  402. if (this_negate)
  403. {
  404. if (gomp_places_list)
  405. any_negate = true;
  406. ++env;
  407. while (isspace ((unsigned char) *env))
  408. ++env;
  409. }
  410. errno = 0;
  411. this_num = strtoul (env, &env, 10);
  412. if (errno)
  413. return false;
  414. while (isspace ((unsigned char) *env))
  415. ++env;
  416. if (*env == ':')
  417. {
  418. ++env;
  419. while (isspace ((unsigned char) *env))
  420. ++env;
  421. errno = 0;
  422. this_len = strtoul (env, &env, 10);
  423. if (errno || this_len == 0)
  424. return false;
  425. while (isspace ((unsigned char) *env))
  426. ++env;
  427. if (*env == ':')
  428. {
  429. ++env;
  430. while (isspace ((unsigned char) *env))
  431. ++env;
  432. errno = 0;
  433. this_stride = strtol (env, &env, 10);
  434. if (errno)
  435. return false;
  436. while (isspace ((unsigned char) *env))
  437. ++env;
  438. }
  439. }
  440. if (this_negate && this_len != 1)
  441. return false;
  442. if (gomp_places_list && pass == this_negate)
  443. {
  444. if (this_negate)
  445. {
  446. if (!gomp_affinity_remove_cpu (p, this_num))
  447. return false;
  448. }
  449. else if (!gomp_affinity_add_cpus (p, this_num, this_len,
  450. this_stride, false))
  451. return false;
  452. }
  453. if (*env == '}')
  454. break;
  455. if (*env != ',')
  456. return false;
  457. ++env;
  458. }
  459. while (1);
  460. }
  461. ++env;
  462. while (isspace ((unsigned char) *env))
  463. ++env;
  464. if (*env == ':')
  465. {
  466. ++env;
  467. while (isspace ((unsigned char) *env))
  468. ++env;
  469. errno = 0;
  470. len = strtoul (env, &env, 10);
  471. if (errno || len == 0 || len >= 65536)
  472. return false;
  473. while (isspace ((unsigned char) *env))
  474. ++env;
  475. if (*env == ':')
  476. {
  477. ++env;
  478. while (isspace ((unsigned char) *env))
  479. ++env;
  480. errno = 0;
  481. stride = strtol (env, &env, 10);
  482. if (errno)
  483. return false;
  484. while (isspace ((unsigned char) *env))
  485. ++env;
  486. }
  487. }
  488. if (*negatep && len != 1)
  489. return false;
  490. *envp = env;
  491. *lenp = len;
  492. *stridep = stride;
  493. return true;
  494. }
  495. static bool
  496. parse_places_var (const char *name, bool ignore)
  497. {
  498. char *env = getenv (name), *end;
  499. bool any_negate = false;
  500. int level = 0;
  501. unsigned long count = 0;
  502. if (env == NULL)
  503. return false;
  504. while (isspace ((unsigned char) *env))
  505. ++env;
  506. if (*env == '\0')
  507. goto invalid;
  508. if (strncasecmp (env, "threads", 7) == 0)
  509. {
  510. env += 7;
  511. level = 1;
  512. }
  513. else if (strncasecmp (env, "cores", 5) == 0)
  514. {
  515. env += 5;
  516. level = 2;
  517. }
  518. else if (strncasecmp (env, "sockets", 7) == 0)
  519. {
  520. env += 7;
  521. level = 3;
  522. }
  523. if (level)
  524. {
  525. count = ULONG_MAX;
  526. while (isspace ((unsigned char) *env))
  527. ++env;
  528. if (*env != '\0')
  529. {
  530. if (*env++ != '(')
  531. goto invalid;
  532. while (isspace ((unsigned char) *env))
  533. ++env;
  534. errno = 0;
  535. count = strtoul (env, &end, 10);
  536. if (errno)
  537. goto invalid;
  538. env = end;
  539. while (isspace ((unsigned char) *env))
  540. ++env;
  541. if (*env != ')')
  542. goto invalid;
  543. ++env;
  544. while (isspace ((unsigned char) *env))
  545. ++env;
  546. if (*env != '\0')
  547. goto invalid;
  548. }
  549. if (ignore)
  550. return false;
  551. return gomp_affinity_init_level (level, count, false);
  552. }
  553. count = 0;
  554. end = env;
  555. do
  556. {
  557. bool negate;
  558. unsigned long len;
  559. long stride;
  560. if (!parse_one_place (&end, &negate, &len, &stride))
  561. goto invalid;
  562. if (negate)
  563. {
  564. if (!any_negate)
  565. count++;
  566. any_negate = true;
  567. }
  568. else
  569. count += len;
  570. if (count > 65536)
  571. goto invalid;
  572. if (*end == '\0')
  573. break;
  574. if (*end != ',')
  575. goto invalid;
  576. end++;
  577. }
  578. while (1);
  579. if (ignore)
  580. return false;
  581. gomp_places_list_len = 0;
  582. gomp_places_list = gomp_affinity_alloc (count, false);
  583. if (gomp_places_list == NULL)
  584. return false;
  585. do
  586. {
  587. bool negate;
  588. unsigned long len;
  589. long stride;
  590. gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
  591. if (!parse_one_place (&env, &negate, &len, &stride))
  592. goto invalid;
  593. if (negate)
  594. {
  595. void *p;
  596. for (count = 0; count < gomp_places_list_len; count++)
  597. if (gomp_affinity_same_place
  598. (gomp_places_list[count],
  599. gomp_places_list[gomp_places_list_len]))
  600. break;
  601. if (count == gomp_places_list_len)
  602. {
  603. gomp_error ("Trying to remove a non-existing place from list "
  604. "of places");
  605. goto invalid;
  606. }
  607. p = gomp_places_list[count];
  608. memmove (&gomp_places_list[count],
  609. &gomp_places_list[count + 1],
  610. (gomp_places_list_len - count - 1) * sizeof (void *));
  611. --gomp_places_list_len;
  612. gomp_places_list[gomp_places_list_len] = p;
  613. }
  614. else if (len == 1)
  615. ++gomp_places_list_len;
  616. else
  617. {
  618. for (count = 0; count < len - 1; count++)
  619. if (!gomp_affinity_copy_place
  620. (gomp_places_list[gomp_places_list_len + count + 1],
  621. gomp_places_list[gomp_places_list_len + count],
  622. stride))
  623. goto invalid;
  624. gomp_places_list_len += len;
  625. }
  626. if (*env == '\0')
  627. break;
  628. env++;
  629. }
  630. while (1);
  631. if (gomp_places_list_len == 0)
  632. {
  633. gomp_error ("All places have been removed");
  634. goto invalid;
  635. }
  636. if (!gomp_affinity_finalize_place_list (false))
  637. goto invalid;
  638. return true;
  639. invalid:
  640. free (gomp_places_list);
  641. gomp_places_list = NULL;
  642. gomp_places_list_len = 0;
  643. gomp_error ("Invalid value for environment variable %s", name);
  644. return false;
  645. }
  646. /* Parse the OMP_STACKSIZE environment varible. Return true if one was
  647. present and it was successfully parsed. */
  648. static bool
  649. parse_stacksize (const char *name, unsigned long *pvalue)
  650. {
  651. char *env, *end;
  652. unsigned long value, shift = 10;
  653. env = getenv (name);
  654. if (env == NULL)
  655. return false;
  656. while (isspace ((unsigned char) *env))
  657. ++env;
  658. if (*env == '\0')
  659. goto invalid;
  660. errno = 0;
  661. value = strtoul (env, &end, 10);
  662. if (errno)
  663. goto invalid;
  664. while (isspace ((unsigned char) *end))
  665. ++end;
  666. if (*end != '\0')
  667. {
  668. switch (tolower ((unsigned char) *end))
  669. {
  670. case 'b':
  671. shift = 0;
  672. break;
  673. case 'k':
  674. break;
  675. case 'm':
  676. shift = 20;
  677. break;
  678. case 'g':
  679. shift = 30;
  680. break;
  681. default:
  682. goto invalid;
  683. }
  684. ++end;
  685. while (isspace ((unsigned char) *end))
  686. ++end;
  687. if (*end != '\0')
  688. goto invalid;
  689. }
  690. if (((value << shift) >> shift) != value)
  691. goto invalid;
  692. *pvalue = value << shift;
  693. return true;
  694. invalid:
  695. gomp_error ("Invalid value for environment variable %s", name);
  696. return false;
  697. }
  698. /* Parse the GOMP_SPINCOUNT environment varible. Return true if one was
  699. present and it was successfully parsed. */
  700. static bool
  701. parse_spincount (const char *name, unsigned long long *pvalue)
  702. {
  703. char *env, *end;
  704. unsigned long long value, mult = 1;
  705. env = getenv (name);
  706. if (env == NULL)
  707. return false;
  708. while (isspace ((unsigned char) *env))
  709. ++env;
  710. if (*env == '\0')
  711. goto invalid;
  712. if (strncasecmp (env, "infinite", 8) == 0
  713. || strncasecmp (env, "infinity", 8) == 0)
  714. {
  715. value = ~0ULL;
  716. end = env + 8;
  717. goto check_tail;
  718. }
  719. errno = 0;
  720. value = strtoull (env, &end, 10);
  721. if (errno)
  722. goto invalid;
  723. while (isspace ((unsigned char) *end))
  724. ++end;
  725. if (*end != '\0')
  726. {
  727. switch (tolower ((unsigned char) *end))
  728. {
  729. case 'k':
  730. mult = 1000LL;
  731. break;
  732. case 'm':
  733. mult = 1000LL * 1000LL;
  734. break;
  735. case 'g':
  736. mult = 1000LL * 1000LL * 1000LL;
  737. break;
  738. case 't':
  739. mult = 1000LL * 1000LL * 1000LL * 1000LL;
  740. break;
  741. default:
  742. goto invalid;
  743. }
  744. ++end;
  745. check_tail:
  746. while (isspace ((unsigned char) *end))
  747. ++end;
  748. if (*end != '\0')
  749. goto invalid;
  750. }
  751. if (value > ~0ULL / mult)
  752. value = ~0ULL;
  753. else
  754. value *= mult;
  755. *pvalue = value;
  756. return true;
  757. invalid:
  758. gomp_error ("Invalid value for environment variable %s", name);
  759. return false;
  760. }
  761. /* Parse a boolean value for environment variable NAME and store the
  762. result in VALUE. */
  763. static void
  764. parse_boolean (const char *name, bool *value)
  765. {
  766. const char *env;
  767. env = getenv (name);
  768. if (env == NULL)
  769. return;
  770. while (isspace ((unsigned char) *env))
  771. ++env;
  772. if (strncasecmp (env, "true", 4) == 0)
  773. {
  774. *value = true;
  775. env += 4;
  776. }
  777. else if (strncasecmp (env, "false", 5) == 0)
  778. {
  779. *value = false;
  780. env += 5;
  781. }
  782. else
  783. env = "X";
  784. while (isspace ((unsigned char) *env))
  785. ++env;
  786. if (*env != '\0')
  787. gomp_error ("Invalid value for environment variable %s", name);
  788. }
  789. /* Parse the OMP_WAIT_POLICY environment variable and store the
  790. result in gomp_active_wait_policy. */
  791. static int
  792. parse_wait_policy (void)
  793. {
  794. const char *env;
  795. int ret = -1;
  796. env = getenv ("OMP_WAIT_POLICY");
  797. if (env == NULL)
  798. return -1;
  799. while (isspace ((unsigned char) *env))
  800. ++env;
  801. if (strncasecmp (env, "active", 6) == 0)
  802. {
  803. ret = 1;
  804. env += 6;
  805. }
  806. else if (strncasecmp (env, "passive", 7) == 0)
  807. {
  808. ret = 0;
  809. env += 7;
  810. }
  811. else
  812. env = "X";
  813. while (isspace ((unsigned char) *env))
  814. ++env;
  815. if (*env == '\0')
  816. return ret;
  817. gomp_error ("Invalid value for environment variable OMP_WAIT_POLICY");
  818. return -1;
  819. }
  820. /* Parse the GOMP_CPU_AFFINITY environment varible. Return true if one was
  821. present and it was successfully parsed. */
  822. static bool
  823. parse_affinity (bool ignore)
  824. {
  825. char *env, *end, *start;
  826. int pass;
  827. unsigned long cpu_beg, cpu_end, cpu_stride;
  828. size_t count = 0, needed;
  829. env = getenv ("GOMP_CPU_AFFINITY");
  830. if (env == NULL)
  831. return false;
  832. start = env;
  833. for (pass = 0; pass < 2; pass++)
  834. {
  835. env = start;
  836. if (pass == 1)
  837. {
  838. if (ignore)
  839. return false;
  840. gomp_places_list_len = 0;
  841. gomp_places_list = gomp_affinity_alloc (count, true);
  842. if (gomp_places_list == NULL)
  843. return false;
  844. }
  845. do
  846. {
  847. while (isspace ((unsigned char) *env))
  848. ++env;
  849. errno = 0;
  850. cpu_beg = strtoul (env, &end, 0);
  851. if (errno || cpu_beg >= 65536)
  852. goto invalid;
  853. cpu_end = cpu_beg;
  854. cpu_stride = 1;
  855. env = end;
  856. if (*env == '-')
  857. {
  858. errno = 0;
  859. cpu_end = strtoul (++env, &end, 0);
  860. if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
  861. goto invalid;
  862. env = end;
  863. if (*env == ':')
  864. {
  865. errno = 0;
  866. cpu_stride = strtoul (++env, &end, 0);
  867. if (errno || cpu_stride == 0 || cpu_stride >= 65536)
  868. goto invalid;
  869. env = end;
  870. }
  871. }
  872. needed = (cpu_end - cpu_beg) / cpu_stride + 1;
  873. if (pass == 0)
  874. count += needed;
  875. else
  876. {
  877. while (needed--)
  878. {
  879. void *p = gomp_places_list[gomp_places_list_len];
  880. gomp_affinity_init_place (p);
  881. if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
  882. ++gomp_places_list_len;
  883. cpu_beg += cpu_stride;
  884. }
  885. }
  886. while (isspace ((unsigned char) *env))
  887. ++env;
  888. if (*env == ',')
  889. env++;
  890. else if (*env == '\0')
  891. break;
  892. }
  893. while (1);
  894. }
  895. if (gomp_places_list_len == 0)
  896. {
  897. free (gomp_places_list);
  898. gomp_places_list = NULL;
  899. return false;
  900. }
  901. return true;
  902. invalid:
  903. gomp_error ("Invalid value for enviroment variable GOMP_CPU_AFFINITY");
  904. return false;
  905. }
  906. static void
  907. parse_acc_device_type (void)
  908. {
  909. const char *env = getenv ("ACC_DEVICE_TYPE");
  910. if (env && *env != '\0')
  911. goacc_device_type = strdup (env);
  912. else
  913. goacc_device_type = NULL;
  914. }
  915. static void
  916. handle_omp_display_env (unsigned long stacksize, int wait_policy)
  917. {
  918. const char *env;
  919. bool display = false;
  920. bool verbose = false;
  921. int i;
  922. env = getenv ("OMP_DISPLAY_ENV");
  923. if (env == NULL)
  924. return;
  925. while (isspace ((unsigned char) *env))
  926. ++env;
  927. if (strncasecmp (env, "true", 4) == 0)
  928. {
  929. display = true;
  930. env += 4;
  931. }
  932. else if (strncasecmp (env, "false", 5) == 0)
  933. {
  934. display = false;
  935. env += 5;
  936. }
  937. else if (strncasecmp (env, "verbose", 7) == 0)
  938. {
  939. display = true;
  940. verbose = true;
  941. env += 7;
  942. }
  943. else
  944. env = "X";
  945. while (isspace ((unsigned char) *env))
  946. ++env;
  947. if (*env != '\0')
  948. gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
  949. if (!display)
  950. return;
  951. fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
  952. fputs (" _OPENMP = '201307'\n", stderr);
  953. fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
  954. gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
  955. fprintf (stderr, " OMP_NESTED = '%s'\n",
  956. gomp_global_icv.nest_var ? "TRUE" : "FALSE");
  957. fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
  958. for (i = 1; i < gomp_nthreads_var_list_len; i++)
  959. fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
  960. fputs ("'\n", stderr);
  961. fprintf (stderr, " OMP_SCHEDULE = '");
  962. switch (gomp_global_icv.run_sched_var)
  963. {
  964. case GFS_RUNTIME:
  965. fputs ("RUNTIME", stderr);
  966. break;
  967. case GFS_STATIC:
  968. fputs ("STATIC", stderr);
  969. break;
  970. case GFS_DYNAMIC:
  971. fputs ("DYNAMIC", stderr);
  972. break;
  973. case GFS_GUIDED:
  974. fputs ("GUIDED", stderr);
  975. break;
  976. case GFS_AUTO:
  977. fputs ("AUTO", stderr);
  978. break;
  979. }
  980. fputs ("'\n", stderr);
  981. fputs (" OMP_PROC_BIND = '", stderr);
  982. switch (gomp_global_icv.bind_var)
  983. {
  984. case omp_proc_bind_false:
  985. fputs ("FALSE", stderr);
  986. break;
  987. case omp_proc_bind_true:
  988. fputs ("TRUE", stderr);
  989. break;
  990. case omp_proc_bind_master:
  991. fputs ("MASTER", stderr);
  992. break;
  993. case omp_proc_bind_close:
  994. fputs ("CLOSE", stderr);
  995. break;
  996. case omp_proc_bind_spread:
  997. fputs ("SPREAD", stderr);
  998. break;
  999. }
  1000. for (i = 1; i < gomp_bind_var_list_len; i++)
  1001. switch (gomp_bind_var_list[i])
  1002. {
  1003. case omp_proc_bind_master:
  1004. fputs (",MASTER", stderr);
  1005. break;
  1006. case omp_proc_bind_close:
  1007. fputs (",CLOSE", stderr);
  1008. break;
  1009. case omp_proc_bind_spread:
  1010. fputs (",SPREAD", stderr);
  1011. break;
  1012. }
  1013. fputs ("'\n", stderr);
  1014. fputs (" OMP_PLACES = '", stderr);
  1015. for (i = 0; i < gomp_places_list_len; i++)
  1016. {
  1017. fputs ("{", stderr);
  1018. gomp_affinity_print_place (gomp_places_list[i]);
  1019. fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
  1020. }
  1021. fputs ("'\n", stderr);
  1022. fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
  1023. /* GOMP's default value is actually neither active nor passive. */
  1024. fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
  1025. wait_policy > 0 ? "ACTIVE" : "PASSIVE");
  1026. fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
  1027. gomp_global_icv.thread_limit_var);
  1028. fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
  1029. gomp_max_active_levels_var);
  1030. fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
  1031. gomp_cancel_var ? "TRUE" : "FALSE");
  1032. fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
  1033. gomp_global_icv.default_device_var);
  1034. if (verbose)
  1035. {
  1036. fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
  1037. fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
  1038. #ifdef HAVE_INTTYPES_H
  1039. fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
  1040. (uint64_t) gomp_spin_count_var);
  1041. #else
  1042. fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
  1043. (unsigned long) gomp_spin_count_var);
  1044. #endif
  1045. }
  1046. fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
  1047. }
  1048. static void __attribute__((constructor))
  1049. initialize_env (void)
  1050. {
  1051. unsigned long thread_limit_var, stacksize;
  1052. int wait_policy;
  1053. /* Do a compile time check that mkomp_h.pl did good job. */
  1054. omp_check_defines ();
  1055. parse_schedule ();
  1056. parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
  1057. parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
  1058. parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
  1059. parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
  1060. parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
  1061. true);
  1062. if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
  1063. {
  1064. gomp_global_icv.thread_limit_var
  1065. = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
  1066. }
  1067. parse_int ("GOMP_DEBUG", &gomp_debug_var, true);
  1068. #ifndef HAVE_SYNC_BUILTINS
  1069. gomp_mutex_init (&gomp_managed_threads_lock);
  1070. #endif
  1071. gomp_init_num_threads ();
  1072. gomp_available_cpus = gomp_global_icv.nthreads_var;
  1073. if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
  1074. &gomp_global_icv.nthreads_var,
  1075. &gomp_nthreads_var_list,
  1076. &gomp_nthreads_var_list_len))
  1077. gomp_global_icv.nthreads_var = gomp_available_cpus;
  1078. bool ignore = false;
  1079. if (parse_bind_var ("OMP_PROC_BIND",
  1080. &gomp_global_icv.bind_var,
  1081. &gomp_bind_var_list,
  1082. &gomp_bind_var_list_len)
  1083. && gomp_global_icv.bind_var == omp_proc_bind_false)
  1084. ignore = true;
  1085. /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
  1086. parsed if present in the environment. If OMP_PROC_BIND was set
  1087. explictly to false, don't populate places list though. If places
  1088. list was successfully set from OMP_PLACES, only parse but don't process
  1089. GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
  1090. default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
  1091. was successfully parsed into a places list, otherwise to
  1092. OMP_PROC_BIND=false. */
  1093. if (parse_places_var ("OMP_PLACES", ignore))
  1094. {
  1095. if (gomp_global_icv.bind_var == omp_proc_bind_false)
  1096. gomp_global_icv.bind_var = true;
  1097. ignore = true;
  1098. }
  1099. if (parse_affinity (ignore))
  1100. {
  1101. if (gomp_global_icv.bind_var == omp_proc_bind_false)
  1102. gomp_global_icv.bind_var = true;
  1103. ignore = true;
  1104. }
  1105. if (gomp_global_icv.bind_var != omp_proc_bind_false)
  1106. gomp_init_affinity ();
  1107. wait_policy = parse_wait_policy ();
  1108. if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
  1109. {
  1110. /* Using a rough estimation of 100000 spins per msec,
  1111. use 5 min blocking for OMP_WAIT_POLICY=active,
  1112. 3 msec blocking when OMP_WAIT_POLICY is not specificed
  1113. and 0 when OMP_WAIT_POLICY=passive.
  1114. Depending on the CPU speed, this can be e.g. 5 times longer
  1115. or 5 times shorter. */
  1116. if (wait_policy > 0)
  1117. gomp_spin_count_var = 30000000000LL;
  1118. else if (wait_policy < 0)
  1119. gomp_spin_count_var = 300000LL;
  1120. }
  1121. /* gomp_throttled_spin_count_var is used when there are more libgomp
  1122. managed threads than available CPUs. Use very short spinning. */
  1123. if (wait_policy > 0)
  1124. gomp_throttled_spin_count_var = 1000LL;
  1125. else if (wait_policy < 0)
  1126. gomp_throttled_spin_count_var = 100LL;
  1127. if (gomp_throttled_spin_count_var > gomp_spin_count_var)
  1128. gomp_throttled_spin_count_var = gomp_spin_count_var;
  1129. /* Not strictly environment related, but ordering constructors is tricky. */
  1130. pthread_attr_init (&gomp_thread_attr);
  1131. pthread_attr_setdetachstate (&gomp_thread_attr, PTHREAD_CREATE_DETACHED);
  1132. if (parse_stacksize ("OMP_STACKSIZE", &stacksize)
  1133. || parse_stacksize ("GOMP_STACKSIZE", &stacksize))
  1134. {
  1135. int err;
  1136. err = pthread_attr_setstacksize (&gomp_thread_attr, stacksize);
  1137. #ifdef PTHREAD_STACK_MIN
  1138. if (err == EINVAL)
  1139. {
  1140. if (stacksize < PTHREAD_STACK_MIN)
  1141. gomp_error ("Stack size less than minimum of %luk",
  1142. PTHREAD_STACK_MIN / 1024ul
  1143. + (PTHREAD_STACK_MIN % 1024 != 0));
  1144. else
  1145. gomp_error ("Stack size larger than system limit");
  1146. }
  1147. else
  1148. #endif
  1149. if (err != 0)
  1150. gomp_error ("Stack size change failed: %s", strerror (err));
  1151. }
  1152. handle_omp_display_env (stacksize, wait_policy);
  1153. /* OpenACC. */
  1154. if (!parse_int ("ACC_DEVICE_NUM", &goacc_device_num, true))
  1155. goacc_device_num = 0;
  1156. parse_acc_device_type ();
  1157. goacc_runtime_initialize ();
  1158. }
  1159. /* The public OpenMP API routines that access these variables. */
  1160. void
  1161. omp_set_num_threads (int n)
  1162. {
  1163. struct gomp_task_icv *icv = gomp_icv (true);
  1164. icv->nthreads_var = (n > 0 ? n : 1);
  1165. }
  1166. void
  1167. omp_set_dynamic (int val)
  1168. {
  1169. struct gomp_task_icv *icv = gomp_icv (true);
  1170. icv->dyn_var = val;
  1171. }
  1172. int
  1173. omp_get_dynamic (void)
  1174. {
  1175. struct gomp_task_icv *icv = gomp_icv (false);
  1176. return icv->dyn_var;
  1177. }
  1178. void
  1179. omp_set_nested (int val)
  1180. {
  1181. struct gomp_task_icv *icv = gomp_icv (true);
  1182. icv->nest_var = val;
  1183. }
  1184. int
  1185. omp_get_nested (void)
  1186. {
  1187. struct gomp_task_icv *icv = gomp_icv (false);
  1188. return icv->nest_var;
  1189. }
  1190. void
  1191. omp_set_schedule (omp_sched_t kind, int modifier)
  1192. {
  1193. struct gomp_task_icv *icv = gomp_icv (true);
  1194. switch (kind)
  1195. {
  1196. case omp_sched_static:
  1197. if (modifier < 1)
  1198. modifier = 0;
  1199. icv->run_sched_modifier = modifier;
  1200. break;
  1201. case omp_sched_dynamic:
  1202. case omp_sched_guided:
  1203. if (modifier < 1)
  1204. modifier = 1;
  1205. icv->run_sched_modifier = modifier;
  1206. break;
  1207. case omp_sched_auto:
  1208. break;
  1209. default:
  1210. return;
  1211. }
  1212. icv->run_sched_var = kind;
  1213. }
  1214. void
  1215. omp_get_schedule (omp_sched_t *kind, int *modifier)
  1216. {
  1217. struct gomp_task_icv *icv = gomp_icv (false);
  1218. *kind = icv->run_sched_var;
  1219. *modifier = icv->run_sched_modifier;
  1220. }
  1221. int
  1222. omp_get_max_threads (void)
  1223. {
  1224. struct gomp_task_icv *icv = gomp_icv (false);
  1225. return icv->nthreads_var;
  1226. }
  1227. int
  1228. omp_get_thread_limit (void)
  1229. {
  1230. struct gomp_task_icv *icv = gomp_icv (false);
  1231. return icv->thread_limit_var > INT_MAX ? INT_MAX : icv->thread_limit_var;
  1232. }
  1233. void
  1234. omp_set_max_active_levels (int max_levels)
  1235. {
  1236. if (max_levels >= 0)
  1237. gomp_max_active_levels_var = max_levels;
  1238. }
  1239. int
  1240. omp_get_max_active_levels (void)
  1241. {
  1242. return gomp_max_active_levels_var;
  1243. }
  1244. int
  1245. omp_get_cancellation (void)
  1246. {
  1247. return gomp_cancel_var;
  1248. }
  1249. omp_proc_bind_t
  1250. omp_get_proc_bind (void)
  1251. {
  1252. struct gomp_task_icv *icv = gomp_icv (false);
  1253. return icv->bind_var;
  1254. }
  1255. void
  1256. omp_set_default_device (int device_num)
  1257. {
  1258. struct gomp_task_icv *icv = gomp_icv (true);
  1259. icv->default_device_var = device_num >= 0 ? device_num : 0;
  1260. }
  1261. int
  1262. omp_get_default_device (void)
  1263. {
  1264. struct gomp_task_icv *icv = gomp_icv (false);
  1265. return icv->default_device_var;
  1266. }
  1267. int
  1268. omp_get_num_devices (void)
  1269. {
  1270. return gomp_get_num_devices ();
  1271. }
  1272. int
  1273. omp_get_num_teams (void)
  1274. {
  1275. /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */
  1276. return 1;
  1277. }
  1278. int
  1279. omp_get_team_num (void)
  1280. {
  1281. /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */
  1282. return 0;
  1283. }
  1284. int
  1285. omp_is_initial_device (void)
  1286. {
  1287. /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */
  1288. return 1;
  1289. }
  1290. ialias (omp_set_dynamic)
  1291. ialias (omp_set_nested)
  1292. ialias (omp_set_num_threads)
  1293. ialias (omp_get_dynamic)
  1294. ialias (omp_get_nested)
  1295. ialias (omp_set_schedule)
  1296. ialias (omp_get_schedule)
  1297. ialias (omp_get_max_threads)
  1298. ialias (omp_get_thread_limit)
  1299. ialias (omp_set_max_active_levels)
  1300. ialias (omp_get_max_active_levels)
  1301. ialias (omp_get_cancellation)
  1302. ialias (omp_get_proc_bind)
  1303. ialias (omp_set_default_device)
  1304. ialias (omp_get_default_device)
  1305. ialias (omp_get_num_devices)
  1306. ialias (omp_get_num_teams)
  1307. ialias (omp_get_team_num)
  1308. ialias (omp_is_initial_device)