1 /* -*- Mode: C; c-basic-offset:4 ; -*- */ 2 /* 3 * (C) 2001 by Argonne National Laboratory. 4 * See COPYRIGHT in top-level directory. 5 */ 6 #ifndef MPID_DATATYPE_H 7 #define MPID_DATATYPE_H 8 9 #include "mpiimpl.h" 10 #include "mpid_dataloop.h" 11 #include "mpihandlemem.h" 12 13 /* NOTE: 14 * - struct MPID_Dataloop and MPID_Segment are defined in 15 * src/mpid/common/datatype/mpid_dataloop.h (and gen_dataloop.h). 16 * - MPIU_Object_alloc_t is defined in src/include/mpihandle.h 17 */ 18 19 #define MPID_Datatype_get_ptr(a,ptr) MPID_Getb_ptr(Datatype,a,0x000000ff,ptr) 20 /* MPID_Datatype_get_basic_id() is useful for creating and indexing into arrays 21 that store data on a per-basic type basis */ 22 #define MPID_Datatype_get_basic_id(a) ((a)&0x000000ff) 23 #define MPID_Datatype_get_basic_size(a) (((a)&0x0000ff00)>>8) 24 25 #define MPID_Datatype_add_ref(datatype_ptr) MPIU_Object_add_ref((datatype_ptr)) 26 27 #define MPID_Datatype_get_basic_type(a,eltype_) do { \ 28 void *ptr; \ 29 switch (HANDLE_GET_KIND(a)) { \ 30 case HANDLE_KIND_DIRECT: \ 31 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 32 eltype_ = ((MPID_Datatype *) ptr)->eltype; \ 33 break; \ 34 case HANDLE_KIND_INDIRECT: \ 35 ptr = ((MPID_Datatype *) \ 36 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 37 eltype_ = ((MPID_Datatype *) ptr)->eltype; \ 38 break; \ 39 case HANDLE_KIND_BUILTIN: \ 40 eltype_ = a; \ 41 break; \ 42 case HANDLE_KIND_INVALID: \ 43 default: \ 44 eltype_ = 0; \ 45 break; \ 46 \ 47 } \ 48 } while(0) 49 50 /* MPID_Datatype_release decrements the reference count on the MPID_Datatype 51 * and, if the refct is then zero, frees the MPID_Datatype and associated 52 * structures. 53 */ 54 #define MPID_Datatype_release(datatype_ptr) do { \ 55 int inuse; \ 56 \ 57 MPIU_Object_release_ref((datatype_ptr),&inuse); \ 58 if (!inuse) { \ 59 int lmpi_errno = MPI_SUCCESS; \ 60 if (MPIR_Process.attr_free && datatype_ptr->attributes) { \ 61 lmpi_errno = MPIR_Process.attr_free( datatype_ptr->handle, \ 62 &datatype_ptr->attributes ); \ 63 } \ 64 /* LEAVE THIS COMMENTED OUT UNTIL WE HAVE SOME USE FOR THE FREE_FN \ 65 if (datatype_ptr->free_fn) { \ 66 mpi_errno = (datatype_ptr->free_fn)( datatype_ptr ); \ 67 if (mpi_errno) { \ 68 MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_TYPE_FREE); \ 69 return MPIR_Err_return_comm( 0, FCNAME, mpi_errno ); \ 70 } \ 71 } */ \ 72 if (lmpi_errno == MPI_SUCCESS) { \ 73 MPID_Datatype_free(datatype_ptr); \ 74 } \ 75 } \ 76 } while(0) 77 78 /* Note: Probably there is some clever way to build all of these from a macro. 79 */ 80 #define MPID_Datatype_get_size_macro(a,size_) do { \ 81 void *ptr; \ 82 switch (HANDLE_GET_KIND(a)) { \ 83 case HANDLE_KIND_DIRECT: \ 84 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 85 size_ = ((MPID_Datatype *) ptr)->size; \ 86 break; \ 87 case HANDLE_KIND_INDIRECT: \ 88 ptr = ((MPID_Datatype *) \ 89 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 90 size_ = ((MPID_Datatype *) ptr)->size; \ 91 break; \ 92 case HANDLE_KIND_BUILTIN: \ 93 size_ = MPID_Datatype_get_basic_size(a); \ 94 break; \ 95 case HANDLE_KIND_INVALID: \ 96 default: \ 97 size_ = 0; \ 98 break; \ 99 \ 100 } \ 101 } while(0) 102 103 /* 104 * The following macro allows us to reference either the regular or 105 * hetero value for the 3 fields (NULL,_size,_depth) in the 106 * MPID_Datatype structure. This is used in the many 107 * macros that access fields of the datatype. We need this macro 108 * to simplify the definition of the other macros in the case where 109 * MPID_HAS_HETERO is *not* defined. 110 */ 111 #if defined(MPID_HAS_HETERO) || 1 112 #define MPID_GET_FIELD(hetero_,value_,fieldname_) do { \ 113 if (hetero_ != MPID_DATALOOP_HETEROGENEOUS) \ 114 value_ = ((MPID_Datatype *)ptr)->dataloop##fieldname_; \ 115 else value_ = ((MPID_Datatype *) ptr)->hetero_dloop##fieldname_; \ 116 } while(0) 117 #else 118 #define MPID_GET_FIELD(hetero_,value_,fieldname_) \ 119 value_ = ((MPID_Datatype *)ptr)->dataloop##fieldname_ 120 #endif 121 122 #if defined(MPID_HAS_HETERO) || 1 123 #define MPID_SET_FIELD(hetero_,value_,fieldname_) do { \ 124 if (hetero_ != MPID_DATALOOP_HETEROGENEOUS) \ 125 ((MPID_Datatype *)ptr)->dataloop##fieldname_ = value_; \ 126 else ((MPID_Datatype *) ptr)->hetero_dloop##fieldname_ = value_; \ 127 } while(0) 128 #else 129 #define MPID_SET_FIELD(hetero_,value_,fieldname_) \ 130 ((MPID_Datatype *)ptr)->dataloop##fieldname_ = value_ 131 #endif 132 133 #define MPID_Datatype_get_loopdepth_macro(a,depth_,hetero_) do { \ 134 void *ptr; \ 135 switch (HANDLE_GET_KIND(a)) { \ 136 case HANDLE_KIND_DIRECT: \ 137 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 138 MPID_GET_FIELD(hetero_,depth_,_depth); \ 139 break; \ 140 case HANDLE_KIND_INDIRECT: \ 141 ptr = ((MPID_Datatype *) \ 142 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 143 MPID_GET_FIELD(hetero_,depth_,_depth); \ 144 break; \ 145 case HANDLE_KIND_INVALID: \ 146 case HANDLE_KIND_BUILTIN: \ 147 default: \ 148 depth_ = 0; \ 149 break; \ 150 } \ 151 } while(0) 152 153 #define MPID_Datatype_get_loopsize_macro(a,depth_,hetero_) do { \ 154 void *ptr; \ 155 switch (HANDLE_GET_KIND(a)) { \ 156 case HANDLE_KIND_DIRECT: \ 157 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 158 MPID_GET_FIELD(hetero_,depth_,_size); \ 159 break; \ 160 case HANDLE_KIND_INDIRECT: \ 161 ptr = ((MPID_Datatype *) \ 162 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 163 MPID_GET_FIELD(hetero_,depth_,_size); \ 164 break; \ 165 case HANDLE_KIND_INVALID: \ 166 case HANDLE_KIND_BUILTIN: \ 167 default: \ 168 depth_ = 0; \ 169 break; \ 170 } \ 171 } while(0) 172 173 #define MPID_Datatype_get_loopptr_macro(a,lptr_,hetero_) do { \ 174 void *ptr; \ 175 switch (HANDLE_GET_KIND(a)) { \ 176 case HANDLE_KIND_DIRECT: \ 177 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 178 MPID_GET_FIELD(hetero_,lptr_,); \ 179 break; \ 180 case HANDLE_KIND_INDIRECT: \ 181 ptr = ((MPID_Datatype *) \ 182 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 183 MPID_GET_FIELD(hetero_,lptr_,); \ 184 break; \ 185 case HANDLE_KIND_INVALID: \ 186 case HANDLE_KIND_BUILTIN: \ 187 default: \ 188 lptr_ = 0; \ 189 break; \ 190 } \ 191 } while(0) 192 #define MPID_Datatype_set_loopdepth_macro(a,depth_,hetero_) do { \ 193 void *ptr; \ 194 switch (HANDLE_GET_KIND(a)) { \ 195 case HANDLE_KIND_DIRECT: \ 196 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 197 MPID_SET_FIELD(hetero_,depth_,_depth); \ 198 break; \ 199 case HANDLE_KIND_INDIRECT: \ 200 ptr = ((MPID_Datatype *) \ 201 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 202 MPID_SET_FIELD(hetero_,depth_,_depth); \ 203 break; \ 204 case HANDLE_KIND_INVALID: \ 205 case HANDLE_KIND_BUILTIN: \ 206 default: \ 207 depth_ = 0; \ 208 break; \ 209 } \ 210 } while(0) 211 212 #define MPID_Datatype_set_loopsize_macro(a,depth_,hetero_) do { \ 213 void *ptr; \ 214 switch (HANDLE_GET_KIND(a)) { \ 215 case HANDLE_KIND_DIRECT: \ 216 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 217 MPID_SET_FIELD(hetero_,depth_,_size); \ 218 break; \ 219 case HANDLE_KIND_INDIRECT: \ 220 ptr = ((MPID_Datatype *) \ 221 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 222 MPID_SET_FIELD(hetero_,depth_,_size); \ 223 break; \ 224 case HANDLE_KIND_INVALID: \ 225 case HANDLE_KIND_BUILTIN: \ 226 default: \ 227 depth_ = 0; \ 228 break; \ 229 } \ 230 } while(0) 231 232 #define MPID_Datatype_set_loopptr_macro(a,lptr_,hetero_) do { \ 233 void *ptr; \ 234 switch (HANDLE_GET_KIND(a)) { \ 235 case HANDLE_KIND_DIRECT: \ 236 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 237 MPID_SET_FIELD(hetero_,lptr_,); \ 238 break; \ 239 case HANDLE_KIND_INDIRECT: \ 240 ptr = ((MPID_Datatype *) \ 241 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 242 MPID_SET_FIELD(hetero_,lptr_,); \ 243 break; \ 244 case HANDLE_KIND_INVALID: \ 245 case HANDLE_KIND_BUILTIN: \ 246 default: \ 247 lptr_ = 0; \ 248 break; \ 249 } \ 250 } while(0) 251 252 #define MPID_Datatype_get_extent_macro(a,extent_) do { \ 253 void *ptr; \ 254 switch (HANDLE_GET_KIND(a)) { \ 255 case HANDLE_KIND_DIRECT: \ 256 ptr = MPID_Datatype_direct+HANDLE_INDEX(a); \ 257 extent_ = ((MPID_Datatype *) ptr)->extent; \ 258 break; \ 259 case HANDLE_KIND_INDIRECT: \ 260 ptr = ((MPID_Datatype *) \ 261 MPIU_Handle_get_ptr_indirect(a,&MPID_Datatype_mem)); \ 262 extent_ = ((MPID_Datatype *) ptr)->extent; \ 263 break; \ 264 case HANDLE_KIND_INVALID: \ 265 case HANDLE_KIND_BUILTIN: \ 266 default: \ 267 extent_ = MPID_Datatype_get_basic_size(a); /* same as size */ \ 268 break; \ 269 } \ 270 } while(0) 271 272 #define MPID_Datatype_valid_ptr(ptr,err) MPID_Valid_ptr_class(Datatype,ptr,MPI_ERR_TYPE,err) 273 274 /* to be used only after MPID_Datatype_valid_ptr(); the check on 275 * err == MPI_SUCCESS ensures that we won't try to dereference the 276 * pointer if something has already been detected as wrong. 277 */ 278 #define MPID_Datatype_committed_ptr(ptr,err) do { \ 279 if ((err == MPI_SUCCESS) && !((ptr)->is_committed)) \ 280 err = MPIR_Err_create_code(MPI_SUCCESS, \ 281 MPIR_ERR_RECOVERABLE, \ 282 FCNAME, \ 283 __LINE__, \ 284 MPI_ERR_TYPE, \ 285 "**dtypecommit", \ 286 0); \ 287 } while(0) 288 289 /*S 290 MPID_Datatype_contents - Holds envelope and contents data for a given 291 datatype 292 293 Notes: 294 Space is allocated beyond the structure itself in order to hold the 295 arrays of types, ints, and aints, in that order. 296 297 S*/ 298 typedef struct MPID_Datatype_contents { 299 int combiner; 300 int nr_ints; 301 int nr_aints; 302 int nr_types; 303 /* space allocated beyond structure used to store the types[], 304 * ints[], and aints[], in that order. 305 */ 306 } MPID_Datatype_contents; 307 308 /* Datatype Structure */ 309 /*S 310 MPID_Datatype - Description of the MPID Datatype structure 311 312 Notes: 313 The 'ref_count' is needed for nonblocking operations such as 314 .vb 315 MPI_Type_struct( ... , &newtype ); 316 MPI_Irecv( buf, 1000, newtype, ..., &request ); 317 MPI_Type_free( &newtype ); 318 ... 319 MPI_Wait( &request, &status ); 320 .ve 321 322 Module: 323 Datatype-DS 324 325 Notes: 326 327 Alternatives: 328 The following alternatives for the layout of this structure were considered. 329 Most were not chosen because any benefit in performance or memory 330 efficiency was outweighed by the added complexity of the implementation. 331 332 A number of fields contain only boolean inforation ('is_contig', 333 'has_sticky_ub', 'has_sticky_lb', 'is_permanent', 'is_committed'). These 334 could be combined and stored in a single bit vector. 335 336 'MPI_Type_dup' could be implemented with a shallow copy, where most of the 337 data fields, would not be copied into the new object created by 338 'MPI_Type_dup'; instead, the new object could point to the data fields in 339 the old object. However, this requires more code to make sure that fields 340 are found in the correct objects and that deleting the old object doesn't 341 invalidate the dup'ed datatype. 342 343 Originally we attempted to keep contents/envelope data in a non-optimized 344 dataloop. The subarray and darray types were particularly problematic, 345 and eventually we decided it would be simpler to just keep contents/ 346 envelope data in arrays separately. 347 348 Earlier versions of the ADI used a single API to change the 'ref_count', 349 with each MPI object type having a separate routine. Since reference 350 count changes are always up or down one, and since all MPI objects 351 are defined to have the 'ref_count' field in the same place, the current 352 ADI3 API uses two routines, 'MPIU_Object_add_ref' and 353 'MPIU_Object_release_ref', to increment and decrement the reference count. 354 355 S*/ 356 typedef struct MPID_Datatype { 357 /* handle and ref_count are filled in by MPIU_Handle_obj_alloc() */ 358 MPIU_OBJECT_HEADER; /* adds handle and ref_count fields */ 359 360 /* basic parameters for datatype, accessible via MPI calls */ 361 int size; 362 MPI_Aint extent, ub, lb, true_ub, true_lb; 363 364 /* chars affecting subsequent datatype processing and creation */ 365 int alignsize, has_sticky_ub, has_sticky_lb; 366 int is_permanent; /* non-zero if datatype is a predefined type */ 367 int is_committed; 368 369 /* element information; used for accumulate and get elements 370 * 371 * if type is composed of more than one element type, then 372 * eltype == MPI_DATATYPE_NULL and element_size == -1 373 */ 374 int eltype, n_elements; 375 MPI_Aint element_size; 376 377 /* information on contiguity of type, for processing shortcuts. 378 * 379 * is_contig is non-zero only if N instances of the type would be 380 * contiguous. 381 */ 382 int is_contig; 383 /* Upper bound on the number of contig blocks for one instance. 384 * It is not trivial to calculate the *real* number of contig 385 * blocks in the case where old datatype is non-contiguous 386 */ 387 int max_contig_blocks; 388 389 /* pointer to contents and envelope data for the datatype */ 390 MPID_Datatype_contents *contents; 391 392 /* dataloop members, including a pointer to the loop, the size in bytes, 393 * and a depth used to verify that we can process it (limited stack depth 394 */ 395 struct MPID_Dataloop *dataloop; /* might be optimized for homogenous */ 396 int dataloop_size; 397 int dataloop_depth; 398 #if defined(MPID_HAS_HETERO) || 1 399 struct MPID_Dataloop *hetero_dloop; /* heterogeneous dataloop */ 400 int hetero_dloop_size; 401 int hetero_dloop_depth; 402 #endif /* MPID_HAS_HETERO */ 403 /* MPI-2 attributes and name */ 404 struct MPID_Attribute *attributes; 405 char name[MPI_MAX_OBJECT_NAME]; 406 407 /* not yet used; will be used to track what processes have cached 408 * copies of this type. 409 */ 410 int32_t cache_id; 411 /* MPID_Lpidmask mask; */ 412 413 /* int (*free_fn)( struct MPID_Datatype * ); */ /* Function to free this datatype */ 414 415 /* Other, device-specific information */ 416 #ifdef MPID_DEV_DATATYPE_DECL 417 MPID_DEV_DATATYPE_DECL 418 #endif 419 } MPID_Datatype; 420 421 extern MPIU_Object_alloc_t MPID_Datatype_mem; 422 423 /* Preallocated datatype objects */ 424 /* This value should be set to greatest value used as the type index suffix in 425 * the predefined handles. That is, look at the last two hex digits of all 426 * predefined datatype handles, take the greatest one, and convert it to decimal 427 * here. */ 428 /* FIXME calculating this value this way is foolish, we should make this more 429 * automatic and less error prone */ 430 #define MPID_DATATYPE_N_BUILTIN 68 431 extern MPID_Datatype MPID_Datatype_builtin[MPID_DATATYPE_N_BUILTIN + 1]; 432 extern MPID_Datatype MPID_Datatype_direct[]; 433 434 #define MPID_DTYPE_BEGINNING 0 435 #define MPID_DTYPE_END -1 436 437 /* LB/UB calculation helper macros */ 438 439 /* MPID_DATATYPE_CONTIG_LB_UB() 440 * 441 * Determines the new LB and UB for a block of old types given the 442 * old type's LB, UB, and extent, and a count of these types in the 443 * block. 444 * 445 * Note: if the displacement is non-zero, the MPID_DATATYPE_BLOCK_LB_UB() 446 * should be used instead (see below). 447 */ 448 #define MPID_DATATYPE_CONTIG_LB_UB(cnt_, \ 449 old_lb_, \ 450 old_ub_, \ 451 old_extent_, \ 452 lb_, \ 453 ub_) \ 454 do { \ 455 if (cnt_ == 0) { \ 456 lb_ = old_lb_; \ 457 ub_ = old_ub_; \ 458 } \ 459 else if (old_ub_ >= old_lb_) { \ 460 lb_ = old_lb_; \ 461 ub_ = old_ub_ + (old_extent_) * (cnt_ - 1); \ 462 } \ 463 else /* negative extent */ { \ 464 lb_ = old_lb_ + (old_extent_) * (cnt_ - 1); \ 465 ub_ = old_ub_; \ 466 } \ 467 } while(0) 468 469 /* MPID_DATATYPE_VECTOR_LB_UB() 470 * 471 * Determines the new LB and UB for a vector of blocks of old types 472 * given the old type's LB, UB, and extent, and a count, stride, and 473 * blocklen describing the vectorization. 474 */ 475 #define MPID_DATATYPE_VECTOR_LB_UB(cnt_, \ 476 stride_, \ 477 blklen_, \ 478 old_lb_, \ 479 old_ub_, \ 480 old_extent_, \ 481 lb_, \ 482 ub_) \ 483 do { \ 484 if (cnt_ == 0 || blklen_ == 0) { \ 485 lb_ = old_lb_; \ 486 ub_ = old_ub_; \ 487 } \ 488 else if (stride_ >= 0 && (old_extent_) >= 0) { \ 489 lb_ = old_lb_; \ 490 ub_ = old_ub_ + (old_extent_) * ((blklen_) - 1) + \ 491 (stride_) * ((cnt_) - 1); \ 492 } \ 493 else if (stride_ < 0 && (old_extent_) >= 0) { \ 494 lb_ = old_lb_ + (stride_) * ((cnt_) - 1); \ 495 ub_ = old_ub_ + (old_extent_) * ((blklen_) - 1); \ 496 } \ 497 else if (stride_ >= 0 && (old_extent_) < 0) { \ 498 lb_ = old_lb_ + (old_extent_) * ((blklen_) - 1); \ 499 ub_ = old_ub_ + (stride_) * ((cnt_) - 1); \ 500 } \ 501 else { \ 502 lb_ = old_lb_ + (old_extent_) * ((blklen_) - 1) + \ 503 (stride_) * ((cnt_) - 1); \ 504 ub_ = old_ub_; \ 505 } \ 506 } while(0) 507 508 /* MPID_DATATYPE_BLOCK_LB_UB() 509 * 510 * Determines the new LB and UB for a block of old types given the LB, 511 * UB, and extent of the old type as well as a new displacement and count 512 * of types. 513 * 514 * Note: we need the extent here in addition to the lb and ub because the 515 * extent might have some padding in it that we need to take into account. 516 */ 517 #define MPID_DATATYPE_BLOCK_LB_UB(cnt_, \ 518 disp_, \ 519 old_lb_, \ 520 old_ub_, \ 521 old_extent_, \ 522 lb_, \ 523 ub_) \ 524 do { \ 525 if (cnt_ == 0) { \ 526 lb_ = old_lb_ + (disp_); \ 527 ub_ = old_ub_ + (disp_); \ 528 } \ 529 else if (old_ub_ >= old_lb_) { \ 530 lb_ = old_lb_ + (disp_); \ 531 ub_ = old_ub_ + (disp_) + (old_extent_) * ((cnt_) - 1); \ 532 } \ 533 else /* negative extent */ { \ 534 lb_ = old_lb_ + (disp_) + (old_extent_) * ((cnt_) - 1); \ 535 ub_ = old_ub_ + (disp_); \ 536 } \ 537 } while(0) 538 539 /* helper macro: takes an MPI_Datatype handle value and returns TRUE in 540 * (*is_config_) if the type is contiguous */ 541 #define MPID_Datatype_is_contig(dtype_, is_contig_) \ 542 do { \ 543 if (HANDLE_GET_KIND(dtype_) == HANDLE_KIND_BUILTIN) { \ 544 *(is_contig_) = TRUE; \ 545 } \ 546 else { \ 547 MPID_Datatype *dtp_ = NULL; \ 548 MPID_Datatype_get_ptr((dtype_), dtp_); \ 549 *(is_contig_) = dtp_->is_contig; \ 550 } \ 551 } while (0) 552 553 /* Datatype functions */ 554 int MPID_Type_commit(MPI_Datatype *type); 555 556 int MPID_Type_dup(MPI_Datatype oldtype, 557 MPI_Datatype *newtype); 558 559 int MPID_Type_struct(int count, 560 const int *blocklength_array, 561 const MPI_Aint *displacement_array, 562 const MPI_Datatype *oldtype_array, 563 MPI_Datatype *newtype); 564 565 int MPID_Type_indexed(int count, 566 const int *blocklength_array, 567 const void *displacement_array, 568 int dispinbytes, 569 MPI_Datatype oldtype, 570 MPI_Datatype *newtype); 571 572 int MPID_Type_blockindexed(int count, 573 int blocklength, 574 const void *displacement_array, 575 int dispinbytes, 576 MPI_Datatype oldtype, 577 MPI_Datatype *newtype); 578 579 int MPID_Type_vector(int count, 580 int blocklength, 581 MPI_Aint stride, 582 int strideinbytes, 583 MPI_Datatype oldtype, 584 MPI_Datatype *newtype); 585 586 int MPID_Type_contiguous(int count, 587 MPI_Datatype oldtype, 588 MPI_Datatype *newtype); 589 590 int MPID_Type_zerolen(MPI_Datatype *newtype); 591 592 int MPID_Type_create_resized(MPI_Datatype oldtype, 593 MPI_Aint lb, 594 MPI_Aint extent, 595 MPI_Datatype *newtype); 596 597 int MPID_Type_get_envelope(MPI_Datatype datatype, 598 int *num_integers, 599 int *num_addresses, 600 int *num_datatypes, 601 int *combiner); 602 603 int MPID_Type_get_contents(MPI_Datatype datatype, 604 int max_integers, 605 int max_addresses, 606 int max_datatypes, 607 int array_of_integers[], 608 MPI_Aint array_of_addresses[], 609 MPI_Datatype array_of_datatypes[]); 610 611 int MPID_Type_create_pairtype(MPI_Datatype datatype, 612 MPID_Datatype *new_dtp); 613 614 /* internal debugging functions */ 615 void MPIDI_Datatype_printf(MPI_Datatype type, 616 int depth, 617 MPI_Aint displacement, 618 int blocklength, 619 int header); 620 621 /* Dataloop functions */ 622 void MPID_Dataloop_copy(void *dest, 623 void *src, 624 int size); 625 626 void MPID_Dataloop_print(struct MPID_Dataloop *dataloop, 627 int depth); 628 629 void MPID_Dataloop_alloc(int kind, 630 int count, 631 DLOOP_Dataloop **new_loop_p, 632 int *new_loop_sz_p); 633 634 void MPID_Dataloop_alloc_and_copy(int kind, 635 int count, 636 struct DLOOP_Dataloop *old_loop, 637 int old_loop_sz, 638 struct DLOOP_Dataloop **new_loop_p, 639 int *new_loop_sz_p); 640 void MPID_Dataloop_struct_alloc(int count, 641 int old_loop_sz, 642 int basic_ct, 643 DLOOP_Dataloop **old_loop_p, 644 DLOOP_Dataloop **new_loop_p, 645 int *new_loop_sz_p); 646 void MPID_Dataloop_dup(DLOOP_Dataloop *old_loop, 647 int old_loop_sz, 648 DLOOP_Dataloop **new_loop_p); 649 void MPID_Dataloop_free(struct MPID_Dataloop **dataloop); 650 651 /* Segment functions specific to MPICH2 */ 652 void MPID_Segment_pack_vector(struct DLOOP_Segment *segp, 653 DLOOP_Offset first, 654 DLOOP_Offset *lastp, 655 DLOOP_VECTOR *vector, 656 int *lengthp); 657 658 void MPID_Segment_unpack_vector(struct DLOOP_Segment *segp, 659 DLOOP_Offset first, 660 DLOOP_Offset *lastp, 661 DLOOP_VECTOR *vector, 662 int *lengthp); 663 664 void MPID_Segment_flatten(struct DLOOP_Segment *segp, 665 DLOOP_Offset first, 666 DLOOP_Offset *lastp, 667 DLOOP_Offset *offp, 668 int *sizep, 669 DLOOP_Offset *lengthp); 670 671 /* misc */ 672 int MPID_Datatype_set_contents(struct MPID_Datatype *ptr, 673 int combiner, 674 int nr_ints, 675 int nr_aints, 676 int nr_types, 677 int *ints, 678 const MPI_Aint *aints, 679 const MPI_Datatype *types); 680 681 void MPID_Datatype_free_contents(struct MPID_Datatype *ptr); 682 void MPIDI_Datatype_get_contents_aints(MPID_Datatype_contents *cp, 683 MPI_Aint *user_aints); 684 void MPIDI_Datatype_get_contents_types(MPID_Datatype_contents *cp, 685 MPI_Datatype *user_types); 686 void MPIDI_Datatype_get_contents_ints(MPID_Datatype_contents *cp, 687 int *user_ints); 688 689 void MPID_Datatype_free(struct MPID_Datatype *ptr); 690 691 void MPID_Dataloop_update(struct DLOOP_Dataloop *dataloop, 692 MPI_Aint ptrdiff); 693 694 int MPIR_Type_get_contig_blocks(MPI_Datatype type, 695 int *nr_blocks_p); 696 697 int MPIR_Type_flatten(MPI_Datatype type, 698 MPI_Aint *off_array, 699 int *size_array, 700 MPI_Aint *array_len_p); 701 702 void MPID_Segment_pack_external32(struct DLOOP_Segment *segp, 703 DLOOP_Offset first, 704 DLOOP_Offset *lastp, 705 void *pack_buffer); 706 707 void MPID_Segment_unpack_external32(struct DLOOP_Segment *segp, 708 DLOOP_Offset first, 709 DLOOP_Offset *lastp, 710 DLOOP_Buffer unpack_buffer); 711 712 MPI_Aint MPID_Datatype_size_external32(MPI_Datatype type); 713 MPI_Aint MPIDI_Datatype_get_basic_size_external32(MPI_Datatype el_type); 714 715 /* debugging helper functions */ 716 char *MPIDU_Datatype_builtin_to_string(MPI_Datatype type); 717 char *MPIDU_Datatype_combiner_to_string(int combiner); 718 void MPIDU_Datatype_debug(MPI_Datatype type, int array_ct); 719 720 /* contents accessor functions */ 721 void MPID_Type_access_contents(MPI_Datatype type, 722 int **ints_p, 723 MPI_Aint **aints_p, 724 MPI_Datatype **types_p); 725 void MPID_Type_release_contents(MPI_Datatype type, 726 int **ints_p, 727 MPI_Aint **aints_p, 728 MPI_Datatype **types_p); 729 730 /* end of file */ 731 #endif 732