/* MSGQUEUE lock is not held */ void MPIDI_Callback_process_trunc(pami_context_t context, MPID_Request *rreq, pami_recv_t *recv, const void *sndbuf) { rreq->status.MPI_ERROR = MPI_ERR_TRUNCATE; /* -------------------------------------------------------------- */ /* The data is already available, so we can just unpack it now. */ /* -------------------------------------------------------------- */ if (recv) { MPIDI_Request_setCA(rreq, MPIDI_CA_UNPACK_UEBUF_AND_COMPLETE); rreq->mpid.uebuflen = MPIR_STATUS_GET_COUNT(rreq->status); rreq->mpid.uebuf = MPIU_Malloc(MPIR_STATUS_GET_COUNT(rreq->status)); MPID_assert(rreq->mpid.uebuf != NULL); rreq->mpid.uebuf_malloc = mpiuMalloc; recv->addr = rreq->mpid.uebuf; } else { MPIDI_Request_setCA(rreq, MPIDI_CA_UNPACK_UEBUF_AND_COMPLETE); rreq->mpid.uebuflen = MPIR_STATUS_GET_COUNT(rreq->status); rreq->mpid.uebuf = (void*)sndbuf; MPIDI_RecvDoneCB(context, rreq, PAMI_SUCCESS); MPID_Request_release(rreq); } }
void MPIR_Get_count_impl(const MPI_Status *status, MPI_Datatype datatype, int *count) { MPI_Count size; MPID_Datatype_get_size_macro(datatype, size); MPIU_Assert(size >= 0 && MPIR_STATUS_GET_COUNT(*status) >= 0); if (size != 0) { /* MPI-3 says return MPI_UNDEFINED if too large for an int */ if ((MPIR_STATUS_GET_COUNT(*status) % size) != 0 || ((MPIR_STATUS_GET_COUNT(*status) / size) > INT_MAX)) (*count) = MPI_UNDEFINED; else (*count) = (int)(MPIR_STATUS_GET_COUNT(*status) / size); } else { if (MPIR_STATUS_GET_COUNT(*status) > 0) { /* --BEGIN ERROR HANDLING-- */ /* case where datatype size is 0 and count is > 0 should * never occur. */ (*count) = MPI_UNDEFINED; /* --END ERROR HANDLING-- */ } else { /* This is ambiguous. However, discussions on MPI Forum reached a consensus that this is the correct return value */ (*count) = 0; } } }
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; }
/*@ MPI_Get_elements_x - Returns the number of basic elements in a datatype Input Parameters: + status - return status of receive operation (Status) - datatype - datatype used by receive operation (handle) Output Parameters: . count - number of received basic elements (integer) .N ThreadSafe .N Fortran .N Errors @*/ int MPI_Get_elements_x(const MPI_Status *status, MPI_Datatype datatype, MPI_Count *count) { int mpi_errno = MPI_SUCCESS; MPI_Count byte_count; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GET_ELEMENTS_X); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GET_ELEMENTS_X); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS { MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno); /* TODO more checks may be appropriate */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS } # endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS { if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) { MPIR_Datatype *datatype_ptr = NULL; MPIR_Datatype_get_ptr(datatype, datatype_ptr); MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno); MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno); } /* TODO more checks may be appropriate (counts, in_place, buffer aliasing, etc) */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ byte_count = MPIR_STATUS_GET_COUNT(*status); mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, count); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GET_ELEMENTS_X); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_get_elements_x", "**mpi_get_elements_x %p %D %p", status, datatype, count); } # endif mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
static inline int ADD_SUFFIX(MPID_nem_ofi_recv_callback)(cq_tagged_entry_t * wc, MPID_Request * rreq) { int err0, err1, src, mpi_errno = MPI_SUCCESS; uint64_t ssend_bits; MPIDI_msg_sz_t sz; MPIDI_VC_t *vc; MPID_Request *sync_req; BEGIN_FUNC(FCNAME); /* ---------------------------------------------------- */ /* Populate the MPI Status and unpack noncontig buffer */ /* ---------------------------------------------------- */ rreq->status.MPI_ERROR = MPI_SUCCESS; #if API_SET == API_SET_1 rreq->status.MPI_SOURCE = get_source(wc->tag); #elif API_SET == API_SET_2 rreq->status.MPI_SOURCE = wc->data; #endif src = rreq->status.MPI_SOURCE; rreq->status.MPI_TAG = get_tag(wc->tag); REQ_OFI(rreq)->req_started = 1; MPIR_STATUS_SET_COUNT(rreq->status, wc->len); if (REQ_OFI(rreq)->pack_buffer) { MPIDI_CH3U_Buffer_copy(REQ_OFI(rreq)->pack_buffer, MPIR_STATUS_GET_COUNT(rreq->status), MPI_BYTE, &err0, rreq->dev.user_buf, rreq->dev.user_count, rreq->dev.datatype, &sz, &err1); MPIR_STATUS_SET_COUNT(rreq->status, sz); MPIU_Free(REQ_OFI(rreq)->pack_buffer); if (err0 || err1) { rreq->status.MPI_ERROR = MPI_ERR_TYPE; } } if ((wc->tag & MPID_PROTOCOL_MASK) == MPID_SYNC_SEND) { /* ---------------------------------------------------- */ /* Ack the sync send and wait for the send request */ /* completion(when callback executed. A protocol bit */ /* MPID_SYNC_SEND_ACK is set in the tag bits to provide */ /* separation of MPI messages and protocol messages */ /* ---------------------------------------------------- */ vc = REQ_OFI(rreq)->vc; if (!vc) { /* MPI_ANY_SOURCE -- Post message from status, complete the VC */ vc = rreq->comm->dev.vcrt->vcr_table[src]; MPIU_Assert(vc); } #if API_SET == API_SET_1 ssend_bits = init_sendtag(rreq->dev.match.parts.context_id, rreq->comm->rank, rreq->status.MPI_TAG, MPID_SYNC_SEND_ACK); #elif API_SET == API_SET_2 ssend_bits = init_sendtag_2(rreq->dev.match.parts.context_id, rreq->status.MPI_TAG, MPID_SYNC_SEND_ACK); #endif MPID_nem_ofi_create_req(&sync_req, 1); sync_req->dev.OnDataAvail = NULL; sync_req->dev.next = NULL; REQ_OFI(sync_req)->event_callback = MPID_nem_ofi_sync_recv_callback; REQ_OFI(sync_req)->parent = rreq; #if API_SET == API_SET_1 FI_RC_RETRY(fi_tsend(gl_data.endpoint, #elif API_SET == API_SET_2 FI_RC_RETRY(fi_tsenddata(gl_data.endpoint, #endif NULL, 0, gl_data.mr, #if API_SET == API_SET_2 rreq->comm->rank, #endif VC_OFI(vc)->direct_addr, ssend_bits, &(REQ_OFI(sync_req)->ofi_context)), tsend); }