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