void chpl_task_addToTaskList(chpl_fn_int_t fid, void *arg, c_sublocid_t subloc, chpl_task_list_p *task_list, int32_t task_list_locale, chpl_bool is_begin_stmt, int lineno, chpl_string filename) { qthread_shepherd_id_t const here_shep_id = qthread_shep(); chpl_bool serial_state = chpl_task_getSerial(); chpl_qthread_wrapper_args_t wrapper_args = {chpl_ftable[fid], arg, filename, lineno, false, {subloc, serial_state}}; assert(subloc != c_sublocid_none); PROFILE_INCR(profile_task_addToTaskList,1); if (serial_state) { syncvar_t ret = SYNCVAR_STATIC_EMPTY_INITIALIZER; qthread_fork_syncvar_copyargs_to(chapel_wrapper, &wrapper_args, sizeof(chpl_qthread_wrapper_args_t), &ret, here_shep_id); qthread_syncvar_readFF(NULL, &ret); } else if (subloc == c_sublocid_any) { qthread_fork_copyargs(chapel_wrapper, &wrapper_args, sizeof(chpl_qthread_wrapper_args_t), NULL); } else { qthread_fork_copyargs_to(chapel_wrapper, &wrapper_args, sizeof(chpl_qthread_wrapper_args_t), NULL, (qthread_shepherd_id_t) subloc); } }
static inline void spawn(int locale, chpl_fn_int_t fid, void *arg, int32_t arg_size, int32_t arg_tid, aligned_t *ret) { qthread_debug(CHAPEL_CALLS, "[%d] begin: locale=%d, fid=%d, arg_size=%d\n", chpl_localeID, locale, fid, arg_size); spawn_wrapper_args_t *wargs; size_t const wargs_size = sizeof(spawn_wrapper_args_t) + arg_size; wargs = (spawn_wrapper_args_t *)chpl_mem_allocMany(1, wargs_size, CHPL_RT_MD_COMM_FORK_SEND_INFO, 0, 0); wargs->serial_state = chpl_task_getSerial(); wargs->fid = fid; wargs->arg_size = arg_size; memcpy(&(wargs->arg), arg, arg_size); if (chpl_localeID == locale) { int const rc = qthread_fork_copyargs(spawn_wrapper, wargs, wargs_size, ret); assert(QTHREAD_SUCCESS == rc); } else { int const rc = qthread_fork_remote(spawn_wrapper, wargs, ret, locale, wargs_size); assert(SPR_OK == rc); } chpl_mem_free(wargs, 0, NULL); qthread_debug(CHAPEL_CALLS, "[%d] end: locale=%d, fid=%d, arg_size=%d\n", chpl_localeID, locale, fid, arg_size); }
// // Call a function in a task. // void chpl_task_taskCallFTable(chpl_fn_int_t fid, // function to call //void* arg, // function arg chpl_task_bundle_t* arg,// function arg size_t arg_size, // length of arg c_sublocid_t subloc, // desired sublocale int lineno, // line at which function begins int32_t filename) { // name of file containing function enter_(); if (chpl_task_getSerial()) { chpl_ftable[fid](arg); } else { myth_chpl_create(/* serial_state = */ false, /* is_executeOn = */ false, lineno, filename, subloc, fid, get_next_task_id(), arg, arg_size); } return_from_(); }
// // Launch a task that is the logical continuation of some other task, // but on a different locale. This is used to invoke the body of an // "on" statement. // void chpl_task_startMovedTask(chpl_fn_int_t fid, // function to call chpl_fn_p fp, //void* arg, // function arg chpl_task_bundle_t* arg,// function arg size_t arg_size, // length of arg in bytes c_sublocid_t subloc, // desired sublocale chpl_taskID_t id, // task identifier chpl_bool serial_state) { // serial state enter_(); if (chpl_task_getSerial()) { chpl_ftable[fid](arg); } else { myth_chpl_create(/* serial_state = */ false, /* is_executeOn = */ true, 0, CHPL_FILE_IDX_UNKNOWN, subloc, fid, id, arg, arg_size); } return_from_(); }
// // Task list processing. These are called by the compiler-emitted // code for all parallel constructs. addToTaskList() is called for // each task and builds a list of all of them. processTaskList() // actually adds the tasks to the task pool. executeTasksInList() // makes sure all the tasks have at least started. freeTaskList() // just reclaims space associated with the list. // void chpl_task_addToTaskList( chpl_fn_int_t fid, // function to call for task //void* arg, // argument to the function chpl_task_bundle_t* arg, size_t arg_size, c_sublocid_t subloc, // desired sublocale void** p_task_list_void, // task list c_nodeid_t task_list_locale, // locale (node) where task list resides chpl_bool is_begin_stmt, // is begin{} stmt? (vs. cobegin or coforall) int lineno, // line at which function begins int32_t filename) { // name of file containing function enter_(); if (chpl_task_getSerial()) { chpl_ftable[fid](arg); } else { myth_chpl_create(/* serial_state = */ false, /* is_executeOn = */ false, lineno, filename, subloc, fid, get_next_task_id(), arg, arg_size); } return_from_(); }
void chpl_task_executeTasksInList(void** p_task_list_void) { task_pool_p* p_task_list_head = (task_pool_p*) p_task_list_void; task_pool_p curr_ptask; task_pool_p child_ptask; // // If we're serial, all the tasks have already been executed. // if (chpl_task_getSerial()) return; curr_ptask = get_current_ptask(); while (*p_task_list_head != NULL) { chpl_fn_p task_to_run_fun = NULL; // begin critical section chpl_thread_mutexLock(&threading_lock); if ((child_ptask = *p_task_list_head) != NULL) { task_to_run_fun = child_ptask->fun; dequeue_task(child_ptask); } // end critical section chpl_thread_mutexUnlock(&threading_lock); if (task_to_run_fun == NULL) continue; set_current_ptask(child_ptask); // begin critical section chpl_thread_mutexLock(&extra_task_lock); extra_task_cnt++; // end critical section chpl_thread_mutexUnlock(&extra_task_lock); if (do_taskReport) { chpl_thread_mutexLock(&taskTable_lock); chpldev_taskTable_set_suspended(curr_ptask->id); chpldev_taskTable_set_active(child_ptask->id); chpl_thread_mutexUnlock(&taskTable_lock); } if (blockreport) initializeLockReportForThread(); chpl_task_do_callbacks(chpl_task_cb_event_kind_begin, child_ptask->filename, child_ptask->lineno, child_ptask->id, child_ptask->is_executeOn); (*task_to_run_fun)(child_ptask->arg); chpl_task_do_callbacks(chpl_task_cb_event_kind_end, child_ptask->filename, child_ptask->lineno, child_ptask->id, child_ptask->is_executeOn); if (do_taskReport) { chpl_thread_mutexLock(&taskTable_lock); chpldev_taskTable_set_active(curr_ptask->id); chpldev_taskTable_remove(child_ptask->id); chpl_thread_mutexUnlock(&taskTable_lock); } // begin critical section chpl_thread_mutexLock(&extra_task_lock); extra_task_cnt--; // end critical section chpl_thread_mutexUnlock(&extra_task_lock); set_current_ptask(curr_ptask); chpl_mem_free(child_ptask, 0, 0); } }
chpl_thread_setPrivateData(tp); (*comm_task_fn)(arg); } void chpl_task_addToTaskList(chpl_fn_int_t fid, void* arg, c_sublocid_t subloc, chpl_task_list_p *task_list, int32_t task_list_locale, chpl_bool is_begin_stmt, int lineno, c_string filename) { chpl_task_prvDataImpl_t chpl_data = { .prvdata = { .serial_state = chpl_task_getSerial() } }; assert(subloc == 0 || subloc == c_sublocid_any); if (task_list_locale == chpl_nodeID) { chpl_task_list_p ltask; ltask = (chpl_task_list_p) chpl_mem_alloc(sizeof(struct chpl_task_list), CHPL_RT_MD_TASK_LIST_DESC, 0, 0); ltask->filename = filename; ltask->lineno = lineno; ltask->fun = chpl_ftable[fid]; ltask->arg = arg; ltask->ptask = NULL;