root/ompi/mca/pml/ob1/pml_ob1_isend.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mca_pml_ob1_isend_init
  2. mca_pml_ob1_send_inline
  3. mca_pml_ob1_isend
  4. mca_pml_ob1_send

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2018 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2007-2016 Los Alamos National Security, LLC.  All rights
  14  *                         reserved.
  15  * Copyright (c) 2014      Cisco Systems, Inc.  All rights reserved.
  16  * Copyright (c) 2015      Research Organization for Information Science
  17  *                         and Technology (RIST). All rights reserved.
  18  * $COPYRIGHT$
  19  *
  20  * Additional copyrights may follow
  21  *
  22  * $HEADER$
  23  */
  24 
  25 #include "ompi_config.h"
  26 
  27 #include "pml_ob1.h"
  28 #include "pml_ob1_sendreq.h"
  29 #include "pml_ob1_recvreq.h"
  30 #include "ompi/peruse/peruse-internal.h"
  31 #include "ompi/runtime/ompi_spc.h"
  32 
  33 /**
  34  * Single usage request. As we allow recursive calls (as an
  35  * example from the request completion callback), we cannot rely
  36  * on using a global request. Thus, once a send acquires ownership
  37  * of this global request, it should set it to NULL to prevent
  38  * the reuse until the first user completes.
  39  */
  40 mca_pml_ob1_send_request_t *mca_pml_ob1_sendreq = NULL;
  41 
  42 int mca_pml_ob1_isend_init(const void *buf,
  43                            size_t count,
  44                            ompi_datatype_t * datatype,
  45                            int dst,
  46                            int tag,
  47                            mca_pml_base_send_mode_t sendmode,
  48                            ompi_communicator_t * comm,
  49                            ompi_request_t ** request)
  50 {
  51     mca_pml_ob1_send_request_t *sendreq = NULL;
  52     MCA_PML_OB1_SEND_REQUEST_ALLOC(comm, dst, sendreq);
  53     if (NULL == sendreq)
  54         return OMPI_ERR_OUT_OF_RESOURCE;
  55 
  56     MCA_PML_OB1_SEND_REQUEST_INIT(sendreq,
  57                                   buf,
  58                                   count,
  59                                   datatype,
  60                                   dst, tag,
  61                                   comm, sendmode, true);
  62 
  63     PERUSE_TRACE_COMM_EVENT (PERUSE_COMM_REQ_ACTIVATE,
  64                              &(sendreq)->req_send.req_base,
  65                              PERUSE_SEND);
  66 
  67     /* Work around a leak in start by marking this request as complete. The
  68      * problem occured because we do not have a way to differentiate an
  69      * inital request and an incomplete pml request in start. This line
  70      * allows us to detect this state. */
  71     sendreq->req_send.req_base.req_pml_complete = true;
  72 
  73     *request = (ompi_request_t *) sendreq;
  74     return OMPI_SUCCESS;
  75 }
  76 
  77 /* try to get a small message out on to the wire quickly */
  78 static inline int mca_pml_ob1_send_inline (const void *buf, size_t count,
  79                                            ompi_datatype_t * datatype,
  80                                            int dst, int tag, int16_t seqn,
  81                                            ompi_proc_t *dst_proc, mca_bml_base_endpoint_t* endpoint,
  82                                            ompi_communicator_t * comm)
  83 {
  84     mca_pml_ob1_match_hdr_t match;
  85     mca_bml_base_btl_t *bml_btl;
  86     opal_convertor_t convertor;
  87     size_t size;
  88     int rc;
  89 
  90     bml_btl = mca_bml_base_btl_array_get_next(&endpoint->btl_eager);
  91     if( NULL == bml_btl->btl->btl_sendi)
  92         return OMPI_ERR_NOT_AVAILABLE;
  93 
  94     ompi_datatype_type_size (datatype, &size);
  95     if ((size * count) > 256) {  /* some random number */
  96         return OMPI_ERR_NOT_AVAILABLE;
  97     }
  98 
  99     if (count > 0) {
 100         /* initialize just enough of the convertor to avoid a SEGV in opal_convertor_cleanup */
 101         OBJ_CONSTRUCT(&convertor, opal_convertor_t);
 102 
 103         /* We will create a convertor specialized for the        */
 104         /* remote architecture and prepared with the datatype.   */
 105         opal_convertor_copy_and_prepare_for_send (dst_proc->super.proc_convertor,
 106                                                   (const struct opal_datatype_t *) datatype,
 107                                                   count, buf, 0, &convertor);
 108         opal_convertor_get_packed_size (&convertor, &size);
 109     } else {
 110         size = 0;
 111     }
 112 
 113     mca_pml_ob1_match_hdr_prepare (&match, MCA_PML_OB1_HDR_TYPE_MATCH, 0,
 114                                    comm->c_contextid, comm->c_my_rank,
 115                                    tag, seqn);
 116 
 117     ob1_hdr_hton(&match, MCA_PML_OB1_HDR_TYPE_MATCH, dst_proc);
 118 
 119     /* try to send immediately */
 120     rc = mca_bml_base_sendi (bml_btl, &convertor, &match, OMPI_PML_OB1_MATCH_HDR_LEN,
 121                              size, MCA_BTL_NO_ORDER, MCA_BTL_DES_FLAGS_PRIORITY | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP,
 122                              MCA_PML_OB1_HDR_TYPE_MATCH, NULL);
 123 
 124     /* This #if is required due to an issue that arises with the IBM CI (XL Compiler).
 125      * The compiler doesn't seem to like having a compiler hint attached to an if
 126      * statement that only has a no-op inside and has the following error:
 127      *
 128      * 1586-494 (U) INTERNAL COMPILER ERROR: Signal 11.
 129      */
 130 #if SPC_ENABLE == 1
 131     if(OPAL_LIKELY(rc == OPAL_SUCCESS)) {
 132         SPC_USER_OR_MPI(tag, (ompi_spc_value_t)size, OMPI_SPC_BYTES_SENT_USER, OMPI_SPC_BYTES_SENT_MPI);
 133     }
 134 #endif
 135 
 136     if (count > 0) {
 137         opal_convertor_cleanup (&convertor);
 138     }
 139 
 140     if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) {
 141         return rc;
 142     }
 143 
 144     return (int) size;
 145 }
 146 
 147 int mca_pml_ob1_isend(const void *buf,
 148                       size_t count,
 149                       ompi_datatype_t * datatype,
 150                       int dst,
 151                       int tag,
 152                       mca_pml_base_send_mode_t sendmode,
 153                       ompi_communicator_t * comm,
 154                       ompi_request_t ** request)
 155 {
 156     mca_pml_ob1_comm_proc_t *ob1_proc = mca_pml_ob1_peer_lookup (comm, dst);
 157     mca_pml_ob1_send_request_t *sendreq = NULL;
 158     ompi_proc_t *dst_proc = ob1_proc->ompi_proc;
 159     mca_bml_base_endpoint_t* endpoint = mca_bml_base_get_endpoint (dst_proc);
 160     int16_t seqn = 0;
 161     int rc;
 162 
 163     if (OPAL_UNLIKELY(NULL == endpoint)) {
 164         return OMPI_ERR_UNREACH;
 165     }
 166 
 167     if (!OMPI_COMM_CHECK_ASSERT_ALLOW_OVERTAKE(comm)) {
 168         seqn = (uint16_t) OPAL_THREAD_ADD_FETCH32(&ob1_proc->send_sequence, 1);
 169     }
 170 
 171     if (MCA_PML_BASE_SEND_SYNCHRONOUS != sendmode) {
 172         rc = mca_pml_ob1_send_inline (buf, count, datatype, dst, tag, seqn, dst_proc,
 173                                       endpoint, comm);
 174         if (OPAL_LIKELY(0 <= rc)) {
 175             /* NTH: it is legal to return ompi_request_empty since the only valid
 176              * field in a send completion status is whether or not the send was
 177              * cancelled (which it can't be at this point anyway). */
 178             *request = &ompi_request_empty;
 179             return OMPI_SUCCESS;
 180         }
 181     }
 182 
 183     MCA_PML_OB1_SEND_REQUEST_ALLOC(comm, dst, sendreq);
 184     if (NULL == sendreq)
 185         return OMPI_ERR_OUT_OF_RESOURCE;
 186 
 187     MCA_PML_OB1_SEND_REQUEST_INIT(sendreq,
 188                                   buf,
 189                                   count,
 190                                   datatype,
 191                                   dst, tag,
 192                                   comm, sendmode, false);
 193 
 194     PERUSE_TRACE_COMM_EVENT (PERUSE_COMM_REQ_ACTIVATE,
 195                              &(sendreq)->req_send.req_base,
 196                              PERUSE_SEND);
 197 
 198     MCA_PML_OB1_SEND_REQUEST_START_W_SEQ(sendreq, endpoint, seqn, rc);
 199     *request = (ompi_request_t *) sendreq;
 200     return rc;
 201 }
 202 
 203 int mca_pml_ob1_send(const void *buf,
 204                      size_t count,
 205                      ompi_datatype_t * datatype,
 206                      int dst,
 207                      int tag,
 208                      mca_pml_base_send_mode_t sendmode,
 209                      ompi_communicator_t * comm)
 210 {
 211     mca_pml_ob1_comm_proc_t *ob1_proc = mca_pml_ob1_peer_lookup (comm, dst);
 212     ompi_proc_t *dst_proc = ob1_proc->ompi_proc;
 213     mca_bml_base_endpoint_t* endpoint = mca_bml_base_get_endpoint (dst_proc);
 214     mca_pml_ob1_send_request_t *sendreq = NULL;
 215     int16_t seqn = 0;
 216     int rc;
 217 
 218     if (OPAL_UNLIKELY(NULL == endpoint)) {
 219         return OMPI_ERR_UNREACH;
 220     }
 221 
 222     if (OPAL_UNLIKELY(MCA_PML_BASE_SEND_BUFFERED == sendmode)) {
 223         /* large buffered sends *need* a real request so use isend instead */
 224         ompi_request_t *brequest;
 225 
 226         rc = mca_pml_ob1_isend (buf, count, datatype, dst, tag, sendmode, comm, &brequest);
 227         if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) {
 228             return rc;
 229         }
 230 
 231         ompi_request_wait_completion (brequest);
 232         ompi_request_free (&brequest);
 233         return OMPI_SUCCESS;
 234     }
 235 
 236     if (!OMPI_COMM_CHECK_ASSERT_ALLOW_OVERTAKE(comm)) {
 237         seqn = (uint16_t) OPAL_THREAD_ADD_FETCH32(&ob1_proc->send_sequence, 1);
 238     }
 239 
 240     /**
 241      * The immediate send will not have a request, so they are
 242      * intracable from the point of view of any debugger attached to
 243      * the parallel application.
 244      */
 245     if (MCA_PML_BASE_SEND_SYNCHRONOUS != sendmode) {
 246         rc = mca_pml_ob1_send_inline (buf, count, datatype, dst, tag, seqn, dst_proc,
 247                                       endpoint, comm);
 248         if (OPAL_LIKELY(0 <= rc)) {
 249             return OMPI_SUCCESS;
 250         }
 251     }
 252 
 253     if (OPAL_LIKELY(!ompi_mpi_thread_multiple)) {
 254         sendreq = mca_pml_ob1_sendreq;
 255         mca_pml_ob1_sendreq = NULL;
 256     }
 257 
 258     if( OPAL_UNLIKELY(NULL == sendreq) ) {
 259         MCA_PML_OB1_SEND_REQUEST_ALLOC(comm, dst, sendreq);
 260         if (NULL == sendreq)
 261             return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
 262     }
 263 
 264     sendreq->req_send.req_base.req_proc = dst_proc;
 265     sendreq->rdma_frag = NULL;
 266 
 267     MCA_PML_OB1_SEND_REQUEST_INIT(sendreq,
 268                                   buf,
 269                                   count,
 270                                   datatype,
 271                                   dst, tag,
 272                                   comm, sendmode, false);
 273 
 274     PERUSE_TRACE_COMM_EVENT (PERUSE_COMM_REQ_ACTIVATE,
 275                              &sendreq->req_send.req_base,
 276                              PERUSE_SEND);
 277 
 278     MCA_PML_OB1_SEND_REQUEST_START_W_SEQ(sendreq, endpoint, seqn, rc);
 279     if (OPAL_LIKELY(rc == OMPI_SUCCESS)) {
 280         ompi_request_wait_completion(&sendreq->req_send.req_base.req_ompi);
 281 
 282         rc = sendreq->req_send.req_base.req_ompi.req_status.MPI_ERROR;
 283     }
 284 
 285     if (OPAL_UNLIKELY(ompi_mpi_thread_multiple || NULL != mca_pml_ob1_sendreq)) {
 286         MCA_PML_OB1_SEND_REQUEST_RETURN(sendreq);
 287     } else {
 288         mca_pml_ob1_send_request_fini (sendreq);
 289         mca_pml_ob1_sendreq = sendreq;
 290     }
 291 
 292     return rc;
 293 }

/* [<][>][^][v][top][bottom][index][help] */