/* StarPU --- Runtime system for heterogeneous multicore architectures. * * Copyright (C) 2010-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria * Copyright (C) 2020 Federal University of Rio Grande do Sul (UFRGS) * * StarPU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * StarPU is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU Lesser General Public License in COPYING.LGPL for more details. */ #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #define mkdir(path, mode) mkdir(path) #if !defined(__MINGW32__) #define ftruncate(fd, length) _chsize(fd, length) #endif #endif #ifndef O_BINARY #define O_BINARY 0 #endif #if !defined(O_DIRECT) && defined(F_NOCACHE) #define O_DIRECT F_NOCACHE #endif #ifndef O_DIRECT #define O_DIRECT 0 #endif int _starpu_silent; void _starpu_util_init(void) { _starpu_silent = starpu_get_env_number_default("STARPU_SILENT", 0); STARPU_HG_DISABLE_CHECKING(_starpu_silent); } #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) #include static char * dirname(char * path) { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; /* Remove trailing slash */ while (strlen(path) > 0 && (*(path+strlen(path)-1) == '/' || *(path+strlen(path)-1) == '\\')) *(path+strlen(path)-1) = '\0'; _splitpath(path, drive, dir, NULL, NULL); _makepath(path, drive, dir, NULL, NULL); return path; } #else #include #endif /* Function with behaviour like `mkdir -p'. This function was adapted from * http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/ */ int _starpu_mkpath(const char *s, mode_t mode) { int olderrno; char *q, *r = NULL, *path = NULL, *up = NULL; int rv = -1; while (s[0] == '/' && s[1] == '/') s++; if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0 #if defined(_WIN32) /* C:/ or C:\ */ || (s[0] && s[1] == ':' && (s[2] == '/' || s[2] == '\\') && !s[3]) #endif ) return 0; if ((path = strdup(s)) == NULL) STARPU_ABORT(); if ((q = strdup(s)) == NULL) STARPU_ABORT(); if ((r = dirname(q)) == NULL) goto out; if ((up = strdup(r)) == NULL) STARPU_ABORT(); if ((_starpu_mkpath(up, mode) == -1) && (errno != EEXIST)) goto out; struct stat sb; if (stat(path, &sb) == 0) { if (!S_ISDIR(sb.st_mode)) { _STARPU_MSG("Error: %s is not a directory:\n", path); STARPU_ABORT(); } /* It already exists and is a directory. */ rv = 0; } else { if ((mkdir(path, mode) == -1) && (errno != EEXIST)) rv = -1; else rv = 0; } out: olderrno = errno; if (up) free(up); free(q); free(path); errno = olderrno; return rv; } void _starpu_mkpath_and_check(const char *path, mode_t mode) { int ret; ret = _starpu_mkpath(path, mode); if (ret == -1 && errno != EEXIST) { _STARPU_MSG("Error making StarPU directory %s:\n", path); perror("mkdir"); STARPU_ABORT(); } } char *_starpu_mkdtemp_internal(char *tmpl) { int len = (int)strlen(tmpl); int i; int count = 1; int ret; int first_letter = (int)'a'; int nb_letters = 25; int len_template = 6; // Initialize template for(i=len-len_template ; i0 && (host = strtok(NULL, " "))); if(rank>=0) { _STARPU_MSG("Missing hostnames in STARPU_MPI_HOSTNAMES\n"); STARPU_ABORT(); } } snprintf(hostname, size-1, "%s", host); free(srv_hosts); hostname[size-1] = 0; } else if (forced_hostname && forced_hostname[0]) { snprintf(hostname, size-1, "%s", forced_hostname); hostname[size-1] = 0; } else { char *c; gethostname(hostname, size-1); hostname[size-1] = 0; c = strchr(hostname, '.'); if (c) *c = 0; } } void starpu_sleep(float nb_sec) { #ifdef STARPU_SIMGRID # ifdef HAVE_SG_ACTOR_SLEEP_FOR sg_actor_sleep_for(nb_sec); # else MSG_process_sleep(nb_sec); # endif #elif defined(STARPU_HAVE_WINDOWS) Sleep(nb_sec * 1000); #else struct timespec req, rem; req.tv_sec = nb_sec; req.tv_nsec = (nb_sec - (float) req.tv_sec) * 1000000000; while (nanosleep(&req, &rem)) req = rem; #endif } void starpu_usleep(float nb_micro_sec) { #ifdef STARPU_SIMGRID # ifdef HAVE_SG_ACTOR_SLEEP_FOR sg_actor_sleep_for(nb_micro_sec / 1000000); # else MSG_process_sleep(nb_micro_sec / 1000000); # endif #elif defined(STARPU_HAVE_WINDOWS) Sleep(nb_micro_sec / 1000); #elif HAVE_UNISTD_H usleep(nb_micro_sec); #else #error no implementation of usleep #endif } char *starpu_getenv(const char *str) { #ifndef STARPU_SIMGRID #if defined(STARPU_DEVEL) || defined(STARPU_DEBUG) struct _starpu_worker * worker; worker = _starpu_get_local_worker_key(); if (worker && worker->worker_is_initialized) _STARPU_DISP( "getenv should not be called from running workers, only for main() or worker initialization, since it is not reentrant\n"); #endif #endif return getenv(str); } int _strings_ncmp(const char *strings[], const char *str) { int pos = 0; while (strings[pos]) { if ((strlen(str) == strlen(strings[pos]) && strncasecmp(str, strings[pos], strlen(strings[pos])) == 0)) break; pos++; } if (strings[pos] == NULL) return -1; return pos; } int starpu_get_env_string_var_default(const char *str, const char *strings[], int defvalue) { int val; char *strval; strval = starpu_getenv(str); if (!strval) { val = defvalue; } else { val = _strings_ncmp(strings, strval); if (val < 0) { int i; _STARPU_MSG("\n"); _STARPU_MSG("Invalid value '%s' for environment variable '%s'\n", strval, str); _STARPU_MSG("Valid values are:\n"); for(i=0;strings[i]!=NULL;i++) _STARPU_MSG("\t%s\n",strings[i]); _STARPU_MSG("\n"); STARPU_ABORT(); } } return val; } static void remove_spaces(char *str) { int i = 0; int j = 0; while (str[j] != '\0') { if (isspace(str[j])) { j++; continue; } if (j > i) { str[i] = str[j]; } i++; j++; } if (j > i) { str[i] = str[j]; } } int starpu_get_env_size_default(const char *str, int defval) { int val; char *strval; strval = starpu_getenv(str); if (!strval) { val = defval; } else { char *value = strdup(strval); if (value == NULL) _STARPU_ERROR("memory allocation failed\n"); remove_spaces(value); if (value[0] == '\0') { free(value); val = defval; } else { char *endptr = NULL; int mult = 1024; errno = 0; int v = (int)strtol(value, &endptr, 10); if (errno != 0) _STARPU_ERROR("could not parse environment variable '%s' with value '%s', strtol failed with error %s\n", str, value, strerror(errno)); if (*endptr != '\0') { switch (*endptr) { case 'b': case 'B': mult = 1; break; case 'k': case 'K': mult = 1024; break; case 'm': case 'M': mult = 1024*1024; break; case 'g': case 'G': mult = 1024*1024*1024; break; default: _STARPU_ERROR("could not parse environment variable '%s' with value '%s' size suffix invalid\n", str, value); } } val = v*mult; free(value); } } return val; } void starpu_display_bindings(void) { #if defined(STARPU_HAVE_HWLOC) && !defined(STARPU_SIMGRID) int hwloc_ret = system("hwloc-ps -a -t -c"); if (hwloc_ret) { _STARPU_DISP("hwloc-ps returned %d\n", hwloc_ret); fflush(stderr); } fflush(stdout); #else _STARPU_DISP("hwloc not available to display bindings.\n"); #endif }