Пример #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);
}
Пример #2
0
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;
}
Пример #3
0
/* Compared to \c ABTI_sched_get_total_size, ABTI_sched_get_effective_size does
 * not count the number of blocked ULTs if a pool has more than one consumer or
 * the caller ES is not the latest consumer. This is necessary when the ES
 * associated with the target scheduler has to be joined and the pool is shared
 * between different schedulers associated with different ESs. */
size_t ABTI_sched_get_effective_size(ABTI_sched *p_sched)
{
    size_t pool_size = 0;
    int p;

#ifndef ABT_CONFIG_DISABLE_POOL_CONSUMER_CHECK
    ABTI_xstream *p_xstream = ABTI_local_get_xstream();
#endif

    for (p = 0; p < p_sched->num_pools; p++) {
        ABT_pool pool = p_sched->pools[p];
        ABTI_pool *p_pool = ABTI_pool_get_ptr(pool);
        pool_size += p_pool->p_get_size(pool);
        pool_size += p_pool->num_migrations;
        switch (p_pool->access) {
            case ABT_POOL_ACCESS_PRIV:
                pool_size += p_pool->num_blocked;
                break;
            case ABT_POOL_ACCESS_SPSC:
            case ABT_POOL_ACCESS_MPSC:
            case ABT_POOL_ACCESS_SPMC:
            case ABT_POOL_ACCESS_MPMC:
#ifdef ABT_CONFIG_DISABLE_POOL_CONSUMER_CHECK
                if (p_pool->num_scheds == 1) {
                    pool_size += p_pool->num_blocked;
                }
#else
                if (p_pool->num_scheds == 1 && p_pool->consumer == p_xstream) {
                    pool_size += p_pool->num_blocked;
                }
#endif
                break;
            default: break;
        }
    }

    return pool_size;
}
Пример #4
0
void ABTI_sched_print(ABTI_sched *p_sched, FILE *p_os, int indent,
                      ABT_bool print_sub)
{
    char *prefix = ABTU_get_indent_str(indent);

    if (p_sched == NULL) {
        fprintf(p_os, "%s== NULL SCHED ==\n", prefix);
        goto fn_exit;
    }

    ABTI_sched_kind kind;
    char *kind_str, *type, *state, *used;
    char *pools_str;
    int i;
    size_t size, pos;

    kind = p_sched->kind;
    if (kind == ABTI_sched_get_kind(ABTI_sched_get_basic_def())) {
        kind_str = "BASIC";
    } else if (kind == ABTI_sched_get_kind(ABTI_sched_get_prio_def())) {
        kind_str = "PRIO";
    } else {
        kind_str = "USER";
    }

    switch (p_sched->type) {
        case ABT_SCHED_TYPE_ULT:  type = "ULT"; break;
        case ABT_SCHED_TYPE_TASK: type = "TASKLET"; break;
        default:                  type = "UNKNOWN"; break;
    }
    switch (p_sched->state) {
        case ABT_SCHED_STATE_READY:      state = "READY"; break;
        case ABT_SCHED_STATE_RUNNING:    state = "RUNNING"; break;
        case ABT_SCHED_STATE_STOPPED:    state = "STOPPED"; break;
        case ABT_SCHED_STATE_TERMINATED: state = "TERMINATED"; break;
        default:                         state = "UNKNOWN"; break;
    }
    switch (p_sched->used) {
        case ABTI_SCHED_NOT_USED: used = "NOT_USED"; break;
        case ABTI_SCHED_MAIN:     used = "MAIN"; break;
        case ABTI_SCHED_IN_POOL:  used = "IN_POOL"; break;
        default:                  type = "UNKNOWN"; break;
    }

    size = sizeof(char) * (p_sched->num_pools * 20 + 4);
    pools_str = (char *)ABTU_calloc(size, 1);
    pools_str[0] = '[';
    pools_str[1] = ' ';
    pos = 2;
    for (i = 0; i < p_sched->num_pools; i++) {
        ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
        sprintf(&pools_str[pos], "%p ", p_pool);
        pos = strlen(pools_str);
    }
    pools_str[pos] = ']';

    fprintf(p_os,
        "%s== SCHED (%p) ==\n"
#ifdef ABT_CONFIG_USE_DEBUG_LOG
        "%sid       : %" PRIu64 "\n"
#endif
        "%skind     : %" PRIu64 " (%s)\n"
        "%stype     : %s\n"
        "%sstate    : %s\n"
        "%sused     : %s\n"
        "%sautomatic: %s\n"
        "%srequest  : 0x%x\n"
        "%snum_pools: %d\n"
        "%spools    : %s\n"
        "%ssize     : %zu\n"
        "%stot_size : %zu\n"
        "%sdata     : %p\n",
        prefix, p_sched,
#ifdef ABT_CONFIG_USE_DEBUG_LOG
        prefix, p_sched->id,
#endif
        prefix, p_sched->kind, kind_str,
        prefix, type,
        prefix, state,
        prefix, used,
        prefix, (p_sched->automatic == ABT_TRUE) ? "TRUE" : "FALSE",
        prefix, p_sched->request,
        prefix, p_sched->num_pools,
        prefix, pools_str,
        prefix, ABTI_sched_get_size(p_sched),
        prefix, ABTI_sched_get_total_size(p_sched),
        prefix, p_sched->data
    );
    ABTU_free(pools_str);

    if (print_sub == ABT_TRUE) {
        for (i = 0; i < p_sched->num_pools; i++) {
            ABTI_pool *p_pool = ABTI_pool_get_ptr(p_sched->pools[i]);
            ABTI_pool_print(p_pool, p_os, indent + 2);
        }
    }

  fn_exit:
    fflush(p_os);
    ABTU_free(prefix);
}
Пример #5
0
/**
 * @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;
}