|
24 | 24 | #include "ompi/request/grequest.h"
|
25 | 25 | #include "ompi/mpi/fortran/base/fint_2_int.h"
|
26 | 26 |
|
| 27 | +/** |
| 28 | + * Internal function to specialize the call to the user provided free_fn |
| 29 | + * for generalized requests. |
| 30 | + * @return The return value of the user specified callback or MPI_SUCCESS. |
| 31 | + */ |
| 32 | +static inline int ompi_grequest_internal_free(ompi_grequest_t* greq) |
| 33 | +{ |
| 34 | + int rc = MPI_SUCCESS; |
| 35 | + if (NULL != greq->greq_free.c_free) { |
| 36 | + /* We were already putting query_fn()'s return value into |
| 37 | + * status.MPI_ERROR but for MPI_{Wait,Test}*. If there's a |
| 38 | + * free callback to invoke, the standard says to use the |
| 39 | + * return value from free_fn() callback, too. |
| 40 | + */ |
| 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); |
| 48 | + } |
| 49 | + rc = greq->greq_base.req_status.MPI_ERROR; |
| 50 | + } |
| 51 | + return rc; |
| 52 | + } |
27 | 53 |
|
28 | 54 | /*
|
29 | 55 | * See the comment in the grequest destructor for the weird semantics
|
|
37 | 63 | */
|
38 | 64 | static int ompi_grequest_free(ompi_request_t** req)
|
39 | 65 | {
|
40 |
| - OBJ_RELEASE(*req); |
41 |
| - *req = MPI_REQUEST_NULL; |
42 |
| - return OMPI_SUCCESS; |
| 66 | + ompi_grequest_t* greq = (ompi_grequest_t*)*req; |
| 67 | + int rc = OMPI_SUCCESS; |
| 68 | + |
| 69 | + if( greq->greq_user_freed ) { |
| 70 | + return OMPI_ERR_OUT_OF_RESOURCE; |
| 71 | + } |
| 72 | + greq->greq_user_freed = true; |
| 73 | + if( REQUEST_COMPLETE(*req) ) { |
| 74 | + rc = ompi_grequest_internal_free(greq); |
| 75 | + } |
| 76 | + if (OMPI_SUCCESS == rc ) { |
| 77 | + OBJ_RELEASE(*req); |
| 78 | + *req = MPI_REQUEST_NULL; |
| 79 | + } |
| 80 | + return rc; |
43 | 81 | }
|
44 | 82 |
|
45 | 83 | static int ompi_grequest_cancel(ompi_request_t* req, int flag)
|
@@ -72,6 +110,7 @@ static void ompi_grequest_construct(ompi_grequest_t* greq)
|
72 | 110 | override this value if the gen request was created from
|
73 | 111 | Fortran */
|
74 | 112 | greq->greq_funcs_are_c = true;
|
| 113 | + greq->greq_user_freed = false; |
75 | 114 | }
|
76 | 115 |
|
77 | 116 | /*
|
@@ -122,23 +161,6 @@ static void ompi_grequest_construct(ompi_grequest_t* greq)
|
122 | 161 | */
|
123 | 162 | static void ompi_grequest_destruct(ompi_grequest_t* greq)
|
124 | 163 | {
|
125 |
| - if (greq->greq_free.c_free != NULL) { |
126 |
| - /* We were already putting query_fn()'s return value into |
127 |
| - * status.MPI_ERROR but for MPI_{Wait,Test}*. If there's a |
128 |
| - * free callback to invoke, the standard says to use the |
129 |
| - * return value from free_fn() callback, too. |
130 |
| - */ |
131 |
| - if (greq->greq_funcs_are_c) { |
132 |
| - greq->greq_base.req_status.MPI_ERROR = |
133 |
| - greq->greq_free.c_free(greq->greq_state); |
134 |
| - } else { |
135 |
| - MPI_Fint ierr; |
136 |
| - greq->greq_free.f_free((MPI_Aint*)greq->greq_state, &ierr); |
137 |
| - greq->greq_base.req_status.MPI_ERROR = |
138 |
| - OMPI_FINT_2_INT(ierr); |
139 |
| - } |
140 |
| - } |
141 |
| - |
142 | 164 | OMPI_REQUEST_FINI(&greq->greq_base);
|
143 | 165 | }
|
144 | 166 |
|
@@ -188,9 +210,13 @@ int ompi_grequest_start(
|
188 | 210 | */
|
189 | 211 | int ompi_grequest_complete(ompi_request_t *req)
|
190 | 212 | {
|
| 213 | + ompi_grequest_t* greq = (ompi_grequest_t*)req; |
191 | 214 | int rc;
|
192 | 215 |
|
193 | 216 | rc = ompi_request_complete(req, true);
|
| 217 | + if( greq->greq_user_freed ) { |
| 218 | + rc = ompi_grequest_internal_free(greq); |
| 219 | + } |
194 | 220 | OBJ_RELEASE(req);
|
195 | 221 | return rc;
|
196 | 222 | }
|
|
0 commit comments