This source file includes following definitions.
- ompi_mtl_portals4_callback
- ompi_mtl_portals4_send_callback
- ompi_mtl_portals4_isend_callback
- ompi_mtl_portals4_short_isend
- ompi_mtl_portals4_long_isend
- ompi_mtl_portals4_pending_list_progress
- ompi_mtl_portals4_send_start
- ompi_mtl_portals4_send
- ompi_mtl_portals4_isend
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 #include "ompi_config.h"
  24 
  25 #include "ompi/communicator/communicator.h"
  26 #include "opal/datatype/opal_convertor.h"
  27 #include "ompi/mca/mtl/base/base.h"
  28 #include "ompi/mca/mtl/base/mtl_base_datatype.h"
  29 
  30 #include "mtl_portals4.h"
  31 #include "mtl_portals4_endpoint.h"
  32 #include "mtl_portals4_request.h"
  33 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
  34 #include "mtl_portals4_flowctl.h"
  35 #endif
  36 
  37 
  38 static inline int
  39 ompi_mtl_portals4_callback(ptl_event_t *ev,
  40                            ompi_mtl_portals4_base_request_t* ptl_base_request,
  41                            bool *complete)
  42 {
  43     int retval = OMPI_SUCCESS, ret, val, add = 1;
  44     ompi_mtl_portals4_isend_request_t* ptl_request =
  45         (ompi_mtl_portals4_isend_request_t*) ptl_base_request;
  46 
  47     if (PTL_EVENT_GET == ev->type) {
  48         ret = OPAL_THREAD_ADD_FETCH32(&(ptl_request->pending_get), -1);
  49         if (ret > 0) {
  50             
  51             OPAL_OUTPUT_VERBOSE((90, ompi_mtl_base_framework.framework_output, "PTL_EVENT_GET received now pending_get=%d",ret));
  52             return retval;
  53         }
  54         assert(ptl_request->pending_get == 0);
  55 
  56         
  57         OPAL_OUTPUT_VERBOSE((90, ompi_mtl_base_framework.framework_output, "PTL_EVENT_GET: PtlMEUnlink is called ptl_request->me_h=%d (pending get=%d)", ptl_request->me_h, ret));
  58 
  59         if (!PtlHandleIsEqual(ptl_request->me_h, PTL_INVALID_HANDLE)) {
  60             ret = PtlMEUnlink(ptl_request->me_h);
  61             if (PTL_OK != ret) {
  62                 opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
  63                                 "%s:%d: send callback PtlMEUnlink returned %d",
  64                                 __FILE__, __LINE__, ret);
  65             }
  66             ptl_request->me_h = PTL_INVALID_HANDLE;
  67         }
  68     }
  69 
  70 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
  71     if (OPAL_UNLIKELY(ev->ni_fail_type == PTL_NI_PT_DISABLED)) {
  72         ompi_mtl_portals4_pending_request_t *pending =
  73             ptl_request->pending;
  74 
  75         OPAL_OUTPUT_VERBOSE((10, ompi_mtl_base_framework.framework_output,
  76                              "send %lu hit flow control (%d)",
  77                              ptl_request->opcount, ev->type));
  78 
  79         
  80         if (pending->fc_notified) {
  81             return OMPI_SUCCESS;
  82         }
  83         pending->fc_notified = 1;
  84 
  85         if (!PtlHandleIsEqual(ptl_request->me_h, PTL_INVALID_HANDLE)) {
  86             ret = PtlMEUnlink(ptl_request->me_h);
  87             if (PTL_OK != ret) {
  88                 opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
  89                                     "%s:%d: send callback PtlMEUnlink returned %d",
  90                                     __FILE__, __LINE__, ret);
  91             }
  92             ptl_request->me_h = PTL_INVALID_HANDLE;
  93         }
  94 
  95         opal_list_append(&ompi_mtl_portals4.flowctl.pending_sends,
  96                          &pending->super.super);
  97         OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
  98         ompi_mtl_portals4_flowctl_trigger();
  99 
 100         return OMPI_SUCCESS;
 101     }
 102 #endif
 103 
 104     if (OPAL_UNLIKELY(ev->ni_fail_type != PTL_NI_OK)) {
 105         opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 106                             "%s:%d: send callback ni_fail_type: %d",
 107                             __FILE__, __LINE__, ev->ni_fail_type);
 108         *complete = true;
 109         return OMPI_ERROR;
 110     }
 111 
 112     OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 113                          "send %lu got event of type %d",
 114                          ptl_request->opcount, ev->type));
 115 
 116     
 117 
 118 
 119 
 120 
 121     if ((PTL_EVENT_ACK == ev->type) &&
 122         (PTL_PRIORITY_LIST == ev->ptl_list) &&
 123         (0 <  ptl_request->pending_get)) {
 124 
 125         if ((eager == ompi_mtl_portals4.protocol) ||
 126              (ptl_request->length % ompi_mtl_portals4.max_msg_size_mtl <= ompi_mtl_portals4.eager_limit)) {
 127            val = OPAL_THREAD_ADD_FETCH32(&(ptl_request->pending_get), -1);
 128         }
 129         if (0 == val) {
 130             add = 2; 
 131             if (!PtlHandleIsEqual(ptl_request->me_h, PTL_INVALID_HANDLE)) {
 132                 ret = PtlMEUnlink(ptl_request->me_h);
 133                 if (PTL_OK != ret) {
 134                     opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 135                                 "%s:%d: send callback PtlMEUnlink returned %d",
 136                                 __FILE__, __LINE__, ret);
 137                 }
 138                 ptl_request->me_h = PTL_INVALID_HANDLE;
 139             }
 140         }
 141     }
 142 
 143     if ((PTL_EVENT_ACK == ev->type) &&
 144         (PTL_PRIORITY_LIST == ev->ptl_list) &&
 145         (ev->mlength == ptl_request->length) &&
 146         (!PtlHandleIsEqual(ptl_request->me_h, PTL_INVALID_HANDLE))) {
 147         
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155         ret = PtlMEUnlink(ptl_request->me_h);
 156         if (PTL_OK != ret) {
 157             opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 158                                 "%s:%d: send callback PtlMEUnlink returned %d",
 159                                 __FILE__, __LINE__, ret);
 160         }
 161         ptl_request->me_h = PTL_INVALID_HANDLE;
 162         add++;
 163     }
 164     val = OPAL_THREAD_ADD_FETCH32((int32_t*)&ptl_request->event_count, add);
 165     assert(val <= 3);
 166 
 167     if (val == 3) {
 168         if (NULL != ptl_request->buffer_ptr) {
 169             free(ptl_request->buffer_ptr);
 170         }
 171 
 172         OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output, "send %lu completed",
 173                              ptl_request->opcount));
 174 
 175         *complete = true;
 176 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
 177         OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 178         opal_free_list_return (&ompi_mtl_portals4.flowctl.pending_fl,
 179                                &ptl_request->pending->super);
 180 
 181         if (OPAL_UNLIKELY(0 != opal_list_get_size(&ompi_mtl_portals4.flowctl.pending_sends))) {
 182             ompi_mtl_portals4_pending_list_progress();
 183         }
 184 #endif
 185     }
 186 
 187     return retval;
 188 }
 189 
 190 
 191 static int
 192 ompi_mtl_portals4_send_callback(ptl_event_t *ev,
 193                                 ompi_mtl_portals4_base_request_t* ptl_base_request)
 194 {
 195     bool complete = false;
 196     int ret;
 197     ompi_mtl_portals4_send_request_t* ptl_request =
 198         (ompi_mtl_portals4_send_request_t*) ptl_base_request;
 199 
 200     ret = ompi_mtl_portals4_callback(ev, ptl_base_request, &complete);
 201     if (complete) {
 202         ptl_request->retval = ret;
 203         opal_atomic_wmb();
 204         ptl_request->complete = true;
 205     }
 206 
 207     return OMPI_SUCCESS;
 208 }
 209 
 210 
 211 static int
 212 ompi_mtl_portals4_isend_callback(ptl_event_t *ev,
 213                                  ompi_mtl_portals4_base_request_t* ptl_base_request)
 214 {
 215     bool complete = false;
 216     int ret;
 217     ompi_mtl_portals4_isend_request_t* ptl_request =
 218         (ompi_mtl_portals4_isend_request_t*) ptl_base_request;
 219 
 220     ret = ompi_mtl_portals4_callback(ev, ptl_base_request, &complete);
 221     if (complete) {
 222         ptl_request->super.super.ompi_req->req_status.MPI_ERROR = ret;
 223         ptl_request->super.super.completion_callback(&ptl_request->super.super);
 224     }
 225 
 226     return OMPI_SUCCESS;
 227 }
 228 
 229 
 230 static inline int
 231 ompi_mtl_portals4_short_isend(mca_pml_base_send_mode_t mode,
 232                               void *start, int length, int contextid, int tag,
 233                               int localrank,
 234                               ptl_process_t ptl_proc,
 235                               ompi_mtl_portals4_isend_request_t *ptl_request)
 236 {
 237     int ret;
 238     ptl_match_bits_t match_bits;
 239     ptl_me_t me;
 240     ptl_hdr_data_t hdr_data;
 241 
 242     MTL_PORTALS4_SET_SEND_BITS(match_bits, contextid, localrank, tag,
 243                                MTL_PORTALS4_SHORT_MSG);
 244 
 245     MTL_PORTALS4_SET_HDR_DATA(hdr_data, ptl_request->opcount, length,
 246                               (MCA_PML_BASE_SEND_SYNCHRONOUS == mode) ? 1 : 0);
 247     ptl_request->me_h = PTL_INVALID_HANDLE;
 248 
 249     if (MCA_PML_BASE_SEND_SYNCHRONOUS == mode) {
 250         me.start = NULL;
 251         me.length = 0;
 252         me.ct_handle = PTL_CT_NONE;
 253         me.min_free = 0;
 254         me.uid = ompi_mtl_portals4.uid;
 255         me.options =
 256             PTL_ME_OP_PUT |
 257             PTL_ME_USE_ONCE |
 258             PTL_ME_EVENT_LINK_DISABLE |
 259             PTL_ME_EVENT_UNLINK_DISABLE;
 260         me.match_id = ptl_proc;
 261         me.match_bits = hdr_data;
 262         me.ignore_bits = 0;
 263 
 264         ret = PtlMEAppend(ompi_mtl_portals4.ni_h,
 265                           ompi_mtl_portals4.read_idx,
 266                           &me,
 267                           PTL_PRIORITY_LIST,
 268                           ptl_request,
 269                           &ptl_request->me_h);
 270         if (OPAL_UNLIKELY(PTL_OK != ret)) {
 271             opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 272                                 "%s:%d: PtlMEAppend failed: %d",
 273                                 __FILE__, __LINE__, ret);
 274             ptl_request->me_h = PTL_INVALID_HANDLE;
 275             return ompi_mtl_portals4_get_error(ret);
 276         }
 277 
 278         OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 279                              "Send %lu short sync send with hdr_data 0x%lx (0x%lx)",
 280                              ptl_request->opcount, hdr_data, match_bits));
 281     } else {
 282         ptl_request->event_count = 1;
 283 
 284         OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 285                              "Send %lu short send with hdr_data 0x%lx (0x%lx)",
 286                              ptl_request->opcount, hdr_data, match_bits));
 287     }
 288 
 289     OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 290                          "Send %lu, start: %p",
 291                          ptl_request->opcount, start));
 292 
 293     ptl_request->pending_get = 0;
 294     ret = PtlPut(ompi_mtl_portals4.send_md_h,
 295                  (ptl_size_t) start,
 296                  length,
 297                  PTL_ACK_REQ,
 298                  ptl_proc,
 299                  ompi_mtl_portals4.recv_idx,
 300                  match_bits,
 301                  0,
 302                  ptl_request,
 303                  hdr_data);
 304     if (OPAL_UNLIKELY(PTL_OK != ret)) {
 305         opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 306                             "%s:%d: PtlPut failed: %d",
 307                             __FILE__, __LINE__, ret);
 308         if (MCA_PML_BASE_SEND_SYNCHRONOUS == mode) {
 309             PtlMEUnlink(ptl_request->me_h);
 310             ptl_request->me_h = PTL_INVALID_HANDLE;
 311         }
 312         return ompi_mtl_portals4_get_error(ret);
 313     }
 314 
 315     return OMPI_SUCCESS;
 316 }
 317 
 318 static inline int
 319 ompi_mtl_portals4_long_isend(void *start, size_t length, int contextid, int tag,
 320                              int localrank,
 321                              ptl_process_t ptl_proc,
 322                              ompi_mtl_portals4_isend_request_t *ptl_request)
 323 {
 324     int ret;
 325     ptl_match_bits_t match_bits;
 326     ptl_me_t me;
 327     ptl_hdr_data_t hdr_data;
 328     ptl_size_t put_length;
 329 
 330     MTL_PORTALS4_SET_SEND_BITS(match_bits, contextid, localrank, tag,
 331                                MTL_PORTALS4_LONG_MSG);
 332 
 333     MTL_PORTALS4_SET_HDR_DATA(hdr_data, ptl_request->opcount, length, 0);
 334 
 335     me.start = start;
 336     me.length = length;
 337     me.ct_handle = PTL_CT_NONE;
 338     me.min_free = 0;
 339     me.uid = ompi_mtl_portals4.uid;
 340     me.options =
 341         PTL_ME_OP_GET |
 342         PTL_ME_EVENT_LINK_DISABLE |
 343         PTL_ME_EVENT_UNLINK_DISABLE;
 344     me.match_id = ptl_proc;
 345     me.match_bits = hdr_data;
 346     me.ignore_bits = 0;
 347 
 348     ret = PtlMEAppend(ompi_mtl_portals4.ni_h,
 349                       ompi_mtl_portals4.read_idx,
 350                       &me,
 351                       PTL_PRIORITY_LIST,
 352                       ptl_request,
 353                       &ptl_request->me_h);
 354     if (OPAL_UNLIKELY(PTL_OK != ret)) {
 355         opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 356                             "%s:%d: PtlMEAppend failed: %d",
 357                             __FILE__, __LINE__, ret);
 358         return ompi_mtl_portals4_get_error(ret);
 359     }
 360 
 361     OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 362                          "Send %lu long send with hdr_data 0x%lx (0x%lx)",
 363                          ptl_request->opcount, hdr_data, match_bits));
 364 
 365     if (rndv == ompi_mtl_portals4.protocol) {
 366         ptl_size_t min = (OPAL_LIKELY (ompi_mtl_portals4.eager_limit < ompi_mtl_portals4.max_msg_size_mtl)) ?
 367             ompi_mtl_portals4.eager_limit :
 368             ompi_mtl_portals4.max_msg_size_mtl;
 369         if ((ptl_size_t) length > (ptl_size_t) min) {
 370             OPAL_OUTPUT_VERBOSE((90, ompi_mtl_base_framework.framework_output,
 371                                  "msg truncated by %ld", length - min));
 372             put_length = (ptl_size_t) min;
 373         }
 374         else
 375             put_length = (ptl_size_t) length;
 376     } else { 
 377         if (length >  ompi_mtl_portals4.max_msg_size_mtl)
 378             put_length = (ptl_size_t) ompi_mtl_portals4.max_msg_size_mtl;
 379         else
 380             put_length = (ptl_size_t) length;
 381     }
 382 
 383     
 384 
 385 
 386 
 387 
 388 
 389     ptl_request->pending_get = (length - 1) / ompi_mtl_portals4.max_msg_size_mtl + 1;
 390     OPAL_OUTPUT_VERBOSE((90, ompi_mtl_base_framework.framework_output, "pending_get=%d", ptl_request->pending_get));
 391 
 392     ret = PtlPut(ompi_mtl_portals4.send_md_h,
 393                  (ptl_size_t) start,
 394                  put_length,
 395                  PTL_ACK_REQ,
 396                  ptl_proc,
 397                  ompi_mtl_portals4.recv_idx,
 398                  match_bits,
 399                  0,
 400                  ptl_request,
 401                  hdr_data);
 402     if (OPAL_UNLIKELY(PTL_OK != ret)) {
 403         opal_output_verbose(1, ompi_mtl_base_framework.framework_output,
 404                             "%s:%d: PtlPut failed: %d",
 405                             __FILE__, __LINE__, ret);
 406         PtlMEUnlink(ptl_request->me_h);
 407         ptl_request->me_h = PTL_INVALID_HANDLE;
 408         return ompi_mtl_portals4_get_error(ret);
 409     }
 410 
 411     return OMPI_SUCCESS;
 412 }
 413 
 414 
 415 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
 416 void
 417 ompi_mtl_portals4_pending_list_progress()
 418 {
 419     int ret, val;
 420     opal_list_item_t *item;
 421     ompi_mtl_portals4_pending_request_t *pending;
 422 
 423     while ((!ompi_mtl_portals4.flowctl.flowctl_active) &&
 424            (0 != opal_list_get_size(&ompi_mtl_portals4.flowctl.pending_sends))) {
 425         val = OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, -1);
 426         if (val < 0) {
 427             OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 428             return;
 429         }
 430 
 431         item = opal_list_remove_first(&ompi_mtl_portals4.flowctl.pending_sends);
 432         if (OPAL_UNLIKELY(NULL == item)) {
 433             OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 434             return;
 435         }
 436 
 437         pending = (ompi_mtl_portals4_pending_request_t*) item;
 438         if (pending->length <= ompi_mtl_portals4.short_limit) {
 439             ret = ompi_mtl_portals4_short_isend(pending->mode,
 440                                                 pending->start,
 441                                                 pending->length,
 442                                                 pending->contextid,
 443                                                 pending->tag,
 444                                                 pending->my_rank,
 445                                                 pending->ptl_proc,
 446                                                 pending->ptl_request);
 447         } else {
 448             ret = ompi_mtl_portals4_long_isend(pending->start,
 449                                                pending->length,
 450                                                pending->contextid,
 451                                                pending->tag,
 452                                                pending->my_rank,
 453                                                pending->ptl_proc,
 454                                                pending->ptl_request);
 455         }
 456         if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
 457             opal_list_prepend(&ompi_mtl_portals4.flowctl.pending_sends,
 458                               &pending->super.super);
 459             OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 460         }
 461     }
 462 }
 463 #endif
 464 
 465 
 466 static inline int
 467 ompi_mtl_portals4_send_start(struct mca_mtl_base_module_t* mtl,
 468                              struct ompi_communicator_t* comm,
 469                              int dest,
 470                              int tag,
 471                              struct opal_convertor_t *convertor,
 472                              mca_pml_base_send_mode_t mode,
 473                              ompi_mtl_portals4_isend_request_t* ptl_request)
 474 {
 475     int ret= OMPI_SUCCESS;
 476     void *start;
 477     size_t length;
 478     bool free_after;
 479     ptl_process_t ptl_proc;
 480 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
 481     opal_free_list_item_t *item;
 482     ompi_mtl_portals4_pending_request_t *pending;
 483 #endif
 484 
 485     if ((ompi_mtl_portals4.use_logical) && (MPI_COMM_WORLD == comm)) {
 486         ptl_proc.rank = dest;
 487     } else {
 488         ompi_proc_t *ompi_proc = ompi_comm_peer_lookup(comm, dest);
 489         ptl_proc = *((ptl_process_t*) ompi_mtl_portals4_get_endpoint (mtl, ompi_proc));
 490     }
 491 
 492     ret = ompi_mtl_datatype_pack(convertor, &start, &length, &free_after);
 493     if (OMPI_SUCCESS != ret) return ret;
 494 
 495     ptl_request->opcount = OPAL_THREAD_ADD_FETCH64((int64_t*)&ompi_mtl_portals4.opcount, 1);
 496     ptl_request->buffer_ptr = (free_after) ? start : NULL;
 497     ptl_request->length = length;
 498     ptl_request->event_count = 0;
 499 
 500     OPAL_OUTPUT_VERBOSE((50, ompi_mtl_base_framework.framework_output,
 501                          "Send %lu to %x,%x of length %ld\n",
 502                          ptl_request->opcount,
 503                          ptl_proc.phys.nid,
 504                          ptl_proc.phys.pid,
 505                          (int64_t)length));
 506 
 507 #if OMPI_MTL_PORTALS4_FLOW_CONTROL
 508     item = opal_free_list_get (&ompi_mtl_portals4.flowctl.pending_fl);
 509     if (NULL == item) return OMPI_ERR_OUT_OF_RESOURCE;
 510 
 511     pending = (ompi_mtl_portals4_pending_request_t*) item;
 512     ptl_request->pending = pending;
 513     pending->mode = mode;
 514     pending->start = start;
 515     pending->length = length;
 516     pending->contextid = comm->c_contextid;
 517     pending->tag = tag;
 518     pending->my_rank = comm->c_my_rank;
 519     pending->fc_notified = 0;
 520     pending->ptl_proc = ptl_proc;
 521     pending->ptl_request = ptl_request;
 522 
 523     if (OPAL_UNLIKELY(OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, -1) < 0)) {
 524         OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 525         opal_list_append(&ompi_mtl_portals4.flowctl.pending_sends,
 526                          &pending->super.super);
 527         return OMPI_SUCCESS;
 528     }
 529 
 530     if (OPAL_UNLIKELY(0 != opal_list_get_size(&ompi_mtl_portals4.flowctl.pending_sends))) {
 531         OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 532         opal_list_append(&ompi_mtl_portals4.flowctl.pending_sends,
 533                          &pending->super.super);
 534         ompi_mtl_portals4_pending_list_progress();
 535         return OMPI_SUCCESS;
 536     }
 537 
 538     if (OPAL_UNLIKELY(ompi_mtl_portals4.flowctl.flowctl_active)) {
 539         OPAL_THREAD_ADD_FETCH32(&ompi_mtl_portals4.flowctl.send_slots, 1);
 540         opal_list_append(&ompi_mtl_portals4.flowctl.pending_sends,
 541                          &pending->super.super);
 542         return OMPI_SUCCESS;
 543     }
 544 #endif
 545     if (length <= ompi_mtl_portals4.short_limit) {
 546         ret = ompi_mtl_portals4_short_isend(mode,
 547                                             start,
 548                                             length,
 549                                             comm->c_contextid,
 550                                             tag,
 551                                             comm->c_my_rank,
 552                                             ptl_proc,
 553                                             ptl_request);
 554     } else {
 555         ret = ompi_mtl_portals4_long_isend(start,
 556                                            length,
 557                                            comm->c_contextid,
 558                                            tag,
 559                                            comm->c_my_rank,
 560                                            ptl_proc,
 561                                            ptl_request);
 562     }
 563 
 564     return ret;
 565 }
 566 
 567 
 568 int
 569 ompi_mtl_portals4_send(struct mca_mtl_base_module_t* mtl,
 570                        struct ompi_communicator_t* comm,
 571                        int dest,
 572                        int tag,
 573                        struct opal_convertor_t *convertor,
 574                        mca_pml_base_send_mode_t mode)
 575 {
 576     int ret = OMPI_SUCCESS;
 577     ompi_mtl_portals4_send_request_t ptl_request;
 578 
 579     ptl_request.complete = false;
 580     ptl_request.retval = OMPI_SUCCESS;
 581     ptl_request.super.super.type = portals4_req_send;
 582     ptl_request.super.super.event_callback = ompi_mtl_portals4_send_callback;
 583 
 584     ret = ompi_mtl_portals4_send_start(mtl, comm, dest, tag,
 585                                        convertor, mode, &ptl_request.super);
 586     if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
 587         if (NULL != ptl_request.super.buffer_ptr) {
 588             free(ptl_request.super.buffer_ptr);
 589         }
 590         return ret;
 591     }
 592 
 593     while (false == ptl_request.complete) {
 594         ompi_mtl_portals4_progress();
 595     }
 596     ret = ptl_request.retval;
 597 
 598     return ret;
 599 }
 600 
 601 
 602 int
 603 ompi_mtl_portals4_isend(struct mca_mtl_base_module_t* mtl,
 604                         struct ompi_communicator_t* comm,
 605                         int dest,
 606                         int tag,
 607                         struct opal_convertor_t *convertor,
 608                         mca_pml_base_send_mode_t mode,
 609                         bool blocking,
 610                         mca_mtl_request_t *mtl_request)
 611 {
 612     int ret = OMPI_SUCCESS;
 613     ompi_mtl_portals4_isend_request_t *ptl_request =
 614         (ompi_mtl_portals4_isend_request_t*) mtl_request;
 615 
 616     ptl_request->super.type = portals4_req_isend;
 617     ptl_request->super.event_callback = ompi_mtl_portals4_isend_callback;
 618 
 619     ret = ompi_mtl_portals4_send_start(mtl, comm, dest, tag,
 620                                        convertor, mode, ptl_request);
 621 
 622     if (OPAL_UNLIKELY(OMPI_SUCCESS != ret && NULL != ptl_request->buffer_ptr)) {
 623         free(ptl_request->buffer_ptr);
 624     }
 625 
 626     return ret;
 627 }