mtest_datatype_gen.c 20.2 KB
Newer Older
Min Si's avatar
Min Si committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
 *
 *  (C) 2014 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */
#include "mtest_datatype.h"
#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
#include <stdio.h>
#endif
#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
#include <stdlib.h>
#endif
#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
#include <string.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
/* The following two includes permit the collection of resource usage
   data in the tests
 */
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <errno.h>

static int dbgflag = 0;         /* Flag used for debugging */
static int wrank = -1;          /* World rank */
static int verbose = 0;         /* Message level (0 is none) */

/*
 * Utility routines for writing MPI datatype communication tests.
 *
 * Both basic and derived datatype are included.
 * For basic datatypes, every type has a test case that both the send and
 * receive buffer use the same datatype and count.
 *
 *  For derived datatypes:
 *    All the test cases are defined in this file, and the datatype definitions
 *    are in file mtest_datatype.c. Each test case will be automatically called
 *    by every datatype.
 *
 *  Test case generation:
 *    Every datatype tests derived datatype send buffer and
 *    derived datatype receive buffer separately. Each test contains various sub
 *    tests for different structures (i.e., different value of count or block
 *    length). The following four structures are defined:
 *      L count & S block length & S stride
 *      S count & L block length & S stride
 *      L count & S block length & L stride
 *      S count & L block length & L stride
 *
 *  How to add a new structure for each datatype:
 *    1. Add structure definition in function MTestDdtStructDefine.
 *    2. Increase MTEST_DDT_NUM_SUBTESTS
 *
 *  Datatype definition:
 *    Every type is initialized by the creation function stored in
 *    mtestDdtCreators variable, all of their create/init/check functions are
64
 *    defined in file mtest_datatype.c.
Min Si's avatar
Min Si committed
65
66
67
68
69
 *
 *  How to add a new derived datatype:
 *    1. Add the new datatype in enum MTEST_DERIVED_DT.
 *    2. Add its create/init/check functions in file mtest_datatype.c
 *    3. Add its creator function to mtestDdtCreators variable
70
 *
71
72
73
74
75
76
 *  Following three test levels of datatype are defined.
 *    1. Basic
 *      All basic datatypes
 *    2. Minimum
 *      All basic datatypes | Vector | Indexed
 *    3. Full
77
78
79
 *      All basic datatypes | Vector | Hvector | Indexed | Hindexed |
 *      Indexed-block | Hindexed-block | Subarray with order-C | Subarray with order-Fortran
 *
80
81
82
83
84
85
86
87
88
89
90
 *  There are two ways to specify the test level of datatype. The second way has
 *  higher priority (means the value specified by the first way will be overwritten
 *  by that in the second way).
 *  1. Specify global test level by setting the MPITEST_DATATYPE_TEST_LEVEL
 *     environment variable before execution (basic,min,full|full by default).
 *  2. Initialize a special level for a datatype loop by calling the corresponding
 *     initialization function before that loop, otherwise the default value specified
 *     in the first way is used.
 *    Basic     : MTestInitBasicDatatypes
 *    Minimum   : MTestInitMinDatatypes
 *    Full      : MTestInitFullDatatypes
Min Si's avatar
Min Si committed
91
92
93
94
 */

static int datatype_index = 0;

95
96
97
98
99
/* ------------------------------------------------------------------------ */
/* Routine and internal parameters to define the range of datatype tests */
/* ------------------------------------------------------------------------ */
#define MTEST_DDT_NUM_SUBTESTS 4        /* 4 kinds of derived datatype structure */
static MTestDdtCreator mtestDdtCreators[MTEST_DDT_MAX];
Min Si's avatar
Min Si committed
100

101
102
103
static int MTEST_BDT_START_IDX = -1;
static int MTEST_BDT_NUM_TESTS = 0;
static int MTEST_BDT_RANGE = 0;
Min Si's avatar
Min Si committed
104

105
106
107
108
static int MTEST_DDT_NUM_TYPES = 0;
static int MTEST_SEND_DDT_START_IDX = 0;
static int MTEST_SEND_DDT_NUM_TESTS = 0;
static int MTEST_SEND_DDT_RANGE = 0;
Min Si's avatar
Min Si committed
109

110
111
112
static int MTEST_RECV_DDT_START_IDX = 0;
static int MTEST_RECV_DDT_NUM_TESTS = 0;
static int MTEST_RECV_DDT_RANGE = 0;
Min Si's avatar
Min Si committed
113

114
enum {
115
116
117
    MTEST_DATATYPE_TEST_LEVEL_FULL,
    MTEST_DATATYPE_TEST_LEVEL_MIN,
    MTEST_DATATYPE_TEST_LEVEL_BASIC,
118
};
Min Si's avatar
Min Si committed
119

120
121
122
123
124
125
/* current datatype test level */
static int MTEST_DATATYPE_TEST_LEVEL = MTEST_DATATYPE_TEST_LEVEL_FULL;
/* default datatype test level specified by environment variable */
static int MTEST_DATATYPE_TEST_LEVEL_ENV = -1;
/* default datatype initialization function */
static void (*MTestInitDefaultTestFunc) (void) = NULL;
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

static void MTestInitDatatypeGen(int basic_dt_num, int derived_dt_num)
{
    MTEST_BDT_START_IDX = 0;
    MTEST_BDT_NUM_TESTS = basic_dt_num;
    MTEST_BDT_RANGE = MTEST_BDT_START_IDX + MTEST_BDT_NUM_TESTS;
    MTEST_DDT_NUM_TYPES = derived_dt_num;
    MTEST_SEND_DDT_START_IDX = MTEST_BDT_NUM_TESTS;
    MTEST_SEND_DDT_NUM_TESTS = MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS;
    MTEST_SEND_DDT_RANGE = MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS;
    MTEST_RECV_DDT_START_IDX = MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS;
    MTEST_RECV_DDT_NUM_TESTS = MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS;
    MTEST_RECV_DDT_RANGE = MTEST_RECV_DDT_START_IDX + MTEST_RECV_DDT_NUM_TESTS;
}

static int MTestIsDatatypeGenInited()
{
    return (MTEST_BDT_START_IDX < 0) ? 0 : 1;
}

static void MTestPrintDatatypeGen()
{
148
    MTestPrintfMsg(1, "MTest datatype test level : %s. %d basic datatype tests, "
149
                   "%d derived datatype tests will be generated\n",
150
                   (MTEST_DATATYPE_TEST_LEVEL == MTEST_DATATYPE_TEST_LEVEL_FULL) ? "FULL" : "MIN",
151
152
153
154
155
156
157
158
159
160
                   MTEST_BDT_NUM_TESTS, MTEST_SEND_DDT_NUM_TESTS + MTEST_RECV_DDT_NUM_TESTS);
}

static void MTestResetDatatypeGen()
{
    MTEST_BDT_START_IDX = -1;
}

void MTestInitFullDatatypes()
{
161
    /* Do not allow to change datatype test level during loop.
162
163
     * Otherwise indexes will be wrong.
     * Test must explicitly call reset or wait for current datatype loop being
164
     * done before changing to another test level. */
165
    if (!MTestIsDatatypeGenInited()) {
166
        MTEST_DATATYPE_TEST_LEVEL = MTEST_DATATYPE_TEST_LEVEL_FULL;
167
168
169
170
171
172
173
174
175
176
        MTestTypeCreatorInit((MTestDdtCreator *) mtestDdtCreators);
        MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_DDT_MAX);
    }
    else {
        printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
    }
}

void MTestInitMinDatatypes()
{
177
    /* Do not allow to change datatype test level during loop.
178
179
     * Otherwise indexes will be wrong.
     * Test must explicitly call reset or wait for current datatype loop being
180
     * done before changing to another test level. */
181
    if (!MTestIsDatatypeGenInited()) {
182
        MTEST_DATATYPE_TEST_LEVEL = MTEST_DATATYPE_TEST_LEVEL_MIN;
183
184
185
186
187
188
189
        MTestTypeMinCreatorInit((MTestDdtCreator *) mtestDdtCreators);
        MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_MIN_DDT_MAX);
    }
    else {
        printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
    }
}
Min Si's avatar
Min Si committed
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
void MTestInitBasicDatatypes()
{
    /* Do not allow to change datatype test level during loop.
     * Otherwise indexes will be wrong.
     * Test must explicitly call reset or wait for current datatype loop being
     * done before changing to another test level. */
    if (!MTestIsDatatypeGenInited()) {
        MTEST_DATATYPE_TEST_LEVEL = MTEST_DATATYPE_TEST_LEVEL_BASIC;
        MTestInitDatatypeGen(MTEST_BDT_MAX, 0);
    }
    else {
        printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
    }
}

static inline void MTestInitDatatypeEnv()
{
    char *envval = 0;

    /* Read global test level specified by user environment variable.
     * Only initialize once at the first time that test calls datatype routine. */
    if (MTEST_DATATYPE_TEST_LEVEL_ENV > -1)
        return;

    /* default full */
    MTEST_DATATYPE_TEST_LEVEL_ENV = MTEST_DATATYPE_TEST_LEVEL_FULL;
    MTestInitDefaultTestFunc = MTestInitFullDatatypes;

    envval = getenv("MPITEST_DATATYPE_TEST_LEVEL");
    if (envval && strlen(envval)) {
        if (!strncmp(envval, "min", strlen("min"))) {
            MTEST_DATATYPE_TEST_LEVEL_ENV = MTEST_DATATYPE_TEST_LEVEL_MIN;
            MTestInitDefaultTestFunc = MTestInitMinDatatypes;
        }
        else if (!strncmp(envval, "basic", strlen("basic"))) {
            MTEST_DATATYPE_TEST_LEVEL_ENV = MTEST_DATATYPE_TEST_LEVEL_BASIC;
            MTestInitDefaultTestFunc = MTestInitBasicDatatypes;
        }
        else if (strncmp(envval, "full", strlen("full"))) {
            fprintf(stderr, "Unknown MPITEST_DATATYPE_TEST_LEVEL %s\n", envval);
        }
    }
}
Min Si's avatar
Min Si committed
234
235
236
237
238

/* -------------------------------------------------------------------------------*/
/* Routine to define various sets of blocklen/count/stride for derived datatypes. */
/* ------------------------------------------------------------------------------ */

239
240
static inline int MTestDdtStructDefine(int ddt_index, MPI_Aint tot_count, MPI_Aint *count,
                                       MPI_Aint *blen, MPI_Aint *stride, MPI_Aint *align_tot_count)
Min Si's avatar
Min Si committed
241
242
243
{
    int merr = 0;
    int ddt_c_st;
244
    MPI_Aint _short = 0, _align_tot_count = 0, _count = 0, _blen = 0, _stride = 0;
Min Si's avatar
Min Si committed
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    ddt_c_st = ddt_index % MTEST_DDT_NUM_SUBTESTS;

    /* Get short value according to user specified tot_count.
     * It is used as count for large-block-length structure, or block length
     * for large-count structure. */
    if (tot_count < 2) {
        _short = 1;
    }
    else if (tot_count < 64) {
        _short = 2;
    }
    else {
        _short = 64;
    }
    _align_tot_count = (tot_count + _short - 1) & ~(_short - 1);

    switch (ddt_c_st) {
    case 0:
        /* Large block length. */
        _count = _short;
        _blen = _align_tot_count / _short;
        _stride = _blen * 2;
        break;
    case 1:
        /* Large count */
        _count = _align_tot_count / _short;
        _blen = _short;
        _stride = _blen * 2;
        break;
    case 2:
        /* Large block length and large stride */
        _count = _short;
        _blen = _align_tot_count / _short;
        _stride = _blen * 10;
        break;
    case 3:
        /* Large count and large stride */
        _count = _align_tot_count / _short;
        _blen = _short;
        _stride = _blen * 10;
        break;
    default:
        /* Undefined index */
        merr = 1;
        break;
    }

    *align_tot_count = _align_tot_count;
    *count = _count;
    *blen = _blen;
    *stride = _stride;

    return merr;
}

/* ------------------------------------------------------------------------ */
/* Routine to generate basic datatypes                                       */
/* ------------------------------------------------------------------------ */

static inline int MTestGetBasicDatatypes(MTestDatatype * sendtype,
305
                                         MTestDatatype * recvtype, MPI_Aint tot_count)
Min Si's avatar
Min Si committed
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
{
    int merr = 0;
    int bdt_index = datatype_index - MTEST_BDT_START_IDX;
    if (bdt_index >= MTEST_BDT_MAX) {
        printf("Wrong index:  global %d, bst %d in %s\n", datatype_index, bdt_index, __FUNCTION__);
        merr++;
        return merr;
    }

    switch (bdt_index) {
    case MTEST_BDT_INT:
        merr = MTestTypeBasicCreate(MPI_INT, sendtype);
        merr = MTestTypeBasicCreate(MPI_INT, recvtype);
        break;
    case MTEST_BDT_DOUBLE:
        merr = MTestTypeBasicCreate(MPI_DOUBLE, sendtype);
        merr = MTestTypeBasicCreate(MPI_DOUBLE, recvtype);
        break;
    case MTEST_BDT_FLOAT_INT:
        merr = MTestTypeBasicCreate(MPI_FLOAT_INT, sendtype);
        merr = MTestTypeBasicCreate(MPI_FLOAT_INT, recvtype);
        break;
    case MTEST_BDT_SHORT:
        merr = MTestTypeBasicCreate(MPI_SHORT, sendtype);
        merr = MTestTypeBasicCreate(MPI_SHORT, recvtype);
        break;
    case MTEST_BDT_LONG:
        merr = MTestTypeBasicCreate(MPI_LONG, sendtype);
        merr = MTestTypeBasicCreate(MPI_LONG, recvtype);
        break;
    case MTEST_BDT_CHAR:
        merr = MTestTypeBasicCreate(MPI_CHAR, sendtype);
        merr = MTestTypeBasicCreate(MPI_CHAR, recvtype);
        break;
    case MTEST_BDT_UINT64_T:
        merr = MTestTypeBasicCreate(MPI_UINT64_T, sendtype);
        merr = MTestTypeBasicCreate(MPI_UINT64_T, recvtype);
        break;
    case MTEST_BDT_FLOAT:
        merr = MTestTypeBasicCreate(MPI_FLOAT, sendtype);
        merr = MTestTypeBasicCreate(MPI_FLOAT, recvtype);
        break;
    case MTEST_BDT_BYTE:
        merr = MTestTypeBasicCreate(MPI_BYTE, sendtype);
        merr = MTestTypeBasicCreate(MPI_BYTE, recvtype);
        break;
    }
    sendtype->count = tot_count;
    recvtype->count = tot_count;

    return merr;
}

/* ------------------------------------------------------------------------ */
/* Routine to generate send/receive derived datatypes                     */
/* ------------------------------------------------------------------------ */

static inline int MTestGetSendDerivedDatatypes(MTestDatatype * sendtype,
364
                                               MTestDatatype * recvtype, MPI_Aint tot_count)
Min Si's avatar
Min Si committed
365
366
367
{
    int merr = 0;
    int ddt_datatype_index, ddt_c_dt;
368
369
    MPI_Count tsize = 1;
    MPI_Aint blen, stride, count, align_tot_count;;
Min Si's avatar
Min Si committed
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
    MPI_Datatype old_type = MPI_DOUBLE;

    /* Check index */
    ddt_datatype_index = datatype_index - MTEST_SEND_DDT_START_IDX;
    ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
    if (ddt_c_dt >= MTEST_DDT_MAX || !mtestDdtCreators[ddt_c_dt]) {
        printf("Wrong index:  global %d, send %d send-ddt %d, or undefined creator in %s\n",
               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
        merr++;
        return merr;
    }

    /* Set datatype structure */
    merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
                                &stride, &align_tot_count);
    if (merr) {
        printf("Wrong index:  global %d, send %d send-ddt %d, or undefined ddt structure in %s\n",
               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
        merr++;
        return merr;
    }

    /* Create send datatype */
    merr = mtestDdtCreators[ddt_c_dt] (count, blen, stride, old_type, "send", sendtype);
    if (merr)
        return merr;

    sendtype->count = 1;
398
    merr = MPI_Type_size_x(sendtype->datatype, &tsize);
Min Si's avatar
Min Si committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
    if (merr)
        MTestPrintError(merr);

    /* Create receive datatype */
    merr = MTestTypeBasicCreate(MPI_CHAR, recvtype);
    if (merr)
        return merr;

    recvtype->count = sendtype->count * tsize;

    return merr;
}

static inline int MTestGetRecvDerivedDatatypes(MTestDatatype * sendtype,
413
                                               MTestDatatype * recvtype, MPI_Aint tot_count)
Min Si's avatar
Min Si committed
414
415
416
{
    int merr = 0;
    int ddt_datatype_index, ddt_c_dt;
417
418
    MPI_Count tsize;
    MPI_Aint blen, stride, count, align_tot_count;
Min Si's avatar
Min Si committed
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    MPI_Datatype old_type = MPI_DOUBLE;

    /* Check index */
    ddt_datatype_index = datatype_index - MTEST_RECV_DDT_START_IDX;
    ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
    if (ddt_c_dt >= MTEST_DDT_MAX || !mtestDdtCreators[ddt_c_dt]) {
        printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined creator in %s\n",
               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
        merr++;
        return merr;
    }

    /* Set datatype structure */
    merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
                                &stride, &align_tot_count);
    if (merr) {
        printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined ddt structure in %s\n",
               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
        return merr;
    }

    /* Create receive datatype */
    merr = mtestDdtCreators[ddt_c_dt] (count, blen, stride, old_type, "recv", recvtype);
    if (merr)
        return merr;

    recvtype->count = 1;
446
    merr = MPI_Type_size_x(recvtype->datatype, &tsize);
Min Si's avatar
Min Si committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
    if (merr)
        MTestPrintError(merr);

    /* Create send datatype */
    merr = MTestTypeBasicCreate(MPI_CHAR, sendtype);
    if (merr)
        return merr;

    sendtype->count = recvtype->count * tsize;

    return merr;
}

/* ------------------------------------------------------------------------ */
/* Exposed routine to external tests                                         */
/* ------------------------------------------------------------------------ */
463
int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, MPI_Aint tot_count)
Min Si's avatar
Min Si committed
464
465
466
467
{
    int merr = 0;

    MTestGetDbgInfo(&dbgflag, &verbose);
468
    MTestInitDatatypeEnv();
Min Si's avatar
Min Si committed
469
470
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);

471
    /* Initialize the default test level if test does not specify. */
472
    if (!MTestIsDatatypeGenInited()) {
473
        MTestInitDefaultTestFunc();
474
475
476
477
478
    }

    if (datatype_index == 0) {
        MTestPrintDatatypeGen();
    }
Min Si's avatar
Min Si committed
479

480
    /* Start generating tests */
Min Si's avatar
Min Si committed
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
    if (datatype_index < MTEST_BDT_RANGE) {
        merr = MTestGetBasicDatatypes(sendtype, recvtype, tot_count);

    }
    else if (datatype_index < MTEST_SEND_DDT_RANGE) {
        merr = MTestGetSendDerivedDatatypes(sendtype, recvtype, tot_count);

    }
    else if (datatype_index < MTEST_RECV_DDT_RANGE) {
        merr = MTestGetRecvDerivedDatatypes(sendtype, recvtype, tot_count);

    }
    else {
        /* out of range */
        datatype_index = -1;
496
        MTestResetDatatypeGen();
Min Si's avatar
Min Si committed
497
498
499
500
501
502
503
504
505
506
507
508
509
510
    }

    /* stop if error reported */
    if (merr) {
        datatype_index = -1;
    }

    if (datatype_index > 0) {
        /* general initialization for receive buffer. */
        recvtype->InitBuf = MTestTypeInitRecv;
    }

    datatype_index++;

511
    if (verbose >= 2 && datatype_index > 0) {
512
        MPI_Count ssize, rsize;
Min Si's avatar
Min Si committed
513
514
        const char *sendtype_nm = MTestGetDatatypeName(sendtype);
        const char *recvtype_nm = MTestGetDatatypeName(recvtype);
515
516
        MPI_Type_size_x(sendtype->datatype, &ssize);
        MPI_Type_size_x(recvtype->datatype, &rsize);
517
518
519
520
521
522

        MTestPrintfMsg(2, "Get datatypes: send = %s(size %d count %d basesize %d), "
                       "recv = %s(size %d count %d basesize %d), tot_count=%d\n",
                       sendtype_nm, ssize, sendtype->count, sendtype->basesize,
                       recvtype_nm, rsize, recvtype->count, recvtype->basesize,
                       tot_count);
Min Si's avatar
Min Si committed
523
524
525
526
527
528
529
530
531
532
533
534
535
        fflush(stdout);
    }

    return datatype_index;
}

/* Reset the datatype index (start from the initial data type.
   Note: This routine is rarely needed; MTestGetDatatypes automatically
   starts over after the last available datatype is used.
*/
void MTestResetDatatypes(void)
{
    datatype_index = 0;
536
    MTestResetDatatypeGen();
Min Si's avatar
Min Si committed
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
}

/* Return the index of the current datatype.  This is rarely needed and
   is provided mostly to enable debugging of the MTest package itself */
int MTestGetDatatypeIndex(void)
{
    return datatype_index;
}

/* Free the storage associated with a datatype */
void MTestFreeDatatype(MTestDatatype * mtype)
{
    int merr;
    /* Invoke a datatype-specific free function to handle
     * both the datatype and the send/receive buffers */
    if (mtype->FreeBuf) {
        (mtype->FreeBuf) (mtype);
    }
    /* Free the datatype itself if it was created */
    if (!mtype->isBasic) {
        merr = MPI_Type_free(&mtype->datatype);
        if (merr)
            MTestPrintError(merr);
    }
}

/* Check that a message was received correctly.  Returns the number of
   errors detected.  Status may be NULL or MPI_STATUS_IGNORE */
int MTestCheckRecv(MPI_Status * status, MTestDatatype * recvtype)
{
    int count;
    int errs = 0, merr;

    if (status && status != MPI_STATUS_IGNORE) {
        merr = MPI_Get_count(status, recvtype->datatype, &count);
        if (merr)
            MTestPrintError(merr);

        /* Check count against expected count */
        if (count != recvtype->count) {
            errs++;
        }
    }

    /* Check received data */
    if (!errs && recvtype->CheckBuf(recvtype)) {
        errs++;
    }
    return errs;
}

/* This next routine uses a circular buffer of static name arrays just to
   simplify the use of the routine */
const char *MTestGetDatatypeName(MTestDatatype * dtype)
{
    static char name[4][MPI_MAX_OBJECT_NAME];
    static int sp = 0;
    int rlen, merr;

    if (sp >= 4)
        sp = 0;
    merr = MPI_Type_get_name(dtype->datatype, name[sp], &rlen);
    if (merr)
        MTestPrintError(merr);
    return (const char *) name[sp++];
}