368 строки
11 KiB
C
368 строки
11 KiB
C
|
/*
|
||
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||
|
* University Research and Technology
|
||
|
* Corporation. All rights reserved.
|
||
|
* Copyright (c) 2004-2005 The University of Tennessee and The University
|
||
|
* of Tennessee Research Foundation. All rights
|
||
|
* reserved.
|
||
|
* Copyright (c) 2004-2005 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 Sandia National Laboratories. All rights
|
||
|
* reserved.
|
||
|
* Copyright (c) 2013 Cisco Systems, Inc. All rights reserved.
|
||
|
* $COPYRIGHT$
|
||
|
*
|
||
|
* Additional copyrights may follow
|
||
|
*
|
||
|
* $HEADER$
|
||
|
*/
|
||
|
|
||
|
#include "ompi_config.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "ompi/proc/proc.h"
|
||
|
|
||
|
#include "btl_usnic.h"
|
||
|
#include "btl_usnic_endpoint.h"
|
||
|
#include "btl_usnic_module.h"
|
||
|
#include "btl_usnic_frag.h"
|
||
|
#include "btl_usnic_ack.h"
|
||
|
|
||
|
static void
|
||
|
common_send_seg_helper(
|
||
|
ompi_btl_usnic_send_segment_t *seg)
|
||
|
{
|
||
|
ompi_btl_usnic_segment_t *bseg;
|
||
|
|
||
|
bseg = &seg->ss_base;
|
||
|
|
||
|
bseg->us_btl_header = (ompi_btl_usnic_btl_header_t *)bseg->us_list.ptr;
|
||
|
bseg->us_btl_header->sender = mca_btl_usnic_component.my_hashed_orte_name;
|
||
|
|
||
|
/* build verbs work request descriptor */
|
||
|
seg->ss_send_desc.wr_id = (unsigned long) seg;
|
||
|
seg->ss_send_desc.sg_list = bseg->us_sg_entry;
|
||
|
seg->ss_send_desc.num_sge = 1;
|
||
|
seg->ss_send_desc.opcode = IBV_WR_SEND;
|
||
|
seg->ss_send_desc.next = NULL;
|
||
|
|
||
|
seg->ss_send_desc.send_flags = IBV_SEND_SIGNALED;
|
||
|
|
||
|
seg->ss_send_posted = 0;
|
||
|
seg->ss_ack_pending = false;
|
||
|
|
||
|
/* verbs SG entry, len will be filled in just before send */
|
||
|
bseg->us_sg_entry[0].addr = (unsigned long) bseg->us_btl_header;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
chunk_seg_constructor(
|
||
|
ompi_btl_usnic_send_segment_t *seg)
|
||
|
{
|
||
|
ompi_btl_usnic_segment_t *bseg;
|
||
|
|
||
|
bseg = &seg->ss_base;
|
||
|
bseg->us_type = OMPI_BTL_USNIC_SEG_CHUNK;
|
||
|
|
||
|
/* some more common initializaiton */
|
||
|
common_send_seg_helper(seg);
|
||
|
seg->ss_flags = 0;
|
||
|
|
||
|
/* payload starts next byte beyond BTL chunk header */
|
||
|
bseg->us_payload.raw = (uint8_t *)(bseg->us_btl_chunk_header + 1);
|
||
|
|
||
|
bseg->us_btl_header->payload_type = OMPI_BTL_USNIC_PAYLOAD_TYPE_CHUNK;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
frag_seg_constructor(
|
||
|
ompi_btl_usnic_send_segment_t *seg)
|
||
|
{
|
||
|
ompi_btl_usnic_segment_t *bseg;
|
||
|
|
||
|
bseg = &seg->ss_base;
|
||
|
bseg->us_type = OMPI_BTL_USNIC_SEG_FRAG;
|
||
|
|
||
|
/* some more common initializaiton */
|
||
|
common_send_seg_helper(seg);
|
||
|
seg->ss_flags = 0;
|
||
|
|
||
|
/* payload starts next byte beyond BTL header */
|
||
|
bseg->us_payload.raw = (uint8_t *)(bseg->us_btl_header + 1);
|
||
|
|
||
|
bseg->us_btl_header->payload_type = OMPI_BTL_USNIC_PAYLOAD_TYPE_FRAG;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ack_seg_constructor(
|
||
|
ompi_btl_usnic_send_segment_t *ack)
|
||
|
{
|
||
|
ompi_btl_usnic_segment_t *bseg;
|
||
|
|
||
|
bseg = &ack->ss_base;
|
||
|
bseg->us_type = OMPI_BTL_USNIC_SEG_ACK;
|
||
|
|
||
|
/* some more common initializaiton */
|
||
|
common_send_seg_helper(ack);
|
||
|
|
||
|
/* ACK value embedded in BTL header */
|
||
|
bseg->us_btl_header->payload_type = OMPI_BTL_USNIC_PAYLOAD_TYPE_ACK;
|
||
|
bseg->us_btl_header->payload_len = 0;
|
||
|
|
||
|
bseg->us_sg_entry[0].length = sizeof(bseg->us_btl_header);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
recv_seg_constructor(
|
||
|
ompi_btl_usnic_recv_segment_t *seg)
|
||
|
{
|
||
|
ompi_btl_usnic_segment_t *bseg;
|
||
|
|
||
|
bseg = &seg->rs_base;
|
||
|
bseg->us_type = OMPI_BTL_USNIC_SEG_RECV;
|
||
|
|
||
|
/* on receive, BTL header starts after protocol header */
|
||
|
seg->rs_protocol_header = bseg->us_list.ptr;
|
||
|
bseg->us_btl_header =
|
||
|
(ompi_btl_usnic_btl_header_t *) (seg->rs_protocol_header + 1);
|
||
|
|
||
|
/* initialize verbs work request */
|
||
|
seg->rs_recv_desc.wr_id = (unsigned long) seg;
|
||
|
seg->rs_recv_desc.sg_list = bseg->us_sg_entry;
|
||
|
seg->rs_recv_desc.num_sge = 1;
|
||
|
|
||
|
/* verbs SG entry, len filled in by caller b/c we don't have value */
|
||
|
bseg->us_sg_entry[0].addr = (unsigned long) seg->rs_protocol_header;
|
||
|
|
||
|
/* initialize mca descriptor */
|
||
|
seg->rs_desc.des_dst = &seg->rs_segment;
|
||
|
seg->rs_desc.des_dst_cnt = 1;
|
||
|
seg->rs_desc.des_src = NULL;
|
||
|
seg->rs_desc.des_src_cnt = 0;
|
||
|
|
||
|
/* PML want to see its header
|
||
|
* This pointer is only correct for incoming segments of type
|
||
|
* OMPI_BTL_USNIC_PAYLOAD_TYPE_FRAG, but that's the only time
|
||
|
* we ever give segment directly to PML, so its OK
|
||
|
*/
|
||
|
bseg->us_payload.pml_header = (mca_btl_base_header_t *)
|
||
|
(bseg->us_btl_header+1);
|
||
|
seg->rs_segment.seg_addr.pval = bseg->us_payload.pml_header;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
send_frag_constructor(ompi_btl_usnic_send_frag_t *frag)
|
||
|
{
|
||
|
mca_btl_base_descriptor_t *desc;
|
||
|
|
||
|
/* Fill in source descriptor */
|
||
|
desc = &frag->sf_base.uf_base;
|
||
|
desc->des_src = frag->sf_base.uf_src_seg;
|
||
|
desc->des_src_cnt = 2;
|
||
|
desc->des_dst = frag->sf_base.uf_dst_seg;
|
||
|
desc->des_dst_cnt = 0;
|
||
|
|
||
|
desc->order = MCA_BTL_NO_ORDER;
|
||
|
desc->des_flags = 0;
|
||
|
|
||
|
frag->sf_seg_post_cnt = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
small_send_frag_constructor(ompi_btl_usnic_small_send_frag_t *frag)
|
||
|
{
|
||
|
ompi_btl_usnic_frag_segment_t *fseg;
|
||
|
|
||
|
send_frag_constructor(&frag->ssf_base);
|
||
|
|
||
|
/* construct the embedded segment */
|
||
|
fseg = &frag->ssf_segment;
|
||
|
fseg->ss_base.us_list.ptr = frag->ssf_base.sf_base.uf_base.super.ptr;
|
||
|
frag_seg_constructor(fseg);
|
||
|
|
||
|
/* set us as parent in dedicated frag */
|
||
|
fseg->ss_parent_frag = (struct ompi_btl_usnic_send_frag_t *)frag;
|
||
|
|
||
|
frag->ssf_base.sf_base.uf_type = OMPI_BTL_USNIC_FRAG_SMALL_SEND;
|
||
|
|
||
|
/* save data pointer for PML */
|
||
|
frag->ssf_base.sf_base.uf_src_seg[0].seg_addr.pval =
|
||
|
fseg->ss_base.us_payload.raw;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
large_send_frag_constructor(ompi_btl_usnic_large_send_frag_t *lfrag)
|
||
|
{
|
||
|
send_frag_constructor(&lfrag->lsf_base);
|
||
|
|
||
|
lfrag->lsf_base.sf_base.uf_type = OMPI_BTL_USNIC_FRAG_LARGE_SEND;
|
||
|
|
||
|
/* save data pointer for PML */
|
||
|
lfrag->lsf_base.sf_base.uf_src_seg[0].seg_addr.pval =
|
||
|
&lfrag->lsf_pml_header;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
put_dest_frag_constructor(ompi_btl_usnic_put_dest_frag_t *pfrag)
|
||
|
{
|
||
|
pfrag->uf_type = OMPI_BTL_USNIC_FRAG_PUT_DEST;
|
||
|
|
||
|
/* point dest to our utility segment */
|
||
|
pfrag->uf_base.des_dst = pfrag->uf_dst_seg;
|
||
|
pfrag->uf_base.des_dst_cnt = 1;
|
||
|
}
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_segment_t,
|
||
|
ompi_free_list_item_t,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_frag_segment_t,
|
||
|
ompi_btl_usnic_segment_t,
|
||
|
frag_seg_constructor,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_chunk_segment_t,
|
||
|
ompi_btl_usnic_segment_t,
|
||
|
chunk_seg_constructor,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_recv_segment_t,
|
||
|
ompi_btl_usnic_segment_t,
|
||
|
recv_seg_constructor,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_ack_segment_t,
|
||
|
ompi_btl_usnic_segment_t,
|
||
|
ack_seg_constructor,
|
||
|
NULL);
|
||
|
|
||
|
/*
|
||
|
* Fragments
|
||
|
*/
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_frag_t,
|
||
|
mca_btl_base_descriptor_t,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_send_frag_t,
|
||
|
ompi_btl_usnic_frag_t,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_large_send_frag_t,
|
||
|
ompi_btl_usnic_send_frag_t,
|
||
|
large_send_frag_constructor,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_small_send_frag_t,
|
||
|
ompi_btl_usnic_send_frag_t,
|
||
|
small_send_frag_constructor,
|
||
|
NULL);
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_put_dest_frag_t,
|
||
|
ompi_btl_usnic_frag_t,
|
||
|
put_dest_frag_constructor,
|
||
|
NULL);
|
||
|
|
||
|
|
||
|
/*******************************************************************************/
|
||
|
|
||
|
#if MSGDEBUG
|
||
|
static void dump_ack_frag(ompi_btl_usnic_frag_t* frag)
|
||
|
{
|
||
|
char out[256];
|
||
|
memset(out, 0, sizeof(out));
|
||
|
|
||
|
snprintf(out, sizeof(out),
|
||
|
"=== ACK frag %p (MCW %d): alloced %d",
|
||
|
(void*) frag,
|
||
|
ompi_proc_local()->proc_name.vpid,
|
||
|
FRAG_STATE_ISSET(frag, FRAG_ALLOCED));
|
||
|
opal_output(0, out);
|
||
|
}
|
||
|
|
||
|
static void dump_send_frag(ompi_btl_usnic_frag_t* frag)
|
||
|
{
|
||
|
char out[256];
|
||
|
memset(out, 0, sizeof(out));
|
||
|
|
||
|
snprintf(out, sizeof(out),
|
||
|
"=== SEND frag %p (MCW %d): alloced %d send_wr %d acked %d enqueued %d pml_callback %d hotel %d || seq %lu",
|
||
|
(void*) frag,
|
||
|
ompi_proc_local()->proc_name.vpid,
|
||
|
FRAG_STATE_ISSET(frag, FRAG_ALLOCED),
|
||
|
frag->send_wr_posted,
|
||
|
FRAG_STATE_ISSET(frag, FRAG_SEND_ACKED),
|
||
|
FRAG_STATE_ISSET(frag, FRAG_SEND_ENQUEUED),
|
||
|
FRAG_STATE_ISSET(frag, FRAG_PML_CALLED_BACK),
|
||
|
FRAG_STATE_ISSET(frag, FRAG_IN_HOTEL),
|
||
|
FRAG_STATE_ISSET(frag, FRAG_ALLOCED) ?
|
||
|
frag->btl_header->seq : (ompi_btl_usnic_seq_t) ~0
|
||
|
);
|
||
|
opal_output(0, out);
|
||
|
}
|
||
|
|
||
|
static void dump_recv_frag(ompi_btl_usnic_frag_t* frag)
|
||
|
{
|
||
|
char out[256];
|
||
|
memset(out, 0, sizeof(out));
|
||
|
|
||
|
snprintf(out, sizeof(out),
|
||
|
"=== RECV frag %p (MCW %d): alloced %d posted %d",
|
||
|
(void*) frag,
|
||
|
ompi_proc_local()->proc_name.vpid,
|
||
|
FRAG_STATE_ISSET(frag, FRAG_ALLOCED),
|
||
|
FRAG_STATE_ISSET(frag, FRAG_RECV_WR_POSTED));
|
||
|
opal_output(0, out);
|
||
|
}
|
||
|
|
||
|
void ompi_btl_usnic_frag_dump(ompi_btl_usnic_frag_t *frag)
|
||
|
{
|
||
|
switch(frag->type) {
|
||
|
case OMPI_BTL_USNIC_FRAG_ACK:
|
||
|
dump_ack_frag(frag);
|
||
|
break;
|
||
|
|
||
|
case OMPI_BTL_USNIC_FRAG_SEND:
|
||
|
dump_send_frag(frag);
|
||
|
break;
|
||
|
|
||
|
case OMPI_BTL_USNIC_FRAG_RECV:
|
||
|
dump_recv_frag(frag);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
opal_output(0, "=== UNKNOWN type frag %p: (!)", (void*) frag);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*******************************************************************************/
|
||
|
|
||
|
#if HISTORY
|
||
|
void ompi_btl_usnic_frag_history(ompi_btl_usnic_frag_t *frag,
|
||
|
char *file, int line,
|
||
|
const char *message)
|
||
|
{
|
||
|
int i = frag->history_next;
|
||
|
ompi_btl_usnic_frag_history_t *h = &(frag->history[i]);
|
||
|
|
||
|
memset(h, 0, sizeof(*h));
|
||
|
strncpy(h->file, file, sizeof(h->file));
|
||
|
h->line = line;
|
||
|
strncpy(h->message, message, sizeof(h->message));
|
||
|
|
||
|
frag->history_next = (frag->history_next + 1) % NUM_FRAG_HISTORY;
|
||
|
if (frag->history_start == frag->history_next) {
|
||
|
frag->history_start = (frag->history_start + 1) % NUM_FRAG_HISTORY;
|
||
|
}
|
||
|
}
|
||
|
#endif
|