2424#include "ompi/request/grequest.h"
2525#include "ompi/mpi/fortran/base/fint_2_int.h"
2626
27- /**
27+ /*
2828 * Internal function to specialize the call to the user provided free_fn
2929 * for generalized requests.
3030 * @return The return value of the user specified callback or MPI_SUCCESS.
3131 */
32- static inline int ompi_grequest_internal_free (ompi_grequest_t * greq )
32+ static inline int ompi_grequest_invoke_free (ompi_grequest_t * greq )
3333{
34- int rc = MPI_SUCCESS ;
34+ int rc = OMPI_SUCCESS ;
35+ MPI_Fint ierr ;
36+
3537 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+ }
3644 /* We were already putting query_fn()'s return value into
3745 * status.MPI_ERROR but for MPI_{Wait,Test}*. If there's a
3846 * free callback to invoke, the standard says to use the
3947 * return value from free_fn() callback, too.
4048 */
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 ;
4851 }
49- rc = greq -> greq_base .req_status .MPI_ERROR ;
5052 }
5153 return rc ;
5254 }
5355
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+
5476/*
5577 * See the comment in the grequest destructor for the weird semantics
5678 * 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)
6688 ompi_grequest_t * greq = (ompi_grequest_t * )* req ;
6789 int rc = OMPI_SUCCESS ;
6890
69- if ( greq -> greq_user_freed ) {
70- return OMPI_ERR_OUT_OF_RESOURCE ;
71- }
7291 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 ) {
7795 OBJ_RELEASE (* req );
7896 * req = MPI_REQUEST_NULL ;
7997 }
@@ -180,7 +198,7 @@ int ompi_grequest_start(
180198 ompi_request_t * * request )
181199{
182200 ompi_grequest_t * greq = OBJ_NEW (ompi_grequest_t );
183- if (greq == NULL ) {
201+ if (greq == NULL ) {
184202 return OMPI_ERR_OUT_OF_RESOURCE ;
185203 }
186204 /* We call RETAIN here specifically to increase the refcount to 2.
@@ -211,13 +229,14 @@ int ompi_grequest_start(
211229int ompi_grequest_complete (ompi_request_t * req )
212230{
213231 ompi_grequest_t * greq = (ompi_grequest_t * )req ;
232+ bool greq_release = !REQUEST_COMPLETE (req );
214233 int rc ;
215234
216235 rc = ompi_request_complete (req , true);
217- if ( greq -> greq_user_freed ) {
236+ if ( OMPI_SUCCESS == rc && greq_release ) {
218237 rc = ompi_grequest_internal_free (greq );
238+ OBJ_RELEASE (req );
219239 }
220- OBJ_RELEASE (req );
221240 return rc ;
222241}
223242
@@ -237,6 +256,11 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
237256 int rc = OMPI_SUCCESS ;
238257 ompi_grequest_t * g = (ompi_grequest_t * ) request ;
239258
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+
240264 /* MPI-3 mandates that the return value from the query function
241265 * (i.e., the int return value from the C function or the ierr
242266 * argument from the Fortran function) must be returned to the
@@ -268,9 +292,8 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
268292 rc = OMPI_FINT_2_INT (ierr );
269293 }
270294 }
271- if ( MPI_SUCCESS != rc ) {
295+ if ( OMPI_SUCCESS != rc ) {
272296 status -> MPI_ERROR = rc ;
273297 }
274298 return rc ;
275299}
276-
0 commit comments