root/contrib/build-mca-comps-outside-of-tree/btl_tcp2_frag.c

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

DEFINITIONS

This source file includes following definitions.
  1. mca_btl_tcp2_frag_common_constructor
  2. mca_btl_tcp2_frag_eager_constructor
  3. mca_btl_tcp2_frag_max_constructor
  4. mca_btl_tcp2_frag_user_constructor
  5. mca_btl_tcp2_frag_send
  6. mca_btl_tcp2_frag_recv

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2006 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
  13  * Copyright (c) 2011      Cisco Systems, Inc.  All rights reserved.
  14  * $COPYRIGHT$
  15  *
  16  * Additional copyrights may follow
  17  *
  18  * $HEADER$
  19  *
  20  * In windows, many of the socket functions return an EWOULDBLOCK
  21  * instead of \ things like EAGAIN, EINPROGRESS, etc. It has been
  22  * verified that this will \ not conflict with other error codes that
  23  * are returned by these functions \ under UNIX/Linux environments
  24  */
  25 
  26 #include "ompi_config.h"
  27 
  28 #ifdef HAVE_SYS_TYPES_H
  29 #include <sys/types.h>
  30 #endif
  31 #ifdef HAVE_SYS_UIO_H
  32 #include <sys/uio.h>
  33 #endif
  34 #ifdef HAVE_NET_UIO_H
  35 #include <net/uio.h>
  36 #endif
  37 #ifdef HAVE_UNISTD_H
  38 #include <unistd.h>
  39 #endif  /* HAVE_UNISTD_H */
  40 
  41 #include "opal/opal_socket_errno.h"
  42 #include "ompi/mca/btl/base/btl_base_error.h"
  43 #include "btl_tcp2_frag.h"
  44 #include "btl_tcp2_endpoint.h"
  45 
  46 static void mca_btl_tcp2_frag_common_constructor(mca_btl_tcp2_frag_t* frag)
  47 {
  48     frag->base.des_src = NULL;
  49     frag->base.des_src_cnt = 0;
  50     frag->base.des_dst = NULL;
  51     frag->base.des_dst_cnt = 0;
  52 }
  53 
  54 static void mca_btl_tcp2_frag_eager_constructor(mca_btl_tcp2_frag_t* frag)
  55 {
  56     frag->size = mca_btl_tcp2_module.super.btl_eager_limit;
  57     frag->my_list = &mca_btl_tcp2_component.tcp_frag_eager;
  58     mca_btl_tcp2_frag_common_constructor(frag);
  59 }
  60 
  61 static void mca_btl_tcp2_frag_max_constructor(mca_btl_tcp2_frag_t* frag)
  62 {
  63     frag->size = mca_btl_tcp2_module.super.btl_max_send_size;
  64     frag->my_list = &mca_btl_tcp2_component.tcp_frag_max;
  65     mca_btl_tcp2_frag_common_constructor(frag);
  66 }
  67 
  68 static void mca_btl_tcp2_frag_user_constructor(mca_btl_tcp2_frag_t* frag)
  69 {
  70     frag->size = 0;
  71     frag->my_list = &mca_btl_tcp2_component.tcp_frag_user;
  72     mca_btl_tcp2_frag_common_constructor(frag);
  73 }
  74 
  75 
  76 OBJ_CLASS_INSTANCE(
  77     mca_btl_tcp2_frag_t,
  78     mca_btl_base_descriptor_t,
  79     NULL,
  80     NULL);
  81 
  82 OBJ_CLASS_INSTANCE(
  83     mca_btl_tcp2_frag_eager_t,
  84     mca_btl_base_descriptor_t,
  85     mca_btl_tcp2_frag_eager_constructor,
  86     NULL);
  87 
  88 OBJ_CLASS_INSTANCE(
  89     mca_btl_tcp2_frag_max_t,
  90     mca_btl_base_descriptor_t,
  91     mca_btl_tcp2_frag_max_constructor,
  92     NULL);
  93 
  94 OBJ_CLASS_INSTANCE(
  95     mca_btl_tcp2_frag_user_t,
  96     mca_btl_base_descriptor_t,
  97     mca_btl_tcp2_frag_user_constructor,
  98     NULL);
  99 
 100 
 101 bool mca_btl_tcp2_frag_send(mca_btl_tcp2_frag_t* frag, int sd)
 102 {
 103     int cnt=-1;
 104     size_t i, num_vecs;
 105 
 106     /* non-blocking write, but continue if interrupted */
 107     while(cnt < 0) {
 108         cnt = writev(sd, frag->iov_ptr, frag->iov_cnt);
 109         if(cnt < 0) {
 110             switch(opal_socket_errno) {
 111             case EINTR:
 112                 continue;
 113             case EWOULDBLOCK:
 114                 return false;
 115             case EFAULT:
 116                 BTL_ERROR(("mca_btl_tcp2_frag_send: writev error (%p, %lu)\n\t%s(%lu)\n",
 117                     frag->iov_ptr[0].iov_base, (unsigned long) frag->iov_ptr[0].iov_len,
 118                     strerror(opal_socket_errno), (unsigned long) frag->iov_cnt));
 119                 mca_btl_tcp2_endpoint_close(frag->endpoint);
 120                 return false;
 121             default:
 122                 BTL_ERROR(("mca_btl_tcp2_frag_send: writev failed: %s (%d)",
 123                            strerror(opal_socket_errno),
 124                            opal_socket_errno));
 125                 mca_btl_tcp2_endpoint_close(frag->endpoint);
 126                 return false;
 127             }
 128         }
 129     }
 130 
 131     /* if the write didn't complete - update the iovec state */
 132     num_vecs = frag->iov_cnt;
 133     for(i=0; i<num_vecs; i++) {
 134         if(cnt >= (int)frag->iov_ptr->iov_len) {
 135             cnt -= frag->iov_ptr->iov_len;
 136             frag->iov_ptr++;
 137             frag->iov_idx++;
 138             frag->iov_cnt--;
 139         } else {
 140             frag->iov_ptr->iov_base = (ompi_iov_base_ptr_t)
 141                 (((unsigned char*)frag->iov_ptr->iov_base) + cnt);
 142             frag->iov_ptr->iov_len -= cnt;
 143             break;
 144         }
 145     }
 146     return (frag->iov_cnt == 0);
 147 }
 148 
 149 bool mca_btl_tcp2_frag_recv(mca_btl_tcp2_frag_t* frag, int sd)
 150 {
 151     int cnt, dont_copy_data = 0;
 152     size_t i, num_vecs;
 153     mca_btl_base_endpoint_t* btl_endpoint = frag->endpoint;
 154 
 155  repeat:
 156     num_vecs = frag->iov_cnt;
 157 #if MCA_BTL_TCP_ENDPOINT_CACHE
 158     if( 0 != btl_endpoint->endpoint_cache_length ) {
 159         size_t length;
 160         /* It's strange at the first look but cnt have to be set to the full amount of data
 161          * available. After going to advance_iov_position we will use cnt to detect if there
 162          * is still some data pending.
 163          */
 164         cnt = length = btl_endpoint->endpoint_cache_length;
 165         for( i = 0; i < frag->iov_cnt; i++ ) {
 166             if( length > frag->iov_ptr[i].iov_len )
 167                 length = frag->iov_ptr[i].iov_len;
 168             if( (0 == dont_copy_data) || (length < frag->iov_ptr[i].iov_len) ) {
 169                 memcpy( frag->iov_ptr[i].iov_base, btl_endpoint->endpoint_cache_pos, length );
 170             } else {
 171                 frag->segments[0].seg_addr.pval = btl_endpoint->endpoint_cache_pos;
 172                 frag->iov_ptr[i].iov_base = btl_endpoint->endpoint_cache_pos;
 173             }
 174             btl_endpoint->endpoint_cache_pos += length;
 175             btl_endpoint->endpoint_cache_length -= length;
 176             length = btl_endpoint->endpoint_cache_length;
 177             if( 0 == length ) {
 178                 btl_endpoint->endpoint_cache_pos = btl_endpoint->endpoint_cache;
 179                 break;
 180             }
 181         }
 182         goto advance_iov_position;
 183     }
 184     /* What's happens if all iovecs are used by the fragment ? It still work, as we reserve one
 185      * iovec for the caching in the fragment structure (the +1).
 186      */
 187     frag->iov_ptr[num_vecs].iov_base = btl_endpoint->endpoint_cache_pos;
 188     frag->iov_ptr[num_vecs].iov_len  =
 189         mca_btl_tcp2_component.tcp_endpoint_cache - btl_endpoint->endpoint_cache_length;
 190     num_vecs++;
 191 #endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */
 192 
 193     /* non-blocking read, but continue if interrupted */
 194     cnt = -1;
 195     while( cnt < 0 ) {
 196         cnt = readv(sd, frag->iov_ptr, num_vecs);
 197         if( 0 < cnt ) goto advance_iov_position;
 198         if( cnt == 0 ) {
 199             mca_btl_tcp2_endpoint_close(btl_endpoint);
 200             return false;
 201         }
 202         switch(opal_socket_errno) {
 203         case EINTR:
 204             continue;
 205         case EWOULDBLOCK:
 206             return false;
 207         case EFAULT:
 208             BTL_ERROR(("mca_btl_tcp2_frag_recv: readv error (%p, %lu)\n\t%s(%lu)\n",
 209                        frag->iov_ptr[0].iov_base, (unsigned long) frag->iov_ptr[0].iov_len,
 210                        strerror(opal_socket_errno), (unsigned long) frag->iov_cnt));
 211             mca_btl_tcp2_endpoint_close(btl_endpoint);
 212             return false;
 213         default:
 214             BTL_ERROR(("mca_btl_tcp2_frag_recv: readv failed: %s (%d)",
 215                        strerror(opal_socket_errno),
 216                        opal_socket_errno));
 217             mca_btl_tcp2_endpoint_close(btl_endpoint);
 218             return false;
 219         }
 220     };
 221 
 222  advance_iov_position:
 223     /* if the read didn't complete - update the iovec state */
 224     num_vecs = frag->iov_cnt;
 225     for( i = 0; i < num_vecs; i++ ) {
 226         if( cnt < (int)frag->iov_ptr->iov_len ) {
 227             frag->iov_ptr->iov_base = (ompi_iov_base_ptr_t)
 228                 (((unsigned char*)frag->iov_ptr->iov_base) + cnt);
 229             frag->iov_ptr->iov_len -= cnt;
 230             cnt = 0;
 231             break;
 232         }
 233         cnt -= frag->iov_ptr->iov_len;
 234         frag->iov_idx++;
 235         frag->iov_ptr++;
 236         frag->iov_cnt--;
 237     }
 238 #if MCA_BTL_TCP_ENDPOINT_CACHE
 239     btl_endpoint->endpoint_cache_length = cnt;
 240 #endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */
 241 
 242     /* read header */
 243     if(frag->iov_cnt == 0) {
 244         if (btl_endpoint->endpoint_nbo && frag->iov_idx == 1) MCA_BTL_TCP_HDR_NTOH(frag->hdr);
 245         switch(frag->hdr.type) {
 246         case MCA_BTL_TCP_HDR_TYPE_SEND:
 247             if(frag->iov_idx == 1 && frag->hdr.size) {
 248                 frag->segments[0].seg_addr.pval = frag+1;
 249                 frag->segments[0].seg_len = frag->hdr.size;
 250                 frag->iov[1].iov_base = (IOVBASE_TYPE*)(frag->segments[0].seg_addr.pval);
 251                 frag->iov[1].iov_len = frag->hdr.size;
 252                 frag->iov_cnt++;
 253 #ifndef __sparc
 254                 /* The following cannot be done for sparc code
 255                  * because it causes alignment errors when accessing
 256                  * structures later on in the btl and pml code.
 257                  */
 258                 dont_copy_data = 1;
 259 #endif
 260                 goto repeat;
 261             }
 262             break;
 263         case MCA_BTL_TCP_HDR_TYPE_PUT:
 264             if(frag->iov_idx == 1) {
 265                 frag->iov[1].iov_base = (IOVBASE_TYPE*)frag->segments;
 266                 frag->iov[1].iov_len = frag->hdr.count * sizeof(mca_btl_base_segment_t);
 267                 frag->iov_cnt++;
 268                 goto repeat;
 269             } else if (frag->iov_idx == 2) {
 270                 for( i = 0; i < frag->hdr.count; i++ ) {
 271                     frag->iov[i+2].iov_base = (IOVBASE_TYPE*)ompi_ptr_ltop(frag->segments[i].seg_addr.lval);
 272                     frag->iov[i+2].iov_len = frag->segments[i].seg_len;
 273                 }
 274                 frag->iov_cnt += frag->hdr.count;
 275                 goto repeat;
 276             }
 277             break;
 278         case MCA_BTL_TCP_HDR_TYPE_GET:
 279         default:
 280             break;
 281         }
 282         return true;
 283     }
 284     return false;
 285 }
 286 

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