1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpi.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "mpitest.h"
10 
11 /*
12 static char MTEST_Descrip[] = "Test of various send cancel calls";
13 */
14 
main(int argc,char * argv[])15 int main(int argc, char *argv[])
16 {
17     int errs = 0;
18     int rank, size, source, dest;
19     MPI_Comm comm;
20     MPI_Status status;
21     MPI_Request req;
22     static int bufsizes[4] = { 1, 100, 10000, 1000000 };
23     char *buf;
24 #ifdef TEST_IRSEND
25     int veryPicky = 0;          /* Set to 1 to test "quality of implementation" in
26                                  * a tricky part of cancel */
27 #endif
28     int cs, flag, n;
29 
30     MTest_Init(&argc, &argv);
31 
32     comm = MPI_COMM_WORLD;
33     MPI_Comm_rank(comm, &rank);
34     MPI_Comm_size(comm, &size);
35 
36     source = 0;
37     dest = size - 1;
38 
39     MTestPrintfMsg(1, "Starting scancel test\n");
40     for (cs = 0; cs < 4; cs++) {
41         if (rank == 0) {
42             n = bufsizes[cs];
43             buf = (char *) malloc(n);
44             if (!buf) {
45                 fprintf(stderr, "Unable to allocate %d bytes\n", n);
46                 MPI_Abort(MPI_COMM_WORLD, 1);
47             }
48             MTestPrintfMsg(1, "(%d) About to create isend and cancel\n", cs);
49             MPI_Isend(buf, n, MPI_CHAR, dest, cs + n + 1, comm, &req);
50             MPI_Cancel(&req);
51             MPI_Wait(&req, &status);
52             MTestPrintfMsg(1, "Completed wait on isend\n");
53             MPI_Test_cancelled(&status, &flag);
54             if (!flag) {
55                 errs++;
56                 printf("Failed to cancel an Isend request\n");
57                 fflush(stdout);
58             } else {
59                 n = 0;
60             }
61             /* Send the size, zero for successfully cancelled */
62             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
63             /* Send the tag so the message can be received */
64             n = cs + n + 1;
65             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
66             free(buf);
67         } else if (rank == dest) {
68             int nn, tag;
69             char *btemp;
70             MPI_Recv(&nn, 1, MPI_INT, 0, 123, comm, &status);
71             MPI_Recv(&tag, 1, MPI_INT, 0, 123, comm, &status);
72             if (nn > 0) {
73                 /* If the message was not cancelled, receive it here */
74                 btemp = (char *) malloc(nn);
75                 if (!btemp) {
76                     fprintf(stderr, "Unable to allocate %d bytes\n", nn);
77                     MPI_Abort(MPI_COMM_WORLD, 1);
78                 }
79                 MPI_Recv(btemp, nn, MPI_CHAR, 0, tag, comm, &status);
80                 free(btemp);
81             }
82         }
83         MPI_Barrier(comm);
84 
85         if (rank == 0) {
86             char *bsendbuf;
87             int bsendbufsize;
88             int bf, bs;
89             n = bufsizes[cs];
90             buf = (char *) malloc(n);
91             if (!buf) {
92                 fprintf(stderr, "Unable to allocate %d bytes\n", n);
93                 MPI_Abort(MPI_COMM_WORLD, 1);
94             }
95             bsendbufsize = n + MPI_BSEND_OVERHEAD;
96             bsendbuf = (char *) malloc(bsendbufsize);
97             if (!bsendbuf) {
98                 fprintf(stderr, "Unable to allocate %d bytes for bsend\n", n);
99                 MPI_Abort(MPI_COMM_WORLD, 1);
100             }
101             MPI_Buffer_attach(bsendbuf, bsendbufsize);
102             MTestPrintfMsg(1, "About to create and cancel ibsend\n");
103             MPI_Ibsend(buf, n, MPI_CHAR, dest, cs + n + 2, comm, &req);
104             MPI_Cancel(&req);
105             MPI_Wait(&req, &status);
106             MPI_Test_cancelled(&status, &flag);
107             if (!flag) {
108                 errs++;
109                 printf("Failed to cancel an Ibsend request\n");
110                 fflush(stdout);
111             } else {
112                 n = 0;
113             }
114             /* Send the size, zero for successfully cancelled */
115             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
116             /* Send the tag so the message can be received */
117             n = cs + n + 2;
118             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
119             free(buf);
120             MPI_Buffer_detach(&bf, &bs);
121             free(bsendbuf);
122         } else if (rank == dest) {
123             int nn, tag;
124             char *btemp;
125             MPI_Recv(&nn, 1, MPI_INT, 0, 123, comm, &status);
126             MPI_Recv(&tag, 1, MPI_INT, 0, 123, comm, &status);
127             if (nn > 0) {
128                 /* If the message was not cancelled, receive it here */
129                 btemp = (char *) malloc(nn);
130                 if (!btemp) {
131                     fprintf(stderr, "Unable to allocate %d bytes\n", nn);
132                     MPI_Abort(MPI_COMM_WORLD, 1);
133                 }
134                 MPI_Recv(btemp, nn, MPI_CHAR, 0, tag, comm, &status);
135                 free(btemp);
136             }
137         }
138         MPI_Barrier(comm);
139 
140         /* Because this test is erroneous, we do not perform it unless
141          * TEST_IRSEND is defined.  */
142 #ifdef TEST_IRSEND
143         /* We avoid ready send to self because an implementation
144          * is free to detect the error in delivering a message to
145          * itself without a pending receive; we could also check
146          * for an error return from the MPI_Irsend */
147         if (rank == 0 && dest != rank) {
148             n = bufsizes[cs];
149             buf = (char *) malloc(n);
150             if (!buf) {
151                 fprintf(stderr, "Unable to allocate %d bytes\n", n);
152                 MPI_Abort(MPI_COMM_WORLD, 1);
153             }
154             MTestPrintfMsg(1, "About to create and cancel irsend\n");
155             MPI_Irsend(buf, n, MPI_CHAR, dest, cs + n + 3, comm, &req);
156             MPI_Cancel(&req);
157             MPI_Wait(&req, &status);
158             MPI_Test_cancelled(&status, &flag);
159             /* This can be pretty ugly.  The standard is clear (Section 3.8)
160              * that either a sent message is received or the
161              * sent message is successfully cancelled.  Since this message
162              * can never be received, the cancel must complete
163              * successfully.
164              *
165              * However, since there is no matching receive, this
166              * program is erroneous.  In this case, we can't really
167              * flag this as an error */
168             if (!flag && veryPicky) {
169                 errs++;
170                 printf("Failed to cancel an Irsend request\n");
171                 fflush(stdout);
172             }
173             if (flag) {
174                 n = 0;
175             }
176             /* Send the size, zero for successfully cancelled */
177             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
178             /* Send the tag so the message can be received */
179             n = cs + n + 3;
180             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
181             free(buf);
182         } else if (rank == dest) {
183             int n, tag;
184             char *btemp;
185             MPI_Recv(&n, 1, MPI_INT, 0, 123, comm, &status);
186             MPI_Recv(&tag, 1, MPI_INT, 0, 123, comm, &status);
187             if (n > 0) {
188                 /* If the message was not cancelled, receive it here */
189                 btemp = (char *) malloc(n);
190                 if (!btemp) {
191                     fprintf(stderr, "Unable to allocate %d bytes\n", n);
192                     MPI_Abort(MPI_COMM_WORLD, 1);
193                 }
194                 MPI_Recv(btemp, n, MPI_CHAR, 0, tag, comm, &status);
195                 free(btemp);
196             }
197         }
198         MPI_Barrier(comm);
199 #endif
200 
201         if (rank == 0) {
202             n = bufsizes[cs];
203             buf = (char *) malloc(n);
204             if (!buf) {
205                 fprintf(stderr, "Unable to allocate %d bytes\n", n);
206                 MPI_Abort(MPI_COMM_WORLD, 1);
207             }
208             MTestPrintfMsg(1, "About to create and cancel issend\n");
209             MPI_Issend(buf, n, MPI_CHAR, dest, cs + n + 4, comm, &req);
210             MPI_Cancel(&req);
211             MPI_Wait(&req, &status);
212             MPI_Test_cancelled(&status, &flag);
213             if (!flag) {
214                 errs++;
215                 printf("Failed to cancel an Issend request\n");
216                 fflush(stdout);
217             } else {
218                 n = 0;
219             }
220             /* Send the size, zero for successfully cancelled */
221             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
222             /* Send the tag so the message can be received */
223             n = cs + n + 4;
224             MPI_Send(&n, 1, MPI_INT, dest, 123, comm);
225             free(buf);
226         } else if (rank == dest) {
227             int nn, tag;
228             char *btemp;
229             MPI_Recv(&nn, 1, MPI_INT, 0, 123, comm, &status);
230             MPI_Recv(&tag, 1, MPI_INT, 0, 123, comm, &status);
231             if (nn > 0) {
232                 /* If the message was not cancelled, receive it here */
233                 btemp = (char *) malloc(nn);
234                 if (!btemp) {
235                     fprintf(stderr, "Unable to allocate %d bytes\n", nn);
236                     MPI_Abort(MPI_COMM_WORLD, 1);
237                 }
238                 MPI_Recv(btemp, nn, MPI_CHAR, 0, tag, comm, &status);
239                 free(btemp);
240             }
241         }
242         MPI_Barrier(comm);
243     }
244 
245     MTest_Finalize(errs);
246     return MTestReturnValue(errs);
247 }
248