Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reduce the size of partial shared malloc tests.
[simgrid.git] / teshsuite / smpi / mpich3-test / attr / attrend2.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2009 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 int exit_keys[NUM_TEST_ATTRS];   /* init to MPI_KEYVAL_INVALID */
26 static 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 errs = 0, wrank;
33     int i;
34
35     MTest_Init(&argc, &argv);
36
37     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
38
39 #if MTEST_HAVE_MIN_MPI_VERSION(2,2)
40     for (i = 0; i < NUM_TEST_ATTRS; ++i) {
41         exit_keys[i] = MPI_KEYVAL_INVALID;
42         was_called[i] = 0;
43
44         /* create the keyval for the exit handler */
45         MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, delete_fn, &exit_keys[i], NULL);
46         /* attach to comm_self */
47         MPI_Comm_set_attr(MPI_COMM_SELF, exit_keys[i], (void *) (long) i);
48     }
49
50     /* we can free the keys now */
51     for (i = 0; i < NUM_TEST_ATTRS; ++i) {
52         MPI_Comm_free_keyval(&exit_keys[i]);
53     }
54
55     /* now, exit MPI */
56     MPI_Finalize();
57
58     /* check that the exit handlers were called in LIFO order, and without error */
59     if (wrank == 0) {
60         /* In case more than one process exits MPI_Finalize */
61         for (i = 0; i < NUM_TEST_ATTRS; ++i) {
62             if (was_called[i] < 1) {
63                 errs++;
64                 printf("Attribute delete function on MPI_COMM_SELF was not called for idx=%d\n", i);
65             }
66             else if (was_called[i] > 1) {
67                 errs++;
68                 printf
69                     ("Attribute delete function on MPI_COMM_SELF was called multiple times for idx=%d\n",
70                      i);
71             }
72         }
73         if (foundError != 0) {
74             errs++;
75             printf("Found %d errors while executing delete function in MPI_COMM_SELF\n",
76                    foundError);
77         }
78         if (errs == 0) {
79             printf(" No Errors\n");
80         }
81         else {
82             printf(" Found %d errors\n", errs);
83         }
84         fflush(stdout);
85     }
86 #else /* this is a pre-MPI-2.2 implementation, ordering is not defined */
87     MPI_Finalize();
88     if (wrank == 0)
89         printf(" No Errors\n");
90 #endif
91
92     return 0;
93 }
94
95 int delete_fn(MPI_Comm comm, int keyval, void *attribute_val, void *extra_state)
96 {
97     int flag;
98     int i;
99     int my_idx = (int) (long) attribute_val;
100
101     if (my_idx < 0 || my_idx > NUM_TEST_ATTRS) {
102         printf("internal error, my_idx=%d is invalid!\n", my_idx);
103         fflush(stdout);
104     }
105
106     was_called[my_idx]++;
107
108     MPI_Finalized(&flag);
109     if (flag) {
110         printf("my_idx=%d, MPI_Finalized returned %d, should have been 0", my_idx, flag);
111         foundError++;
112     }
113
114     /* since attributes were added in 0..(NUM_TEST_ATTRS-1) order, they will be
115      * called in (NUM_TEST_ATTRS-1)..0 order */
116     for (i = 0; i < my_idx; ++i) {
117         if (was_called[i] != 0) {
118             printf("my_idx=%d, was_called[%d]=%d but should be 0\n", my_idx, i, was_called[i]);
119             foundError++;
120         }
121     }
122     for (i = my_idx; i < NUM_TEST_ATTRS; ++i) {
123         if (was_called[i] != 1) {
124             printf("my_idx=%d, was_called[%d]=%d but should be 1\n", my_idx, i, was_called[i]);
125             foundError++;
126         }
127     }
128
129     return MPI_SUCCESS;
130 }