Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
/**
 * @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;
}
Exemplo n.º 3
0
/**
 * @ingroup SCHED
 * @brief   Set the specific data of the target user-defined scheduler
 *
 * This function will be called by the user during the initialization of his
 * user-defined scheduler.
 *
 * @param[in] sched handle to the scheduler
 * @param[in] data specific data of the scheduler
 * @return Error code
 * @retval ABT_SUCCESS on success
 */
int ABT_sched_set_data(ABT_sched sched, void *data)
{
    int abt_errno = ABT_SUCCESS;
    ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
    ABTI_CHECK_NULL_SCHED_PTR(p_sched);
    p_sched->data = data;

  fn_exit:
    return abt_errno;

  fn_fail:
    HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
    goto fn_exit;
}
Exemplo n.º 4
0
/**
 * @ingroup SCHED
 * @brief   Ask a scheduler to stop as soon as possible
 *
 * The scheduler will stop even if its pools are not empty. It is the user's
 * responsibility to ensure that the left work will be done by another scheduler.
 *
 * @param[in] sched  handle to the target scheduler
 * @return Error code
 * @retval ABT_SUCCESS on success
 */
int ABT_sched_exit(ABT_sched sched)
{
    int abt_errno = ABT_SUCCESS;
    ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
    ABTI_CHECK_NULL_SCHED_PTR(p_sched);

    ABTI_sched_set_request(p_sched, ABTI_SCHED_REQ_EXIT);

  fn_exit:
    return abt_errno;

  fn_fail:
    HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
    goto fn_exit;
}
Exemplo n.º 5
0
/**
 * @ingroup SCHED
 * @brief   Get the number of pools associated with scheduler.
 *
 * \c ABT_sched_get_num_pools returns the number of pools associated with
 * the target scheduler \c sched through \c num_pools.
 *
 * @param[in]  sched     handle to the target scheduler
 * @param[out] num_pools the number of all pools associated with \c sched
 * @return Error code
 * @retval ABT_SUCCESS       on success
 * @retval ABT_ERR_INV_SCHED invalid scheduler
 */
int ABT_sched_get_num_pools(ABT_sched sched, int *num_pools)
{
    int abt_errno = ABT_SUCCESS;

    ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
    ABTI_CHECK_NULL_SCHED_PTR(p_sched);

    *num_pools = p_sched->num_pools;

  fn_exit:
    return abt_errno;

  fn_fail:
    HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
    goto fn_exit;
}
Exemplo n.º 6
0
/**
 * @ingroup SCHED
 * @brief   Get the sum of the sizes of the pool of \c sched.
 *
 * The size includes the blocked and migrating ULTs.
 *
 * @param[in]  sched handle to the scheduler
 * @param[out] size  total number of work units
 * @return Error code
 * @retval ABT_SUCCESS on success
 */
int ABT_sched_get_total_size(ABT_sched sched, size_t *size)
{
    int abt_errno = ABT_SUCCESS;
    size_t pool_size = 0;

    ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
    ABTI_CHECK_NULL_SCHED_PTR(p_sched);

    pool_size = ABTI_sched_get_total_size(p_sched);

  fn_exit:
    *size = pool_size;
    return abt_errno;

  fn_fail:
    HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
    goto fn_exit;
}
Exemplo n.º 7
0
/**
 * @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;
}
Exemplo n.º 8
0
/**
 * @ingroup SCHED
 * @brief   Get the pools of the scheduler \c sched.
 *
 * @param[in]  sched     handle to the target scheduler
 * @param[in]  max_pools maximum number of pools to get
 * @param[in]  idx       index of the first pool to get
 * @param[out] pools     array of handles to the pools
 * @return Error code
 * @retval ABT_SUCCESS on success
 */
int ABT_sched_get_pools(ABT_sched sched, int max_pools, int idx,
                        ABT_pool *pools)
{
    int abt_errno = ABT_SUCCESS;

    ABTI_sched *p_sched = ABTI_sched_get_ptr(sched);
    ABTI_CHECK_NULL_SCHED_PTR(p_sched);

    ABTI_CHECK_TRUE(idx+max_pools <= p_sched->num_pools, ABT_ERR_SCHED);

    int p;
    for (p = idx; p < idx+max_pools; p++) {
        pools[p-idx] = p_sched->pools[p];
    }

  fn_exit:
    return abt_errno;

  fn_fail:
    HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
    goto fn_exit;
}
Exemplo n.º 9
0
/**
 * @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;
}