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