1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2011 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2009 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006-2007 Voltaire. All rights reserved.
* Copyright (c) 2009 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2010-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2015 Mellanox Technologies. All rights reserved.
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/mca/btl/sm/btl_sm.h"
#include "opal/mca/btl/sm/btl_sm_fifo.h"
#include "opal/mca/btl/sm/btl_sm_frag.h"
#include "opal/mca/btl/sm/btl_sm_fbox.h"
/**
* Initiate an inline send to the peer.
*
* @param btl (IN) BTL module
* @param peer (IN) BTL peer addressing
*/
int mca_btl_sm_sendi(struct mca_btl_base_module_t *btl, struct mca_btl_base_endpoint_t *endpoint,
struct opal_convertor_t *convertor, void *header, size_t header_size,
size_t payload_size, uint8_t order, uint32_t flags, mca_btl_base_tag_t tag,
mca_btl_base_descriptor_t **descriptor)
{
mca_btl_sm_frag_t *frag;
void *data_ptr = NULL;
size_t length;
/* don't attempt sendi if there are pending fragments on the endpoint */
if (OPAL_UNLIKELY(opal_list_get_size(&endpoint->pending_frags))) {
if (descriptor) {
*descriptor = NULL;
}
return OPAL_ERR_OUT_OF_RESOURCE;
}
if (payload_size) {
opal_convertor_get_current_pointer(convertor, &data_ptr);
}
if (!(payload_size && (opal_convertor_need_buffers(convertor) || opal_convertor_on_device(convertor)))
&& mca_btl_sm_fbox_sendi(endpoint, tag, header, header_size, data_ptr, payload_size)) {
return OPAL_SUCCESS;
}
length = header_size + payload_size;
/* allocate a fragment, giving up if we can't get one */
frag = (mca_btl_sm_frag_t *) mca_btl_sm_alloc(btl, endpoint, order, length,
flags | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP);
if (OPAL_UNLIKELY(NULL == frag)) {
if (descriptor) {
*descriptor = NULL;
}
return OPAL_ERR_OUT_OF_RESOURCE;
}
/* fill in fragment fields */
frag->hdr->len = length;
frag->hdr->tag = tag;
/* write the match header (with MPI comm/tag/etc. info) */
memcpy(frag->segments[0].seg_addr.pval, header, header_size);
/* write the message data if there is any */
/* we can't use single-copy semantics here since as caller will consider the send
complete when we return */
if (payload_size) {
uint32_t iov_count = 1;
struct iovec iov;
/* pack the data into the supplied buffer */
iov.iov_base = (IOVBASE_TYPE *) ((uintptr_t) frag->segments[0].seg_addr.pval + header_size);
iov.iov_len = length = payload_size;
(void) opal_convertor_pack(convertor, &iov, &iov_count, &length);
assert(length == payload_size);
}
/* write the fragment pointer to peer's the FIFO. the progress function will return the fragment
*/
if (!sm_fifo_write_ep(frag->hdr, endpoint)) {
if (descriptor) {
*descriptor = &frag->base;
} else {
mca_btl_sm_free(btl, &frag->base);
}
return OPAL_ERR_OUT_OF_RESOURCE;
}
return OPAL_SUCCESS;
}
|