Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cf6d39f6040ca0cdbb3848e24b657cd9c05d45a6
[simgrid.git] / teshsuite / smpi / mpich3-test / attr / attrend2.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2008 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 /*
8       The MPI-2.2 specification makes it clear that attributes are called on
9       MPI_COMM_WORLD and MPI_COMM_SELF at the very beginning of MPI_Finalize in
10       LIFO order with respect to the order in which they are set.  This is
11       useful for tools that want to perform the MPI equivalent of an "at_exit"
12       action.
13  */
14 #include <stdio.h>
15 #include "mpi.h"
16 #include "mpitest.h"
17
18 /* 20 ought to be enough attributes to ensure that hash-table based MPI
19  * implementations do not accidentally pass the test except by being extremely
20  * "lucky".  There are (20!) possible permutations which means that there is
21  * about a 1 in 2.43e18 chance of getting LIFO ordering out of a hash table,
22  * assuming a decent hash function is used. */
23 #define NUM_TEST_ATTRS (20)
24
25 static __attribute__((unused)) int exit_keys[NUM_TEST_ATTRS]; /* init to MPI_KEYVAL_INVALID */
26 static __attribute__((unused)) int was_called[NUM_TEST_ATTRS];
27 int foundError = 0;
28 int delete_fn (MPI_Comm, int, void *, void *);
29
30 int main(int argc, char **argv)
31 {
32     int wrank;
33
34     MTest_Init(&argc, &argv);
35
36     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
37
38 #if MTEST_HAVE_MIN_MPI_VERSION(2,2)
39     int errs = 0, wrank;
40     int i;
41     for (i = 0; i < NUM_TEST_ATTRS; ++i) {
42         exit_keys[i] = MPI_KEYVAL_INVALID;
43         was_called[i] = 0;
44
45         /* create the keyval for the exit handler */
46         MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, delete_fn, &exit_keys[i], NULL);
47         /* attach to comm_self */
48         MPI_Comm_set_attr(MPI_COMM_SELF, exit_keys[i], (void*)(long)i);
49     }
50
51     /* we can free the keys now */
52     for (i = 0; i < NUM_TEST_ATTRS; ++i) {
53         MPI_Comm_free_keyval(&exit_keys[i]);
54     }
55
56     /* now, exit MPI */
57     MPI_Finalize();
58
59     /* check that the exit handlers were called in LIFO order, and without error */
60     if (wrank == 0) {
61         /* In case more than one process exits MPI_Finalize */
62         for (i = 0; i < NUM_TEST_ATTRS; ++i) {
63             if (was_called[i] < 1) {
64                 errs++;
65                 printf("Attribute delete function on MPI_COMM_SELF was not called for idx=%d\n", i);
66             }
67             else if (was_called[i] > 1) {
68                 errs++;
69                 printf("Attribute delete function on MPI_COMM_SELF was called multiple times for idx=%d\n", i);
70             }
71         }
72         if (foundError != 0) {
73             errs++;
74             printf("Found %d errors while executing delete function in MPI_COMM_SELF\n", foundError);
75         }
76         if (errs == 0) {
77             printf(" No Errors\n");
78         }
79         else {
80             printf(" Found %d errors\n", errs);
81         }
82         fflush(stdout);
83     }
84 #else /* this is a pre-MPI-2.2 implementation, ordering is not defined */
85     MPI_Finalize();
86     if (wrank == 0)
87         printf(" No Errors\n");
88 #endif
89
90     return 0;
91 }
92
93 int delete_fn(MPI_Comm comm, int keyval, void *attribute_val, void *extra_state)
94 {
95     int flag;
96     int i;
97     int my_idx = (int)(long)attribute_val;
98
99     if (my_idx < 0 || my_idx > NUM_TEST_ATTRS) {
100         printf("internal error, my_idx=%d is invalid!\n", my_idx);
101         fflush(stdout);
102     }
103
104     was_called[my_idx]++;
105
106     MPI_Finalized(&flag);
107     if (flag) {
108         printf("my_idx=%d, MPI_Finalized returned %d, should have been 0", my_idx, flag);
109         foundError++;
110     }
111
112     /* since attributes were added in 0..(NUM_TEST_ATTRS-1) order, they will be
113      * called in (NUM_TEST_ATTRS-1)..0 order */
114     for (i = 0; i < my_idx; ++i) {
115         if (was_called[i] != 0) {
116             printf("my_idx=%d, was_called[%d]=%d but should be 0\n", my_idx, i, was_called[i]);
117             foundError++;
118         }
119     }
120     for (i = my_idx; i < NUM_TEST_ATTRS; ++i) {
121         if (was_called[i] != 1) {
122             printf("my_idx=%d, was_called[%d]=%d but should be 1\n", my_idx, i, was_called[i]);
123             foundError++;
124         }
125     }
126
127     return MPI_SUCCESS;
128 }
129