utils.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. * Copyright (C) 2020 Federal University of Rio Grande do Sul (UFRGS)
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include <starpu.h>
  18. #include <common/config.h>
  19. #include <common/utils.h>
  20. #include <core/workers.h>
  21. #include <errno.h>
  22. #ifdef HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #endif
  25. #include <fcntl.h>
  26. #include <ctype.h>
  27. #if defined(_WIN32) && !defined(__CYGWIN__)
  28. #include <io.h>
  29. #include <sys/locking.h>
  30. #define mkdir(path, mode) mkdir(path)
  31. #if !defined(__MINGW32__)
  32. #define ftruncate(fd, length) _chsize(fd, length)
  33. #endif
  34. #endif
  35. #ifndef O_BINARY
  36. #define O_BINARY 0
  37. #endif
  38. #if !defined(O_DIRECT) && defined(F_NOCACHE)
  39. #define O_DIRECT F_NOCACHE
  40. #endif
  41. #ifndef O_DIRECT
  42. #define O_DIRECT 0
  43. #endif
  44. int _starpu_silent;
  45. void _starpu_util_init(void)
  46. {
  47. _starpu_silent = starpu_get_env_number_default("STARPU_SILENT", 0);
  48. STARPU_HG_DISABLE_CHECKING(_starpu_silent);
  49. }
  50. #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
  51. #include <direct.h>
  52. static char * dirname(char * path)
  53. {
  54. char drive[_MAX_DRIVE];
  55. char dir[_MAX_DIR];
  56. /* Remove trailing slash */
  57. while (strlen(path) > 0 && (*(path+strlen(path)-1) == '/' || *(path+strlen(path)-1) == '\\'))
  58. *(path+strlen(path)-1) = '\0';
  59. _splitpath(path, drive, dir, NULL, NULL);
  60. _makepath(path, drive, dir, NULL, NULL);
  61. return path;
  62. }
  63. #else
  64. #include <libgen.h>
  65. #endif
  66. /* Function with behaviour like `mkdir -p'. This function was adapted from
  67. * http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/ */
  68. int _starpu_mkpath(const char *s, mode_t mode)
  69. {
  70. int olderrno;
  71. char *q, *r = NULL, *path = NULL, *up = NULL;
  72. int rv = -1;
  73. while (s[0] == '/' && s[1] == '/')
  74. s++;
  75. if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0
  76. #if defined(_WIN32)
  77. /* C:/ or C:\ */
  78. || (s[0] && s[1] == ':' && (s[2] == '/' || s[2] == '\\') && !s[3])
  79. #endif
  80. )
  81. return 0;
  82. if ((path = strdup(s)) == NULL)
  83. STARPU_ABORT();
  84. if ((q = strdup(s)) == NULL)
  85. STARPU_ABORT();
  86. if ((r = dirname(q)) == NULL)
  87. goto out;
  88. if ((up = strdup(r)) == NULL)
  89. STARPU_ABORT();
  90. if ((_starpu_mkpath(up, mode) == -1) && (errno != EEXIST))
  91. goto out;
  92. struct stat sb;
  93. if (stat(path, &sb) == 0)
  94. {
  95. if (!S_ISDIR(sb.st_mode))
  96. {
  97. _STARPU_MSG("Error: %s already exists and is not a directory:\n", path);
  98. STARPU_ABORT();
  99. }
  100. /* It already exists and is a directory. */
  101. rv = 0;
  102. }
  103. else
  104. {
  105. if ((mkdir(path, mode) == -1) && (errno != EEXIST))
  106. rv = -1;
  107. else
  108. rv = 0;
  109. }
  110. out:
  111. olderrno = errno;
  112. if (up)
  113. free(up);
  114. free(q);
  115. free(path);
  116. errno = olderrno;
  117. return rv;
  118. }
  119. void _starpu_mkpath_and_check(const char *path, mode_t mode)
  120. {
  121. int ret;
  122. ret = _starpu_mkpath(path, mode);
  123. if (ret == -1 && errno != EEXIST)
  124. {
  125. _STARPU_MSG("Error making StarPU directory %s:\n", path);
  126. perror("mkdir");
  127. STARPU_ABORT();
  128. }
  129. }
  130. char *_starpu_mkdtemp_internal(char *tmpl)
  131. {
  132. int len = (int)strlen(tmpl);
  133. int i;
  134. int count = 1;
  135. int ret;
  136. int first_letter = (int)'a';
  137. int nb_letters = 25;
  138. int len_template = 6;
  139. // Initialize template
  140. for(i=len-len_template ; i<len ; i++)
  141. {
  142. STARPU_ASSERT_MSG(tmpl[i] == 'X', "Template must terminate by XXXXXX\n");
  143. tmpl[i] = (char) (first_letter + starpu_lrand48() % nb_letters);
  144. }
  145. // Try to create directory
  146. ret = mkdir(tmpl, 0777);
  147. while ((ret == -1) && (errno == EEXIST))
  148. {
  149. // Generate a new name
  150. for(i=len-len_template ; i<len ; i++)
  151. {
  152. tmpl[i] = (char) (first_letter + starpu_lrand48() % nb_letters);
  153. }
  154. count ++;
  155. if (count == 1000)
  156. {
  157. // We consider that after 1000 tries, we will not be able to create a directory
  158. _STARPU_MSG("Error making StarPU temporary directory\n");
  159. return NULL;
  160. }
  161. ret = mkdir(tmpl, 0777);
  162. }
  163. return tmpl;
  164. }
  165. char *_starpu_mkdtemp(char *tmpl)
  166. {
  167. #if defined(HAVE_MKDTEMP)
  168. return mkdtemp(tmpl);
  169. #else
  170. return _starpu_mkdtemp_internal(tmpl);
  171. #endif
  172. }
  173. char *_starpu_mktemp(const char *directory, int flags, int *fd)
  174. {
  175. /* create template for mkstemp */
  176. const char *tmp = "STARPU_XXXXXX";
  177. char *baseCpy;
  178. _STARPU_MALLOC(baseCpy, strlen(directory)+1+strlen(tmp)+1);
  179. snprintf(baseCpy, strlen(directory)+1+strlen(tmp)+1, "%s/%s", directory, tmp);
  180. #if defined(STARPU_HAVE_WINDOWS)
  181. _mktemp(baseCpy);
  182. *fd = open(baseCpy, flags);
  183. #elif defined (HAVE_MKOSTEMP)
  184. flags &= ~O_RDWR;
  185. *fd = mkostemp(baseCpy, flags);
  186. if (*fd < 0 && (flags & O_DIRECT))
  187. {
  188. /* It failed, but perhaps still created the file, clean the mess */
  189. unlink(baseCpy);
  190. }
  191. #else
  192. STARPU_ASSERT(flags == (O_RDWR | O_BINARY) || flags == (O_RDWR | O_BINARY | O_DIRECT));
  193. *fd = mkstemp(baseCpy);
  194. #endif
  195. /* fail */
  196. if (*fd < 0)
  197. {
  198. int err = errno;
  199. if (err != ENOENT)
  200. _STARPU_DISP("Could not create temporary file in directory '%s', mk[o]stemp failed with error '%s'\n", directory, strerror(errno));
  201. free(baseCpy);
  202. errno = err;
  203. return NULL;
  204. }
  205. #if !defined(STARPU_HAVE_WINDOWS) && !defined (HAVE_MKOSTEMP)
  206. /* Add O_DIRECT after the mkstemp call */
  207. if ((flags & O_DIRECT) != 0)
  208. {
  209. int flag = fcntl(*fd, F_GETFL);
  210. flag |= O_DIRECT;
  211. if (fcntl(*fd, F_SETFL, flag) < 0)
  212. {
  213. int err = errno;
  214. _STARPU_DISP("Could set O_DIRECT on the temporary file in directory '%s', fcntl failed with error '%s'\n", directory, strerror(errno));
  215. close(*fd);
  216. unlink(baseCpy);
  217. free(baseCpy);
  218. errno = err;
  219. return NULL;
  220. }
  221. }
  222. #endif
  223. return baseCpy;
  224. }
  225. char *_starpu_mktemp_many(const char *directory, int depth, int flags, int *fd)
  226. {
  227. size_t len = strlen(directory);
  228. char path[len + depth*4 + 1];
  229. int i;
  230. struct stat sb;
  231. char *retpath;
  232. if (stat(directory, &sb) != 0)
  233. {
  234. _STARPU_DISP("Directory '%s' does not exist\n", directory);
  235. return NULL;
  236. }
  237. if (!S_ISDIR(sb.st_mode))
  238. {
  239. _STARPU_DISP("'%s' is not a directory\n", directory);
  240. return NULL;
  241. }
  242. memcpy(path, directory, len+1);
  243. retry:
  244. for (i = 0; i < depth; i++)
  245. {
  246. int r = starpu_lrand48();
  247. int ret;
  248. path[len + i*4 + 0] = '/';
  249. path[len + i*4 + 1] = '0' + (r/1)%10;
  250. path[len + i*4 + 2] = '0' + (r/10)%10;
  251. path[len + i*4 + 3] = '0' + (r/100)%10;
  252. path[len + i*4 + 4] = 0;
  253. ret = mkdir(path, 0777);
  254. if (ret == 0)
  255. continue;
  256. if (errno == EEXIST)
  257. continue;
  258. if (errno == ENOENT)
  259. {
  260. /* D'oh, somebody removed our directories in between,
  261. * restart from scratch */
  262. i = -1;
  263. continue;
  264. }
  265. _STARPU_DISP("Could not create temporary directory '%s', mkdir failed with error '%s'\n", path, strerror(errno));
  266. return NULL;
  267. }
  268. retpath = _starpu_mktemp(path, flags, fd);
  269. if (!retpath)
  270. {
  271. if (errno == ENOENT)
  272. {
  273. /* Somebody else dropped our directory, retry */
  274. goto retry;
  275. }
  276. /* That failed, drop our directories */
  277. _starpu_rmdir_many(path, depth);
  278. }
  279. return retpath;
  280. }
  281. void _starpu_rmtemp_many(char *path, int depth)
  282. {
  283. int i;
  284. for (i = 0; i < depth; i++)
  285. {
  286. path = dirname(path);
  287. if (rmdir(path) < 0 && errno != ENOTEMPTY && errno != EBUSY)
  288. _STARPU_DISP("Could not remove temporary directory '%s', rmdir failed with error '%s'\n", path, strerror(errno));
  289. }
  290. }
  291. void _starpu_rmdir_many(char *path, int depth)
  292. {
  293. int i;
  294. for (i = 0; i < depth; i++)
  295. {
  296. if (rmdir(path) < 0 && errno != ENOTEMPTY && errno != EBUSY && errno != ENOENT)
  297. _STARPU_DISP("Could not remove temporary directory '%s', rmdir failed with error '%s'\n", path, strerror(errno));
  298. path = dirname(path);
  299. }
  300. }
  301. int _starpu_ftruncate(int fd, size_t length)
  302. {
  303. return ftruncate(fd, length);
  304. }
  305. int _starpu_fftruncate(FILE *file, size_t length)
  306. {
  307. return ftruncate(fileno(file), length);
  308. }
  309. static int _starpu_warn_nolock(int err)
  310. {
  311. if (0
  312. #ifdef ENOLCK
  313. || err == ENOLCK
  314. #endif
  315. #ifdef ENOTSUP
  316. || err == ENOTSUP
  317. #endif
  318. #ifdef EOPNOTSUPP
  319. || err == EOPNOTSUPP
  320. #endif
  321. #ifdef EROFS
  322. || err == EROFS
  323. #endif
  324. )
  325. {
  326. static int warn;
  327. if (!warn)
  328. {
  329. warn = 1;
  330. _STARPU_DISP("warning: Couldn't lock performance file, StarPU home (%s, coming from $HOME or $STARPU_HOME) is probably on some network filesystem like NFS which does not support locking.\n", _starpu_get_home_path());
  331. }
  332. return 1;
  333. }
  334. return 0;
  335. }
  336. int _starpu_frdlock(FILE *file)
  337. {
  338. int ret;
  339. #if defined(_WIN32) && !defined(__CYGWIN__)
  340. do
  341. {
  342. ret = _locking(fileno(file), _LK_RLCK, 10);
  343. }
  344. while (ret == EDEADLOCK);
  345. #else
  346. struct flock lock =
  347. {
  348. .l_type = F_RDLCK,
  349. .l_whence = SEEK_SET,
  350. .l_start = 0,
  351. .l_len = 0
  352. };
  353. ret = fcntl(fileno(file), F_SETLKW, &lock);
  354. #endif
  355. if (ret != 0 && _starpu_warn_nolock(errno))
  356. return -1;
  357. STARPU_ASSERT(ret == 0);
  358. return ret;
  359. }
  360. int _starpu_frdunlock(FILE *file)
  361. {
  362. int ret;
  363. #if defined(_WIN32) && !defined(__CYGWIN__)
  364. # ifndef _LK_UNLCK
  365. # define _LK_UNLCK _LK_UNLOCK
  366. # endif
  367. ret = _lseek(fileno(file), 0, SEEK_SET);
  368. STARPU_ASSERT(ret == 0);
  369. ret = _locking(fileno(file), _LK_UNLCK, 10);
  370. #else
  371. struct flock lock =
  372. {
  373. .l_type = F_UNLCK,
  374. .l_whence = SEEK_SET,
  375. .l_start = 0,
  376. .l_len = 0
  377. };
  378. ret = fcntl(fileno(file), F_SETLKW, &lock);
  379. #endif
  380. if (ret != 0 && _starpu_warn_nolock(errno))
  381. return -1;
  382. STARPU_ASSERT(ret == 0);
  383. return ret;
  384. }
  385. int _starpu_fwrlock(FILE *file)
  386. {
  387. int ret;
  388. #if defined(_WIN32) && !defined(__CYGWIN__)
  389. ret = _lseek(fileno(file), 0, SEEK_SET);
  390. STARPU_ASSERT(ret == 0);
  391. do
  392. {
  393. ret = _locking(fileno(file), _LK_LOCK, 10);
  394. }
  395. while (ret == EDEADLOCK);
  396. #else
  397. struct flock lock =
  398. {
  399. .l_type = F_WRLCK,
  400. .l_whence = SEEK_SET,
  401. .l_start = 0,
  402. .l_len = 0
  403. };
  404. ret = fcntl(fileno(file), F_SETLKW, &lock);
  405. #endif
  406. if (ret != 0 && _starpu_warn_nolock(errno))
  407. return -1;
  408. STARPU_ASSERT(ret == 0);
  409. return ret;
  410. }
  411. int _starpu_fwrunlock(FILE *file)
  412. {
  413. fflush(file);
  414. return _starpu_frdunlock(file);
  415. }
  416. int _starpu_check_mutex_deadlock(starpu_pthread_mutex_t *mutex)
  417. {
  418. int ret;
  419. ret = starpu_pthread_mutex_trylock(mutex);
  420. if (!ret)
  421. {
  422. STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
  423. return 0;
  424. }
  425. if (ret == EBUSY)
  426. return 0;
  427. STARPU_ASSERT (ret != EDEADLK);
  428. return 1;
  429. }
  430. char *_starpu_get_home_path(void)
  431. {
  432. char *path = starpu_getenv("XDG_CACHE_HOME");
  433. if (!path)
  434. path = starpu_getenv("STARPU_HOME");
  435. #ifdef _WIN32
  436. if (!path)
  437. path = starpu_getenv("LOCALAPPDATA");
  438. if (!path)
  439. path = starpu_getenv("USERPROFILE");
  440. #endif
  441. if (!path)
  442. path = starpu_getenv("HOME");
  443. if (!path)
  444. {
  445. static int warn;
  446. path = starpu_getenv("TMPDIR");
  447. if (!path)
  448. path = starpu_getenv("TEMP");
  449. if (!path)
  450. path = starpu_getenv("TMP");
  451. if (!path)
  452. path = "/tmp";
  453. if (!warn)
  454. {
  455. warn = 1;
  456. _STARPU_DISP("couldn't find a $STARPU_HOME place to put .starpu data, using %s\n", path);
  457. }
  458. }
  459. return path;
  460. }
  461. #pragma weak starpu_mpi_world_rank
  462. extern int starpu_mpi_world_rank(void);
  463. void _starpu_gethostname(char *hostname, size_t size)
  464. {
  465. char *force_mpi_hostnames = starpu_getenv("STARPU_MPI_HOSTNAMES");
  466. char *forced_hostname = starpu_getenv("STARPU_HOSTNAME");
  467. if (force_mpi_hostnames && force_mpi_hostnames[0])
  468. {
  469. char *host=NULL, *srv_hosts;
  470. srv_hosts = strdup(force_mpi_hostnames);
  471. int rank;
  472. if (starpu_mpi_world_rank)
  473. {
  474. rank = starpu_mpi_world_rank();
  475. }
  476. else
  477. {
  478. _STARPU_DISP("StarPU-MPI unavailable, the rank of this process is 0");
  479. rank = 0;
  480. }
  481. if (force_mpi_hostnames != NULL)
  482. {
  483. host = strtok(srv_hosts, " ");
  484. while (rank-->0 && (host = strtok(NULL, " ")));
  485. if(rank>=0)
  486. {
  487. _STARPU_MSG("Missing hostnames in STARPU_MPI_HOSTNAMES\n");
  488. STARPU_ABORT();
  489. }
  490. }
  491. snprintf(hostname, size-1, "%s", host);
  492. free(srv_hosts);
  493. hostname[size-1] = 0;
  494. }
  495. else if (forced_hostname && forced_hostname[0])
  496. {
  497. snprintf(hostname, size-1, "%s", forced_hostname);
  498. hostname[size-1] = 0;
  499. }
  500. else
  501. {
  502. char *c;
  503. gethostname(hostname, size-1);
  504. hostname[size-1] = 0;
  505. c = strchr(hostname, '.');
  506. if (c)
  507. *c = 0;
  508. }
  509. }
  510. void starpu_sleep(float nb_sec)
  511. {
  512. #ifdef STARPU_SIMGRID
  513. # ifdef HAVE_SG_ACTOR_SLEEP_FOR
  514. sg_actor_sleep_for(nb_sec);
  515. # else
  516. MSG_process_sleep(nb_sec);
  517. # endif
  518. #elif defined(STARPU_HAVE_WINDOWS)
  519. Sleep(nb_sec * 1000);
  520. #else
  521. struct timespec req, rem;
  522. req.tv_sec = nb_sec;
  523. req.tv_nsec = (nb_sec - (float) req.tv_sec) * 1000000000;
  524. while (nanosleep(&req, &rem))
  525. req = rem;
  526. #endif
  527. }
  528. void starpu_usleep(float nb_micro_sec)
  529. {
  530. #ifdef STARPU_SIMGRID
  531. # ifdef HAVE_SG_ACTOR_SLEEP_FOR
  532. sg_actor_sleep_for(nb_micro_sec / 1000000);
  533. # else
  534. MSG_process_sleep(nb_micro_sec / 1000000);
  535. # endif
  536. #elif defined(STARPU_HAVE_WINDOWS)
  537. Sleep(nb_micro_sec / 1000);
  538. #elif HAVE_UNISTD_H
  539. usleep(nb_micro_sec);
  540. #else
  541. #error no implementation of usleep
  542. #endif
  543. }
  544. char *starpu_getenv(const char *str)
  545. {
  546. #ifndef STARPU_SIMGRID
  547. #if defined(STARPU_DEVEL) || defined(STARPU_DEBUG)
  548. struct _starpu_worker * worker;
  549. worker = _starpu_get_local_worker_key();
  550. if (worker && worker->worker_is_initialized)
  551. _STARPU_DISP( "getenv should not be called from running workers, only for main() or worker initialization, since it is not reentrant\n");
  552. #endif
  553. #endif
  554. return getenv(str);
  555. }
  556. int _strings_ncmp(const char *strings[], const char *str)
  557. {
  558. int pos = 0;
  559. while (strings[pos])
  560. {
  561. if ((strlen(str) == strlen(strings[pos]) && strncasecmp(str, strings[pos], strlen(strings[pos])) == 0))
  562. break;
  563. pos++;
  564. }
  565. if (strings[pos] == NULL)
  566. return -1;
  567. return pos;
  568. }
  569. int starpu_get_env_string_var_default(const char *str, const char *strings[], int defvalue)
  570. {
  571. int val;
  572. char *strval;
  573. strval = starpu_getenv(str);
  574. if (!strval)
  575. {
  576. val = defvalue;
  577. }
  578. else
  579. {
  580. val = _strings_ncmp(strings, strval);
  581. if (val < 0)
  582. {
  583. int i;
  584. _STARPU_MSG("\n");
  585. _STARPU_MSG("Invalid value '%s' for environment variable '%s'\n", strval, str);
  586. _STARPU_MSG("Valid values are:\n");
  587. for(i=0;strings[i]!=NULL;i++) _STARPU_MSG("\t%s\n",strings[i]);
  588. _STARPU_MSG("\n");
  589. STARPU_ABORT();
  590. }
  591. }
  592. return val;
  593. }
  594. static void remove_spaces(char *str)
  595. {
  596. int i = 0;
  597. int j = 0;
  598. while (str[j] != '\0')
  599. {
  600. if (isspace(str[j]))
  601. {
  602. j++;
  603. continue;
  604. }
  605. if (j > i)
  606. {
  607. str[i] = str[j];
  608. }
  609. i++;
  610. j++;
  611. }
  612. if (j > i)
  613. {
  614. str[i] = str[j];
  615. }
  616. }
  617. int starpu_get_env_size_default(const char *str, int defval)
  618. {
  619. int val;
  620. char *strval;
  621. strval = starpu_getenv(str);
  622. if (!strval)
  623. {
  624. val = defval;
  625. }
  626. else
  627. {
  628. char *value = strdup(strval);
  629. if (value == NULL)
  630. _STARPU_ERROR("memory allocation failed\n");
  631. remove_spaces(value);
  632. if (value[0] == '\0')
  633. {
  634. free(value);
  635. val = defval;
  636. }
  637. else
  638. {
  639. char *endptr = NULL;
  640. int mult = 1024;
  641. errno = 0;
  642. int v = (int)strtol(value, &endptr, 10);
  643. if (errno != 0)
  644. _STARPU_ERROR("could not parse environment variable '%s' with value '%s', strtol failed with error %s\n", str, value, strerror(errno));
  645. if (*endptr != '\0')
  646. {
  647. switch (*endptr)
  648. {
  649. case 'b':
  650. case 'B': mult = 1; break;
  651. case 'k':
  652. case 'K': mult = 1024; break;
  653. case 'm':
  654. case 'M': mult = 1024*1024; break;
  655. case 'g':
  656. case 'G': mult = 1024*1024*1024; break;
  657. default:
  658. _STARPU_ERROR("could not parse environment variable '%s' with value '%s' size suffix invalid\n", str, value);
  659. }
  660. }
  661. val = v*mult;
  662. free(value);
  663. }
  664. }
  665. return val;
  666. }
  667. void starpu_display_bindings(void)
  668. {
  669. #if defined(STARPU_HAVE_HWLOC) && !defined(STARPU_SIMGRID)
  670. int hwloc_ret = system("hwloc-ps -a -t -c");
  671. if (hwloc_ret)
  672. {
  673. _STARPU_DISP("hwloc-ps returned %d\n", hwloc_ret);
  674. fflush(stderr);
  675. }
  676. fflush(stdout);
  677. #else
  678. _STARPU_DISP("hwloc not available to display bindings.\n");
  679. #endif
  680. }