Fixes trac:496
* Add some more error checking to GREQUEST_START * Move the error checking in GREQUEST_COMPLETE up to inside the MPI_PARAM_CHECK block, where it belongs * Invoke the gen request query_fn in all the Right spots (per MPI-2:8.2) * Distinguish between grequests created from C and Fortran * Use the OBJ system to reference count to release the grequest at the Right time and invoke the grequest free_fn properly (see lengthy comment in grequest.c above the destructor) * Have ompi_grequest_complete() call ompi_request_complete() rather than [poorly] copy the contents of ompi_request_complete() * Fix Fortran function callback pointer typedefs to use proper Fortran types * Edit ompi_request_test* and ompi_request_wait* to properly handle generalized requests. This adds an "if" statement in the critical path for all the back-end test* and wait* functions :-(, but fortunately George took out two "if" statements from the critical path last week. So we're still ahead. :-) * Move ompi_request_test() out of request.h and into request.c (all other test* and wait* functions were already in the .c file -- and ompi_request_test() was too long to be statically inlined anyway) This commit was SVN r12402. The following Trac tickets were found above: Ticket 496 --> https://svn.open-mpi.org/trac/ompi/ticket/496
Этот коммит содержится в:
родитель
e99dcb6e73
Коммит
431f940a52
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -39,18 +40,13 @@ int MPI_Grequest_complete(MPI_Request request)
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (request == MPI_REQUEST_NULL) {
|
||||
rc = MPI_ERR_REQUEST;
|
||||
} else if (OMPI_REQUEST_GEN != request->req_type) {
|
||||
rc = MPI_ERR_REQUEST;
|
||||
}
|
||||
OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME);
|
||||
}
|
||||
|
||||
switch(request->req_type) {
|
||||
case OMPI_REQUEST_GEN:
|
||||
rc = ompi_grequest_complete((ompi_grequest_t*)request);
|
||||
break;
|
||||
default:
|
||||
rc = MPI_ERR_REQUEST;
|
||||
break;
|
||||
}
|
||||
rc = ompi_grequest_complete(request);
|
||||
OMPI_ERRHANDLER_RETURN(rc, MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -40,6 +41,10 @@ int MPI_Grequest_start(MPI_Grequest_query_function *query_fn,
|
||||
int rc;
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == request) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
rc = ompi_grequest_start(query_fn,free_fn,cancel_fn,extra_state,request);
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (C) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -20,6 +21,7 @@
|
||||
|
||||
#include "ompi/mpi/c/bindings.h"
|
||||
#include "ompi/request/request.h"
|
||||
#include "ompi/request/grequest.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Request_get_status = PMPI_Request_get_status
|
||||
@ -55,6 +57,12 @@ int MPI_Request_get_status(MPI_Request request, int *flag,
|
||||
}
|
||||
if( request->req_complete ) {
|
||||
*flag = true;
|
||||
/* If this is a generalized request, we *always* have to call
|
||||
the query function to get the status (MPI-2:8.2), even if
|
||||
the user passed STATUS_IGNORE. */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
*status = request->req_status;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -70,6 +71,11 @@ void mpi_grequest_start_f(MPI_F_Grequest_query_function* query_fn,
|
||||
(MPI_Grequest_cancel_function *) cancel_fn,
|
||||
extra_state, &c_req));
|
||||
if (MPI_SUCCESS == OMPI_FINT_2_INT(*ierr)) {
|
||||
/* Manually override the function pointer type flag on the
|
||||
grequest to indicate that these are Fortran functions */
|
||||
ompi_grequest_t *g = (ompi_grequest_t*) c_req;
|
||||
g->greq_funcs_are_c = false;
|
||||
|
||||
*request = MPI_Request_c2f(c_req);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -18,27 +19,43 @@
|
||||
|
||||
#include "ompi_config.h"
|
||||
#include "ompi/request/grequest.h"
|
||||
#include "ompi/mpi/f77/fint_2_int.h"
|
||||
|
||||
|
||||
/*
|
||||
* See the comment in the grequest destructor for the weird semantics
|
||||
* here. If the request has been marked complete via a call to
|
||||
* MPI_GREQUEST_COMPLETE, actually release the object. OTherwise,
|
||||
* just mark this object as "freed" so that a later call to
|
||||
* MPI_GREQUEST_COMPLETE will release it (!).
|
||||
*
|
||||
* Note that TEST* and WAIT* will call this function when a request
|
||||
* has been completed.
|
||||
*/
|
||||
static int ompi_grequest_free(ompi_request_t** req)
|
||||
{
|
||||
int rc = OMPI_SUCCESS;
|
||||
ompi_grequest_t* greq = *(ompi_grequest_t**)req;
|
||||
if(greq->greq_free.c_free != NULL)
|
||||
rc = greq->greq_free.c_free(greq->greq_state);
|
||||
if(rc == OMPI_SUCCESS) {
|
||||
OBJ_RELEASE(greq);
|
||||
*req = MPI_REQUEST_NULL;
|
||||
}
|
||||
return rc;
|
||||
OBJ_RELEASE(*req);
|
||||
*req = MPI_REQUEST_NULL;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
static int ompi_grequest_cancel(ompi_request_t* req, int flag)
|
||||
{
|
||||
int rc = OMPI_SUCCESS;
|
||||
MPI_Fint ierr;
|
||||
MPI_Flogical fflag;
|
||||
ompi_grequest_t* greq = (ompi_grequest_t*)req;
|
||||
if(greq->greq_cancel.c_cancel != NULL)
|
||||
rc = greq->greq_cancel.c_cancel(greq->greq_state, flag);
|
||||
|
||||
if (greq->greq_cancel.c_cancel != NULL) {
|
||||
if (greq->greq_funcs_are_c) {
|
||||
rc = greq->greq_cancel.c_cancel(greq->greq_state,
|
||||
greq->greq_base.req_complete);
|
||||
} else {
|
||||
fflag = (MPI_Flogical) greq->greq_base.req_complete;
|
||||
greq->greq_cancel.f_cancel(greq->greq_state, &fflag, &ierr);
|
||||
rc = OMPI_FINT_2_INT(ierr);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -48,10 +65,70 @@ static void ompi_grequest_construct(ompi_grequest_t* greq)
|
||||
greq->greq_base.req_cancel = ompi_grequest_cancel;
|
||||
greq->greq_base.req_type = OMPI_REQUEST_GEN;
|
||||
greq->greq_base.req_mpi_object.comm = &ompi_mpi_comm_world;
|
||||
/* Set the function pointers to C here; the F77 MPI API will
|
||||
override this value if the gen request was created from
|
||||
Fortran */
|
||||
greq->greq_funcs_are_c = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* MPI has some weird semantics with respect to generalized requests
|
||||
* -- different than all other MPI object types. So we move some
|
||||
* cleanup stuff here to the destructor rather than in
|
||||
* greqeust_request_free -- mainly because the cleanup may be required
|
||||
* in two different places.
|
||||
*
|
||||
* Specifically, generalized requests can be completed (and therefore
|
||||
* released) the following ways:
|
||||
*
|
||||
* 1. Call to MPI_GREQUEST_COMPLETE and then a corresponding call to
|
||||
* some flavor of MPI_TEST* or MPI_WAIT*. This will both complete the
|
||||
* requests and destroy the coresponding MPI generalized request
|
||||
* object.
|
||||
*
|
||||
* 2. Call MPI_REQUEST_FREE and then (!) -- with some other
|
||||
* still-valid copy of the handler -- call MPI_GREQUEST_COMPLETE.
|
||||
*
|
||||
* 3. Reverse the order of #2 -- call MPI_GREQUEST_COMPLETE and then
|
||||
* MPI_REQUEST_FREE.
|
||||
*
|
||||
* So any one of these functions may actually be the one that
|
||||
* de-allocates the back-end request object. Hence, this is perfect
|
||||
* for our reference counting system -- so the call to the gen request
|
||||
* free_fn() is back here in the destructor, whenever the object is
|
||||
* actually freed.
|
||||
*
|
||||
* Hence, the following must occur before a grequest is freed:
|
||||
*
|
||||
* - ompi_grequest_complete() (i.e., GREQUEST_COMPLETE) is invoked
|
||||
* - ompi_grequest_free() is invoked
|
||||
*
|
||||
* Remember that ompi_grequest_free() is invoked by MPI_TEST* and
|
||||
* MPI_WAIT* when the request was previously marked as complete and
|
||||
* TEST* / WAIT* notified the user as such, and this function is also
|
||||
* invoked by REQUEST_FREE). Hence, these two functions will *always*
|
||||
* be invoked, but the order in which they are invoked is up to the
|
||||
* user. So this is a perfect opprotunity for the OBJ_* reference
|
||||
* count system. When we create an ompi_grequest_t in
|
||||
* ompi_grequest_start(), we both OBJ_NEW and OBJ_RETAIN it so that
|
||||
* its reference count goes to 0. Then in ompi_grequest_complete()
|
||||
* and ompi_grequest_free(), we OBJ_RELEASE it. Hence, when both of
|
||||
* them have RELEASEd -- regardless of the order in which the
|
||||
* functions were invoked, then the destructor is invoked and
|
||||
* everything is cleaned up (and we invoked the grequest free_fn).
|
||||
*/
|
||||
static void ompi_grequest_destruct(ompi_grequest_t* greq)
|
||||
{
|
||||
MPI_Fint ierr;
|
||||
|
||||
if (greq->greq_free.c_free != NULL) {
|
||||
if (greq->greq_funcs_are_c) {
|
||||
greq->greq_free.c_free(greq->greq_state);
|
||||
} else {
|
||||
greq->greq_free.f_free(greq->greq_state, &ierr);
|
||||
}
|
||||
}
|
||||
|
||||
OMPI_REQUEST_FINI(&greq->greq_base);
|
||||
}
|
||||
|
||||
@ -74,27 +151,75 @@ int ompi_grequest_start(
|
||||
if(greq == NULL) {
|
||||
return OMPI_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
/* We call RETAIN here specifically to increase the refcount to 2.
|
||||
See comment before the destructor for an explanation. */
|
||||
OBJ_RETAIN(greq);
|
||||
|
||||
greq->greq_base.req_state = OMPI_REQUEST_ACTIVE;
|
||||
greq->greq_state = gstate;
|
||||
greq->greq_query.c_query = gquery_fn;
|
||||
greq->greq_free.c_free = gfree_fn;
|
||||
greq->greq_cancel.c_cancel = gcancel_fn;
|
||||
greq->greq_base.req_status = ompi_status_empty;
|
||||
|
||||
*request = &greq->greq_base;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
int ompi_grequest_complete(ompi_grequest_t* grequest)
|
||||
|
||||
/*
|
||||
* Beware the odd semantics listed in MPI-2:8.2... See the comment in
|
||||
* the grequest destructor.
|
||||
*
|
||||
* First do the normal stuff to complete the request (i.e., call
|
||||
* ompi_request_complete()). Then, if this request object was
|
||||
* previously freed via MPI_REQUEST_FREE, release it.
|
||||
*/
|
||||
int ompi_grequest_complete(ompi_request_t *req)
|
||||
{
|
||||
int rc = OMPI_SUCCESS;
|
||||
OPAL_THREAD_LOCK(&ompi_request_lock);
|
||||
grequest->greq_base.req_complete = true;
|
||||
grequest->greq_base.req_status = ompi_status_empty;
|
||||
if(grequest->greq_query.c_query != NULL)
|
||||
rc = grequest->greq_query.c_query(grequest->greq_state, &grequest->greq_base.req_status);
|
||||
if(ompi_request_waiting)
|
||||
opal_condition_signal(&ompi_request_cond);
|
||||
OPAL_THREAD_UNLOCK(&ompi_request_lock);
|
||||
int rc;
|
||||
|
||||
rc = ompi_request_complete(req);
|
||||
OBJ_RELEASE(req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Grequest queries are invoked in two places:
|
||||
*
|
||||
* 1. MPI_TEST* / MPI_WAIT*, when requests have completed.
|
||||
*
|
||||
* 2. MPI_REQUEST_GET_STATUS, when requests may or may not have
|
||||
* completed.
|
||||
*
|
||||
*/
|
||||
int ompi_grequest_invoke_query(ompi_request_t *request,
|
||||
ompi_status_public_t *status)
|
||||
{
|
||||
int rc;
|
||||
ompi_grequest_t *g = (ompi_grequest_t*) request;
|
||||
|
||||
/* MPI-2:8.2 does not say what to do with the return value from
|
||||
the query function (i.e., the int return value from the C
|
||||
function or the ierr argument from the Fortran function).
|
||||
Making the command decision here to ignore it. If the handler
|
||||
wants to pass an error back, it should set it in the MPI_ERROR
|
||||
field in the status (which is always kept, regardless if the
|
||||
top-level function was invoked with MPI_STATUS[ES]_IGNORE or
|
||||
not). */
|
||||
if (NULL != g->greq_query.c_query) {
|
||||
if (g->greq_funcs_are_c) {
|
||||
rc = g->greq_query.c_query(g->greq_state, status);
|
||||
} else {
|
||||
MPI_Fint ierr;
|
||||
MPI_Fint fstatus[sizeof(MPI_Status) / sizeof(int)];
|
||||
g->greq_query.f_query(g->greq_state, fstatus, &ierr);
|
||||
MPI_Status_f2c(fstatus, status);
|
||||
rc = OMPI_FINT_2_INT(ierr);
|
||||
}
|
||||
}
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -30,9 +31,14 @@ OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_grequest_t);
|
||||
/*
|
||||
* Fortran types for the generalized request functions.
|
||||
*/
|
||||
typedef void (MPI_F_Grequest_query_function)(void* extra_state, MPI_Status* status, int* ierr );
|
||||
typedef void (MPI_F_Grequest_free_function)( void* extra_state, int* err );
|
||||
typedef void (MPI_F_Grequest_cancel_function)( void* extra_state, int* complete, int* ierr );
|
||||
typedef void (MPI_F_Grequest_query_function)(MPI_Aint *extra_state,
|
||||
MPI_Fint *status,
|
||||
MPI_Fint *ierr);
|
||||
typedef void (MPI_F_Grequest_free_function)(MPI_Aint *extra_state,
|
||||
MPI_Fint *ierr);
|
||||
typedef void (MPI_F_Grequest_cancel_function)(MPI_Aint *extra_state,
|
||||
MPI_Flogical *complete,
|
||||
MPI_Fint *ierr);
|
||||
|
||||
typedef union {
|
||||
MPI_Grequest_query_function* c_query;
|
||||
@ -55,6 +61,7 @@ struct ompi_grequest_t {
|
||||
MPI_Grequest_free_fct_t greq_free;
|
||||
MPI_Grequest_cancel_fct_t greq_cancel;
|
||||
void *greq_state;
|
||||
bool greq_funcs_are_c;
|
||||
};
|
||||
typedef struct ompi_grequest_t ompi_grequest_t;
|
||||
|
||||
@ -62,7 +69,6 @@ typedef struct ompi_grequest_t ompi_grequest_t;
|
||||
/*
|
||||
* Start a generalized request.
|
||||
*/
|
||||
|
||||
OMPI_DECLSPEC int ompi_grequest_start(
|
||||
MPI_Grequest_query_function *gquery,
|
||||
MPI_Grequest_free_function *gfree,
|
||||
@ -71,9 +77,15 @@ OMPI_DECLSPEC int ompi_grequest_start(
|
||||
ompi_request_t** request);
|
||||
|
||||
/*
|
||||
* Mark a generalized request as complete.
|
||||
* Complete a generalized request
|
||||
*/
|
||||
OMPI_DECLSPEC int ompi_grequest_complete(ompi_grequest_t*);
|
||||
OMPI_DECLSPEC int ompi_grequest_complete(ompi_request_t *req);
|
||||
|
||||
/*
|
||||
* Invoke the query function on a generalized request
|
||||
*/
|
||||
OMPI_DECLSPEC int ompi_grequest_invoke_query(ompi_request_t *request,
|
||||
ompi_status_public_t *status);
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -19,8 +20,72 @@
|
||||
#include "ompi_config.h"
|
||||
#include "ompi/constants.h"
|
||||
#include "ompi/request/request.h"
|
||||
#include "ompi/request/grequest.h"
|
||||
|
||||
|
||||
int ompi_request_test( ompi_request_t ** rptr,
|
||||
int *completed,
|
||||
ompi_status_public_t * status )
|
||||
{
|
||||
int rc;
|
||||
ompi_request_t *request = *rptr;
|
||||
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
||||
int do_it_once = 0;
|
||||
|
||||
recheck_request_status:
|
||||
#endif
|
||||
opal_atomic_mb();
|
||||
if( request->req_state == OMPI_REQUEST_INACTIVE ) {
|
||||
*completed = true;
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
*status = ompi_status_empty;
|
||||
}
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
if (request->req_complete) {
|
||||
*completed = true;
|
||||
/* For a generalized request, we *have* to call the query_fn
|
||||
if it completes, even if the user provided
|
||||
STATUS_IGNORE. See MPI-2:8.2. */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
int old_error = status->MPI_ERROR;
|
||||
*status = request->req_status;
|
||||
status->MPI_ERROR = old_error;
|
||||
}
|
||||
} else if (MPI_STATUS_IGNORE != status) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
int old_error = status->MPI_ERROR;
|
||||
*status = request->req_status;
|
||||
status->MPI_ERROR = old_error;
|
||||
}
|
||||
if( request->req_persistent ) {
|
||||
request->req_state = OMPI_REQUEST_INACTIVE;
|
||||
return request->req_status.MPI_ERROR;
|
||||
}
|
||||
rc = request->req_status.MPI_ERROR;
|
||||
if (OMPI_SUCCESS != ompi_request_free(rptr)) {
|
||||
return OMPI_ERROR;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
||||
if( 0 == do_it_once ) {
|
||||
/**
|
||||
* If we run the opal_progress then check the status of the request before
|
||||
* leaving. We will call the opal_progress only once per call.
|
||||
*/
|
||||
opal_progress();
|
||||
do_it_once++;
|
||||
goto recheck_request_status;
|
||||
}
|
||||
#endif
|
||||
*completed = false;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
int ompi_request_test_any(
|
||||
size_t count,
|
||||
ompi_request_t ** requests,
|
||||
@ -45,12 +110,26 @@ int ompi_request_test_any(
|
||||
if( request->req_complete ) {
|
||||
*index = i;
|
||||
*completed = true;
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
/* MPI 2:8.2 says that generalized requests always have
|
||||
the query function invoked in TEST* / WAIT*
|
||||
(#@$%@#$%!!! Would have been simpler to call it in
|
||||
GREQUEST_COMPLETE!), even if the user passed in
|
||||
STATUS_IGNORE */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
int old_error = status->MPI_ERROR;
|
||||
*status = request->req_status;
|
||||
status->MPI_ERROR = old_error;
|
||||
}
|
||||
} else if (MPI_STATUS_IGNORE != status) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
int old_error = status->MPI_ERROR;
|
||||
*status = request->req_status;
|
||||
status->MPI_ERROR = old_error;
|
||||
}
|
||||
|
||||
if( request->req_persistent ) {
|
||||
request->req_state = OMPI_REQUEST_INACTIVE;
|
||||
return OMPI_SUCCESS;
|
||||
@ -120,6 +199,9 @@ int ompi_request_test_all(
|
||||
statuses[i] = ompi_status_empty;
|
||||
continue;
|
||||
}
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
statuses[i] = request->req_status;
|
||||
if( request->req_persistent ) {
|
||||
request->req_state = OMPI_REQUEST_INACTIVE;
|
||||
@ -137,6 +219,12 @@ int ompi_request_test_all(
|
||||
if( request->req_state == OMPI_REQUEST_INACTIVE) {
|
||||
continue;
|
||||
}
|
||||
/* See note above: if a generalized request completes, we
|
||||
*have* to call the query fn, even if STATUSES_IGNORE
|
||||
was supplied */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if( request->req_persistent ) {
|
||||
request->req_state = OMPI_REQUEST_INACTIVE;
|
||||
continue;
|
||||
@ -197,6 +285,9 @@ int ompi_request_test_some(
|
||||
request = requests[indices[i]];
|
||||
|
||||
if (MPI_STATUSES_IGNORE != statuses) {
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
statuses[i] = request->req_status;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -19,6 +20,7 @@
|
||||
#include "ompi_config.h"
|
||||
#include "ompi/constants.h"
|
||||
#include "ompi/request/request.h"
|
||||
#include "ompi/request/grequest.h"
|
||||
|
||||
int ompi_request_wait(
|
||||
ompi_request_t ** req_ptr,
|
||||
@ -49,7 +51,12 @@ int ompi_request_wait(
|
||||
finished:
|
||||
#endif
|
||||
|
||||
/* return status */
|
||||
/* return status. If it's a generalized request, we *have* to
|
||||
invoke the query_fn, even if the user procided STATUS_IGNORE.
|
||||
MPI-2:8.2. */
|
||||
if (OMPI_REQUEST_GEN == req->req_type) {
|
||||
ompi_grequest_invoke_query(req, &req->req_status);
|
||||
}
|
||||
if( MPI_STATUS_IGNORE != status ) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
status->MPI_TAG = req->req_status.MPI_TAG;
|
||||
@ -161,7 +168,11 @@ finished:
|
||||
}
|
||||
} else {
|
||||
assert( true == request->req_complete );
|
||||
/* return status */
|
||||
/* Per note above, we have to call gen request query_fn even
|
||||
if STATUS_IGNORE was provided */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
rc = ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
int old_error = status->MPI_ERROR;
|
||||
@ -260,6 +271,9 @@ int ompi_request_wait_all(
|
||||
for( i = 0; i < count; i++, rptr++ ) {
|
||||
request = *rptr;
|
||||
assert( true == request->req_complete );
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if( request->req_state == OMPI_REQUEST_INACTIVE ) {
|
||||
statuses[i] = ompi_status_empty;
|
||||
} else {
|
||||
@ -281,6 +295,11 @@ int ompi_request_wait_all(
|
||||
request = *rptr;
|
||||
|
||||
assert( true == request->req_complete );
|
||||
/* Per note above, we have to call gen request query_fn
|
||||
even if STATUSES_IGNORE was provided */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
rc = ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if( request->req_state == OMPI_REQUEST_INACTIVE ) {
|
||||
rc = ompi_status_empty.MPI_ERROR;
|
||||
} else {
|
||||
@ -407,6 +426,11 @@ finished:
|
||||
request = requests[indices[i]];
|
||||
assert( true == request->req_complete );
|
||||
/* return status */
|
||||
/* Per note above, we have to call gen request query_fn even
|
||||
if STATUS_IGNORE was provided */
|
||||
if (OMPI_REQUEST_GEN == request->req_type) {
|
||||
ompi_grequest_invoke_query(request, &request->req_status);
|
||||
}
|
||||
if (MPI_STATUSES_IGNORE != statuses) {
|
||||
statuses[i] = request->req_status;
|
||||
}
|
||||
|
@ -242,59 +242,9 @@ static inline int ompi_request_free(ompi_request_t** request)
|
||||
* request handle at index set to NULL.
|
||||
*/
|
||||
|
||||
|
||||
static inline int ompi_request_test( ompi_request_t ** rptr,
|
||||
OMPI_DECLSPEC int ompi_request_test( ompi_request_t ** rptr,
|
||||
int *completed,
|
||||
ompi_status_public_t * status )
|
||||
{
|
||||
int rc;
|
||||
ompi_request_t *request = *rptr;
|
||||
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
||||
int do_it_once = 0;
|
||||
|
||||
recheck_request_status:
|
||||
#endif
|
||||
opal_atomic_mb();
|
||||
if( request->req_state == OMPI_REQUEST_INACTIVE ) {
|
||||
*completed = true;
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
*status = ompi_status_empty;
|
||||
}
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
if (request->req_complete) {
|
||||
*completed = true;
|
||||
if (MPI_STATUS_IGNORE != status) {
|
||||
/* See MPI-1.2, sec 3.2.5, p.22 */
|
||||
int old_error = status->MPI_ERROR;
|
||||
*status = request->req_status;
|
||||
status->MPI_ERROR = old_error;
|
||||
}
|
||||
if( request->req_persistent ) {
|
||||
request->req_state = OMPI_REQUEST_INACTIVE;
|
||||
return request->req_status.MPI_ERROR;
|
||||
}
|
||||
rc = request->req_status.MPI_ERROR;
|
||||
if (OMPI_SUCCESS != ompi_request_free(rptr)) {
|
||||
return OMPI_ERROR;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
||||
if( 0 == do_it_once ) {
|
||||
/**
|
||||
* If we run the opal_progress then check the status of the request before
|
||||
* leaving. We will call the opal_progress only once per call.
|
||||
*/
|
||||
opal_progress();
|
||||
do_it_once++;
|
||||
goto recheck_request_status;
|
||||
}
|
||||
#endif
|
||||
*completed = false;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
ompi_status_public_t * status );
|
||||
|
||||
/**
|
||||
* Non-blocking test for request completion.
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user