1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
4 * (C) 2009 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
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"
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)
25 static int exit_keys[NUM_TEST_ATTRS]; /* init to MPI_KEYVAL_INVALID */
26 static int was_called[NUM_TEST_ATTRS];
28 int delete_fn(MPI_Comm, int, void *, void *);
30 int main(int argc, char **argv)
35 MTest_Init(&argc, &argv);
37 MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
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;
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);
50 /* we can free the keys now */
51 for (i = 0; i < NUM_TEST_ATTRS; ++i) {
52 MPI_Comm_free_keyval(&exit_keys[i]);
58 /* check that the exit handlers were called in LIFO order, and without error */
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) {
64 printf("Attribute delete function on MPI_COMM_SELF was not called for idx=%d\n", i);
66 else if (was_called[i] > 1) {
69 ("Attribute delete function on MPI_COMM_SELF was called multiple times for idx=%d\n",
73 if (foundError != 0) {
75 printf("Found %d errors while executing delete function in MPI_COMM_SELF\n",
79 printf(" No Errors\n");
82 printf(" Found %d errors\n", errs);
86 #else /* this is a pre-MPI-2.2 implementation, ordering is not defined */
89 printf(" No Errors\n");
95 int delete_fn(MPI_Comm comm, int keyval, void *attribute_val, void *extra_state)
99 int my_idx = (int) (long) attribute_val;
101 if (my_idx < 0 || my_idx > NUM_TEST_ATTRS) {
102 printf("internal error, my_idx=%d is invalid!\n", my_idx);
106 was_called[my_idx]++;
108 MPI_Finalized(&flag);
110 printf("my_idx=%d, MPI_Finalized returned %d, should have been 0", my_idx, flag);
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]);
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]);