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