root/ompi/datatype/ompi_datatype_args.c

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

DEFINITIONS

This source file includes following definitions.
  1. ompi_datatype_set_args
  2. ompi_datatype_print_args
  3. ompi_datatype_get_args
  4. ompi_datatype_copy_args
  5. ompi_datatype_release_args
  6. __ompi_datatype_pack_description
  7. ompi_datatype_get_pack_description
  8. ompi_datatype_pack_description_length
  9. __ompi_datatype_create_from_packed_description
  10. __ompi_datatype_create_from_args
  11. ompi_datatype_create_from_packed_description
  12. ompi_datatype_get_single_predefined_type_from_args

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2016 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2006 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2009      Oak Ridge National Labs.  All rights reserved.
  14  * Copyright (c) 2013-2017 Los Alamos National Security, LLC.  All rights
  15  *                         reserved.
  16  * Copyright (c) 2015-2019 Research Organization for Information Science
  17  *                         and Technology (RIST).  All rights reserved.
  18  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  19  * $COPYRIGHT$
  20  *
  21  * Additional copyrights may follow
  22  *
  23  * $HEADER$
  24  */
  25 
  26 #include "ompi_config.h"
  27 
  28 #include <stddef.h>
  29 
  30 #include "opal/align.h"
  31 #include "opal/types.h"
  32 #include "opal/util/arch.h"
  33 #include "opal/datatype/opal_datatype.h"
  34 #include "opal/datatype/opal_datatype_internal.h"
  35 #include "ompi/constants.h"
  36 #include "ompi/datatype/ompi_datatype.h"
  37 #include "ompi/datatype/ompi_datatype_internal.h"
  38 #include "ompi/proc/proc.h"
  39 
  40 static inline int
  41 __ompi_datatype_pack_description( ompi_datatype_t* datatype,
  42                                   void** packed_buffer, int* next_index );
  43 static ompi_datatype_t*
  44 __ompi_datatype_create_from_args( int32_t* i, ptrdiff_t * a,
  45                                   ompi_datatype_t** d, int32_t type );
  46 
  47 typedef struct __dt_args {
  48     opal_atomic_int32_t ref_count;
  49     int32_t            create_type;
  50     size_t             total_pack_size;
  51     int32_t            ci;
  52     int32_t            ca;
  53     int32_t            cd;
  54     int*               i;
  55     ptrdiff_t* a;
  56     ompi_datatype_t**  d;
  57 } ompi_datatype_args_t;
  58 
  59 /**
  60  * Some architectures really don't like having unaligned
  61  * accesses.  We'll be int aligned, because any sane system will
  62  * require that.  But we might not be long aligned, and some
  63  * architectures will complain if a long is accessed on int
  64  * alignment (but not long alignment).  On those architectures,
  65  * copy the buffer into an aligned buffer first.
  66  */
  67 #if OPAL_ALIGN_WORD_SIZE_INTEGERS
  68 #define OMPI_DATATYPE_ALIGN_PTR(PTR, TYPE) \
  69     (PTR) = OPAL_ALIGN_PTR((PTR), sizeof(ptrdiff_t), TYPE)
  70 #else
  71 #define OMPI_DATATYPE_ALIGN_PTR(PTR, TYPE)
  72 #endif  /* OPAL_ALIGN_WORD_SIZE_INTEGERS */
  73 
  74 /**
  75  * Some architectures require 64 bits pointers (to pointers) to
  76  * be 64 bits aligned. As in the ompi_datatype_args_t structure we have
  77  * 2 such array of pointers and one to an array of ints, if we start by
  78  * setting the 64 bits aligned one we will not have any trouble. Problem
  79  * originally reported on SPARC 64.
  80  */
  81 #define ALLOC_ARGS(PDATA, IC, AC, DC)                                   \
  82     do {                                                                \
  83         int length = sizeof(ompi_datatype_args_t) + (IC) * sizeof(int) + \
  84             (AC) * sizeof(ptrdiff_t) + (DC) * sizeof(MPI_Datatype); \
  85         char* buf = (char*)malloc( length );                            \
  86         ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)buf;       \
  87         pArgs->ci = (IC);                                               \
  88         pArgs->ca = (AC);                                               \
  89         pArgs->cd = (DC);                                               \
  90         buf += sizeof(ompi_datatype_args_t);                            \
  91         if( pArgs->ca == 0 ) pArgs->a = NULL;                           \
  92         else {                                                          \
  93             pArgs->a = (ptrdiff_t*)buf;                         \
  94             buf += pArgs->ca * sizeof(ptrdiff_t);               \
  95         }                                                               \
  96         if( pArgs->cd == 0 ) pArgs->d = NULL;                           \
  97         else {                                                          \
  98             pArgs->d = (ompi_datatype_t**)buf;                          \
  99             buf += pArgs->cd * sizeof(MPI_Datatype);                    \
 100         }                                                               \
 101         if( pArgs->ci == 0 ) pArgs->i = NULL;                           \
 102         else pArgs->i = (int*)buf;                                      \
 103         pArgs->ref_count = 1;                                           \
 104         pArgs->total_pack_size = (4 + (IC) + (DC)) * sizeof(int) +      \
 105             (AC) * sizeof(ptrdiff_t);                                   \
 106         (PDATA)->args = (void*)pArgs;                                   \
 107         (PDATA)->packed_description = 0;                                \
 108     } while(0)
 109 
 110 
 111 int32_t ompi_datatype_set_args( ompi_datatype_t* pData,
 112                                 int32_t ci, const int32_t** i,
 113                                 int32_t ca, const ptrdiff_t* a,
 114                                 int32_t cd, ompi_datatype_t* const * d, int32_t type)
 115 {
 116     int pos;
 117     ompi_datatype_args_t* pArgs;
 118 
 119     assert( NULL == pData->args );
 120     ALLOC_ARGS( pData, ci, ca, cd );
 121 
 122     pArgs = (ompi_datatype_args_t*)pData->args;
 123     pArgs->create_type = type;
 124 
 125     switch(type) {
 126 
 127     case MPI_COMBINER_DUP:
 128         pArgs->total_pack_size = 0;  /* store no extra data */
 129         break;
 130 
 131     case MPI_COMBINER_CONTIGUOUS:
 132         pArgs->i[0] = i[0][0];
 133         break;
 134 
 135     case MPI_COMBINER_VECTOR:
 136         pArgs->i[0] = i[0][0];
 137         pArgs->i[1] = i[1][0];
 138         pArgs->i[2] = i[2][0];
 139         break;
 140 
 141     case MPI_COMBINER_HVECTOR_INTEGER:
 142     case MPI_COMBINER_HVECTOR:
 143         pArgs->i[0] = i[0][0];
 144         pArgs->i[1] = i[1][0];
 145         break;
 146 
 147     case MPI_COMBINER_INDEXED:
 148         pos = 1;
 149         pArgs->i[0] = i[0][0];
 150         memcpy( pArgs->i + pos, i[1], i[0][0] * sizeof(int) );
 151         pos += i[0][0];
 152         memcpy( pArgs->i + pos, i[2], i[0][0] * sizeof(int) );
 153         break;
 154 
 155     case MPI_COMBINER_HINDEXED_INTEGER:
 156     case MPI_COMBINER_HINDEXED:
 157         pArgs->i[0] = i[0][0];
 158         memcpy( pArgs->i + 1, i[1], i[0][0] * sizeof(int) );
 159         break;
 160 
 161     case MPI_COMBINER_INDEXED_BLOCK:
 162         pArgs->i[0] = i[0][0];
 163         pArgs->i[1] = i[1][0];
 164         memcpy( pArgs->i + 2, i[2], i[0][0] * sizeof(int) );
 165         break;
 166 
 167     case MPI_COMBINER_STRUCT_INTEGER:
 168     case MPI_COMBINER_STRUCT:
 169         pArgs->i[0] = i[0][0];
 170         memcpy( pArgs->i + 1, i[1], i[0][0] * sizeof(int) );
 171         break;
 172 
 173     case MPI_COMBINER_SUBARRAY:
 174         pos = 1;
 175         pArgs->i[0] = i[0][0];
 176         memcpy( pArgs->i + pos, i[1], pArgs->i[0] * sizeof(int) );
 177         pos += pArgs->i[0];
 178         memcpy( pArgs->i + pos, i[2], pArgs->i[0] * sizeof(int) );
 179         pos += pArgs->i[0];
 180         memcpy( pArgs->i + pos, i[3], pArgs->i[0] * sizeof(int) );
 181         pos += pArgs->i[0];
 182         pArgs->i[pos] = i[4][0];
 183         break;
 184 
 185     case MPI_COMBINER_DARRAY:
 186         pos = 3;
 187         pArgs->i[0] = i[0][0];
 188         pArgs->i[1] = i[1][0];
 189         pArgs->i[2] = i[2][0];
 190 
 191         memcpy( pArgs->i + pos, i[3], i[2][0] * sizeof(int) );
 192         pos += i[2][0];
 193         memcpy( pArgs->i + pos, i[4], i[2][0] * sizeof(int) );
 194         pos += i[2][0];
 195         memcpy( pArgs->i + pos, i[5], i[2][0] * sizeof(int) );
 196         pos += i[2][0];
 197         memcpy( pArgs->i + pos, i[6], i[2][0] * sizeof(int) );
 198         pos += i[2][0];
 199         pArgs->i[pos] = i[7][0];
 200         break;
 201 
 202     case MPI_COMBINER_F90_REAL:
 203     case MPI_COMBINER_F90_COMPLEX:
 204         pArgs->i[0] = i[0][0];
 205         pArgs->i[1] = i[1][0];
 206         break;
 207 
 208     case MPI_COMBINER_F90_INTEGER:
 209         pArgs->i[0] = i[0][0];
 210         break;
 211 
 212     case MPI_COMBINER_RESIZED:
 213         break;
 214 
 215     case MPI_COMBINER_HINDEXED_BLOCK:
 216         pArgs->i[0] = i[0][0];
 217         pArgs->i[1] = i[1][0];
 218         break;
 219 
 220     default:
 221         break;
 222     }
 223 
 224     /* copy the array of MPI_Aint, aka ptrdiff_t */
 225     if( pArgs->a != NULL )
 226         memcpy( pArgs->a, a, ca * sizeof(ptrdiff_t) );
 227 
 228     for( pos = 0; pos < cd; pos++ ) {
 229         pArgs->d[pos] = d[pos];
 230         if( !(ompi_datatype_is_predefined(d[pos])) ) {
 231             /* We handle a user defined datatype. We should make sure that the
 232              * user will not have the oportunity to destroy it before all derived
 233              * datatypes are destroyed. As we keep pointers to every datatype
 234              * (for MPI_Type_get_content and MPI_Type_get_envelope) we have to make
 235              * sure that those datatype will be available if the user ask for them.
 236              * However, there is no easy way to free them in this case ...
 237              */
 238             OBJ_RETAIN( d[pos] );
 239             pArgs->total_pack_size += ((ompi_datatype_args_t*)d[pos]->args)->total_pack_size;
 240         } else {
 241             pArgs->total_pack_size += sizeof(int); /* _NAMED */
 242         }
 243         pArgs->total_pack_size += sizeof(int);  /* each data has an ID */
 244     }
 245 
 246     return OMPI_SUCCESS;
 247 }
 248 
 249 
 250 int32_t ompi_datatype_print_args( const ompi_datatype_t* pData )
 251 {
 252     int32_t i;
 253     ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args;
 254 
 255     if( ompi_datatype_is_predefined(pData) ) {
 256         /* nothing to do for predefined data-types */
 257         return OMPI_SUCCESS;
 258     }
 259 
 260     if( pArgs == NULL ) return MPI_ERR_INTERN;
 261 
 262     printf( "type %d count ints %d count disp %d count datatype %d\n",
 263             pArgs->create_type, pArgs->ci, pArgs->ca, pArgs->cd );
 264     if( pArgs->i != NULL ) {
 265         printf( "ints:     " );
 266         for( i = 0; i < pArgs->ci; i++ ) {
 267             printf( "%d ", pArgs->i[i] );
 268         }
 269         printf( "\n" );
 270     }
 271     if( pArgs->a != NULL ) {
 272         printf( "MPI_Aint: " );
 273         for( i = 0; i < pArgs->ca; i++ ) {
 274             printf( "%ld ", (long)pArgs->a[i] );
 275         }
 276         printf( "\n" );
 277     }
 278     if( pArgs->d != NULL ) {
 279         int count = 1;
 280         ompi_datatype_t *temp, *old;
 281 
 282         printf( "types:    " );
 283         old = pArgs->d[0];
 284         for( i = 1; i < pArgs->cd; i++ ) {
 285             temp = pArgs->d[i];
 286             if( old == temp ) {
 287                 count++;
 288                 continue;
 289             }
 290             if( count <= 1 ) {
 291                 if( ompi_datatype_is_predefined(old) )
 292                     printf( "%s ", old->name );
 293                 else
 294                     printf( "%p ", (void*)old );
 295             } else {
 296                 if( ompi_datatype_is_predefined(old) )
 297                     printf( "(%d * %s) ", count, old->name );
 298                 else
 299                     printf( "(%d * %p) ", count, (void*)old );
 300             }
 301             count = 1;
 302             old = temp;
 303         }
 304         if( count <= 1 ) {
 305             if( ompi_datatype_is_predefined(old) )
 306                 printf( "%s ", old->name );
 307             else
 308                 printf( "%p ", (void*)old );
 309         } else {
 310             if( ompi_datatype_is_predefined(old) )
 311                 printf( "(%d * %s) ", count, old->name );
 312             else
 313                 printf( "(%d * %p) ", count, (void*)old );
 314         }
 315         printf( "\n" );
 316     }
 317     return OMPI_SUCCESS;
 318 }
 319 
 320 
 321 int32_t ompi_datatype_get_args( const ompi_datatype_t* pData, int32_t which,
 322                                 int32_t* ci, int32_t* i,
 323                                 int32_t* ca, ptrdiff_t* a,
 324                                 int32_t* cd, ompi_datatype_t** d, int32_t* type)
 325 {
 326     ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args;
 327 
 328     if( NULL == pArgs ) {  /* only for predefined datatypes */
 329         if( ompi_datatype_is_predefined(pData) ) {
 330             switch(which){
 331             case 0:
 332                 *ci = 0;
 333                 *ca = 0;
 334                 *cd = 0;
 335                 *type = MPI_COMBINER_NAMED;
 336                 break;
 337             default:
 338                 return MPI_ERR_INTERN;
 339             }
 340             return OMPI_SUCCESS;
 341         }
 342         return MPI_ERR_INTERN;
 343     }
 344 
 345     switch(which){
 346     case 0:     /* GET THE LENGTHS */
 347         *ci = pArgs->ci;
 348         *ca = pArgs->ca;
 349         *cd = pArgs->cd;
 350         *type = pArgs->create_type;
 351         break;
 352     case 1:     /* GET THE ARGUMENTS */
 353         if(*ci < pArgs->ci || *ca < pArgs->ca || *cd < pArgs->cd) {
 354             return MPI_ERR_ARG;
 355         }
 356         if( (NULL != i) && (NULL != pArgs->i) ) {
 357             memcpy( i, pArgs->i, pArgs->ci * sizeof(int) );
 358         }
 359         if( (NULL != a) && (NULL != pArgs->a) ) {
 360             memcpy( a, pArgs->a, pArgs->ca * sizeof(ptrdiff_t) );
 361         }
 362         if( (NULL != d) && (NULL != pArgs->d) ) {
 363             memcpy( d, pArgs->d, pArgs->cd * sizeof(MPI_Datatype) );
 364         }
 365         break;
 366     default:
 367         return MPI_ERR_INTERN;
 368     }
 369     return OMPI_SUCCESS;
 370 }
 371 
 372 
 373 int32_t ompi_datatype_copy_args( const ompi_datatype_t* source_data,
 374                                  ompi_datatype_t* dest_data )
 375 {
 376     ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)source_data->args;
 377 
 378     /* Increase the reference count of the datatype enveloppe. This
 379      * prevent us from making extra copies for the enveloppe (which is mostly
 380      * a read only memory).
 381      */
 382     if( NULL != pArgs ) {
 383         OPAL_THREAD_ADD_FETCH32(&pArgs->ref_count, 1);
 384         dest_data->args = pArgs;
 385     }
 386     return OMPI_SUCCESS;
 387 }
 388 
 389 
 390 /* In the dt_add function we increase the reference count for all datatypes
 391  * (except for the predefined ones) that get added to another datatype. This
 392  * insure that they cannot get released until all the references to them
 393  * get removed.
 394  */
 395 int32_t ompi_datatype_release_args( ompi_datatype_t* pData )
 396 {
 397     int i;
 398     ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args;
 399 
 400     assert( 0 < pArgs->ref_count );
 401     OPAL_THREAD_ADD_FETCH32(&pArgs->ref_count, -1);
 402     if( 0 == pArgs->ref_count ) {
 403         /* There are some duplicated datatypes around that have a pointer to this
 404          * args. We will release them only when the last datatype will dissapear.
 405          */
 406         for( i = 0; i < pArgs->cd; i++ ) {
 407             if( !(ompi_datatype_is_predefined(pArgs->d[i])) ) {
 408                 OBJ_RELEASE( pArgs->d[i] );
 409             }
 410         }
 411         free( pData->args );
 412     }
 413     pData->args = NULL;
 414 
 415     return OMPI_SUCCESS;
 416 }
 417 
 418 
 419 static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype,
 420                                                     void** packed_buffer, int* next_index )
 421 {
 422     int i, *position = (int*)*packed_buffer;
 423     ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args;
 424     char* next_packed = (char*)*packed_buffer;
 425 
 426     if( ompi_datatype_is_predefined(datatype) ) {
 427         position[0] = MPI_COMBINER_NAMED;
 428         position[1] = datatype->id;   /* On the OMPI - layer, copy the ompi_datatype.id */
 429         next_packed += (2 * sizeof(int));
 430         *packed_buffer = next_packed;
 431         return OMPI_SUCCESS;
 432     }
 433     /* For duplicated datatype we don't have to store all the information */
 434     if( MPI_COMBINER_DUP == args->create_type ) {
 435         ompi_datatype_t* temp_data = args->d[0];
 436         return __ompi_datatype_pack_description(temp_data,
 437                                                 packed_buffer,
 438                                                 next_index );
 439     }
 440     position[0] = args->create_type;
 441     position[1] = args->ci;
 442     position[2] = args->ca;
 443     position[3] = args->cd;
 444     next_packed += (4 * sizeof(int));
 445     /* Spoiler: We will access the data in this storage structure, and thus we
 446      * need to align it to the expected boundaries (special thanks to Sparc64).
 447      * The simplest way is to ensure that prior to each type that must be 64
 448      * bits aligned, we have a pointer that is 64 bits aligned. That will minimize
 449      * the memory requirements in all cases where no displacements are stored.
 450      */
 451     if( 0 < args->ca ) {
 452         /* description of the displacements must be 64 bits aligned */
 453         OMPI_DATATYPE_ALIGN_PTR(next_packed, char*);
 454 
 455         memcpy( next_packed, args->a, sizeof(ptrdiff_t) * args->ca );
 456         next_packed += sizeof(ptrdiff_t) * args->ca;
 457     }
 458     position = (int*)next_packed;
 459     next_packed += sizeof(int) * args->cd;
 460 
 461     /* copy the aray of counts (32 bits aligned) */
 462     memcpy( next_packed, args->i, sizeof(int) * args->ci );
 463     next_packed += args->ci * sizeof(int);
 464 
 465     /* copy the rest of the data */
 466     for( i = 0; i < args->cd; i++ ) {
 467         ompi_datatype_t* temp_data = args->d[i];
 468         if( ompi_datatype_is_predefined(temp_data) ) {
 469             position[i] = temp_data->id;  /* On the OMPI - layer, copy the ompi_datatype.id */
 470         } else {
 471             position[i] = *next_index;
 472             (*next_index)++;
 473             __ompi_datatype_pack_description( temp_data,
 474                                               (void**)&next_packed,
 475                                               next_index );
 476         }
 477     }
 478     *packed_buffer = next_packed;
 479     return OMPI_SUCCESS;
 480 }
 481 
 482 
 483 int ompi_datatype_get_pack_description( ompi_datatype_t* datatype,
 484                                         const void** packed_buffer )
 485 {
 486     ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args;
 487     int next_index = OMPI_DATATYPE_MAX_PREDEFINED;
 488     void *packed_description = (void *) datatype->packed_description;
 489     void* recursive_buffer;
 490 
 491     if (NULL == packed_description) {
 492         void *_tmp_ptr = NULL;
 493         if (opal_atomic_compare_exchange_strong_ptr (&datatype->packed_description, (intptr_t *) &_tmp_ptr, 1)) {
 494             if( ompi_datatype_is_predefined(datatype) ) {
 495                 packed_description = malloc(2 * sizeof(int));
 496             } else if( NULL == args ) {
 497                 return OMPI_ERROR;
 498             } else {
 499                 packed_description = malloc(args->total_pack_size);
 500             }
 501             recursive_buffer = packed_description;
 502             __ompi_datatype_pack_description( datatype, &recursive_buffer, &next_index );
 503 
 504             if (!ompi_datatype_is_predefined(datatype)) {
 505                 /* If the precomputed size is not large enough we're already in troubles, we
 506                  * have overwritten outside of the allocated buffer. Raise the alarm !
 507                  * If not reassess the size of the packed buffer necessary for holding the
 508                  * datatype description.
 509                  */
 510                 assert(args->total_pack_size >= (uintptr_t)((char*)recursive_buffer - (char *) packed_description));
 511                 args->total_pack_size = (uintptr_t)((char*)recursive_buffer - (char *) packed_description);
 512             }
 513 
 514             opal_atomic_wmb ();
 515             datatype->packed_description = (intptr_t) packed_description;
 516         } else {
 517             /* another thread beat us to it */
 518             packed_description = (void *) datatype->packed_description;
 519         }
 520     }
 521 
 522     if ((void *) 1 == packed_description) {
 523         struct timespec interval = {.tv_sec = 0, .tv_nsec = 1000};
 524 
 525         /* wait until the packed description is updated */
 526         while (1 == datatype->packed_description) {
 527             nanosleep (&interval, NULL);
 528         }
 529 
 530         packed_description = (void *) datatype->packed_description;
 531     }
 532 
 533     *packed_buffer = (const void *) packed_description;
 534     return OMPI_SUCCESS;
 535 }
 536 
 537 size_t ompi_datatype_pack_description_length( ompi_datatype_t* datatype )
 538 {
 539     void *packed_description = (void *) datatype->packed_description;
 540 
 541     if( ompi_datatype_is_predefined(datatype) ) {
 542         return 2 * sizeof(int);
 543     }
 544     if( NULL == packed_description || (void *) 1 == packed_description) {
 545         const void* buf;
 546         int rc;
 547 
 548         rc = ompi_datatype_get_pack_description(datatype, &buf);
 549         if( OMPI_SUCCESS != rc ) {
 550             return 0;
 551         }
 552     }
 553     assert( NULL != (ompi_datatype_args_t*)datatype->args );
 554     assert( NULL != (ompi_datatype_args_t*)datatype->packed_description );
 555     return ((ompi_datatype_args_t*)datatype->args)->total_pack_size;
 556 }
 557 
 558 static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** packed_buffer,
 559                                                                         const struct ompi_proc_t* remote_processor )
 560 {
 561     int* position;
 562     ompi_datatype_t* datatype = NULL;
 563     ompi_datatype_t** array_of_datatype;
 564     ptrdiff_t* array_of_disp;
 565     int* array_of_length;
 566     int number_of_length, number_of_disp, number_of_datatype, data_id;
 567     int create_type, i;
 568     char* next_buffer;
 569 
 570 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 571     bool need_swap = false;
 572 
 573     if( (remote_processor->super.proc_arch ^ ompi_proc_local()->super.proc_arch) &
 574         OPAL_ARCH_ISBIGENDIAN ) {
 575         need_swap = true;
 576     }
 577 #endif
 578 
 579     next_buffer = (char*)*packed_buffer;
 580     position = (int*)next_buffer;
 581 
 582     create_type = position[0];
 583 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 584     if (need_swap) {
 585         create_type = opal_swap_bytes4(create_type);
 586     }
 587 #endif
 588     if( MPI_COMBINER_NAMED == create_type ) {
 589         /* there we have a simple predefined datatype */
 590         data_id = position[1];
 591 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 592         if (need_swap) {
 593             data_id = opal_swap_bytes4(data_id);
 594         }
 595 #endif
 596         assert( data_id < OMPI_DATATYPE_MAX_PREDEFINED );
 597         *packed_buffer = position + 2;
 598         return (ompi_datatype_t*)ompi_datatype_basicDatatypes[data_id];
 599     }
 600 
 601     number_of_length   = position[1];
 602     number_of_disp     = position[2];
 603     number_of_datatype = position[3];
 604 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 605     if (need_swap) {
 606         number_of_length   = opal_swap_bytes4(number_of_length);
 607         number_of_disp     = opal_swap_bytes4(number_of_disp);
 608         number_of_datatype = opal_swap_bytes4(number_of_datatype);
 609     }
 610 #endif
 611     array_of_datatype = (ompi_datatype_t**)malloc( sizeof(ompi_datatype_t*) *
 612                                                    number_of_datatype );
 613     next_buffer += (4 * sizeof(int));  /* move after the header */
 614 
 615     /* description of the displacements (if ANY !)  should always be aligned
 616        on MPI_Aint, aka ptrdiff_t */
 617     if (number_of_disp > 0) {
 618         OMPI_DATATYPE_ALIGN_PTR(next_buffer, char*);
 619     }
 620 
 621     array_of_disp   = (ptrdiff_t*)next_buffer;
 622     next_buffer    += number_of_disp * sizeof(ptrdiff_t);
 623     /* the other datatypes */
 624     position        = (int*)next_buffer;
 625     next_buffer    += number_of_datatype * sizeof(int);
 626     /* the array of lengths (32 bits aligned) */
 627     array_of_length = (int*)next_buffer;
 628     next_buffer    += (number_of_length * sizeof(int));
 629 
 630     for( i = 0; i < number_of_datatype; i++ ) {
 631         data_id = position[i];
 632 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 633         if (need_swap) {
 634             data_id = opal_swap_bytes4(data_id);
 635         }
 636 #endif
 637         if( data_id < OMPI_DATATYPE_MAX_PREDEFINED ) {
 638             array_of_datatype[i] = (ompi_datatype_t*)ompi_datatype_basicDatatypes[data_id];
 639             continue;
 640         }
 641         array_of_datatype[i] =
 642             __ompi_datatype_create_from_packed_description( (void**)&next_buffer,
 643                                                             remote_processor );
 644         if( NULL == array_of_datatype[i] ) {
 645             /* don't cleanup more than required. We can now modify these
 646              * values as we already know we have failed to rebuild the
 647              * datatype.
 648              */
 649             array_of_datatype[i] = (ompi_datatype_t*)ompi_datatype_basicDatatypes[OPAL_DATATYPE_INT1]; /*XXX TODO */
 650             number_of_datatype = i;
 651             goto cleanup_and_exit;
 652         }
 653     }
 654 
 655 #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
 656     if (need_swap) {
 657         for (i = 0 ; i < number_of_length ; ++i) {
 658             array_of_length[i] = opal_swap_bytes4(array_of_length[i]);
 659         }
 660         for (i = 0 ; i < number_of_disp ; ++i) {
 661 #if SIZEOF_PTRDIFF_T == 4
 662             array_of_disp[i] = opal_swap_bytes4(array_of_disp[i]);
 663 #elif SIZEOF_PTRDIFF_T == 8
 664             array_of_disp[i] = (MPI_Aint)opal_swap_bytes8(array_of_disp[i]);
 665 #else
 666 #error "Unknown size of ptrdiff_t"
 667 #endif
 668         }
 669     }
 670 #endif
 671     datatype = __ompi_datatype_create_from_args( array_of_length, array_of_disp,
 672                                                  array_of_datatype, create_type );
 673     *packed_buffer = next_buffer;
 674  cleanup_and_exit:
 675     for( i = 0; i < number_of_datatype; i++ ) {
 676         if( !(ompi_datatype_is_predefined(array_of_datatype[i])) ) {
 677             OBJ_RELEASE(array_of_datatype[i]);
 678         }
 679     }
 680     free( array_of_datatype );
 681     return datatype;
 682 }
 683 
 684 static ompi_datatype_t* __ompi_datatype_create_from_args( int32_t* i, MPI_Aint* a,
 685                                                           ompi_datatype_t** d, int32_t type )
 686 {
 687     ompi_datatype_t* datatype = NULL;
 688 
 689     switch(type){
 690         /******************************************************************/
 691     case MPI_COMBINER_DUP:
 692         /* should we duplicate d[0]? */
 693         /* ompi_datatype_set_args( datatype, 0, NULL, 0, NULL, 1, d[0], MPI_COMBINER_DUP ); */
 694         assert(0);  /* shouldn't happen */
 695         break;
 696         /******************************************************************/
 697     case MPI_COMBINER_CONTIGUOUS:
 698         ompi_datatype_create_contiguous( i[0], d[0], &datatype );
 699         ompi_datatype_set_args( datatype, 1, (const int **) &i, 0, NULL, 1, d, MPI_COMBINER_CONTIGUOUS );
 700         break;
 701         /******************************************************************/
 702     case MPI_COMBINER_VECTOR:
 703         ompi_datatype_create_vector( i[0], i[1], i[2], d[0], &datatype );
 704         {
 705             const int* a_i[3] = {&i[0], &i[1], &i[2]};
 706             ompi_datatype_set_args( datatype, 3, a_i, 0, NULL, 1, d, MPI_COMBINER_VECTOR );
 707         }
 708         break;
 709         /******************************************************************/
 710     case MPI_COMBINER_HVECTOR_INTEGER:
 711     case MPI_COMBINER_HVECTOR:
 712         ompi_datatype_create_hvector( i[0], i[1], a[0], d[0], &datatype );
 713         {
 714             const int* a_i[2] = {&i[0], &i[1]};
 715             ompi_datatype_set_args( datatype, 2, a_i, 1, a, 1, d, MPI_COMBINER_HVECTOR );
 716         }
 717         break;
 718         /******************************************************************/
 719     case MPI_COMBINER_INDEXED:  /* TO CHECK */
 720         ompi_datatype_create_indexed( i[0], &(i[1]), &(i[1+i[0]]), d[0], &datatype );
 721         {
 722             const int* a_i[3] = {&i[0], &i[1], &(i[1+i[0]])};
 723             ompi_datatype_set_args( datatype, 2 * i[0] + 1, a_i, 0, NULL, 1, d, MPI_COMBINER_INDEXED );
 724         }
 725         break;
 726         /******************************************************************/
 727     case MPI_COMBINER_HINDEXED_INTEGER:
 728     case MPI_COMBINER_HINDEXED:
 729         ompi_datatype_create_hindexed( i[0], &(i[1]), a, d[0], &datatype );
 730         {
 731             const int* a_i[2] = {&i[0], &i[1]};
 732             ompi_datatype_set_args( datatype, i[0] + 1, a_i, i[0], a, 1, d, MPI_COMBINER_HINDEXED );
 733         }
 734         break;
 735         /******************************************************************/
 736     case MPI_COMBINER_INDEXED_BLOCK:
 737         ompi_datatype_create_indexed_block( i[0], i[1], &(i[2]), d[0], &datatype );
 738         {
 739             const int* a_i[3] = {&i[0], &i[1], &i[2]};
 740             ompi_datatype_set_args( datatype, i[0] + 2, a_i, 0, NULL, 1, d, MPI_COMBINER_INDEXED_BLOCK );
 741         }
 742         break;
 743         /******************************************************************/
 744     case MPI_COMBINER_STRUCT_INTEGER:
 745     case MPI_COMBINER_STRUCT:
 746         ompi_datatype_create_struct( i[0], &(i[1]), a, d, &datatype );
 747         {
 748             const int* a_i[2] = {&i[0], &i[1]};
 749             ompi_datatype_set_args( datatype, i[0] + 1, a_i, i[0], a, i[0], d, MPI_COMBINER_STRUCT );
 750         }
 751         break;
 752         /******************************************************************/
 753     case MPI_COMBINER_SUBARRAY:
 754         ompi_datatype_create_subarray( i[0], &i[1 + 0 * i[0]], &i[1 + 1 * i[0]],
 755                                        &i[1 + 2 * i[0]], i[1 + 3 * i[0]],
 756                                        d[0], &datatype );
 757         {
 758             const int* a_i[5] = {&i[0], &i[1 + 0 * i[0]], &i[1 + 1 * i[0]], &i[1 + 2 * i[0]], &i[1 + 3 * i[0]]};
 759             ompi_datatype_set_args( datatype, 3 * i[0] + 2, a_i, 0, NULL, 1, d, MPI_COMBINER_SUBARRAY);
 760         }
 761         break;
 762         /******************************************************************/
 763     case MPI_COMBINER_DARRAY:
 764         ompi_datatype_create_darray( i[0] /* size */, i[1] /* rank */, i[2] /* ndims */,
 765                                      &i[3 + 0 * i[2]], &i[3 + 1 * i[2]],
 766                                      &i[3 + 2 * i[2]], &i[3 + 3 * i[2]],
 767                                      i[3 + 4 * i[2]], d[0], &datatype );
 768         {
 769             const int* a_i[8] = {&i[0], &i[1], &i[2], &i[3 + 0 * i[2]], &i[3 + 1 * i[2]], &i[3 + 2 * i[2]],
 770                                  &i[3 + 3 * i[2]], &i[3 + 4 * i[2]]};
 771             ompi_datatype_set_args( datatype, 4 * i[2] + 4, a_i, 0, NULL, 1, d, MPI_COMBINER_DARRAY);
 772         }
 773         break;
 774         /******************************************************************/
 775     case MPI_COMBINER_F90_REAL:
 776     case MPI_COMBINER_F90_COMPLEX:
 777         /*pArgs->i[0] = i[0][0];
 778           pArgs->i[1] = i[1][0];
 779         */
 780         break;
 781         /******************************************************************/
 782     case MPI_COMBINER_F90_INTEGER:
 783         /*pArgs->i[0] = i[0][0];*/
 784         break;
 785         /******************************************************************/
 786     case MPI_COMBINER_RESIZED:
 787         ompi_datatype_create_resized(d[0], a[0], a[1], &datatype);
 788         ompi_datatype_set_args( datatype, 0, NULL, 2, a, 1, d, MPI_COMBINER_RESIZED );
 789         break;
 790         /******************************************************************/
 791     case MPI_COMBINER_HINDEXED_BLOCK:
 792         ompi_datatype_create_hindexed_block( i[0], i[1], a, d[0], &datatype );
 793         {
 794             const int* a_i[2] = {&i[0], &i[1]};
 795             ompi_datatype_set_args( datatype, 2, a_i, i[0], a, 1, d, MPI_COMBINER_HINDEXED_BLOCK );
 796         }
 797         break;
 798         /******************************************************************/
 799      default:
 800         break;
 801     }
 802 
 803     return datatype;
 804 }
 805 
 806 ompi_datatype_t* ompi_datatype_create_from_packed_description( void** packed_buffer,
 807                                                                struct ompi_proc_t* remote_processor )
 808 {
 809     ompi_datatype_t* datatype;
 810 
 811     datatype = __ompi_datatype_create_from_packed_description( packed_buffer,
 812                                                                remote_processor );
 813     if( NULL == datatype ) {
 814         return NULL;
 815     }
 816     ompi_datatype_commit( &datatype );
 817     return datatype;
 818 }
 819 
 820 /**
 821  * Parse the datatype description from the args and find if the
 822  * datatype is created from a single predefined type. If yes,
 823  * return the type, otherwise return NULL.
 824  */
 825 ompi_datatype_t* ompi_datatype_get_single_predefined_type_from_args( ompi_datatype_t* type )
 826 {
 827     ompi_datatype_t *predef = NULL, *current_type, *current_predef;
 828     ompi_datatype_args_t* args = (ompi_datatype_args_t*)type->args;
 829     int i;
 830 
 831     if( ompi_datatype_is_predefined(type) )
 832         return type;
 833 
 834     for( i = 0; i < args->cd; i++ ) {
 835         current_type = args->d[i];
 836         if( ompi_datatype_is_predefined(current_type) ) {
 837             current_predef = current_type;
 838         } else {
 839             current_predef = ompi_datatype_get_single_predefined_type_from_args(current_type);
 840             if( NULL == current_predef ) { /* No single predefined datatype */
 841                 return NULL;
 842             }
 843         }
 844         if( NULL == predef ) {  /* This is the first iteration */
 845             predef = current_predef;
 846         } else {
 847             /**
 848              *  What exactly should we consider as identical types?
 849              *  If they are the same MPI level type, or if they map
 850              *  to the same OPAL datatype? In other words, MPI_FLOAT
 851              *  and MPI_REAL4 are they identical?
 852              */
 853             if( predef != current_predef ) {
 854                 return NULL;
 855             }
 856         }
 857     }
 858     return predef;
 859 }

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