/* Must hold module's lock before calling... */
static inline void
ompi_osc_pt2pt_flip_sendreqs(ompi_osc_pt2pt_module_t *module)
{
    unsigned int *tmp;

    tmp = module->p2p_copy_num_pending_sendreqs;
    module->p2p_copy_num_pending_sendreqs = 
        module->p2p_num_pending_sendreqs;
    module->p2p_num_pending_sendreqs = tmp;
    memset(module->p2p_num_pending_sendreqs, 0,
           sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));

    /* Copy in all the pending requests */
    opal_list_join(&module->p2p_copy_pending_sendreqs,
                   opal_list_get_end(&module->p2p_copy_pending_sendreqs),
                   &module->p2p_pending_sendreqs);
}
示例#2
0
文件: opal_list.c 项目: aosm/openmpi
int main(int argc, char **argv)
{
    /* local variables */
    opal_list_t list, x;
    size_t indx,i,list_size, tmp_size_1, tmp_size_2,size_elements;
    int error_cnt;
    test_data_t *elements, *ele;
    opal_list_item_t *item;

    opal_init();

    test_init("opal_list_t");

    /* initialize list */
    OBJ_CONSTRUCT(&list, opal_list_t);
    OBJ_CONSTRUCT(&x, opal_list_t);

    /* check length of list */
    list_size=opal_list_get_size(&list);
    if( 0 == list_size ) {
        test_success();
    } else {
        test_failure(" opal_list_get_size");
    }

    /* check for empty */
    if (opal_list_is_empty(&list)) {
        test_success();
    } else {
        test_failure(" opal_list_is_empty(empty list)");
    }

    /* create test elements */
    size_elements=4;
    elements=(test_data_t *)malloc(sizeof(test_data_t)*size_elements);
    assert(elements);
    for(i=0 ; i < size_elements ; i++) {
        OBJ_CONSTRUCT(elements + i, test_data_t);
        (elements+i)->data=i;
    }

    /* populate list */
    for(i=0 ; i < size_elements ; i++) {
        opal_list_append(&list,(opal_list_item_t *)(elements+i));
    }
    list_size=opal_list_get_size(&list);
    if( list_size == size_elements ) {
        test_success();
    } else {
        test_failure(" populating list");
    }

    /* checking for empty on non-empty list */
    if (!opal_list_is_empty(&list)) {
        test_success();
    } else {
        test_failure(" opal_list_is_empty(non-empty list)");
    }

    /* check that list is ordered as expected */
    i=0;
    error_cnt=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        if( ele->data != i )
            error_cnt++;
        i++;
    }
    if( 0 == error_cnt ) {
        test_success();
    } else {
        test_failure(" error in list order ");
    }

    /* check opal_list_get_first */
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_get_first(&list);
    assert(ele);
    if( 0 == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_get_first");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( size_elements == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_get_first - list size changed ");
    }

    /* check opal_list_get_last */
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_get_last(&list);
    assert(ele);
    if( (size_elements-1) == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_get_last");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( size_elements == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_get_first - list size changed ");
    }

    /* check opal_list_remove_first */
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_remove_first(&list);
    assert(ele);
    if( 0 == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove_first");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( (size_elements-1) == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove_first - list size changed ");
    }

    /* test opal_list_prepend */
    opal_list_prepend(&list,(opal_list_item_t *)elements);
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_get_first(&list);
    assert(ele);
    if( 0 == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_prepend");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( size_elements == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_prepend - list size changed ");
    }

    /* check opal_list_remove_last */
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_remove_last(&list);
    assert(ele);
    if( (size_elements-1) == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove_last");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( (size_elements-1) == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove_last - list size changed ");
    }

    /* test opal_list_append */
    opal_list_append(&list,(opal_list_item_t *)(elements+size_elements-1));
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) opal_list_get_last(&list);
    assert(ele);
    if( (size_elements-1) == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_append");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( size_elements == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_append - list size changed ");
    }

    /* remove element from list */
    indx=size_elements/2;
    if( 0 == indx )
        indx=1;
    assert(2 <= size_elements);
    ele = (test_data_t *)NULL;
    ele = (test_data_t *) 
        opal_list_remove_item(&list,(opal_list_item_t *)(elements+indx));
    assert(ele);
    if( (indx-1) == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove - previous");
    }
    ele=(test_data_t *)(((opal_list_item_t *)ele)->opal_list_next);
    if( (indx+1) == ele->data ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove - next");
    }
    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( (size_elements-1) == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove - list size changed incorrectly");
    }

    /* test the insert function */
    i=opal_list_insert(&list,(opal_list_item_t *)(elements+indx),indx);
    if( 1 == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_remove_item \n");
    }

    i=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        i++;
    }
    if( size_elements == i ) {
        test_success();
    } else {
        test_failure(" error in opal_list_insert - incorrect list length");
    }
    i=0;
    error_cnt=0;
    for(ele = (test_data_t *) opal_list_get_first(&list);
            ele != (test_data_t *) opal_list_get_end(&list);
            ele = (test_data_t *) ((opal_list_item_t *)ele)->opal_list_next) {
        if( ele->data != i )
            error_cnt++;
        i++;
    }
    if( 0 == error_cnt ) {
        test_success();
    } else {
        test_failure(" error in list order - opal_list_remove_item ");
    }

    /* test the splice and join functions  */
    list_size = opal_list_get_size(&list);
    for (i = 0, item = opal_list_get_first(&list) ; 
         i < list_size / 2 ; ++i, item = opal_list_get_next(item)) {
    }
    opal_list_splice(&x, opal_list_get_end(&x),
                     &list, item, opal_list_get_end(&list));
    tmp_size_1 = opal_list_get_size(&list);
    tmp_size_2 = opal_list_get_size(&x);
    if (tmp_size_1 != i) {
        test_failure(" error in splice (size of list)");
    } else if (tmp_size_2 != list_size - tmp_size_1) {
        test_failure(" error in splice (size of x)");
    } else {
        test_success();
    }

    opal_list_join(&list, opal_list_get_end(&list), &x);
    tmp_size_1 = opal_list_get_size(&list);
    tmp_size_2 = opal_list_get_size(&x);
    if (tmp_size_1 != list_size) {
        test_failure(" error in join (size of list)");
    } else if (tmp_size_2 != 0) {
        test_failure(" error in join (size of x)");
    } else {
        test_success();
    }

    if (NULL != elements) free(elements);

    opal_finalize();

    return test_finalize();
}
int
ompi_osc_pt2pt_passive_unlock_complete(ompi_osc_pt2pt_module_t *module)
{
    ompi_osc_pt2pt_pending_lock_t *new_pending = NULL;
    opal_list_t copy_unlock_acks;

    if (module->p2p_num_pending_in != 0) return OMPI_SUCCESS;

    OPAL_THREAD_LOCK(&(module->p2p_lock)); 
    if (module->p2p_num_pending_in != 0) {
        OPAL_THREAD_UNLOCK(&module->p2p_lock);
        return OMPI_SUCCESS;
    }

    if (module->p2p_lock_status == MPI_LOCK_EXCLUSIVE) {
        ompi_win_remove_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
        module->p2p_lock_status = 0;
    } else {
        module->p2p_shared_count -= opal_list_get_size(&module->p2p_unlocks_pending);
        OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_output,
                             "%d: decrementing shared count to %d",
                             ompi_comm_rank(module->p2p_comm), 
                             module->p2p_shared_count));
        if (module->p2p_shared_count == 0) {
            ompi_win_remove_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
            module->p2p_lock_status = 0;
        }
    }

    OBJ_CONSTRUCT(&copy_unlock_acks, opal_list_t);
    /* copy over any unlocks that have been satisfied (possibly
       multiple if SHARED) */
    opal_list_join(&copy_unlock_acks,
                   opal_list_get_end(&copy_unlock_acks),
                   &module->p2p_unlocks_pending);
    OPAL_THREAD_UNLOCK(&module->p2p_lock);

    /* issue whichever unlock acks we should issue */
    while (NULL != (new_pending = (ompi_osc_pt2pt_pending_lock_t*)
                    opal_list_remove_first(&copy_unlock_acks))) {
        OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_output,
                             "%d: sending unlock ack to proc %d",
                             ompi_comm_rank(module->p2p_comm),
                             new_pending->proc->proc_name.vpid));
        ompi_osc_pt2pt_control_send(module,
                                   new_pending->proc,
                                   OMPI_OSC_PT2PT_HDR_UNLOCK_REPLY,
                                   OMPI_SUCCESS, OMPI_SUCCESS);
        OBJ_RELEASE(new_pending);
    }

    OBJ_DESTRUCT(&copy_unlock_acks);

    /* if we were really unlocked, see if we have another lock request
       we can satisfy */
    OPAL_THREAD_LOCK(&module->p2p_lock);
    if (0 == module->p2p_lock_status) {
        new_pending = (ompi_osc_pt2pt_pending_lock_t*) 
            opal_list_remove_first(&(module->p2p_locks_pending));
        if (NULL != new_pending) {
            OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_output,
                                 "%d: sending lock ack to proc %d",
                                 ompi_comm_rank(module->p2p_comm),
                                 new_pending->proc->proc_name.vpid));
            ompi_win_append_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
            /* set lock state and generate a lock request */
            module->p2p_lock_status = new_pending->lock_type;
            if (MPI_LOCK_SHARED == new_pending->lock_type) {
                module->p2p_shared_count++;
            }
        }
    } else {
        new_pending = NULL;
    }
    OPAL_THREAD_UNLOCK(&(module->p2p_lock));

    if (NULL != new_pending) {
        ompi_osc_pt2pt_control_send(module,
                                    new_pending->proc,
                                    OMPI_OSC_PT2PT_HDR_LOCK_REQ,
                                    ompi_comm_rank(module->p2p_comm),
                                    OMPI_SUCCESS);
        OBJ_RELEASE(new_pending);
    }

    return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_fence(int assert, ompi_win_t *win)
{
    unsigned int incoming_reqs;
    int ret = OMPI_SUCCESS, i;
    ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
    int num_outgoing = 0;

    if (0 != (assert & MPI_MODE_NOPRECEDE)) {
        /* check that the user didn't lie to us - since NOPRECEDED
           must be specified by all processes if it is specified by
           any process, if we see this it is safe to assume that there
           are no pending operations anywhere needed to close out this
           epoch.  No need to lock, since it's a lookup and any
           pending modification of the pending_sendreqs during this
           time is an erroneous program. */
        if (0 != opal_list_get_size(&(module->p2p_pending_sendreqs))) {
            return MPI_ERR_RMA_SYNC;
        }

    } else {
        opal_list_item_t *item;

        /* "atomically" copy all the data we're going to be modifying
           into the copy... */
        OPAL_THREAD_LOCK(&(module->p2p_lock));
        ompi_osc_pt2pt_flip_sendreqs(module);
        OPAL_THREAD_UNLOCK(&(module->p2p_lock));

        num_outgoing = opal_list_get_size(&(module->p2p_copy_pending_sendreqs));

        /* find out how much data everyone is going to send us. */
        ret = module->p2p_comm->
            c_coll.coll_reduce_scatter(module->p2p_copy_num_pending_sendreqs,
                                       &incoming_reqs,
                                       module->p2p_fence_coll_counts,
                                       MPI_UNSIGNED,
                                       MPI_SUM,
                                       module->p2p_comm,
                                       module->p2p_comm->c_coll.coll_reduce_scatter_module);

        if (OMPI_SUCCESS != ret) {
            /* put the stupid data back for the user.  This is not
               cheap, but the user lost his data if we don't. */
            OPAL_THREAD_LOCK(&(module->p2p_lock));
            opal_list_join(&module->p2p_pending_sendreqs,
                           opal_list_get_end(&module->p2p_pending_sendreqs),
                           &module->p2p_copy_pending_sendreqs);
            
            for (i = 0 ; i < ompi_comm_size(module->p2p_comm) ; ++i) {
                module->p2p_num_pending_sendreqs[i] +=
                    module->p2p_copy_num_pending_sendreqs[i];
            }

            OPAL_THREAD_UNLOCK(&(module->p2p_lock));
            return ret;
        }

        OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_output,
                             "fence: waiting on %d in and %d out",
                             module->p2p_num_pending_in,
                             module->p2p_num_pending_out));

        /* try to start all the requests.  We've copied everything we
           need out of pending_sendreqs, so don't need the lock
           here */
        while (NULL != 
               (item = opal_list_remove_first(&(module->p2p_copy_pending_sendreqs)))) {
            ompi_osc_pt2pt_sendreq_t *req = 
                (ompi_osc_pt2pt_sendreq_t*) item;

            ret = ompi_osc_pt2pt_sendreq_send(module, req);

            if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret ) {
                opal_output_verbose(5, ompi_osc_base_output,
                                    "complete: failure in starting sendreq (%d).  Will try later.",
                                    ret);
                opal_list_append(&(module->p2p_copy_pending_sendreqs), item);
            } else if (OMPI_SUCCESS != ret) {
                return ret;
            } 
        }

        OPAL_THREAD_LOCK(&module->p2p_lock);
        /* possible we've already received a couple in messages, so
           add however many we're going to wait for */
        module->p2p_num_pending_in += incoming_reqs;
        module->p2p_num_pending_out += num_outgoing;

        /* now we know how many things we're waiting for - wait for them... */
        while (module->p2p_num_pending_in > 0 ||
               0 != module->p2p_num_pending_out) {
            opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
        }
        OPAL_THREAD_UNLOCK(&module->p2p_lock);
    }

    /* all transfers are done - back to the real world we go */
    if (0 == (assert & MPI_MODE_NOSUCCEED)) {
        ompi_win_set_mode(win, OMPI_WIN_FENCE);
    } else {
        ompi_win_set_mode(win, 0);
    }

    return OMPI_SUCCESS;
}