void chpl_task_init(void) { size_t css; int _ = enter_(); myth_globalattr_t attr[1]; int r = myth_globalattr_init(attr); (void)_; (void)r; assert(r == 0); /* set call stack size */ css = chpl_task_getEnvCallStackSize(); if (css) { myth_globalattr_set_stacksize(attr, css); } else { /* chpl_task_getDefaultCallStackSize() generally returns a too larger value. we do not use it. this essentially uses MassiveThreads default stack size */ #if 0 css = chpl_task_getDefaultCallStackSize(); myth_globalattr_set_stacksize(attr, css); #endif } myth_init_ex(attr); r = myth_key_create(&myth_key_serial_state, 0); assert(r == 0); (void)r; return_from_(); }
void chpl_thread_init(void(*threadBeginFn)(void*), void(*threadEndFn)(void)) { // // This threading layer does not have any inherent limit on the number // of threads. Its limit is the lesser of any limits imposed by the // comm layer and the user. // { uint32_t lim; if ((lim = chpl_task_getenvNumThreadsPerLocale()) > 0) maxThreads = lim; else if ((lim = chpl_comm_getMaxThreads()) > 0) maxThreads = lim; } // // Count the main thread on locale 0 as already existing, since it // is (or soon will be) running the main program. // if (chpl_nodeID == 0) numThreads = 1; // // If a value was specified for the call stack size config const, use // that (rounded up to a whole number of pages) to set the system and // pthread stack limits. // if (pthread_attr_init(&thread_attributes) != 0) chpl_internal_error("pthread_attr_init() failed"); // // If a value was specified for the call stack size, use that (rounded // up to a whole number of pages) to set the system and pthread stack // limits. This will in turn limit the stack for any task hosted by // either the main process or a pthread. // { size_t css; size_t pagesize = (size_t) sysconf(_SC_PAGESIZE); struct rlimit rlim; if ((css = chpl_task_getEnvCallStackSize()) == 0) css = chpl_task_getDefaultCallStackSize(); assert(css > 0); css = (css + pagesize - 1) & ~(pagesize - 1); if (getrlimit(RLIMIT_STACK, &rlim) != 0) chpl_internal_error("getrlimit() failed"); if (rlim.rlim_max != RLIM_INFINITY && css > rlim.rlim_max) { char warning[128]; sprintf(warning, "call stack size capped at %lu\n", (unsigned long)rlim.rlim_max); chpl_warning(warning, 0, 0); css = rlim.rlim_max; } rlim.rlim_cur = css; #ifndef __CYGWIN__ // // Cygwin can't do setrlimit(RLIMIT_STACK). // if (setrlimit(RLIMIT_STACK, &rlim) != 0) chpl_internal_error("setrlimit() failed"); #endif if (pthread_attr_setstacksize(&thread_attributes, css) != 0) chpl_internal_error("pthread_attr_setstacksize() failed"); } if (pthread_attr_getstacksize(&thread_attributes, &threadCallStackSize) != 0) chpl_internal_error("pthread_attr_getstacksize() failed"); saved_threadBeginFn = threadBeginFn; saved_threadEndFn = threadEndFn; CHPL_TLS_INIT(chpl_thread_id); CHPL_TLS_SET(chpl_thread_id, (intptr_t) --curr_thread_id); CHPL_TLS_INIT(chpl_thread_data); pthread_mutex_init(&thread_info_lock, NULL); pthread_mutex_init(&numThreadsLock, NULL); // // This is something of a hack, but it makes us a bit more resilient // if we're out of memory or near to it at shutdown time. Launch, // cancel, and join with an initial pthread, forcing initialization // needed by any of those activities. (In particular we have found // that cancellation needs to dlopen(3) a shared object, which fails // if we are out of memory. Doing it now means that shared object is // already available when we need it later.) // { pthread_t initial_pthread; if (!pthread_create(&initial_pthread, NULL, initial_pthread_func, NULL)) { (void) pthread_cancel(initial_pthread); (void) pthread_join(initial_pthread, NULL); } } }