39dbeeedfb
This commit was SVN r6327.
351 строка
10 KiB
C
351 строка
10 KiB
C
/*
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
* All rights reserved.
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
* All rights reserved.
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
* University of Stuttgart. All rights reserved.
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
* All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
/**
|
|
* @file
|
|
*
|
|
* Top-level description of requests
|
|
*/
|
|
|
|
#ifndef OMPI_REQUEST_H
|
|
#define OMPI_REQUEST_H
|
|
|
|
#include "mpi.h"
|
|
#include "opal/class/opal_list.h"
|
|
#include "class/ompi_pointer_array.h"
|
|
#include "errhandler/errhandler.h"
|
|
#include "opal/runtime/opal_progress.h"
|
|
#include "opal/threads/mutex.h"
|
|
#include "opal/threads/condition.h"
|
|
|
|
#if defined(c_plusplus) || defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
/**
|
|
* Request class
|
|
*/
|
|
OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_request_t);
|
|
|
|
/**
|
|
* Enum inidicating the type of the request
|
|
*/
|
|
typedef enum {
|
|
OMPI_REQUEST_PML, /**< MPI point-to-point request */
|
|
OMPI_REQUEST_IO, /**< MPI-2 IO request */
|
|
OMPI_REQUEST_GEN, /**< MPI-2 generalized request */
|
|
OMPI_REQUEST_NULL, /**< NULL request */
|
|
OMPI_REQUEST_MAX /**< Maximum request type */
|
|
} ompi_request_type_t;
|
|
|
|
/**
|
|
* Enum indicating the state of the request
|
|
*/
|
|
typedef enum {
|
|
/** Indicates that the request should not be progressed */
|
|
OMPI_REQUEST_INVALID,
|
|
/** A defined, but inactive request (i.e., it's valid, but should
|
|
not be progressed) */
|
|
OMPI_REQUEST_INACTIVE,
|
|
/** A valid and progressing request */
|
|
OMPI_REQUEST_ACTIVE,
|
|
/** The request has been cancelled */
|
|
OMPI_REQUEST_CANCELLED
|
|
} ompi_request_state_t;
|
|
|
|
|
|
struct ompi_request_t;
|
|
|
|
/*
|
|
* Required function to free the request and any associated resources.
|
|
*/
|
|
typedef int (*ompi_request_free_fn_t)(struct ompi_request_t** rptr);
|
|
|
|
/*
|
|
* Optional function to cancel a pending request.
|
|
*/
|
|
typedef int (*ompi_request_cancel_fn_t)(struct ompi_request_t* request, int flag);
|
|
|
|
|
|
/**
|
|
* Main top-level request struct definition
|
|
*/
|
|
struct ompi_request_t {
|
|
opal_list_item_t super; /**< Base type */
|
|
ompi_request_type_t req_type; /**< Enum indicating the type of the request */
|
|
ompi_status_public_t req_status; /**< Completion status */
|
|
volatile bool req_complete; /**< Flag indicating wether request has completed */
|
|
volatile ompi_request_state_t req_state; /**< enum indicate state of the request */
|
|
int req_f_to_c_index; /**< Index in Fortran <-> C translation array */
|
|
ompi_request_free_fn_t req_fini; /**< Called by test/wait */
|
|
ompi_request_free_fn_t req_free; /**< Called by free */
|
|
ompi_request_cancel_fn_t req_cancel; /**< Optional function to cancel the request */
|
|
};
|
|
|
|
/**
|
|
* Convenience typedef
|
|
*/
|
|
typedef struct ompi_request_t ompi_request_t;
|
|
|
|
|
|
/**
|
|
* Initialize a request. This is a macro to avoid function call
|
|
* overhead, since this is typically invoked in the critical
|
|
* performance path (since requests may be re-used, it is possible
|
|
* that we will have to initialize a request multiple times).
|
|
*/
|
|
#define OMPI_REQUEST_INIT(request) \
|
|
do { \
|
|
(request)->req_state = OMPI_REQUEST_INACTIVE; \
|
|
(request)->req_complete = false; \
|
|
(request)->req_f_to_c_index = MPI_UNDEFINED; \
|
|
} while (0);
|
|
|
|
/**
|
|
* Finalize a request. This is a macro to avoid function call
|
|
* overhead, since this is typically invoked in the critical
|
|
* performance path (since requests may be re-used, it is possible
|
|
* that we will have to finalize a request multiple times).
|
|
*
|
|
* When finalizing a request, if MPI_Request_f2c() was previously
|
|
* invoked on that request, then this request was added to the f2c
|
|
* table, and we need to remove it
|
|
*/
|
|
|
|
#define OMPI_REQUEST_FINI(request) \
|
|
do { \
|
|
(request)->req_state = OMPI_REQUEST_INVALID; \
|
|
if (MPI_UNDEFINED != (request)->req_f_to_c_index) { \
|
|
ompi_pointer_array_set_item(&ompi_request_f_to_c_table, \
|
|
(request)->req_f_to_c_index, NULL); \
|
|
(request)->req_f_to_c_index = MPI_UNDEFINED; \
|
|
} \
|
|
} while (0);
|
|
|
|
/**
|
|
* Globals used for tracking requests and request completion.
|
|
*/
|
|
OMPI_DECLSPEC extern ompi_pointer_array_t ompi_request_f_to_c_table;
|
|
OMPI_DECLSPEC extern volatile int ompi_request_waiting;
|
|
OMPI_DECLSPEC extern opal_mutex_t ompi_request_lock;
|
|
OMPI_DECLSPEC extern opal_condition_t ompi_request_cond;
|
|
OMPI_DECLSPEC extern int ompi_request_poll_iterations;
|
|
OMPI_DECLSPEC extern ompi_request_t ompi_request_null;
|
|
OMPI_DECLSPEC extern ompi_status_public_t ompi_status_empty;
|
|
|
|
|
|
/**
|
|
* Initialize the MPI_Request subsystem; invoked during MPI_INIT.
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_init(void);
|
|
|
|
/**
|
|
* Shut down the MPI_Request subsystem; invoked during MPI_FINALIZE.
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_finalize(void);
|
|
|
|
|
|
/**
|
|
* Cancel a pending request.
|
|
*/
|
|
|
|
static inline int ompi_request_cancel(ompi_request_t* request)
|
|
{
|
|
if (request->req_cancel != NULL) {
|
|
return request->req_cancel(request, true);
|
|
}
|
|
return OMPI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
* Signal a request as complete. Note this will
|
|
* wake any thread pending on the request.
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_complete(ompi_request_t* request);
|
|
|
|
/**
|
|
* Free a request.
|
|
*
|
|
* @param request (INOUT) Pointer to request.
|
|
*/
|
|
|
|
static inline int ompi_request_free(ompi_request_t** request)
|
|
{
|
|
return (*request)->req_free(request);
|
|
}
|
|
|
|
/**
|
|
* Non-blocking test for request completion.
|
|
*
|
|
* @param request (IN) Array of requests
|
|
* @param complete (OUT) Flag indicating if index is valid (a request completed).
|
|
* @param status (OUT) Status of completed request.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
* Note that upon completion, the request is freed, and the
|
|
* request handle at index set to NULL.
|
|
*/
|
|
|
|
|
|
static inline int ompi_request_test(
|
|
ompi_request_t ** rptr,
|
|
int *completed,
|
|
ompi_status_public_t * status)
|
|
{
|
|
ompi_request_t *request = *rptr;
|
|
opal_atomic_mb();
|
|
if (request == MPI_REQUEST_NULL ||
|
|
request->req_state == OMPI_REQUEST_INACTIVE) {
|
|
*completed = true;
|
|
if (MPI_STATUS_IGNORE != status) {
|
|
*status = ompi_status_empty;
|
|
}
|
|
return OMPI_SUCCESS;
|
|
}
|
|
else if (request->req_complete) {
|
|
*completed = true;
|
|
if (MPI_STATUS_IGNORE != status) {
|
|
*status = request->req_status;
|
|
}
|
|
return request->req_fini(rptr);
|
|
} else {
|
|
*completed = false;
|
|
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
|
opal_progress();
|
|
#endif
|
|
return OMPI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Non-blocking test for request completion.
|
|
*
|
|
* @param count (IN) Number of requests
|
|
* @param request (IN) Array of requests
|
|
* @param index (OUT) Index of first completed request.
|
|
* @param complete (OUT) Flag indicating if index is valid (a request completed).
|
|
* @param status (OUT) Status of completed request.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
* Note that upon completion, the request is freed, and the
|
|
* request handle at index set to NULL.
|
|
*/
|
|
|
|
int ompi_request_test_any(
|
|
size_t count,
|
|
ompi_request_t ** requests,
|
|
int *index,
|
|
int *completed,
|
|
ompi_status_public_t * status);
|
|
|
|
/**
|
|
* Non-blocking test for request completion.
|
|
*
|
|
* @param count (IN) Number of requests
|
|
* @param requests (IN) Array of requests
|
|
* @param completed (OUT) Flag indicating wether all requests completed.
|
|
* @param statuses (OUT) Array of completion statuses.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
* This routine returns completed==true if all requests have completed.
|
|
* The statuses parameter is only updated if all requests completed. Likewise,
|
|
* the requests array is not modified (no requests freed), unless all requests
|
|
* have completed.
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_test_all(
|
|
size_t count,
|
|
ompi_request_t ** requests,
|
|
int *completed,
|
|
ompi_status_public_t * statuses);
|
|
|
|
|
|
/**
|
|
* Wait (blocking-mode) for one requests to complete.
|
|
*
|
|
* @param request (IN) Pointer to request.
|
|
* @param status (OUT) Status of completed request.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
*/
|
|
|
|
static inline int ompi_request_wait(
|
|
ompi_request_t ** req_ptr,
|
|
ompi_status_public_t * status)
|
|
{
|
|
ompi_request_t *req = *req_ptr;
|
|
if(req->req_complete == false) {
|
|
/* give up and sleep until completion */
|
|
OPAL_THREAD_LOCK(&ompi_request_lock);
|
|
ompi_request_waiting++;
|
|
while (req->req_complete == false) {
|
|
opal_condition_wait(&ompi_request_cond, &ompi_request_lock);
|
|
}
|
|
ompi_request_waiting--;
|
|
OPAL_THREAD_UNLOCK(&ompi_request_lock);
|
|
}
|
|
|
|
/* return status */
|
|
if (MPI_STATUS_IGNORE != status) {
|
|
*status = req->req_status;
|
|
}
|
|
|
|
/* return request to pool */
|
|
return req->req_fini(req_ptr);
|
|
}
|
|
|
|
|
|
/**
|
|
* Wait (blocking-mode) for one of N requests to complete.
|
|
*
|
|
* @param count (IN) Number of requests
|
|
* @param requests (IN) Array of requests
|
|
* @param index (OUT) Index into request array of completed request.
|
|
* @param status (OUT) Status of completed request.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_wait_any(
|
|
size_t count,
|
|
ompi_request_t ** requests,
|
|
int *index,
|
|
ompi_status_public_t * status);
|
|
|
|
/**
|
|
* Wait (blocking-mode) for all of N requests to complete.
|
|
*
|
|
* @param count (IN) Number of requests
|
|
* @param requests (IN) Array of requests
|
|
* @param statuses (OUT) Array of completion statuses.
|
|
* @return OMPI_SUCCESS or failure status.
|
|
*
|
|
*/
|
|
|
|
OMPI_DECLSPEC int ompi_request_wait_all(
|
|
size_t count,
|
|
ompi_request_t ** requests,
|
|
ompi_status_public_t * statuses);
|
|
|
|
|
|
#if defined(c_plusplus) || defined(__cplusplus)
|
|
}
|
|
#endif
|
|
#endif
|
|
|