1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpiimpl.h"
7
8 #if !defined(MPIR_REQUEST_PTR_ARRAY_SIZE)
9 #define MPIR_REQUEST_PTR_ARRAY_SIZE 16
10 #endif
11
12 /* -- Begin Profiling Symbol Block for routine MPI_Testany */
13 #if defined(HAVE_PRAGMA_WEAK)
14 #pragma weak MPI_Testany = PMPI_Testany
15 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
16 #pragma _HP_SECONDARY_DEF PMPI_Testany MPI_Testany
17 #elif defined(HAVE_PRAGMA_CRI_DUP)
18 #pragma _CRI duplicate MPI_Testany as PMPI_Testany
19 #elif defined(HAVE_WEAK_ATTRIBUTE)
20 int MPI_Testany(int count, MPI_Request array_of_requests[], int *indx, int *flag,
21 MPI_Status * status) __attribute__ ((weak, alias("PMPI_Testany")));
22 #endif
23 /* -- End Profiling Symbol Block */
24
25 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
26 the MPI routines */
27 #ifndef MPICH_MPI_FROM_PMPI
28 #undef MPI_Testany
29 #define MPI_Testany PMPI_Testany
30
MPIR_Testany_state(int count,MPIR_Request * request_ptrs[],int * indx,int * flag,MPI_Status * status,MPID_Progress_state * state)31 int MPIR_Testany_state(int count, MPIR_Request * request_ptrs[],
32 int *indx, int *flag, MPI_Status * status, MPID_Progress_state * state)
33 {
34 int i;
35 int n_inactive = 0;
36 int mpi_errno = MPI_SUCCESS;
37
38 mpi_errno = MPID_Progress_test(state);
39 /* --BEGIN ERROR HANDLING-- */
40 MPIR_ERR_CHECK(mpi_errno);
41 /* --END ERROR HANDLING-- */
42
43 for (i = 0; i < count; i++) {
44 if ((i + 1) % MPIR_CVAR_REQUEST_POLL_FREQ == 0) {
45 mpi_errno = MPID_Progress_test(state);
46 MPIR_ERR_CHECK(mpi_errno);
47 }
48
49 if (request_ptrs[i] != NULL && MPIR_Request_has_poll_fn(request_ptrs[i])) {
50 mpi_errno = MPIR_Grequest_poll(request_ptrs[i], status);
51 if (mpi_errno != MPI_SUCCESS)
52 goto fn_fail;
53 }
54 if (!MPIR_Request_is_active(request_ptrs[i])) {
55 n_inactive += 1;
56 } else if (MPIR_Request_is_complete(request_ptrs[i])) {
57 *flag = TRUE;
58 *indx = i;
59 goto fn_exit;
60 }
61 }
62
63 if (n_inactive == count) {
64 *flag = TRUE;
65 *indx = MPI_UNDEFINED;
66 }
67
68 fn_exit:
69 return mpi_errno;
70 fn_fail:
71 goto fn_exit;
72 }
73
MPIR_Testany_impl(int count,MPIR_Request * request_ptrs[],int * indx,int * flag,MPI_Status * status)74 int MPIR_Testany_impl(int count, MPIR_Request * request_ptrs[],
75 int *indx, int *flag, MPI_Status * status)
76 {
77 return MPIR_Testany_state(count, request_ptrs, indx, flag, status, NULL);
78 }
79
80 #endif
81
82 /*@
83 MPI_Testany - Tests for completion of any previdously initiated
84 requests
85
86 Input Parameters:
87 + count - list length (integer)
88 - array_of_requests - array of requests (array of handles)
89
90 Output Parameters:
91 + indx - index of operation that completed, or 'MPI_UNDEFINED' if none
92 completed (integer)
93 . flag - true if one of the operations is complete (logical)
94 - status - status object (Status). May be 'MPI_STATUS_IGNORE'.
95
96 Notes:
97
98 While it is possible to list a request handle more than once in the
99 'array_of_requests', such an action is considered erroneous and may cause the
100 program to unexecpectedly terminate or produce incorrect results.
101
102 .N ThreadSafe
103
104 .N waitstatus
105
106 .N Fortran
107
108 .N Errors
109 .N MPI_SUCCESS
110 @*/
MPI_Testany(int count,MPI_Request array_of_requests[],int * indx,int * flag,MPI_Status * status)111 int MPI_Testany(int count, MPI_Request array_of_requests[], int *indx,
112 int *flag, MPI_Status * status)
113 {
114 MPIR_Request *request_ptr_array[MPIR_REQUEST_PTR_ARRAY_SIZE];
115 MPIR_Request **request_ptrs = request_ptr_array;
116 int i;
117 int n_inactive;
118 int last_disabled_anysource = -1;
119 int first_nonnull = count;
120 int mpi_errno = MPI_SUCCESS;
121 MPIR_CHKLMEM_DECL(1);
122 MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_TESTANY);
123
124 MPIR_ERRTEST_INITIALIZED_ORDIE();
125
126 MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
127 MPIR_FUNC_TERSE_REQUEST_ENTER(MPID_STATE_MPI_TESTANY);
128
129 /* Check the arguments */
130 #ifdef HAVE_ERROR_CHECKING
131 {
132 MPID_BEGIN_ERROR_CHECKS;
133 {
134 MPIR_ERRTEST_COUNT(count, mpi_errno);
135
136 if (count != 0) {
137 MPIR_ERRTEST_ARGNULL(array_of_requests, "array_of_requests", mpi_errno);
138 /* NOTE: MPI_STATUS_IGNORE != NULL */
139 MPIR_ERRTEST_ARGNULL(status, "status", mpi_errno);
140 }
141 MPIR_ERRTEST_ARGNULL(indx, "indx", mpi_errno);
142 MPIR_ERRTEST_ARGNULL(flag, "flag", mpi_errno);
143
144 for (i = 0; i < count; i++) {
145 MPIR_ERRTEST_ARRAYREQUEST_OR_NULL(array_of_requests[i], i, mpi_errno);
146 }
147 }
148 MPID_END_ERROR_CHECKS;
149 }
150 #endif /* HAVE_ERROR_CHECKING */
151
152 /* ... body of routine ... */
153
154 /* Convert MPI request handles to a request object pointers */
155 if (count > MPIR_REQUEST_PTR_ARRAY_SIZE) {
156 MPIR_CHKLMEM_MALLOC_ORJUMP(request_ptrs, MPIR_Request **, count * sizeof(MPIR_Request *),
157 mpi_errno, "request pointers", MPL_MEM_OBJECT);
158 }
159
160 n_inactive = 0;
161 *flag = FALSE;
162 *indx = MPI_UNDEFINED;
163
164 for (i = 0; i < count; i++) {
165 if (array_of_requests[i] != MPI_REQUEST_NULL) {
166 MPIR_Request_get_ptr(array_of_requests[i], request_ptrs[i]);
167 /* Validate object pointers if error checking is enabled */
168 #ifdef HAVE_ERROR_CHECKING
169 {
170 MPID_BEGIN_ERROR_CHECKS;
171 {
172 MPIR_Request_valid_ptr(request_ptrs[i], mpi_errno);
173 if (mpi_errno)
174 goto fn_fail;
175 }
176 MPID_END_ERROR_CHECKS;
177 }
178 #endif
179 if (unlikely(MPIR_Request_is_anysrc_mismatched(request_ptrs[i]))) {
180 last_disabled_anysource = i;
181 }
182
183 if (MPIR_Request_is_complete(request_ptrs[i])) {
184 if (MPIR_Request_is_active(request_ptrs[i])) {
185 *indx = i;
186 *flag = TRUE;
187 break;
188 } else {
189 request_ptrs[i] = NULL;
190 }
191 } else {
192 if (first_nonnull == count)
193 first_nonnull = i;
194 }
195 } else {
196 request_ptrs[i] = NULL;
197 n_inactive += 1;
198 }
199 }
200
201 if (n_inactive == count) {
202 *flag = TRUE;
203 *indx = MPI_UNDEFINED;
204 if (status != NULL) /* could be null if count=0 */
205 MPIR_Status_set_empty(status);
206 goto fn_exit;
207 }
208
209 if (*indx == MPI_UNDEFINED) {
210 mpi_errno =
211 MPID_Testany(count - first_nonnull, &request_ptrs[first_nonnull], indx, flag, status);
212 /* --BEGIN ERROR HANDLING-- */
213 if (mpi_errno != MPI_SUCCESS) {
214 goto fn_fail;
215 }
216 /* --END ERROR HANDLING-- */
217
218 if (*indx != MPI_UNDEFINED) {
219 *indx += first_nonnull;
220 }
221 }
222
223 if (*indx != MPI_UNDEFINED) {
224 mpi_errno = MPIR_Request_completion_processing(request_ptrs[*indx], status);
225 if (!MPIR_Request_is_persistent(request_ptrs[*indx])) {
226 MPIR_Request_free(request_ptrs[*indx]);
227 array_of_requests[*indx] = MPI_REQUEST_NULL;
228 }
229 MPIR_ERR_CHECK(mpi_errno);
230 goto fn_exit;
231 }
232
233 /* If none of the requests completed, mark the last anysource request as
234 * pending failure. */
235 if (unlikely(last_disabled_anysource != -1)) {
236 MPIR_ERR_SET(mpi_errno, MPIX_ERR_PROC_FAILED_PENDING, "**failure_pending");
237 if (status != MPI_STATUS_IGNORE)
238 status->MPI_ERROR = mpi_errno;
239 *flag = TRUE;
240 goto fn_fail;
241 }
242
243 /* ... end of body of routine ... */
244
245 fn_exit:
246 if (count > MPIR_REQUEST_PTR_ARRAY_SIZE) {
247 MPIR_CHKLMEM_FREEALL();
248 }
249
250 MPIR_FUNC_TERSE_REQUEST_EXIT(MPID_STATE_MPI_TESTANY);
251 MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
252 return mpi_errno;
253
254 fn_fail:
255 /* --BEGIN ERROR HANDLING-- */
256 #ifdef HAVE_ERROR_CHECKING
257 {
258 mpi_errno =
259 MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
260 "**mpi_testany", "**mpi_testany %d %p %p %p %p", count,
261 array_of_requests, indx, flag, status);
262 }
263 #endif
264 mpi_errno = MPIR_Err_return_comm(NULL, __func__, mpi_errno);
265 goto fn_exit;
266 /* --END ERROR HANDLING-- */
267 }
268