499e4de1e7
This commit was SVN r6321.
162 строки
5.4 KiB
C
162 строки
5.4 KiB
C
/*
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
* All rights reserved.
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
* 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$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
/**
|
|
* @file
|
|
*/
|
|
#ifndef MCA_PTL_TCP_SEND_FRAG_H
|
|
#define MCA_PTL_TCP_SEND_FRAG_H
|
|
|
|
#include "ompi_config.h"
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
#include <sys/socket.h>
|
|
#endif
|
|
#ifdef HAVE_NETINET_IN_H
|
|
#include <netinet/in.h>
|
|
#endif
|
|
#include "include/sys/atomic.h"
|
|
#include "mca/ptl/base/ptl_base_sendreq.h"
|
|
#include "mca/ptl/base/ptl_base_sendfrag.h"
|
|
#include "ptl_tcp.h"
|
|
#include "ptl_tcp_recvfrag.h"
|
|
#if defined(c_plusplus) || defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
extern opal_class_t mca_ptl_tcp_send_frag_t_class;
|
|
struct mca_ptl_base_peer_t;
|
|
|
|
|
|
/**
|
|
* TCP send fragment derived type.
|
|
*/
|
|
struct mca_ptl_tcp_send_frag_t {
|
|
mca_ptl_base_send_frag_t frag_send; /**< base send fragment descriptor */
|
|
int32_t free_after; /**< keep trace of which vectors we have to free */
|
|
struct iovec *frag_vec_ptr; /**< pointer into iovec array */
|
|
size_t frag_vec_cnt; /**< number of iovec structs left to process */
|
|
struct iovec frag_vec[2]; /**< array of iovecs for send */
|
|
struct iovec frag_saved_vec; /**< save the initial values from the current iovec */
|
|
volatile int frag_progressed; /**< for threaded case - has request status been updated */
|
|
};
|
|
typedef struct mca_ptl_tcp_send_frag_t mca_ptl_tcp_send_frag_t;
|
|
|
|
|
|
#define MCA_PTL_TCP_SEND_FRAG_ALLOC(item, rc) \
|
|
OMPI_FREE_LIST_GET(&mca_ptl_tcp_component.tcp_send_frags, item, rc);
|
|
|
|
|
|
bool mca_ptl_tcp_send_frag_handler(mca_ptl_tcp_send_frag_t*, int sd);
|
|
|
|
|
|
/**
|
|
* Initialize a fragment descriptor.
|
|
*
|
|
* frag (IN) Fragment
|
|
* peer (IN) PTL peer addressing information
|
|
* request (IN) Send request
|
|
* offset (IN) Current offset into packed buffer
|
|
* size (IN/OUT) Requested size / actual size returned
|
|
* flags (IN)
|
|
*/
|
|
|
|
int mca_ptl_tcp_send_frag_init(
|
|
mca_ptl_tcp_send_frag_t*,
|
|
struct mca_ptl_base_peer_t*,
|
|
struct mca_ptl_base_send_request_t*,
|
|
size_t offset,
|
|
size_t* size,
|
|
int flags);
|
|
|
|
|
|
/**
|
|
* For fragments that require an acknowledgment, this routine will be called
|
|
* twice, once when the send completes, and again when the acknowledgment is
|
|
* returned. Only the last caller should update the request status, so we
|
|
* add a lock w/ the frag_progressed flag.
|
|
*/
|
|
|
|
static inline void mca_ptl_tcp_send_frag_progress(mca_ptl_tcp_send_frag_t* frag)
|
|
{
|
|
mca_ptl_base_send_request_t* request = frag->frag_send.frag_request;
|
|
bool frag_ack;
|
|
|
|
/* if this is an ack - simply return to pool */
|
|
if(request == NULL) {
|
|
mca_ptl_tcp_send_frag_return(frag->frag_send.frag_base.frag_owner, frag);
|
|
return;
|
|
}
|
|
|
|
/* Done when:
|
|
* (1) ack is not required and send completes
|
|
* (2) ack is received and send has completed
|
|
*/
|
|
frag_ack = (frag->frag_send.frag_base.frag_header.
|
|
hdr_common.hdr_flags & MCA_PTL_FLAGS_ACK) ? true : false;
|
|
if(frag_ack == false || ompi_atomic_add_32(&frag->frag_progressed,1) == 2) {
|
|
|
|
/* update request status */
|
|
frag->frag_send.frag_base.frag_owner->ptl_send_progress(
|
|
frag->frag_send.frag_base.frag_owner,
|
|
request,
|
|
frag->frag_send.frag_base.frag_size);
|
|
|
|
/* the first fragment is allocated with the request,
|
|
* all others need to be returned to free list
|
|
*/
|
|
if (request->req_cached == false ||
|
|
frag->frag_send.frag_base.frag_header.hdr_common.hdr_type == MCA_PTL_HDR_TYPE_FRAG) {
|
|
mca_ptl_tcp_send_frag_return(frag->frag_send.frag_base.frag_owner, frag);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static inline void mca_ptl_tcp_send_frag_init_ack(
|
|
mca_ptl_tcp_send_frag_t* ack,
|
|
struct mca_ptl_base_module_t* ptl,
|
|
struct mca_ptl_base_peer_t* ptl_peer,
|
|
mca_ptl_tcp_recv_frag_t* frag)
|
|
{
|
|
mca_ptl_base_header_t* hdr = &ack->frag_send.frag_base.frag_header;
|
|
mca_ptl_base_recv_request_t* request = frag->frag_recv.frag_request;
|
|
hdr->hdr_common.hdr_type = MCA_PTL_HDR_TYPE_ACK;
|
|
hdr->hdr_common.hdr_flags = 0;
|
|
hdr->hdr_ack.hdr_src_ptr = frag->frag_recv.frag_base.frag_header.hdr_rndv.hdr_src_ptr;
|
|
hdr->hdr_ack.hdr_dst_match.lval = 0; /* for VALGRIND/PURIFY - REPLACE WITH MACRO */
|
|
hdr->hdr_ack.hdr_dst_match.pval = request;
|
|
hdr->hdr_ack.hdr_dst_addr.lval = 0; /* for VALGRIND/PURIFY - REPLACE WITH MACRO */
|
|
hdr->hdr_ack.hdr_dst_addr.pval = request->req_recv.req_base.req_addr;
|
|
hdr->hdr_ack.hdr_dst_size = request->req_recv.req_bytes_packed;
|
|
ack->frag_send.frag_request = 0;
|
|
ack->frag_send.frag_base.frag_peer = ptl_peer;
|
|
ack->frag_send.frag_base.frag_owner = ptl;
|
|
ack->frag_send.frag_base.frag_addr = NULL;
|
|
ack->frag_send.frag_base.frag_size = 0;
|
|
ack->frag_vec_ptr = ack->frag_vec;
|
|
ack->frag_vec[0].iov_base = (ompi_iov_base_ptr_t)hdr;
|
|
ack->frag_vec[0].iov_len = sizeof(mca_ptl_base_header_t);
|
|
ack->frag_vec_cnt = 1;
|
|
ack->free_after = 0;
|
|
}
|
|
|
|
#if defined(c_plusplus) || defined(__cplusplus)
|
|
}
|
|
#endif
|
|
#endif
|
|
|