|
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