Exemple #1
0
static int handler_recv_dequeue_complete(const ptl_event_t *e)
{
    int mpi_errno = MPI_SUCCESS;
    MPID_Request *const rreq = e->user_ptr;
    int is_contig;
    MPI_Aint last;
    MPI_Aint dt_true_lb;
    MPIDI_msg_sz_t data_sz;
    MPID_Datatype *dt_ptr ATTRIBUTE((unused));

    MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_DEQUEUE_COMPLETE);

    MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_DEQUEUE_COMPLETE);

    MPIU_Assert(e->type == PTL_EVENT_PUT || e->type == PTL_EVENT_PUT_OVERFLOW);

    MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, is_contig, data_sz, dt_ptr, dt_true_lb);
    
    dequeue_req(e);

    if (e->type == PTL_EVENT_PUT_OVERFLOW) {
        /* unpack the data from unexpected buffer */
        MPIU_DBG_MSG_D(CH3_CHANNEL, VERBOSE, "is_contig = %d", is_contig);

        if (is_contig) {
            MPIU_Memcpy((char *)rreq->dev.user_buf + dt_true_lb, e->start, e->mlength);
        } else {
            last = e->mlength;
            MPID_Segment_unpack(rreq->dev.segment_ptr, rreq->dev.segment_first, &last, e->start);
            if (last != e->mlength)
                MPIR_ERR_SET(rreq->status.MPI_ERROR, MPI_ERR_TYPE, "**dtypemismatch");
        }
    } else {
        /* Data was placed directly into the user buffer, so datatype mismatch
           is harder to detect. We use a simple check ensuring the received bytes
           are a multiple of a single basic element. Currently, we do not detect
           mismatches with datatypes constructed of more than one basic type */
        MPI_Datatype dt_basic_type;
        MPID_Datatype_get_basic_type(rreq->dev.datatype, dt_basic_type);
        if (dt_basic_type != MPI_DATATYPE_NULL && (e->mlength % MPID_Datatype_get_basic_size(dt_basic_type)) != 0)
            MPIR_ERR_SET(rreq->status.MPI_ERROR, MPI_ERR_TYPE, "**dtypemismatch");
    }
    
    mpi_errno = handler_recv_complete(e);

 fn_exit:
    MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_RECV_DEQUEUE_COMPLETE);
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}
int MPIR_Get_elements_x_impl(const MPI_Status *status, MPI_Datatype datatype, MPI_Count *elements)
{
    int mpi_errno = MPI_SUCCESS;
    MPIR_Datatype *datatype_ptr = NULL;
    MPI_Count byte_count;

    if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
        MPID_Datatype_get_ptr(datatype, datatype_ptr);
    }

    /* three cases:
     * - nice, simple, single element type
     * - derived type with a zero size
     * - type with multiple element types (nastiest)
     */
    if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN ||
        (datatype_ptr->builtin_element_size != -1 && datatype_ptr->size > 0))
    {
        byte_count = MPIR_STATUS_GET_COUNT(*status);

        /* QUESTION: WHAT IF SOMEONE GAVE US AN MPI_UB OR MPI_LB???
         */

        /* in both cases we do not limit the number of types that might
         * be in bytes
         */
        if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
            MPI_Datatype basic_type = MPI_DATATYPE_NULL;
            MPID_Datatype_get_basic_type(datatype_ptr->basic_type, basic_type);
            *elements = MPIR_Type_get_basic_type_elements(&byte_count,
                                                          -1,
                                                          basic_type);
        }
        else {
            /* Behaves just like MPI_Get_Count in the predefined case */
            MPI_Count size;
            MPID_Datatype_get_size_macro(datatype, size);
            if ((byte_count % size) != 0)
                *elements = MPI_UNDEFINED;
            else
                *elements = MPIR_Type_get_basic_type_elements(&byte_count,
                                                              -1,
                                                              datatype);
        }
        MPIR_Assert(byte_count >= 0);
    }
    else if (datatype_ptr->size == 0) {
        if (MPIR_STATUS_GET_COUNT(*status) > 0) {
            /* --BEGIN ERROR HANDLING-- */

            /* datatype size of zero and count > 0 should never happen. */

            (*elements) = MPI_UNDEFINED;
            /* --END ERROR HANDLING-- */
        }
        else {
            /* This is ambiguous.  However, discussions on MPI Forum
             * reached a consensus that this is the correct return
             * value
             */
            (*elements) = 0;
        }
    }
    else /* derived type with weird element type or weird size */ {
        MPIR_Assert(datatype_ptr->builtin_element_size == -1);

        byte_count = MPIR_STATUS_GET_COUNT(*status);
        *elements = MPIR_Type_get_elements(&byte_count, -1, datatype);
    }

    return mpi_errno;
}
/* MPIR_Type_get_elements
 *
 * Arguments:
 * - bytes_p - input/output byte count
 * - count - maximum number of this type to subtract from the bytes; a count
 *           of <0 indicates use as many as we like
 * - datatype - input datatype
 *
 * Returns number of elements available given the two constraints of number of
 * bytes and count of types.  Also reduces the byte count by the amount taken
 * up by the types.
 *
 * This is called from MPI_Get_elements() when it sees a type with multiple
 * element types (datatype_ptr->element_sz = -1).  This function calls itself too.
 */
PMPI_LOCAL MPI_Count MPIR_Type_get_elements(MPI_Count *bytes_p,
                                            MPI_Count count,
                                            MPI_Datatype datatype)
{
    MPIR_Datatype *datatype_ptr = NULL;

    MPID_Datatype_get_ptr(datatype, datatype_ptr); /* invalid if builtin */

    /* if we have gotten down to a type with only one element type,
     * call MPIR_Type_get_basic_type_elements() and return.
     */
    if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN ||
        datatype == MPI_FLOAT_INT ||
        datatype == MPI_DOUBLE_INT ||
        datatype == MPI_LONG_INT ||
        datatype == MPI_SHORT_INT ||
        datatype == MPI_LONG_DOUBLE_INT)
    {
        return MPIR_Type_get_basic_type_elements(bytes_p, count, datatype);
    }
    else if (datatype_ptr->builtin_element_size >= 0) {
        MPI_Datatype basic_type = MPI_DATATYPE_NULL;
        MPID_Datatype_get_basic_type(datatype_ptr->basic_type, basic_type);
        return MPIR_Type_get_basic_type_elements(bytes_p,
                                                 count * datatype_ptr->n_builtin_elements,
                                                 basic_type);
    }
    else {
        /* we have bytes left and still don't have a single element size; must
         * recurse.
         */
        int i, j, *ints;
        MPI_Count typecount = 0, nr_elements = 0, last_nr_elements;
        MPI_Aint *aints;
        MPI_Datatype *types;

        /* Establish locations of arrays */
        MPID_Type_access_contents(datatype_ptr->handle, &ints, &aints, &types);
        if (!ints || !aints || !types)
            return MPI_ERR_TYPE;

        switch (datatype_ptr->contents->combiner) {
            case MPI_COMBINER_NAMED:
            case MPI_COMBINER_DUP:
            case MPI_COMBINER_RESIZED:
                return MPIR_Type_get_elements(bytes_p, count, *types);
                break;
            case MPI_COMBINER_CONTIGUOUS:
            case MPI_COMBINER_VECTOR:
            case MPI_COMBINER_HVECTOR_INTEGER:
            case MPI_COMBINER_HVECTOR:
                /* count is first in ints array */
                return MPIR_Type_get_elements(bytes_p, count * (*ints), *types);
                break;
            case MPI_COMBINER_INDEXED_BLOCK:
            case MPI_COMBINER_HINDEXED_BLOCK:
                /* count is first in ints array, blocklength is second */
                return MPIR_Type_get_elements(bytes_p,
                                              count * ints[0] * ints[1],
                                              *types);
                break;
            case MPI_COMBINER_INDEXED:
            case MPI_COMBINER_HINDEXED_INTEGER:
            case MPI_COMBINER_HINDEXED:
                for (i=0; i < (*ints); i++) {
                    /* add up the blocklengths to get a max. # of the next type */
                    typecount += ints[i+1];
                }
                return MPIR_Type_get_elements(bytes_p, count * typecount, *types);
                break;
            case MPI_COMBINER_STRUCT_INTEGER:
            case MPI_COMBINER_STRUCT:
                /* In this case we can't simply multiply the count of the next
                 * type by the count of the current type, because we need to
                 * cycle through the types just as the struct would.  thus the
                 * nested loops.
                 *
                 * We need to keep going until we get less elements than expected
                 * or we run out of bytes.
                 */


                last_nr_elements = 1; /* seed value */
                for (j=0;
                     (count < 0 || j < count) &&
                         *bytes_p > 0 && last_nr_elements > 0;
                     j++)
                {
                    /* recurse on each type; bytes are reduced in calls */
                    for (i=0; i < (*ints); i++) {
                        /* skip zero-count elements of the struct */
                        if (ints[i+1] == 0) continue;

                        last_nr_elements = MPIR_Type_get_elements(bytes_p,
                                                                  ints[i+1],
                                                                  types[i]);
                        nr_elements += last_nr_elements;

                        MPIR_Assert(last_nr_elements >= 0);

                        if (last_nr_elements < ints[i+1]) break;
                    }
                }
                return nr_elements;
                break;
            case MPI_COMBINER_SUBARRAY:
            case MPI_COMBINER_DARRAY:
            case MPI_COMBINER_F90_REAL:
            case MPI_COMBINER_F90_COMPLEX:
            case MPI_COMBINER_F90_INTEGER:
            default:
                /* --BEGIN ERROR HANDLING-- */
                MPIR_Assert(0);
                return -1;
                break;
                /* --END ERROR HANDLING-- */
        }
    }
}