Commit 448451f7 authored by Darius Buntinas's avatar Darius Buntinas
Browse files

[svn-r10211] added more code for portals4

parent cf29e1c3
......@@ -14,10 +14,12 @@
#define PTL_LARGE_THRESHOLD (64*1024) /* 64K */
ptl_handle_ni_t MPIDI_nem_ptl_ni;
ptl_pt_index_t MPIDI_nem_ptl_pt;
ptl_pt_index_t MPIDI_nem_ptl_control_pt; /* portal for MPICH control messages */
ptl_handle_eq_t MPIDI_nem_ptl_eq;
extern ptl_handle_ni_t MPIDI_nem_ptl_ni;
extern ptl_pt_index_t MPIDI_nem_ptl_pt;
extern ptl_pt_index_t MPIDI_nem_ptl_control_pt; /* portal for MPICH control messages */
extern ptl_handle_eq_t MPIDI_nem_ptl_eq;
extern ptl_handle_md_t MPIDI_nem_ptl_global_md;
#define MPID_NEM_PTL_MAX_OVERFLOW_DATA 32 /* that's way more than we need */
typedef struct MPID_nem_ptl_pack_overflow
......@@ -27,6 +29,8 @@ typedef struct MPID_nem_ptl_pack_overflow
char buf[MPID_NEM_PTL_MAX_OVERFLOW_DATA];
} MPID_nem_ptl_pack_overflow_t;
typedef int (* event_handler_fn)(const ptl_event_t *e);
#define MPID_NEM_PTL_NUM_CHUNK_BUFFERS 2
typedef struct {
......@@ -36,26 +40,35 @@ typedef struct {
ptl_handle_md_t md;
ptl_handle_me_t me;
void *chunk_buffer[MPID_NEM_PTL_NUM_CHUNK_BUFFERS];
MPIDI_msg_sz_t bytes_put;
event_handler_fn ack_handler;
event_handler_fn put_handler;
event_handler_fn get_handler;
event_handler_fn reply_handler;
} MPID_nem_ptl_req_area;
/* macro for ptl private in req */
#define REQ_PTL(req) ((MPID_nem_ptl_req_area *)((req)->ch.netmod_area.padding))
#define MPID_nem_ptl_init_sreq(sreq_) do { \
#define MPID_nem_ptl_init_req(req_) do { \
int i; \
for (i = 0; i < MPID_NEM_PTL_NUM_CHUNK_BUFFERS; ++i) { \
REQ_PTL(sreq)->overflow[i].len = 0; \
REQ_PTL(sreq_)->chunk_buffer[i] = NULL; \
REQ_PTL(req)->overflow[i].len = 0; \
REQ_PTL(req_)->chunk_buffer[i] = NULL; \
} \
REQ_PTL(sreq_)->noncontig = FALSE; \
REQ_PTL(sreq_)->large = FALSE; \
REQ_PTL(sreq_)->md = PTL_INVALID_HANDLE; \
REQ_PTL(sreq_)->me = PTL_INVALID_HANDLE; \
REQ_PTL(req_)->noncontig = FALSE; \
REQ_PTL(req_)->large = FALSE; \
REQ_PTL(req_)->md = PTL_INVALID_HANDLE; \
REQ_PTL(req_)->me = PTL_INVALID_HANDLE; \
REQ_PTL(req_)->ack_handler = NULL; \
REQ_PTL(req_)->put_handler = NULL; \
REQ_PTL(req_)->get_handler = NULL; \
REQ_PTL(req_)->reply_handler = NULL; \
} while (0)
#define MPID_nem_ptl_request_create_sreq(sreq_, errno_, on_fail_) do { \
#define MPID_nem_ptl_request_create_req(sreq_, errno_, on_fail_) do { \
MPIDI_Request_create_sreq(sreq_, errno_, on_fail_); \
MPID_nem_ptl_init_sreq(sreq_); \
MPID_nem_ptl_init_req(req_); \
} while (0)
typedef struct {
......@@ -100,15 +113,14 @@ typedef struct {
#define NPTL_MAX_PROCS (NPTL_SOURCE_MASK+1)
/* create a match value */
#define NPTL_TAG_SHIFT 32
#define NPTL_TAG_SHIFT 32 /* tag and ctx_id are limited to 32 bits each */
#define NPTL_MATCH(tag, context_id) (((ptl_match_bits)(tag) << NPTL_TAG_SHIFT) | (ptl_match_bits)(context_id))
struct MPID_nem_ptl_sendbuf;
#define NPTL_MATCH_GET_TAG(match_bits) ((match_bits) >> NPTL_TAG_SHIFT)
#define NPTL_ANY_TAG_MASK NPTL_MATCH(~0, 0)
int MPID_nem_ptl_send_init(void);
int MPID_nem_ptl_send_finalize(void);
int MPID_nem_ptl_send_completed(struct MPID_nem_ptl_sendbuf *sb);
int MPID_nem_ptl_ev_send_handler(ptl_event_t *e);
int MPID_nem_ptl_sendq_complete_with_error(MPIDI_VC_t *vc, int req_errno);
int MPID_nem_ptl_SendNoncontig(MPIDI_VC_t *vc, MPID_Request *sreq, void *hdr, MPIDI_msg_sz_t hdr_sz);
int MPID_nem_ptl_iStartContigMsg(MPIDI_VC_t *vc, void *hdr, MPIDI_msg_sz_t hdr_sz, void *data, MPIDI_msg_sz_t data_sz,
......
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2012 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
......@@ -35,7 +35,8 @@ MPID_nem_netmod_funcs_t MPIDI_nem_portals4_funcs = {
vc_init,
vc_destroy,
vc_terminate,
NULL /* anysource iprobe */
MPID_nem_ptl_anysource_iprobe,
MPID_nem_ptl_anysource_improbe
};
static MPIDI_Comm_ops_t comm_ops = {
......
......@@ -118,7 +118,7 @@ int MPID_nem_ptl_poll(int is_blocking_poll)
assert(0);
}
MPIU_DBG_MSG(CH3_CHANNEL, VERBOSE, "Send completed");
mpi_errno = MPID_nem_ptl_send_completed(event.user_ptr);
mpi_errno = MPID_nem_ptl_ev_send_handler(&event);
if (mpi_errno) MPIU_ERR_POP(mpi_errno);
break;
case PTL_EVENT_ACK:
......
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2012 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_probe
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_probe(MPIDI_VC_t *vc, int source, int tag, MPID_Comm *comm, int context_offset, MPI_Status *status)
{
MPIU_Assertp(0 && "This function shouldn't be called.");
return MPI_SUCCESS;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_iprobe
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_iprobe(MPIDI_VC_t *vc, int source, int tag, MPID_Comm *comm, int context_offset, int *flag, MPI_Status *status)
{
int mpi_errno = MPI_SUCCESS;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_IPROBE);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_IPROBE);
me.ct_handle = PTL_CT_NONE;
me.uid = PTL_UID_ANY;
me.options = ( PTL_ME_OP_PUT | PTL_ME_IS_ACCESSIBLE | PTL_ME_EVENT_LINK_DISABLE |
PTL_ME_EVENT_UNLINK_DISABLE | PTL_ME_USE_ONCE );
if (source == MPI_ANY_SOURCE)
me.match_id = PTL_ID_ANY;
else
me.match_id = vc_ptl->id;
me.match_bits = NPTL_MATCH(tag, context_id);
if (tag == MPI_ANY_TAG)
me.ignore_bits = NPTL_ANY_TAG_MASK;
else
me.ignore_bits = 0;
me.min_free = 0;
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_PTL_IPROBE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_improbe
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_improbe(MPIDI_VC_t *vc, int source, int tag, MPID_Comm *comm, int context_offset, int *flag,
MPID_Request **message, MPI_Status *status)
{
int mpi_errno = MPI_SUCCESS;
ptl_me_t me;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_IMPROBE);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_IMPROBE);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_PTL_IMPROBE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_anysource_iprobe
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_anysource_iprobe(int tag, MPID_Comm * comm, int context_offset, int *flag, MPI_Status * status)
{
int mpi_errno = MPI_SUCCESS;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IPROBE);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IPROBE);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IPROBE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_anysource_improbe
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_anysource_improbe(int tag, MPID_Comm * comm, int context_offset, int *flag, MPID_Request **message,
MPI_Status * status)
{
int mpi_errno = MPI_SUCCESS;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IMPROBE);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IMPROBE);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_PTL_ANYSOURCE_IMPROBE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_cancel_recv
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_cancel_recv(MPIDI_VC_t *vc, MPID_Request_t *rreq)
{
int mpi_errno = MPI_SUCCESS;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_CANCEL_RECV);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_CANCEL_RECV);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_PTL_CANCEL_RECV);
return mpi_errno;
fn_fail:
goto fn_exit;
}
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2012 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#include "ptl_impl.h"
#undef FUNCNAME
#define FUNCNAME dequeue_req
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static void dequeue_req(const ptl_event_t *e)
{
int found;
MPID_Request *const rreq = e->user_ptr;
found = MPIDI_CH3U_Recvq_DP(rreq);
MPIU_Assert(found);
rreq->status.MPI_SOURCE = NPTL_HEADER_SOURCE(e->hdr_data);
rreq->status.MPI_TAG = NPTL_MATCH_GET_TAG(NPTL_HEADER_MATCH_BITS(e->hdr_data));
}
#undef FUNCNAME
#define FUNCNAME handler_recv_complete
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_complete(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPID_Request *const rreq = e->user_ptr;
int ret;
int found;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_COMPLETE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_COMPLETE);
req->dev.recv_data_sz += e->mlength;
req->status.count = req->dev.recv_data_sz;
if (REQ_PTL(rreq)->md != PTL_INVALID_HANDLE) {
ret = PtlMDRelease(REQ_PTL(rreq)->md);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlmdrelease");
}
for (i = 0; i < MPID_NEM_PTL_NUM_CHUNK_BUFFERS; ++i)
if (REQ_PTL(rreq)->chunk_buffer[i])
MPIU_Free(REQ_PTL(rreq)->chunk_buffer[i]);
MPIDI_CH3U_Request_complete(rreq);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_RECV_COMPLETE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME handler_recv_dequeue_complete
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_dequeue_complete(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPID_Request *const rreq = e->user_ptr;
int ret;
int found;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_DEQUEUE_COMPLETE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_DEQUEUE_COMPLETE);
dequeue_req(e);
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;
}
#undef FUNCNAME
#define FUNCNAME handler_recv_unpack_complete
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_unpack_complete(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPID_Request *const rreq = e->user_ptr;
MPI_Aint last;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_UNPACK_COMPLETE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_UNPACK_COMPLETE);
unpack_byte(req->dev.segment_ptr, req->dev.segment_first, e->mlength, REQ_PTL(rreq_)->chunk_buffer[0]);
mpi_errno = handler_recv_complete(e);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_RECV_UNPACK_COMPLETE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME handler_recv_dequeue_unpack_complete
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_dequeue_unpack_complete(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPID_Request *const rreq = e->user_ptr;
MPI_Aint last;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_DEQUEUE_UNPACK_COMPLETE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_DEQUEUE_UNPACK_COMPLETE);
dequeue_req(e);
mpi_errno = handler_recv_unpack_complete(e);
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_RECV_DEQUEUE_UNPACK_COMPLETE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME handler_recv_dequeue_large
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_dequeue_large(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPID_Request *const rreq = e->user_ptr;
int ret;
int dt_contig;
MPIDI_msg_sz_t data_sz;
MPID_Datatype *dt_ptr;
MPI_Aint dt_true_lb;
MPI_Aint last;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_DEQUEUE_LARGE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_DEQUEUE_LARGE);
dequeue_req(e);
if (!(e->hdr_data & NPTL_LARGE)) {
/* all data has already been received; we're done */
mpi_errno = handler_recv_complete(e);
if (mpi_errno) MPIU_ERR_POP(mpi_errno);
goto fn_exit;
}
/* we need to receive more data. record how much we've received so far */
req->dev.recv_data_sz = e->mlength;
/* we need to GET the rest of the data from the sender's buffer */
MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, dt_contig, data_sz, dt_ptr, dt_true_lb);
if (dt_contig) {
/* recv buffer is contig */
ret = PtlGet(MPIDI_nem_ptl_global_md, (ptl_size_t)rreq->user_buf + PTL_LARGE_THRESHOLD, data_sz - PTL_LARGE_THRESHOLD,
vc_ptl->id, vc_ptl->pt, NPTL_HEADER_MATCH_BITS(e->hdr_data), 0, req);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlget");
REQ_PTL(rreq)->put_handler = NULL;
REQ_PTL(rreq)->reply_handler = handler_recv_complete;
goto fn_exit;
}
/* noncontig recv buffer */
last = rreq->dev.segment_size;
rreq->dev.iov_count = MPID_IOV_LIMIT;
MPID_Segment_pack_vector(rreq->dev.segment_ptr, rreq->dev.segment_first, &last, rreq->dev.iov, &rreq->dev.iov_count);
if (last == rreq->dev.segment_size) {
/* Rest of message fits in one IOV */
ptl_md_t md;
md.start = rreq->dev.iov;
md.length = rreq->dev.iov_count;
md.options = PTL_IOVEC;
md.eq_handle = MPIDI_nem_ptl_eq;
md.ct_handle = PTL_CT_NONE;
ret = PtlMDBind(MPIDI_nem_ptl_ni, &md, &REQ_PTL(rreq)->md);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlmdbind");
REQ_PTL(rreq)->put_handler = NULL;
REQ_PTL(rreq)->reply_handler = handler_recv_complete;
ret = PtlGet(REQ_PTL(rreq)->md, 0, rreq->dev.segment_size - rreq->dev.segment_first, vc_ptl->id, vc_ptl->pt,
NPTL_HEADER_MATCH_BITS(e->hdr_data), 0, req);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlget");
REQ_PTL(rreq)->put_handler = NULL;
REQ_PTL(rreq)->reply_handler = handler_recv_complete;
goto fn_exit;
}
/* message won't fit in a single IOV, allocate buffer and unpack when received */
/* FIXME: For now, allocate a single large buffer to hold entire message */
MPIU_CHKPMEM_MALLOC(REQ_PTL(rreq)->chunk_buffer[0], void *, rreq->dev.segment_size - rreq->dev.segment_first, mpi_errno, "chunk_buffer");
ret = PtlGet(MPIDI_nem_ptl_global_md, (ptl_size_t)REQ_PTL(rreq)->chunk_buffer[0],
rreq->dev.segment_size - rreq->dev.segment_first, vc_ptl->id, vc_ptl->pt,
NPTL_HEADER_MATCH_BITS(e->hdr_data), 0, req);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlget");
REQ_PTL(rreq)->put_handler = NULL;
REQ_PTL(rreq)->reply_handler = handler_recv_unpack_complete;
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_RECV_DEQUEUE_LARGE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME handler_recv_dequeue_unpack_large
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
static int handler_recv_dequeue_unpack_large(const ptl_event_t *e)
{
int mpi_errno = MPI_SUCCESS;
MPIDI_STATE_DECL(MPID_STATE_HANDLER_RECV_DEQUEUE_UNPACK_LARGE);
MPIDI_FUNC_ENTER(MPID_STATE_HANDLER_RECV_DEQUEUE_UNPACK_LARGE);
dequeue_req(e);
if (!(e->hdr_data & NPTL_LARGE)) {
/* all data has already been received; we're done */
mpi_errno = handler_recv_unpack_complete(e);
if (mpi_errno) MPIU_ERR_POP(mpi_errno);
goto fn_exit;
}
/* we need to receive more data. record how much we've received so far */
req->dev.recv_data_sz = e->mlength;
MPIU_Assert(e->mlength == PTL_LARGE_THRESHOLD);
unpack_byte(rreq->dev.segment_ptr, rreq->dev.segment_first, PTL_LARGE_THRESHOLD, REQ_PTL(rreq)->chunk_buffer[0],
&REQ_PTL(rreq)->overflow[0]);
rreq->dev.segment_first += PTL_LARGE_THRESHOLD;
MPIU_Free(REQ_PTL(rreq)->chunk_buffer[0]);
MPIU_CHKPMEM_MALLOC(REQ_PTL(rreq)->chunk_buffer[0], void *, rreq->dev.segment_size - rreq->dev.segment_first, mpi_errno, "chunk_buffer");
ret = PtlGet(MPIDI_nem_ptl_global_md, (ptl_size_t)REQ_PTL(rreq)->chunk_buffer[0],
rreq->dev.segment_size - rreq->dev.segment_first, vc_ptl->id, vc_ptl->pt,
NPTL_HEADER_MATCH_BITS(e->hdr_data), 0, req);
MPIU_ERR_CHKANDJUMP(ret, mpi_errno, MPI_ERR_OTHER, "**ptlget");
REQ_PTL(rreq)->put_handler = NULL;
REQ_PTL(rreq)->reply_handler = handler_recv_unpack_complete;
fn_exit:
MPIDI_FUNC_EXIT(MPID_STATE_HANDLER_DEQUEUE_RECV_UNPACK_LARGE);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_nem_ptl_recv_posted
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPID_nem_ptl_recv_posted(MPIDI_VC_t *vc, MPID_Request_t *rreq)
{
int mpi_errno = MPI_SUCCESS;
MPID_nem_ptl_vc_area *const vc_ptl = VC_PTL(vc);
ptl_me_t me;
int dt_contig;
MPIDI_msg_sz_t data_sz;
MPID_Datatype *dt_ptr;
MPI_Aint dt_true_lb;
MPI_Aint last;
MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_PTL_RECV_POSTED);
MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_PTL_RECV_POSTED);
MPID_nem_ptl_init_req(rreq);
me.ct_handle = PTL_CT_NONE;
me.uid = PTL_UID_ANY;
me.options = ( PTL_ME_OP_PUT | PTL_ME_IS_ACCESSIBLE | PTL_ME_EVENT_LINK_DISABLE |
PTL_ME_EVENT_UNLINK_DISABLE | PTL_ME_USE_ONCE );
me.match_id = vc_ptl->id;
me.match_bits = NPTL_MATCH(rreq->dev.match.parts.tag, rreq->dev.match.parts.context_id);
me.ignore_bits = 0;
me.min_free = 0;
MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, dt_contig, data_sz, dt_ptr, dt_true_lb);
if (data_sz < PTL_LARGE_THRESHOLD) {
if (dt_contig) {
/* small contig message */
me.start = rreq->dev.user_buf;
me.length = data_sz;
REQ_PTL(rreq)->put_handler = handler_recv_dequeue_complete;
} else {
/* small noncontig */
rreq->dev.segment_ptr = MPID_Segment_alloc();
MPIU_ERR_CHKANDJUMP1(rreq->dev.segment_ptr == NULL, mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, rreq->dev.datatype, rreq->dev.segment_ptr, 0);
rreq->dev.segment_first = 0;
rreq->dev.segment_size = data_sz;
last = rreq->dev.segment_size;
rreq->dev.iov_count = MPID_IOV_LIMIT;
MPID_Segment_pack_vector(rreq->dev.segment_ptr, 0, &last, rreq->dev.iov, &rreq->dev.iov_count);
if (last == rreq->dev.segment_size) {
/* entire message fits in IOV */
me.start = rreq->dev.iov;
me.length = rreq->dev.iov_count;
me.options |= PTL_IOVEC;
REQ_PTL(rreq)->put_handler = handler_recv_dequeue_complete;
} else {
/* IOV is not long enough to describe entire message: recv into
buffer and unpack later */
MPIU_CHKPMEM_MALLOC(REQ_PTL(req)->chunk_buffer[0], void *, data_sz, mpi_errno, "chunk_buffer");
me.start = REQ_PTL(rreq)->chunk_buffer[0];
me.length = data_sz;
REQ_PTL(rreq)->put_handler = handler_recv_dequeue_unpack_complete;
}
}
} else {
/* Large message: Create an ME for the first chunk of data, then do a GET for the rest */
if (dt_contig) {
/* large contig message */
me.start = rreq->dev.user_buf;
me.length = PTL_LARGE_THRESHOLD;
REQ_PTL(req_)->put_handler = handler_recv_dequeue_large;
} else {
/* large noncontig */
rreq->dev.segment_ptr = MPID_Segment_alloc();
MPIU_ERR_CHKANDJUMP1(rreq->dev.segment_ptr == NULL, mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, rreq->dev.datatype, rreq->dev.segment_ptr, 0);
rreq->dev.segment_first = 0;
rreq->dev.segment_size = data_sz;