24
24
#include "ompi/request/grequest.h"
25
25
#include "ompi/mpi/fortran/base/fint_2_int.h"
26
26
27
- /**
27
+ /*
28
28
* Internal function to specialize the call to the user provided free_fn
29
29
* for generalized requests.
30
30
* @return The return value of the user specified callback or MPI_SUCCESS.
31
31
*/
32
- static inline int ompi_grequest_internal_free (ompi_grequest_t * greq )
32
+ static inline int ompi_grequest_invoke_free (ompi_grequest_t * greq )
33
33
{
34
- int rc = MPI_SUCCESS ;
34
+ int rc = OMPI_SUCCESS ;
35
+ MPI_Fint ierr ;
36
+
35
37
if (NULL != greq -> greq_free .c_free ) {
38
+ if (greq -> greq_funcs_are_c ) {
39
+ rc = greq -> greq_free .c_free (greq -> greq_state );
40
+ } else {
41
+ greq -> greq_free .f_free ((MPI_Aint * )greq -> greq_state , & ierr );
42
+ rc = OMPI_FINT_2_INT (ierr );
43
+ }
36
44
/* We were already putting query_fn()'s return value into
37
45
* status.MPI_ERROR but for MPI_{Wait,Test}*. If there's a
38
46
* free callback to invoke, the standard says to use the
39
47
* return value from free_fn() callback, too.
40
48
*/
41
- if (greq -> greq_funcs_are_c ) {
42
- greq -> greq_base .req_status .MPI_ERROR =
43
- greq -> greq_free .c_free (greq -> greq_state );
44
- } else {
45
- MPI_Fint ierr ;
46
- greq -> greq_free .f_free ((MPI_Aint * )greq -> greq_state , & ierr );
47
- greq -> greq_base .req_status .MPI_ERROR = OMPI_FINT_2_INT (ierr );
49
+ if (OMPI_SUCCESS != rc ) {
50
+ greq -> greq_base .req_status .MPI_ERROR = rc ;
48
51
}
49
- rc = greq -> greq_base .req_status .MPI_ERROR ;
50
52
}
51
53
return rc ;
52
54
}
53
55
56
+
57
+ /*
58
+ * Internal function to dispatch the call to the user provided free_fn
59
+ * for generalized requests. The freeing code executes as soon as both
60
+ * wait/free and complete have occured.
61
+ * @return The return value of the user specified callback or MPI_SUCCESS.
62
+ */
63
+ static inline int ompi_grequest_internal_free (ompi_grequest_t * greq )
64
+ {
65
+ int rc = OMPI_SUCCESS ;
66
+
67
+ if (REQUEST_COMPLETE (& greq -> greq_base ) && greq -> greq_user_freed ) {
68
+ rc = ompi_grequest_invoke_free (greq );
69
+ /* The free_fn() callback should be invoked only once. */
70
+ if (NULL != greq -> greq_free .c_free )
71
+ greq -> greq_free .c_free = NULL ;
72
+ }
73
+ return rc ;
74
+ }
75
+
54
76
/*
55
77
* See the comment in the grequest destructor for the weird semantics
56
78
* here. If the request has been marked complete via a call to
@@ -66,14 +88,10 @@ static int ompi_grequest_free(ompi_request_t** req)
66
88
ompi_grequest_t * greq = (ompi_grequest_t * )* req ;
67
89
int rc = OMPI_SUCCESS ;
68
90
69
- if ( greq -> greq_user_freed ) {
70
- return OMPI_ERR_OUT_OF_RESOURCE ;
71
- }
72
91
greq -> greq_user_freed = true;
73
- if ( REQUEST_COMPLETE (* req ) ) {
74
- rc = ompi_grequest_internal_free (greq );
75
- }
76
- if (OMPI_SUCCESS == rc ) {
92
+ rc = ompi_grequest_internal_free (greq );
93
+
94
+ if (OMPI_SUCCESS == rc ) {
77
95
OBJ_RELEASE (* req );
78
96
* req = MPI_REQUEST_NULL ;
79
97
}
@@ -180,7 +198,7 @@ int ompi_grequest_start(
180
198
ompi_request_t * * request )
181
199
{
182
200
ompi_grequest_t * greq = OBJ_NEW (ompi_grequest_t );
183
- if (greq == NULL ) {
201
+ if (greq == NULL ) {
184
202
return OMPI_ERR_OUT_OF_RESOURCE ;
185
203
}
186
204
/* We call RETAIN here specifically to increase the refcount to 2.
@@ -211,13 +229,14 @@ int ompi_grequest_start(
211
229
int ompi_grequest_complete (ompi_request_t * req )
212
230
{
213
231
ompi_grequest_t * greq = (ompi_grequest_t * )req ;
232
+ bool greq_release = !REQUEST_COMPLETE (req );
214
233
int rc ;
215
234
216
235
rc = ompi_request_complete (req , true);
217
- if ( greq -> greq_user_freed ) {
236
+ if ( OMPI_SUCCESS == rc && greq_release ) {
218
237
rc = ompi_grequest_internal_free (greq );
238
+ OBJ_RELEASE (req );
219
239
}
220
- OBJ_RELEASE (req );
221
240
return rc ;
222
241
}
223
242
@@ -237,6 +256,11 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
237
256
int rc = OMPI_SUCCESS ;
238
257
ompi_grequest_t * g = (ompi_grequest_t * ) request ;
239
258
259
+ /* MPI mandates that query_fn must be called after the request is
260
+ * completed. Make sure the caller does not break the contract.
261
+ */
262
+ assert ( REQUEST_COMPLETE (request ) );
263
+
240
264
/* MPI-3 mandates that the return value from the query function
241
265
* (i.e., the int return value from the C function or the ierr
242
266
* argument from the Fortran function) must be returned to the
@@ -268,9 +292,8 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
268
292
rc = OMPI_FINT_2_INT (ierr );
269
293
}
270
294
}
271
- if ( MPI_SUCCESS != rc ) {
295
+ if ( OMPI_SUCCESS != rc ) {
272
296
status -> MPI_ERROR = rc ;
273
297
}
274
298
return rc ;
275
299
}
276
-
0 commit comments