unsigned long INTERNAL qt_internal_get_env_num(const char *envariable, unsigned long dflt, unsigned long zerodflt) { const char *str; unsigned long tmp = dflt; if (dflt != 0) { char dflt_str[10]; snprintf(dflt_str, 10, "%lu", dflt); str = qt_internal_get_env_str(envariable, dflt_str); } else { str = qt_internal_get_env_str(envariable, NULL); } if (str && *str) { char *errptr; tmp = strtoul(str, &errptr, 0); if (*errptr != 0) { fprintf(stderr, "unparsable %s (%s)\n", envariable, str); tmp = dflt; } if (tmp == 0) { qthread_debug(CORE_DETAILS, "since envariable %s is 0, choosing default: %u\n", envariable, zerodflt); tmp = zerodflt; } else { qthread_debug(CORE_DETAILS, "envariable %s parsed as %u\n", envariable, tmp); } } return tmp; }
unsigned char INTERNAL qt_internal_get_env_bool(const char *envariable, unsigned char dflt) { const char *str; unsigned char tmp = dflt; const char *dflt_str; if (dflt) { dflt_str = "yes"; } else { dflt_str = "no"; } str = qt_internal_get_env_str(envariable, dflt_str); if (str && *str) { char *errptr; tmp = (strtoul(str, &errptr, 0) != 0); if (*errptr != 0) { if (!strcasecmp(str, "yes") || !strcasecmp(str, "true")) { tmp = 1; } else if (!strcasecmp(str, "no") || !strcasecmp(str, "false")) { tmp = 0; } else { fprintf(stderr, "unparsable %s (%s)\n", envariable, str); tmp = dflt; } } qthread_debug(CORE_DETAILS, "envariable %s parsed as %s\n", envariable, tmp?"TRUE":"FALSE"); } return tmp; }
void chpl_task_init(void) { int32_t numCoresPerLocale; int32_t numThreadsPerLocale; size_t callStackSize; pthread_t initer; char newenv_sheps[100] = { 0 }; char newenv_stack[100] = { 0 }; // Set up available hardware parallelism numThreadsPerLocale = chpl_task_getenvNumThreadsPerLocale(); numCoresPerLocale = chpl_numCoresOnThisLocale(); if (numThreadsPerLocale == 0) numThreadsPerLocale = chpl_comm_getMaxThreads(); if (0 < numThreadsPerLocale) { // We are assuming the user wants to constrain the hardware // resources used during this run of the application. // Unset relevant Qthreads environment variables qt_internal_unset_envstr("HWPAR"); qt_internal_unset_envstr("NUM_SHEPHERDS"); qt_internal_unset_envstr("NUM_WORKERS_PER_SHEPHERD"); if (numCoresPerLocale < numThreadsPerLocale) { if (2 == verbosity) { printf("QTHREADS: Ignored --numThreadsPerLocale=%d to prevent oversubsription of the system.\n", numThreadsPerLocale); } // Do not oversubscribe the system, use all available resources. numThreadsPerLocale = numCoresPerLocale; } // Set environment variable for Qthreads snprintf(newenv_sheps, 99, "%i", (int)numThreadsPerLocale); setenv("QT_HWPAR", newenv_sheps, 1); } else if (qt_internal_get_env_str("HWPAR", NULL) || qt_internal_get_env_str("NUM_SHEPHERDS", NULL) || qt_internal_get_env_str("NUM_WORKERS_PER_SHEPHERD", NULL)) { // Assume the user wants has manually set the desired Qthreads // environment variables. } else { // Default to using all hardware resources. numThreadsPerLocale = numCoresPerLocale; snprintf(newenv_sheps, 99, "%i", (int)numThreadsPerLocale); setenv("QT_HWPAR", newenv_sheps, 1); } // Precendence (high-to-low): // 1) Chapel minimum // 2) QTHREAD_STACK_SIZE // In practice we never get to #2, because the Chapel minimum is // always > 0, but we cover that case as a backstop. callStackSize = chpl_task_getMinCallStackSize(); if (callStackSize <= 0) callStackSize = 1024 * 1024 * sizeof(size_t); snprintf(newenv_stack, 99, "%zu", callStackSize); setenv("QT_STACK_SIZE", newenv_stack, 1); // Turn on informative Qthreads setting messages with Chapel's verbose flag if (verbosity == 2) { setenv("QT_INFO", "1", 1); } pthread_create(&initer, NULL, initializer, NULL); while (chpl_qthread_done_initializing == 0) SPINLOCK_BODY(); if (blockreport || taskreport) { if (signal(SIGINT, SIGINT_handler) == SIG_ERR) { perror("Could not register SIGINT handler"); } } }