/** * @ingroup SCHED * @brief Check if the scheduler needs to stop * * Check if there has been an exit or a finish request and if the conditions * are respected (empty pool for a finish request). * If we are on the primary ES, we will jump back to the main ULT, * if the scheduler has nothing to do. * * It is the user's responsibility to take proper measures to stop the * scheduling loop, depending on the value given by stop. * * @param[in] sched handle to the target scheduler * @param[out] stop indicate if the scheduler has to stop * @return Error code * @retval ABT_SUCCESS on success */ int ABT_sched_has_to_stop(ABT_sched sched, ABT_bool *stop) { int abt_errno = ABT_SUCCESS; *stop = ABT_FALSE; /* When this routine is called by an external thread, e.g., pthread */ if (lp_ABTI_local == NULL) { abt_errno = ABT_ERR_INV_XSTREAM; goto fn_exit; } ABTI_xstream *p_xstream = ABTI_local_get_xstream(); ABTI_sched *p_sched = ABTI_sched_get_ptr(sched); ABTI_CHECK_NULL_SCHED_PTR(p_sched); *stop = ABTI_sched_has_to_stop(p_sched, p_xstream); fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }
static void sched_run(ABT_sched sched) { uint32_t work_count = 0; sched_data *p_data; int num_pools; ABT_pool *p_pools; ABT_unit unit; int target; unsigned seed = time(NULL); CNT_DECL(run_cnt); ABTI_xstream *p_xstream = ABTI_local_get_xstream(); ABTI_sched *p_sched = ABTI_sched_get_ptr(sched); ABT_sched_get_data(sched, (void **)&p_data); ABT_sched_get_num_pools(sched, &num_pools); p_pools = (ABT_pool *)ABTU_malloc(num_pools * sizeof(ABT_pool)); ABT_sched_get_pools(sched, num_pools, 0, p_pools); while (1) { CNT_INIT(run_cnt, 0); /* Execute one work unit from the scheduler's pool */ ABT_pool pool = p_pools[0]; ABTI_pool *p_pool = ABTI_pool_get_ptr(pool); size_t size = ABTI_pool_get_size(p_pool); if (size > 0) { unit = ABTI_pool_pop(p_pool); if (unit != ABT_UNIT_NULL) { ABTI_xstream_run_unit(p_xstream, unit, p_pool); CNT_INC(run_cnt); } } else if (num_pools > 1) { /* Steal a work unit from other pools */ target = (num_pools == 2) ? 1 : (rand_r(&seed) % (num_pools-1) + 1); pool = p_pools[target]; p_pool = ABTI_pool_get_ptr(pool); size = ABTI_pool_get_size(p_pool); if (size > 0) { unit = ABTI_pool_pop(p_pool); LOG_EVENT_POOL_POP(p_pool, unit); if (unit != ABT_UNIT_NULL) { ABT_unit_set_associated_pool(unit, pool); ABTI_xstream_run_unit(p_xstream, unit, p_pool); CNT_INC(run_cnt); } } } if (++work_count >= p_data->event_freq) { ABT_bool stop = ABTI_sched_has_to_stop(p_sched, p_xstream); if (stop == ABT_TRUE) break; work_count = 0; ABTI_xstream_check_events(p_xstream, sched); SCHED_SLEEP(run_cnt, p_data->sleep_time); } } ABTU_free(p_pools); }