1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpiimpl.h"
7 #include "datatype.h"
8 
9 /* This is the utility file for datatypes that contains the basic datatype
10    items and storage management.  It also contains a temporary routine
11    that is used by ROMIO to test to see if datatypes are contiguous */
12 
13 /* Preallocated datatype objects */
14 MPIR_Datatype MPIR_Datatype_builtin[MPIR_DATATYPE_N_BUILTIN];
15 MPIR_Datatype MPIR_Datatype_direct[MPIR_DATATYPE_PREALLOC];
16 
17 MPIR_Object_alloc_t MPIR_Datatype_mem = { 0, 0, 0, 0, MPIR_DATATYPE,
18     sizeof(MPIR_Datatype), MPIR_Datatype_direct,
19     MPIR_DATATYPE_PREALLOC,
20     NULL
21 };
22 
23 MPI_Datatype MPIR_Datatype_index_to_predefined[MPIR_DATATYPE_N_PREDEFINED];
24 
25 static int pairtypes_finalize_cb(void *dummy);
26 static int datatype_attr_finalize_cb(void *dummy);
27 
28 typedef struct mpi_names_t {
29     MPI_Datatype dtype;
30     const char *name;
31 } mpi_names_t;
32 #define type_name_entry(x_) { x_, #x_ }
33 
34 static mpi_names_t mpi_dtypes[] = {
35     type_name_entry(MPI_CHAR),
36     type_name_entry(MPI_UNSIGNED_CHAR),
37     type_name_entry(MPI_SIGNED_CHAR),
38     type_name_entry(MPI_BYTE),
39     type_name_entry(MPI_WCHAR),
40     type_name_entry(MPI_SHORT),
41     type_name_entry(MPI_UNSIGNED_SHORT),
42     type_name_entry(MPI_INT),
43     type_name_entry(MPI_UNSIGNED),
44     type_name_entry(MPI_LONG),
45     type_name_entry(MPI_UNSIGNED_LONG),
46     type_name_entry(MPI_FLOAT),
47     type_name_entry(MPI_DOUBLE),
48     type_name_entry(MPI_LONG_DOUBLE),
49     type_name_entry(MPI_LONG_LONG_INT),
50     type_name_entry(MPI_UNSIGNED_LONG_LONG),
51     type_name_entry(MPI_PACKED),
52     type_name_entry(MPI_LB),
53     type_name_entry(MPI_UB),
54     type_name_entry(MPI_2INT),
55 
56     /* C99 types */
57     type_name_entry(MPI_INT8_T),
58     type_name_entry(MPI_INT16_T),
59     type_name_entry(MPI_INT32_T),
60     type_name_entry(MPI_INT64_T),
61     type_name_entry(MPI_UINT8_T),
62     type_name_entry(MPI_UINT16_T),
63     type_name_entry(MPI_UINT32_T),
64     type_name_entry(MPI_UINT64_T),
65     type_name_entry(MPI_C_BOOL),
66     type_name_entry(MPI_C_COMPLEX),
67     type_name_entry(MPI_C_DOUBLE_COMPLEX),
68     type_name_entry(MPI_C_LONG_DOUBLE_COMPLEX),
69 
70     /* address/offset/count types */
71     type_name_entry(MPI_AINT),
72     type_name_entry(MPI_OFFSET),
73     type_name_entry(MPI_COUNT),
74 
75     /* Fortran types */
76     type_name_entry(MPI_COMPLEX),
77     type_name_entry(MPI_DOUBLE_COMPLEX),
78     type_name_entry(MPI_LOGICAL),
79     type_name_entry(MPI_REAL),
80     type_name_entry(MPI_DOUBLE_PRECISION),
81     type_name_entry(MPI_INTEGER),
82     type_name_entry(MPI_2INTEGER),
83     type_name_entry(MPI_2REAL),
84     type_name_entry(MPI_2DOUBLE_PRECISION),
85     type_name_entry(MPI_CHARACTER),
86     /* Size-specific types; these are in section 10.2.4 (Extended Fortran
87      * Support) as well as optional in MPI-1
88      */
89     type_name_entry(MPI_REAL4),
90     type_name_entry(MPI_REAL8),
91     type_name_entry(MPI_REAL16),
92     type_name_entry(MPI_COMPLEX8),
93     type_name_entry(MPI_COMPLEX16),
94     type_name_entry(MPI_COMPLEX32),
95     type_name_entry(MPI_INTEGER1),
96     type_name_entry(MPI_INTEGER2),
97     type_name_entry(MPI_INTEGER4),
98     type_name_entry(MPI_INTEGER8),
99     type_name_entry(MPI_INTEGER16),
100 
101     /* C++ types */
102     type_name_entry(MPI_CXX_BOOL),
103     type_name_entry(MPI_CXX_FLOAT_COMPLEX),
104     type_name_entry(MPI_CXX_DOUBLE_COMPLEX),
105     type_name_entry(MPI_CXX_LONG_DOUBLE_COMPLEX),
106 };
107 
108 static mpi_names_t mpi_pairtypes[] = {
109     type_name_entry(MPI_FLOAT_INT),
110     type_name_entry(MPI_DOUBLE_INT),
111     type_name_entry(MPI_LONG_INT),
112     type_name_entry(MPI_SHORT_INT),
113     type_name_entry(MPI_LONG_DOUBLE_INT),
114 };
115 
predefined_index_init(void)116 static void predefined_index_init(void)
117 {
118     int i;
119 
120     for (i = 0; i < MPIR_DATATYPE_N_PREDEFINED; i++)
121         MPIR_Datatype_index_to_predefined[i] = MPI_DATATYPE_NULL;
122 
123     /* Set index to handle mapping for builtin datatypes */
124     for (i = 0; i < sizeof(mpi_dtypes) / sizeof(mpi_dtypes[0]); i++) {
125         MPI_Datatype d = mpi_dtypes[i].dtype;
126         if (d != MPI_DATATYPE_NULL) {
127             int index = MPIR_Datatype_predefined_get_index(d);
128             MPIR_Datatype_index_to_predefined[index] = d;
129         }
130     }
131 
132     /* Set index to handle mapping for pairtype datatypes */
133     for (i = 0; i < sizeof(mpi_pairtypes) / sizeof(mpi_pairtypes[0]); i++) {
134         MPI_Datatype d = mpi_pairtypes[i].dtype;
135         if (d != MPI_DATATYPE_NULL) {
136             int index = MPIR_Datatype_predefined_get_index(d);
137             MPIR_Datatype_index_to_predefined[index] = d;
138         }
139     }
140 }
141 
pairtypes_finalize_cb(void * dummy ATTRIBUTE ((unused)))142 static int pairtypes_finalize_cb(void *dummy ATTRIBUTE((unused)))
143 {
144     int i;
145     MPIR_Datatype *dptr;
146 
147     for (i = 0; i < sizeof(mpi_pairtypes) / sizeof(mpi_pairtypes[0]); i++) {
148         if (mpi_pairtypes[i].dtype != MPI_DATATYPE_NULL) {
149             MPIR_Datatype_get_ptr(mpi_pairtypes[i].dtype, dptr);
150             MPIR_Datatype_free(dptr);
151             mpi_pairtypes[i].dtype = MPI_DATATYPE_NULL;
152         }
153     }
154     return 0;
155 }
156 
157 /* Call this routine to associate a MPIR_Datatype with each predefined
158    datatype. */
MPIR_Datatype_init_predefined(void)159 int MPIR_Datatype_init_predefined(void)
160 {
161     int mpi_errno = MPI_SUCCESS;
162     unsigned int i;
163     MPIR_Datatype *dptr;
164     MPI_Datatype d = MPI_DATATYPE_NULL;
165 
166     for (i = 0; i < sizeof(mpi_dtypes) / sizeof(mpi_dtypes[0]); i++) {
167         /* Compute the index from the value of the handle */
168         d = mpi_dtypes[i].dtype;
169 
170         /* Some of the size-specific types may be null, as might be types
171          * based on 'long long' and 'long double' if those types were
172          * disabled at configure time.  skip those cases. */
173         if (d == MPI_DATATYPE_NULL)
174             continue;
175 
176         MPIR_Datatype_get_ptr(d, dptr);
177         /* --BEGIN ERROR HANDLING-- */
178         if (dptr < MPIR_Datatype_builtin || dptr > MPIR_Datatype_builtin + MPIR_DATATYPE_N_BUILTIN) {
179             mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
180                                              MPIR_ERR_FATAL, __func__,
181                                              __LINE__, MPI_ERR_INTERN,
182                                              "**typeinitbadmem", "**typeinitbadmem %d", i);
183             return mpi_errno;
184         }
185         /* --END ERROR HANDLING-- */
186 
187         /* dptr will point into MPIR_Datatype_builtin */
188         dptr->handle = d;
189         dptr->is_contig = 1;
190         MPIR_Object_set_ref(dptr, 1);
191         dptr->size = MPIR_Datatype_get_basic_size(d);
192         dptr->extent = dptr->size;
193         dptr->ub = dptr->size;
194         dptr->true_ub = dptr->size;
195         dptr->contents = NULL;  /* should never get referenced? */
196         MPL_strncpy(dptr->name, mpi_dtypes[i].name, MPI_MAX_OBJECT_NAME);
197     }
198 
199     /* Setup pairtypes. The following assertions ensure that:
200      * - this function is called before other types are allocated
201      * - there are enough spaces in the direct block to hold our types
202      * - we actually get the values we expect (otherwise errors regarding
203      *   these types could be terribly difficult to track down!)
204      */
205     MPIR_Assert(MPIR_Datatype_mem.initialized == 0);
206     MPIR_Assert(MPIR_DATATYPE_PREALLOC >= 5);
207 
208     for (i = 0; i < sizeof(mpi_pairtypes) / sizeof(mpi_pairtypes[0]); ++i) {
209         /* types based on 'long long' and 'long double', may be disabled at
210          * configure time, and their values set to MPI_DATATYPE_NULL.  skip any
211          * such types. */
212         if (mpi_pairtypes[i].dtype == MPI_DATATYPE_NULL)
213             continue;
214         /* XXX: this allocation strategy isn't right if one or more of the
215          * pairtypes is MPI_DATATYPE_NULL.  in fact, the assert below will
216          * fail if any type other than the las in the list is equal to
217          * MPI_DATATYPE_NULL.  obviously, this should be fixed, but I need
218          * to talk to Rob R. first. -- BRT */
219         /* XXX DJG it does work, but only because MPI_LONG_DOUBLE_INT is the
220          * only one that is ever optional and it comes last */
221 
222         dptr = (MPIR_Datatype *) MPIR_Handle_obj_alloc(&MPIR_Datatype_mem);
223 
224         MPIR_Assert(dptr);
225         MPIR_Assert(dptr->handle == mpi_pairtypes[i].dtype);
226         /* this is a redundant alternative to the previous statement */
227         MPIR_Assert(HANDLE_INDEX(mpi_pairtypes[i].dtype) == i);
228 
229         mpi_errno = MPIR_Type_create_pairtype(mpi_pairtypes[i].dtype, (MPIR_Datatype *) dptr);
230         MPIR_ERR_CHECK(mpi_errno);
231         MPL_strncpy(dptr->name, mpi_pairtypes[i].name, MPI_MAX_OBJECT_NAME);
232     }
233 
234     MPIR_Add_finalize(pairtypes_finalize_cb, 0, MPIR_FINALIZE_CALLBACK_PRIO - 1);
235     predefined_index_init();
236 
237   fn_fail:
238     return mpi_errno;
239 }
240 
MPIR_Datatype_builtintype_alignment(MPI_Datatype type)241 int MPIR_Datatype_builtintype_alignment(MPI_Datatype type)
242 {
243     if (type == MPI_DATATYPE_NULL)
244         return 1;
245 
246     int size = MPIR_Datatype_get_basic_size(type);
247 
248     if (type == MPI_CHAR || type == MPI_UNSIGNED_CHAR || type == MPI_SIGNED_CHAR) {
249         return ALIGNOF_CHAR;
250     } else if (type == MPI_BYTE || type == MPI_UINT8_T || type == MPI_INT8_T ||
251                type == MPI_PACKED || type == MPI_LB || type == MPI_UB) {
252         return ALIGNOF_INT8_T;
253     } else if (type == MPI_WCHAR) {
254         return ALIGNOF_WCHAR_T;
255     } else if (type == MPI_SHORT || type == MPI_UNSIGNED_SHORT) {
256         return ALIGNOF_SHORT;
257     } else if (type == MPI_INT || type == MPI_UNSIGNED || type == MPI_2INT) {
258         return ALIGNOF_INT;
259     } else if (type == MPI_LONG || type == MPI_UNSIGNED_LONG) {
260         return ALIGNOF_LONG;
261     } else if (type == MPI_FLOAT || type == MPI_C_COMPLEX) {
262         return ALIGNOF_FLOAT;
263     } else if (type == MPI_DOUBLE || type == MPI_C_DOUBLE_COMPLEX) {
264         return ALIGNOF_DOUBLE;
265     } else if (type == MPI_LONG_DOUBLE || type == MPI_C_LONG_DOUBLE_COMPLEX) {
266         return ALIGNOF_LONG_DOUBLE;
267     } else if (type == MPI_LONG_LONG_INT || type == MPI_UNSIGNED_LONG_LONG) {
268         return ALIGNOF_LONG_LONG;
269     } else if (type == MPI_INT16_T || type == MPI_UINT16_T) {
270         return ALIGNOF_INT16_T;
271     } else if (type == MPI_INT32_T || type == MPI_UINT32_T) {
272         return ALIGNOF_INT32_T;
273     } else if (type == MPI_INT64_T || type == MPI_UINT64_T) {
274         return ALIGNOF_INT64_T;
275     } else if (type == MPI_C_BOOL) {
276         return ALIGNOF_BOOL;
277     } else if (type == MPI_AINT || type == MPI_OFFSET || type == MPI_COUNT) {
278         if (size == sizeof(int8_t))
279             return ALIGNOF_INT8_T;
280         else if (size == sizeof(int16_t))
281             return ALIGNOF_INT16_T;
282         else if (size == sizeof(int32_t))
283             return ALIGNOF_INT32_T;
284         else if (size == sizeof(int64_t))
285             return ALIGNOF_INT64_T;
286 #ifdef HAVE_FORTRAN_BINDING
287     } else if (type == MPI_CHARACTER) {
288         return ALIGNOF_CHAR;
289     } else if (type == MPI_LOGICAL || type == MPI_INTEGER || type == MPI_2INTEGER ||
290                type == MPI_INTEGER1 || type == MPI_INTEGER2 || type == MPI_INTEGER4 ||
291                type == MPI_INTEGER8 || type == MPI_INTEGER16) {
292         if (size == sizeof(int8_t))
293             return ALIGNOF_INT8_T;
294         else if (size == sizeof(int16_t))
295             return ALIGNOF_INT16_T;
296         else if (size == sizeof(int32_t))
297             return ALIGNOF_INT32_T;
298         else if (size == sizeof(int64_t))
299             return ALIGNOF_INT64_T;
300     } else if (type == MPI_COMPLEX || type == MPI_DOUBLE_COMPLEX || type == MPI_REAL ||
301                type == MPI_DOUBLE_PRECISION || type == MPI_2REAL || type == MPI_2DOUBLE_PRECISION ||
302                type == MPI_REAL4 || type == MPI_REAL8 || type == MPI_REAL16) {
303         if (size == sizeof(float))
304             return ALIGNOF_FLOAT;
305         else if (size == sizeof(double))
306             return ALIGNOF_DOUBLE;
307         else if (size == sizeof(long double))
308             return ALIGNOF_LONG_DOUBLE;
309     } else if (type == MPI_COMPLEX8 || type == MPI_COMPLEX16 || type == MPI_COMPLEX32) {
310         if (size / 2 == sizeof(float))
311             return ALIGNOF_FLOAT;
312         else if (size / 2 == sizeof(double))
313             return ALIGNOF_DOUBLE;
314         else if (size / 2 == sizeof(long double))
315             return ALIGNOF_LONG_DOUBLE;
316 #endif /* HAVE_FORTRAN_BINDING */
317 
318 #ifdef HAVE_CXX_BINDING
319     } else if (type == MPI_CXX_BOOL) {
320         return ALIGNOF_BOOL;
321     } else if (type == MPI_CXX_FLOAT_COMPLEX) {
322         return ALIGNOF_FLOAT;
323     } else if (type == MPI_CXX_DOUBLE_COMPLEX) {
324         return ALIGNOF_DOUBLE;
325     } else if (type == MPI_CXX_LONG_DOUBLE_COMPLEX) {
326         return ALIGNOF_LONG_DOUBLE;
327 #endif /* HAVE_CXX_BINDING */
328     }
329 
330     return 1;
331 }
332 
MPIR_Datatype_commit_pairtypes(void)333 int MPIR_Datatype_commit_pairtypes(void)
334 {
335     /* commit pairtypes */
336     for (int i = 0; i < sizeof(mpi_pairtypes) / sizeof(mpi_pairtypes[0]); i++) {
337         if (mpi_pairtypes[i].dtype != MPI_DATATYPE_NULL) {
338             int err;
339 
340             err = MPIR_Type_commit(&mpi_pairtypes[i].dtype);
341 
342             /* --BEGIN ERROR HANDLING-- */
343             if (err) {
344                 return MPIR_Err_create_code(MPI_SUCCESS,
345                                             MPIR_ERR_RECOVERABLE,
346                                             "MPIR_Type_commit",
347                                             __LINE__, MPI_ERR_OTHER, "**nomem", 0);
348             }
349             /* --END ERROR HANDLING-- */
350         }
351     }
352 
353     return MPI_SUCCESS;
354 }
355 
356 /* This will eventually be removed once ROMIO knows more about MPICH */
MPIR_Datatype_iscontig(MPI_Datatype datatype,int * flag)357 void MPIR_Datatype_iscontig(MPI_Datatype datatype, int *flag)
358 {
359     if (HANDLE_IS_BUILTIN(datatype))
360         *flag = 1;
361     else {
362         MPIR_Datatype_is_contig(datatype, flag);
363     }
364 }
365 
366 /* If an attribute is added to a predefined type, we free the attributes
367    in Finalize */
datatype_attr_finalize_cb(void * dummy ATTRIBUTE ((unused)))368 static int datatype_attr_finalize_cb(void *dummy ATTRIBUTE((unused)))
369 {
370     MPIR_Datatype *dtype;
371     int i, mpi_errno = MPI_SUCCESS;
372 
373     for (i = 0; i < MPIR_DATATYPE_N_BUILTIN; i++) {
374         dtype = &MPIR_Datatype_builtin[i];
375         if (dtype && MPIR_Process.attr_free && dtype->attributes) {
376             mpi_errno = MPIR_Process.attr_free(dtype->handle, &dtype->attributes);
377             /* During finalize, we ignore error returns from the free */
378         }
379     }
380     return mpi_errno;
381 }
382 
MPII_Datatype_attr_finalize(void)383 void MPII_Datatype_attr_finalize(void)
384 {
385     static int called = 0;
386 
387     /* FIXME: This needs to be make thread safe */
388     if (!called) {
389         called = 1;
390         MPIR_Add_finalize(datatype_attr_finalize_cb, 0, MPIR_FINALIZE_CALLBACK_PRIO - 1);
391     }
392 }
393 
394 /*@
395   MPII_Type_zerolen - create an empty datatype
396 
397 Input Parameters:
398 . none
399 
400 Output Parameters:
401 . newtype - handle of new contiguous datatype
402 
403   Return Value:
404   MPI_SUCCESS on success, MPI error code on failure.
405 @*/
406 
MPII_Type_zerolen(MPI_Datatype * newtype)407 int MPII_Type_zerolen(MPI_Datatype * newtype)
408 {
409     int mpi_errno;
410     MPIR_Datatype *new_dtp;
411 
412     /* allocate new datatype object and handle */
413     new_dtp = (MPIR_Datatype *) MPIR_Handle_obj_alloc(&MPIR_Datatype_mem);
414     /* --BEGIN ERROR HANDLING-- */
415     if (!new_dtp) {
416         mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
417                                          "MPII_Type_zerolen",
418                                          __LINE__, MPI_ERR_OTHER, "**nomem", 0);
419         return mpi_errno;
420     }
421     /* --END ERROR HANDLING-- */
422 
423     /* handle is filled in by MPIR_Handle_obj_alloc() */
424     MPIR_Object_set_ref(new_dtp, 1);
425     new_dtp->is_committed = 0;
426     new_dtp->attributes = NULL;
427     new_dtp->name[0] = 0;
428     new_dtp->contents = NULL;
429     new_dtp->flattened = NULL;
430 
431     new_dtp->typerep.handle = NULL;
432 
433     new_dtp->size = 0;
434     new_dtp->lb = 0;
435     new_dtp->ub = 0;
436     new_dtp->true_lb = 0;
437     new_dtp->true_ub = 0;
438     new_dtp->extent = 0;
439 
440     new_dtp->alignsize = 0;
441     new_dtp->builtin_element_size = 0;
442     new_dtp->basic_type = 0;
443     new_dtp->n_builtin_elements = 0;
444     new_dtp->is_contig = 1;
445 
446     *newtype = new_dtp->handle;
447     return MPI_SUCCESS;
448 }
449 
MPII_Datatype_get_contents_ints(MPIR_Datatype_contents * cp,int * user_ints)450 void MPII_Datatype_get_contents_ints(MPIR_Datatype_contents * cp, int *user_ints)
451 {
452     char *ptr;
453     int epsilon;
454     int struct_sz, types_sz;
455 
456     struct_sz = sizeof(MPIR_Datatype_contents);
457     types_sz = cp->nr_types * sizeof(MPI_Datatype);
458 
459     /* pad the struct, types, and ints before we allocate.
460      *
461      * note: it's not necessary that we pad the aints,
462      *       because they are last in the region.
463      */
464     if ((epsilon = struct_sz % MAX_ALIGNMENT)) {
465         struct_sz += MAX_ALIGNMENT - epsilon;
466     }
467     if ((epsilon = types_sz % MAX_ALIGNMENT)) {
468         types_sz += MAX_ALIGNMENT - epsilon;
469     }
470 
471     ptr = ((char *) cp) + struct_sz + types_sz;
472     MPIR_Memcpy(user_ints, ptr, cp->nr_ints * sizeof(int));
473 
474     return;
475 }
476 
MPII_Datatype_get_contents_aints(MPIR_Datatype_contents * cp,MPI_Aint * user_aints)477 void MPII_Datatype_get_contents_aints(MPIR_Datatype_contents * cp, MPI_Aint * user_aints)
478 {
479     char *ptr;
480     int epsilon;
481     int struct_sz, ints_sz, types_sz;
482 
483     struct_sz = sizeof(MPIR_Datatype_contents);
484     types_sz = cp->nr_types * sizeof(MPI_Datatype);
485     ints_sz = cp->nr_ints * sizeof(int);
486 
487     /* pad the struct, types, and ints before we allocate.
488      *
489      * note: it's not necessary that we pad the aints,
490      *       because they are last in the region.
491      */
492     if ((epsilon = struct_sz % MAX_ALIGNMENT)) {
493         struct_sz += MAX_ALIGNMENT - epsilon;
494     }
495     if ((epsilon = types_sz % MAX_ALIGNMENT)) {
496         types_sz += MAX_ALIGNMENT - epsilon;
497     }
498     if ((epsilon = ints_sz % MAX_ALIGNMENT)) {
499         ints_sz += MAX_ALIGNMENT - epsilon;
500     }
501 
502     ptr = ((char *) cp) + struct_sz + types_sz + ints_sz;
503     MPIR_Memcpy(user_aints, ptr, cp->nr_aints * sizeof(MPI_Aint));
504 
505     return;
506 }
507 
MPII_Datatype_get_contents_types(MPIR_Datatype_contents * cp,MPI_Datatype * user_types)508 void MPII_Datatype_get_contents_types(MPIR_Datatype_contents * cp, MPI_Datatype * user_types)
509 {
510     char *ptr;
511     int epsilon;
512     int struct_sz;
513 
514     struct_sz = sizeof(MPIR_Datatype_contents);
515 
516     /* pad the struct, types, and ints before we allocate.
517      *
518      * note: it's not necessary that we pad the aints,
519      *       because they are last in the region.
520      */
521     if ((epsilon = struct_sz % MAX_ALIGNMENT)) {
522         struct_sz += MAX_ALIGNMENT - epsilon;
523     }
524 
525     ptr = ((char *) cp) + struct_sz;
526     MPIR_Memcpy(user_types, ptr, cp->nr_types * sizeof(MPI_Datatype));
527 
528     return;
529 }
530 
531 /* MPII_Datatype_indexed_count_contig()
532  *
533  * Determines the actual number of contiguous blocks represented by the
534  * blocklength/displacement arrays.  This might be less than count (as
535  * few as 1).
536  *
537  * Extent passed in is for the original type.
538  */
MPII_Datatype_indexed_count_contig(MPI_Aint count,const MPI_Aint * blocklength_array,const void * displacement_array,int dispinbytes,MPI_Aint old_extent)539 MPI_Aint MPII_Datatype_indexed_count_contig(MPI_Aint count,
540                                             const MPI_Aint * blocklength_array,
541                                             const void *displacement_array,
542                                             int dispinbytes, MPI_Aint old_extent)
543 {
544     MPI_Aint i, contig_count = 1;
545     MPI_Aint cur_blklen, first;
546 
547     if (count) {
548         /* Skip any initial zero-length blocks */
549         for (first = 0; first < count; ++first)
550             if ((MPI_Aint) blocklength_array[first])
551                 break;
552 
553         if (first == count) {   /* avoid invalid reads later on */
554             contig_count = 0;
555             return contig_count;
556         }
557 
558         cur_blklen = (MPI_Aint) blocklength_array[first];
559         if (!dispinbytes) {
560             MPI_Aint cur_tdisp = (MPI_Aint) ((int *) displacement_array)[first];
561 
562             for (i = first + 1; i < count; ++i) {
563                 if (blocklength_array[i] == 0) {
564                     continue;
565                 } else if (cur_tdisp + (MPI_Aint) cur_blklen ==
566                            (MPI_Aint) ((int *) displacement_array)[i]) {
567                     /* adjacent to current block; add to block */
568                     cur_blklen += (MPI_Aint) blocklength_array[i];
569                 } else {
570                     cur_tdisp = (MPI_Aint) ((int *) displacement_array)[i];
571                     cur_blklen = (MPI_Aint) blocklength_array[i];
572                     contig_count++;
573                 }
574             }
575         } else {
576             MPI_Aint cur_bdisp = (MPI_Aint) ((MPI_Aint *) displacement_array)[first];
577 
578             for (i = first + 1; i < count; ++i) {
579                 if (blocklength_array[i] == 0) {
580                     continue;
581                 } else if (cur_bdisp + (MPI_Aint) cur_blklen * old_extent ==
582                            (MPI_Aint) ((MPI_Aint *) displacement_array)[i]) {
583                     /* adjacent to current block; add to block */
584                     cur_blklen += (MPI_Aint) blocklength_array[i];
585                 } else {
586                     cur_bdisp = (MPI_Aint) ((MPI_Aint *) displacement_array)[i];
587                     cur_blklen = (MPI_Aint) blocklength_array[i];
588                     contig_count++;
589                 }
590             }
591         }
592     }
593     return contig_count;
594 }
595 
MPII_Datatype_blockindexed_count_contig(MPI_Aint count,MPI_Aint blklen,const void * disp_array,int dispinbytes,MPI_Aint old_extent)596 MPI_Aint MPII_Datatype_blockindexed_count_contig(MPI_Aint count,
597                                                  MPI_Aint blklen,
598                                                  const void *disp_array,
599                                                  int dispinbytes, MPI_Aint old_extent)
600 {
601     int i, contig_count = 1;
602 
603     if (!dispinbytes) {
604         /* this is from the MPI type, is of type int */
605         MPI_Aint cur_tdisp = (MPI_Aint) ((int *) disp_array)[0];
606 
607         for (i = 1; i < count; i++) {
608             MPI_Aint next_tdisp = (MPI_Aint) ((int *) disp_array)[i];
609 
610             if (cur_tdisp + (MPI_Aint) blklen != next_tdisp) {
611                 contig_count++;
612             }
613             cur_tdisp = next_tdisp;
614         }
615     } else {
616         /* this is from the MPI type, is of type MPI_Aint */
617         MPI_Aint cur_bdisp = (MPI_Aint) ((MPI_Aint *) disp_array)[0];
618 
619         for (i = 1; i < count; i++) {
620             MPI_Aint next_bdisp = (MPI_Aint) ((MPI_Aint *) disp_array)[i];
621 
622             if (cur_bdisp + (MPI_Aint) blklen * old_extent != next_bdisp) {
623                 contig_count++;
624             }
625             cur_bdisp = next_bdisp;
626         }
627     }
628     return contig_count;
629 }
630 
631 /*@
632   MPIR_Datatype_free
633 
634 Input Parameters:
635 . MPIR_Datatype ptr - pointer to MPID datatype structure that is no longer
636   referenced
637 
638 Output Parameters:
639   none
640 
641   Return Value:
642   none
643 
644   This function handles freeing dynamically allocated memory associated with
645   the datatype.  In the process MPIR_Datatype_free_contents() is also called,
646   which handles decrementing reference counts to constituent types (in
647   addition to freeing the space used for contents information).
648   MPIR_Datatype_free_contents() will call MPIR_Datatype_free() on constituent
649   types that are no longer referenced as well.
650 
651   @*/
MPIR_Datatype_free(MPIR_Datatype * ptr)652 void MPIR_Datatype_free(MPIR_Datatype * ptr)
653 {
654     MPL_DBG_MSG_P(MPIR_DBG_DATATYPE, VERBOSE, "type %x freed.", ptr->handle);
655 
656     MPID_Type_free_hook(ptr);
657 
658     /* before freeing the contents, check whether the pointer is not
659      * null because it is null in the case of a datatype shipped to the target
660      * for RMA ops */
661     if (ptr->contents) {
662         MPIR_Datatype_free_contents(ptr);
663     }
664     if (ptr->typerep.handle) {
665         MPIR_Typerep_free(ptr);
666     }
667     MPL_free(ptr->flattened);
668     MPIR_Handle_obj_free(&MPIR_Datatype_mem, ptr);
669 }
670 
MPIR_Datatype_get_flattened(MPI_Datatype type,void ** flattened,int * flattened_sz)671 void MPIR_Datatype_get_flattened(MPI_Datatype type, void **flattened, int *flattened_sz)
672 {
673     MPIR_Datatype *dt_ptr;
674 
675     MPIR_Datatype_get_ptr(type, dt_ptr);
676     if (dt_ptr->flattened == NULL) {
677         MPIR_Typerep_flatten_size(dt_ptr, &dt_ptr->flattened_sz);
678         dt_ptr->flattened = MPL_malloc(dt_ptr->flattened_sz, MPL_MEM_DATATYPE);
679         MPIR_Assert(dt_ptr->flattened);
680         MPIR_Typerep_flatten(dt_ptr, dt_ptr->flattened);
681     }
682 
683     *flattened = dt_ptr->flattened;
684     *flattened_sz = dt_ptr->flattened_sz;
685 }
686