static int sched_init(ABT_sched sched, ABT_sched_config config) { int abt_errno = ABT_SUCCESS; /* Default settings */ sched_data *p_data = (sched_data *)ABTU_malloc(sizeof(sched_data)); p_data->event_freq = ABTI_global_get_sched_event_freq(); #ifdef ABT_CONFIG_USE_SCHED_SLEEP p_data->sleep_time.tv_sec = 0; p_data->sleep_time.tv_nsec = ABTI_global_get_sched_sleep_nsec(); #endif /* Set the variables from the config */ ABT_sched_config_read(config, 1, &p_data->event_freq); abt_errno = ABT_sched_set_data(sched, (void *)p_data); ABTI_CHECK_ERROR(abt_errno); fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_WITH_CODE("randws: sched_init", abt_errno); goto fn_exit; }
int ABTI_sched_free(ABTI_sched *p_sched) { int abt_errno = ABT_SUCCESS; int p; /* If sched is currently used, free is not allowed. */ if (p_sched->used != ABTI_SCHED_NOT_USED) { abt_errno = ABT_ERR_SCHED; goto fn_fail; } /* If sched is a default provided one, it should free its pool here. * Otherwise, freeing the pool is the user's reponsibility. */ for (p = 0; p < p_sched->num_pools; p++) { ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[p]); int32_t num_scheds = ABTI_pool_release(p_pool); if (p_pool->automatic == ABT_TRUE && num_scheds == 0) { abt_errno = ABT_pool_free(p_sched->pools+p); ABTI_CHECK_ERROR(abt_errno); } } ABTU_free(p_sched->pools); /* Free the associated work unit */ if (p_sched->type == ABT_SCHED_TYPE_ULT) { if (p_sched->p_thread) { if (p_sched->p_thread->type == ABTI_THREAD_TYPE_MAIN_SCHED) { ABTI_thread_free_main_sched(p_sched->p_thread); } else { ABTI_thread_free(p_sched->p_thread); } } } else if (p_sched->type == ABT_SCHED_TYPE_TASK) { if (p_sched->p_task) { ABTI_task_free(p_sched->p_task); } } LOG_EVENT("[S%" PRIu64 "] freed\n", p_sched->id); p_sched->free(ABTI_sched_get_handle(p_sched)); p_sched->data = NULL; ABTU_free(p_sched); fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }
/** * @ingroup SCHED * @brief Release the scheduler object associated with sched handle. * * If this routine successfully returns, sched is set as ABT_SCHED_NULL. The * scheduler will be automatically freed. * If \c sched is currently being used by an ES or in a pool, freeing \c sched * is not allowed. In this case, this routine fails and returns \c * ABT_ERR_SCHED. * * @param[in,out] sched handle to the target scheduler * @return Error code * @retval ABT_SUCCESS on success */ int ABT_sched_free(ABT_sched *sched) { int abt_errno = ABT_SUCCESS; ABTI_sched *p_sched = ABTI_sched_get_ptr(*sched); ABTI_CHECK_NULL_SCHED_PTR(p_sched); /* Free the scheduler */ abt_errno = ABTI_sched_free(p_sched); ABTI_CHECK_ERROR(abt_errno); /* Return value */ *sched = ABT_SCHED_NULL; fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }
/** * @ingroup SCHED * @brief Create a new user-defined scheduler and return its handle through * newsched. * * The pools used by the new scheduler are provided by \c pools. The contents * of this array is copied, so it can be freed. If a pool in the array is * ABT_POOL_NULL, the corresponding pool is automatically created. * The config must have been created by ABT_sched_config_create, and will be * used as argument in the initialization. If no specific configuration is * required, the parameter will be ABT_CONFIG_NULL. * * @param[in] def definition required for scheduler creation * @param[in] num_pools number of pools associated with this scheduler * @param[in] pools pools associated with this scheduler * @param[in] config specific config used during the scheduler creation * @param[out] newsched handle to a new scheduler * @return Error code * @retval ABT_SUCCESS on success */ int ABT_sched_create(ABT_sched_def *def, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched) { int abt_errno = ABT_SUCCESS; ABTI_sched *p_sched; int p; ABTI_CHECK_TRUE(newsched != NULL, ABT_ERR_SCHED); p_sched = (ABTI_sched *)ABTU_malloc(sizeof(ABTI_sched)); /* Copy of the contents of pools */ ABT_pool *pool_list; pool_list = (ABT_pool *)ABTU_malloc(num_pools*sizeof(ABT_pool)); for (p = 0; p < num_pools; p++) { if (pools[p] == ABT_POOL_NULL) { abt_errno = ABT_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPSC, ABT_TRUE, &pool_list[p]); ABTI_CHECK_ERROR(abt_errno); } else { pool_list[p] = pools[p]; } } /* Check if the pools are available */ for (p = 0; p < num_pools; p++) { ABTI_pool_retain(ABTI_pool_get_ptr(pool_list[p])); } p_sched->used = ABTI_SCHED_NOT_USED; p_sched->automatic = ABT_FALSE; p_sched->kind = ABTI_sched_get_kind(def); p_sched->state = ABT_SCHED_STATE_READY; p_sched->request = 0; p_sched->pools = pool_list; p_sched->num_pools = num_pools; p_sched->type = def->type; p_sched->p_thread = NULL; p_sched->p_task = NULL; p_sched->p_ctx = NULL; p_sched->init = def->init; p_sched->run = def->run; p_sched->free = def->free; p_sched->get_migr_pool = def->get_migr_pool; #ifdef ABT_CONFIG_USE_DEBUG_LOG p_sched->id = ABTI_sched_get_new_id(); #endif LOG_EVENT("[S%" PRIu64 "] created\n", p_sched->id); /* Return value */ *newsched = ABTI_sched_get_handle(p_sched); /* Specific initialization */ p_sched->init(*newsched, config); fn_exit: return abt_errno; fn_fail: *newsched = ABT_SCHED_NULL; HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }
/** * @ingroup SCHED * @brief Create a predefined scheduler. * * \c ABT_sched_create_basic() creates a predefined scheduler and returns its * handle through \c newsched. The pools used by the new scheduler are * provided by \c pools. The contents of this array is copied, so it can be * freed. If a pool in the array is \c ABT_POOL_NULL, the corresponding pool is * automatically created. The pool array can be \c NULL. In this case, all * the pools will be created automatically. The config must have been created * by \c ABT_sched_config_create(), and will be used as argument in the * initialization. If no specific configuration is required, the parameter can * be \c ABT_CONFIG_NULL. * * NOTE: The new scheduler will be automatically freed when it is not used * anymore or its associated ES is terminated. Accordingly, the pools * associated with the new scheduler will be automatically freed if they are * exclusive to the scheduler and are not user-defined ones (i.e., created by * \c ABT_pool_create_basic() or implicitly created because \c pools is \c NULL * or a pool in the \c pools array is \c ABT_POOL_NULL). If the pools were * created using \c ABT_pool_create() by the user, they have to be freed * explicitly with \c ABT_pool_free(). * * @param[in] predef predefined scheduler * @param[in] num_pools number of pools associated with this scheduler * @param[in] pools pools associated with this scheduler * @param[in] config specific config used during the scheduler creation * @param[out] newsched handle to a new scheduler * @return Error code * @retval ABT_SUCCESS on success */ int ABT_sched_create_basic(ABT_sched_predef predef, int num_pools, ABT_pool *pools, ABT_sched_config config, ABT_sched *newsched) { int abt_errno = ABT_SUCCESS; ABT_pool_access access; ABT_bool automatic; int p; /* We set the access to the default one */ access = ABT_POOL_ACCESS_MPSC; automatic = ABT_TRUE;; /* We read the config and set the configured parameters */ abt_errno = ABTI_sched_config_read_global(config, &access, &automatic); ABTI_CHECK_ERROR(abt_errno); /* A pool array is provided, predef has to be compatible */ if (pools != NULL) { /* Copy of the contents of pools */ ABT_pool *pool_list; pool_list = (ABT_pool *)ABTU_malloc(num_pools*sizeof(ABT_pool)); for (p = 0; p < num_pools; p++) { if (pools[p] == ABT_POOL_NULL) { abt_errno = ABT_pool_create_basic(ABT_POOL_FIFO, access, ABT_TRUE, &pool_list[p]); ABTI_CHECK_ERROR(abt_errno); } else { pool_list[p] = pools[p]; } } /* Creation of the scheduler */ switch (predef) { case ABT_SCHED_DEFAULT: case ABT_SCHED_BASIC: abt_errno = ABT_sched_create(ABTI_sched_get_basic_def(), num_pools, pool_list, ABT_SCHED_CONFIG_NULL, newsched); break; case ABT_SCHED_PRIO: abt_errno = ABT_sched_create(ABTI_sched_get_prio_def(), num_pools, pool_list, ABT_SCHED_CONFIG_NULL, newsched); break; case ABT_SCHED_RANDWS: abt_errno = ABT_sched_create(ABTI_sched_get_randws_def(), num_pools, pool_list, ABT_SCHED_CONFIG_NULL, newsched); break; default: abt_errno = ABT_ERR_INV_SCHED_PREDEF; break; } ABTI_CHECK_ERROR(abt_errno); ABTU_free(pool_list); } /* No pool array is provided, predef has to be compatible */ else { /* Set the number of pools */ switch (predef) { case ABT_SCHED_DEFAULT: case ABT_SCHED_BASIC: num_pools = 1; break; case ABT_SCHED_PRIO: num_pools = ABTI_SCHED_NUM_PRIO; break; case ABT_SCHED_RANDWS: num_pools = 1; break; default: abt_errno = ABT_ERR_INV_SCHED_PREDEF; ABTI_CHECK_ERROR(abt_errno); break; } /* Creation of the pools */ /* To avoid the malloc overhead, we use a stack array. */ ABT_pool pool_list[ABTI_SCHED_NUM_PRIO]; int p; for (p = 0; p < num_pools; p++) { abt_errno = ABT_pool_create_basic(ABT_POOL_FIFO, access, ABT_TRUE, pool_list+p); ABTI_CHECK_ERROR(abt_errno); } /* Creation of the scheduler */ switch (predef) { case ABT_SCHED_DEFAULT: case ABT_SCHED_BASIC: abt_errno = ABT_sched_create(ABTI_sched_get_basic_def(), num_pools, pool_list, config, newsched); break; case ABT_SCHED_PRIO: abt_errno = ABT_sched_create(ABTI_sched_get_prio_def(), num_pools, pool_list, config, newsched); break; case ABT_SCHED_RANDWS: abt_errno = ABT_sched_create(ABTI_sched_get_randws_def(), num_pools, pool_list, config, newsched); break; default: abt_errno = ABT_ERR_INV_SCHED_PREDEF; ABTI_CHECK_ERROR(abt_errno); break; } } ABTI_CHECK_ERROR(abt_errno); ABTI_sched *p_sched = ABTI_sched_get_ptr(*newsched); p_sched->automatic = automatic; fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); *newsched = ABT_SCHED_NULL; goto fn_exit; }