1
1

Merge one-sided updates to the trunk - written by Brian Barrett and Nathan Hjelmn

cmr=v1.7.5:reviewer=hjelmn:subject=Update one-sided to MPI-3

This commit was SVN r30816.
Этот коммит содержится в:
Ralph Castain 2014-02-25 17:36:43 +00:00
родитель 202bf90287
Коммит 49d938de29
132 изменённых файлов: 13242 добавлений и 8659 удалений

5
RMA_TODO.txt Обычный файл
Просмотреть файл

@ -0,0 +1,5 @@
- Support non-contiguous operations in Portals4 implementation
- Add memory barriers where needed in synchronization primitives of
Portals4 implementation
- Re-implement rdma component

Просмотреть файл

@ -127,6 +127,8 @@ int ompi_attr_create_predefined(void)
OMPI_SUCCESS != (ret = create_win(MPI_WIN_BASE)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_SIZE)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_DISP_UNIT)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_CREATE_FLAVOR)) ||
OMPI_SUCCESS != (ret = create_win(MPI_WIN_MODEL)) ||
#if 0
/* JMS For when we implement IMPI */
OMPI_SUCCESS != (ret = create_comm(IMPI_CLIENT_SIZE, true)) ||
@ -193,6 +195,8 @@ int ompi_attr_free_predefined(void)
OMPI_SUCCESS != (ret = free_win(MPI_WIN_BASE)) ||
OMPI_SUCCESS != (ret = free_win(MPI_WIN_SIZE)) ||
OMPI_SUCCESS != (ret = free_win(MPI_WIN_DISP_UNIT)) ||
OMPI_SUCCESS != (ret = free_win(MPI_WIN_CREATE_FLAVOR)) ||
OMPI_SUCCESS != (ret = free_win(MPI_WIN_MODEL)) ||
#if 0
/* JMS For when we implement IMPI */
OMPI_SUCCESS != (ret = free_comm(IMPI_CLIENT_SIZE)) ||

Просмотреть файл

@ -128,11 +128,7 @@ int main(int argc, char **argv) {
GAP_CHECK("w_f_to_c_index", test_win, w_f_to_c_index, w_keyhash, 1);
GAP_CHECK("error_handler", test_win, error_handler, w_f_to_c_index, 1);
GAP_CHECK("errhandler_type", test_win, errhandler_type, error_handler, 1);
GAP_CHECK("w_disp_unit", test_win, w_disp_unit, errhandler_type, 1);
GAP_CHECK("w_baseptr", test_win, w_baseptr, w_disp_unit, 1);
GAP_CHECK("w_size", test_win, w_size, w_baseptr, 1);
GAP_CHECK("w_mode", test_win, w_mode, w_size, 1);
GAP_CHECK("w_osc_module", test_win, w_osc_module, w_size, 1);
GAP_CHECK("w_osc_module", test_win, w_osc_module, errhandler_type, 1);
/* Test Predefined info sizes */
printf("=============================================\n");

Просмотреть файл

@ -107,6 +107,9 @@ ompi_mpi_errcode_t ompi_t_err_cvar_set_never;
ompi_mpi_errcode_t ompi_t_err_pvar_no_startstop;
ompi_mpi_errcode_t ompi_t_err_pvar_no_write;
ompi_mpi_errcode_t ompi_t_err_pvar_no_atomic;
ompi_mpi_errcode_t ompi_err_rma_range;
ompi_mpi_errcode_t ompi_err_rma_attach;
ompi_mpi_errcode_t ompi_err_rma_flavor;
static void ompi_mpi_errcode_construct(ompi_mpi_errcode_t* errcode);
static void ompi_mpi_errcode_destruct(ompi_mpi_errcode_t* errcode);
@ -202,6 +205,9 @@ int ompi_mpi_errcode_init (void)
CONSTRUCT_ERRCODE( ompi_t_err_pvar_no_startstop, MPI_T_ERR_PVAR_NO_STARTSTOP, "MPI_T_ERR_PVAR_NO_STARTSTOP: variable cannot be started or stopped" );
CONSTRUCT_ERRCODE( ompi_t_err_pvar_no_write, MPI_T_ERR_PVAR_NO_WRITE, "MPI_T_ERR_PVAR_NO_WRITE: variable cannot be written or reset" );
CONSTRUCT_ERRCODE( ompi_t_err_pvar_no_atomic, MPI_T_ERR_PVAR_NO_ATOMIC, "MPI_T_ERR_PVAR_NO_ATOMIC: variable cannot be read and written atomically" );
CONSTRUCT_ERRCODE( ompi_err_rma_range, MPI_ERR_RMA_RANGE, "MPI_ERR_RMA_RANGE: invalid RMA address range" );
CONSTRUCT_ERRCODE( ompi_err_rma_attach, MPI_ERR_RMA_ATTACH, "MPI_ERR_RMA_ATTACH: Could not attach RMA segment" );
CONSTRUCT_ERRCODE( ompi_err_rma_flavor, MPI_ERR_RMA_FLAVOR, "MPI_ERR_RMA_FLAVOR: Invalid type of window" );
/* Per MPI-3 p353:27-32, MPI_LASTUSEDCODE must be >=
MPI_ERR_LASTCODE. So just start it as == MPI_ERR_LASTCODE. */
@ -292,6 +298,9 @@ int ompi_mpi_errcode_finalize(void)
OBJ_DESTRUCT(&ompi_t_err_pvar_no_startstop);
OBJ_DESTRUCT(&ompi_t_err_pvar_no_write);
OBJ_DESTRUCT(&ompi_t_err_pvar_no_atomic);
OBJ_DESTRUCT(&ompi_err_rma_range);
OBJ_DESTRUCT(&ompi_err_rma_attach);
OBJ_DESTRUCT(&ompi_err_rma_flavor);
OBJ_DESTRUCT(&ompi_mpi_errcodes);
return OMPI_SUCCESS;

Просмотреть файл

@ -13,7 +13,7 @@
* Copyright (c) 2008-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2009-2012 Oak Rigde National Laboratory. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2012-2013 Los Alamos Nat Security, LLC. All rights reserved.
* Copyright (c) 2012-2014 Los Alamos Nat Security, LLC. All rights reserved.
* Copyright (c) 2011-2013 INRIA. All rights reserved.
* $COPYRIGHT$
*
@ -488,6 +488,13 @@ typedef int (MPI_Grequest_cancel_function)(void *, int);
#define MPI_LOCK_EXCLUSIVE 1
#define MPI_LOCK_SHARED 2
#define MPI_WIN_FLAVOR_CREATE 1
#define MPI_WIN_FLAVOR_ALLOCATE 2
#define MPI_WIN_FLAVOR_DYNAMIC 3
#define MPI_WIN_FLAVOR_SHARED 4
#define MPI_WIN_UNIFIED 0
#define MPI_WIN_SEPARATE 1
/*
* Predefined attribute keyvals
@ -509,6 +516,8 @@ enum {
MPI_WIN_BASE,
MPI_WIN_SIZE,
MPI_WIN_DISP_UNIT,
MPI_WIN_CREATE_FLAVOR,
MPI_WIN_MODEL,
/* Even though these four are IMPI attributes, they need to be there
for all MPI jobs */
@ -590,10 +599,14 @@ enum {
#define MPI_T_ERR_PVAR_NO_STARTSTOP 65
#define MPI_T_ERR_PVAR_NO_WRITE 66
#define MPI_T_ERR_PVAR_NO_ATOMIC 67
#define MPI_ERR_RMA_RANGE 68
#define MPI_ERR_RMA_ATTACH 69
#define MPI_ERR_RMA_FLAVOR 70
/* Per MPI-3 p349 47, MPI_ERR_LASTCODE must be >= the last predefined
MPI_ERR_<foo> code. So just set it equal to the last code --
MPI_T_ERR_PVAR_NO_ATOMIC, in this case. */
#define MPI_ERR_LASTCODE MPI_T_ERR_PVAR_NO_ATOMIC
MPI_ERR_RMA_FLAVOR, in this case. */
#define MPI_ERR_LASTCODE MPI_ERR_RMA_FLAVOR
#define MPI_ERR_SYSRESOURCE -2
@ -888,6 +901,7 @@ OMPI_DECLSPEC extern struct ompi_predefined_op_t ompi_mpi_op_bxor;
OMPI_DECLSPEC extern struct ompi_predefined_op_t ompi_mpi_op_maxloc;
OMPI_DECLSPEC extern struct ompi_predefined_op_t ompi_mpi_op_minloc;
OMPI_DECLSPEC extern struct ompi_predefined_op_t ompi_mpi_op_replace;
OMPI_DECLSPEC extern struct ompi_predefined_op_t ompi_mpi_op_no_op;
OMPI_DECLSPEC extern struct ompi_predefined_datatype_t ompi_mpi_datatype_null;
@ -1019,6 +1033,7 @@ OMPI_DECLSPEC extern MPI_Fint *MPI_F_STATUSES_IGNORE;
#define MPI_MAXLOC OMPI_PREDEFINED_GLOBAL(MPI_Op, ompi_mpi_op_maxloc)
#define MPI_MINLOC OMPI_PREDEFINED_GLOBAL(MPI_Op, ompi_mpi_op_minloc)
#define MPI_REPLACE OMPI_PREDEFINED_GLOBAL(MPI_Op, ompi_mpi_op_replace)
#define MPI_NO_OP OMPI_PREDEFINED_GLOBAL(MPI_Op, ompi_mpi_op_no_op)
/* C datatypes */
#define MPI_DATATYPE_NULL OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_datatype_null)
@ -1298,6 +1313,9 @@ OMPI_DECLSPEC int MPI_Comm_spawn_multiple(int count, char *array_of_commands[],
OMPI_DECLSPEC int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
OMPI_DECLSPEC int MPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm *newcomm);
OMPI_DECLSPEC int MPI_Comm_test_inter(MPI_Comm comm, int *flag);
OMPI_DECLSPEC int MPI_Compare_and_swap(void *origin_addr, void *compare_addr,
void *result_addr, MPI_Datatype datatype, int target_rank,
MPI_Aint target_disp, MPI_Win win);
OMPI_DECLSPEC int MPI_Dims_create(int nnodes, int ndims, int dims[]);
OMPI_DECLSPEC MPI_Fint MPI_Errhandler_c2f(MPI_Errhandler errhandler);
OMPI_DECLSPEC int MPI_Errhandler_create(MPI_Handler_function *function,
@ -1313,6 +1331,8 @@ OMPI_DECLSPEC int MPI_Error_class(int errorcode, int *errorclass);
OMPI_DECLSPEC int MPI_Error_string(int errorcode, char *string, int *resultlen);
OMPI_DECLSPEC int MPI_Exscan(const void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
OMPI_DECLSPEC int MPI_Fetch_and_op(void *origin_addr, void *result_addr, MPI_Datatype datatype,
int target_rank, MPI_Aint target_disp, MPI_Op op, MPI_Win win);
OMPI_DECLSPEC int MPI_Iexscan(const void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request *request);
#if OMPI_PROVIDE_MPI_FILE_INTERFACE
@ -1428,6 +1448,10 @@ OMPI_DECLSPEC int MPI_Get(void *origin_addr, int origin_count,
MPI_Datatype origin_datatype, int target_rank,
MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win);
OMPI_DECLSPEC int MPI_Get_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win);
OMPI_DECLSPEC int MPI_Get_library_version(char *version, int *resultlen);
OMPI_DECLSPEC int MPI_Get_processor_name(char *name, int *resultlen);
OMPI_DECLSPEC int MPI_Get_version(int *version, int *subversion);
@ -1575,6 +1599,9 @@ OMPI_DECLSPEC int MPI_Put(const void *origin_addr, int origin_count, MPI_Dataty
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win);
OMPI_DECLSPEC int MPI_Query_thread(int *provided);
OMPI_DECLSPEC int MPI_Raccumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int MPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int source,
int tag, MPI_Comm comm, MPI_Request *request);
OMPI_DECLSPEC int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
@ -1603,6 +1630,17 @@ OMPI_DECLSPEC MPI_Request MPI_Request_f2c(MPI_Fint request);
OMPI_DECLSPEC int MPI_Request_free(MPI_Request *request);
OMPI_DECLSPEC int MPI_Request_get_status(MPI_Request request, int *flag,
MPI_Status *status);
OMPI_DECLSPEC int MPI_Rget(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype,
MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int MPI_Rget_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op,
MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int MPI_Rput(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_cout,
MPI_Datatype target_datatype, MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int MPI_Rsend(const void *ibuf, int count, MPI_Datatype datatype, int dest,
int tag, MPI_Comm comm);
OMPI_DECLSPEC int MPI_Rsend_init(const void *buf, int count, MPI_Datatype datatype,
@ -1768,39 +1806,55 @@ OMPI_DECLSPEC int MPI_Wait(MPI_Request *request, MPI_Status *status);
OMPI_DECLSPEC int MPI_Waitsome(int incount, MPI_Request array_of_requests[],
int *outcount, int array_of_indices[],
MPI_Status array_of_statuses[]);
OMPI_DECLSPEC int MPI_Win_allocate(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win);
OMPI_DECLSPEC int MPI_Win_allocate_shared(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win);
OMPI_DECLSPEC int MPI_Win_attach(MPI_Win win, void *base, MPI_Aint size);
OMPI_DECLSPEC MPI_Fint MPI_Win_c2f(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_call_errhandler(MPI_Win win, int errorcode);
OMPI_DECLSPEC int MPI_Win_complete(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_create(void *base, MPI_Aint size, int disp_unit,
MPI_Info info, MPI_Comm comm, MPI_Win *win);
OMPI_DECLSPEC int MPI_Win_create_dynamic(MPI_Info info, MPI_Comm comm, MPI_Win *win);
OMPI_DECLSPEC int MPI_Win_create_errhandler(MPI_Win_errhandler_function *function,
MPI_Errhandler *errhandler);
OMPI_DECLSPEC int MPI_Win_create_keyval(MPI_Win_copy_attr_function *win_copy_attr_fn,
MPI_Win_delete_attr_function *win_delete_attr_fn,
int *win_keyval, void *extra_state);
OMPI_DECLSPEC int MPI_Win_delete_attr(MPI_Win win, int win_keyval);
OMPI_DECLSPEC int MPI_Win_detach(MPI_Win win, void *base);
OMPI_DECLSPEC MPI_Win MPI_Win_f2c(MPI_Fint win);
OMPI_DECLSPEC int MPI_Win_fence(int assert, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_flush(int rank, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_flush_all(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_flush_local(int rank, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_flush_local_all(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_free(MPI_Win *win);
OMPI_DECLSPEC int MPI_Win_free_keyval(int *win_keyval);
OMPI_DECLSPEC int MPI_Win_get_attr(MPI_Win win, int win_keyval,
void *attribute_val, int *flag);
OMPI_DECLSPEC int MPI_Win_get_errhandler(MPI_Win win, MPI_Errhandler *errhandler);
OMPI_DECLSPEC int MPI_Win_get_group(MPI_Win win, MPI_Group *group);
OMPI_DECLSPEC int MPI_Win_get_info(MPI_Win win, MPI_Info *info_used);
OMPI_DECLSPEC int MPI_Win_get_name(MPI_Win win, char *win_name, int *resultlen);
OMPI_DECLSPEC int MPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_lock_all(int assert, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_post(MPI_Group group, int assert, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_set_attr(MPI_Win win, int win_keyval, void *attribute_val);
OMPI_DECLSPEC int MPI_Win_set_errhandler(MPI_Win win, MPI_Errhandler errhandler);
OMPI_DECLSPEC int MPI_Win_set_info(MPI_Win win, MPI_Info info);
OMPI_DECLSPEC int MPI_Win_set_name(MPI_Win win, const char *win_name);
OMPI_DECLSPEC int MPI_Win_shared_query(MPI_Win win, int rank, MPI_Aint *size, int *disp_unit, void *baseptr);
OMPI_DECLSPEC int MPI_Win_start(MPI_Group group, int assert, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_sync(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_test(MPI_Win win, int *flag);
OMPI_DECLSPEC int MPI_Win_unlock(int rank, MPI_Win win);
OMPI_DECLSPEC int MPI_Win_unlock_all(MPI_Win win);
OMPI_DECLSPEC int MPI_Win_wait(MPI_Win win);
OMPI_DECLSPEC double MPI_Wtick(void);
OMPI_DECLSPEC double MPI_Wtime(void);
/*
* Profiling MPI API
*/
@ -1949,6 +2003,9 @@ OMPI_DECLSPEC int PMPI_Comm_spawn_multiple(int count, char *array_of_commands[]
OMPI_DECLSPEC int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
OMPI_DECLSPEC int PMPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm *newcomm);
OMPI_DECLSPEC int PMPI_Comm_test_inter(MPI_Comm comm, int *flag);
OMPI_DECLSPEC int PMPI_Compare_and_swap(void *origin_addr, void *compare_addr,
void *result_addr, MPI_Datatype datatype, int target_rank,
MPI_Aint target_disp, MPI_Win win);
OMPI_DECLSPEC int PMPI_Dims_create(int nnodes, int ndims, int dims[]);
OMPI_DECLSPEC MPI_Fint PMPI_Errhandler_c2f(MPI_Errhandler errhandler);
OMPI_DECLSPEC int PMPI_Errhandler_create(MPI_Handler_function *function,
@ -1964,6 +2021,8 @@ OMPI_DECLSPEC int PMPI_Error_class(int errorcode, int *errorclass);
OMPI_DECLSPEC int PMPI_Error_string(int errorcode, char *string, int *resultlen);
OMPI_DECLSPEC int PMPI_Exscan(const void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Fetch_and_op(void *origin_addr, void *result_addr, MPI_Datatype datatype,
int target_rank, MPI_Aint target_disp, MPI_Op op, MPI_Win win);
OMPI_DECLSPEC int PMPI_Iexscan(const void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request *request);
#if OMPI_PROVIDE_MPI_FILE_INTERFACE
@ -2081,6 +2140,10 @@ OMPI_DECLSPEC int PMPI_Get(void *origin_addr, int origin_count,
MPI_Datatype origin_datatype, int target_rank,
MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win);
OMPI_DECLSPEC int PMPI_Get_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win);
OMPI_DECLSPEC int PMPI_Get_library_version(char *version, int *resultlen);
OMPI_DECLSPEC int PMPI_Get_processor_name(char *name, int *resultlen);
OMPI_DECLSPEC int PMPI_Get_version(int *version, int *subversion);
@ -2228,6 +2291,9 @@ OMPI_DECLSPEC int PMPI_Put(const void *origin_addr, int origin_count, MPI_Datat
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win);
OMPI_DECLSPEC int PMPI_Query_thread(int *provided);
OMPI_DECLSPEC int PMPI_Raccumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int PMPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int source,
int tag, MPI_Comm comm, MPI_Request *request);
OMPI_DECLSPEC int PMPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
@ -2256,6 +2322,17 @@ OMPI_DECLSPEC MPI_Request PMPI_Request_f2c(MPI_Fint request);
OMPI_DECLSPEC int PMPI_Request_free(MPI_Request *request);
OMPI_DECLSPEC int PMPI_Request_get_status(MPI_Request request, int *flag,
MPI_Status *status);
OMPI_DECLSPEC int PMPI_Rget(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype,
MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int PMPI_Rget_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op,
MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int PMPI_Rput(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_cout,
MPI_Datatype target_datatype, MPI_Win win, MPI_Request *request);
OMPI_DECLSPEC int PMPI_Rsend(const void *ibuf, int count, MPI_Datatype datatype, int dest,
int tag, MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Rsend_init(const void *buf, int count, MPI_Datatype datatype,
@ -2421,34 +2498,51 @@ OMPI_DECLSPEC int PMPI_Wait(MPI_Request *request, MPI_Status *status);
OMPI_DECLSPEC int PMPI_Waitsome(int incount, MPI_Request array_of_requests[],
int *outcount, int array_of_indices[],
MPI_Status array_of_statuses[]);
OMPI_DECLSPEC int PMPI_Win_allocate(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win);
OMPI_DECLSPEC int PMPI_Win_allocate_shared(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win);
OMPI_DECLSPEC int PMPI_Win_attach(MPI_Win win, void *base, MPI_Aint size);
OMPI_DECLSPEC MPI_Fint PMPI_Win_c2f(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_call_errhandler(MPI_Win win, int errorcode);
OMPI_DECLSPEC int PMPI_Win_complete(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_create(void *base, MPI_Aint size, int disp_unit,
MPI_Info info, MPI_Comm comm, MPI_Win *win);
OMPI_DECLSPEC int PMPI_Win_create_dynamic(MPI_Info info, MPI_Comm comm, MPI_Win *win);
OMPI_DECLSPEC int PMPI_Win_create_errhandler(MPI_Win_errhandler_function *function,
MPI_Errhandler *errhandler);
OMPI_DECLSPEC int PMPI_Win_create_keyval(MPI_Win_copy_attr_function *win_copy_attr_fn,
MPI_Win_delete_attr_function *win_delete_attr_fn,
int *win_keyval, void *extra_state);
OMPI_DECLSPEC int PMPI_Win_delete_attr(MPI_Win win, int win_keyval);
OMPI_DECLSPEC int PMPI_Win_detach(MPI_Win win, void *base);
OMPI_DECLSPEC MPI_Win PMPI_Win_f2c(MPI_Fint win);
OMPI_DECLSPEC int PMPI_Win_fence(int assert, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_flush(int rank, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_flush_all(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_flush_local(int rank, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_flush_local_all(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_free(MPI_Win *win);
OMPI_DECLSPEC int PMPI_Win_free_keyval(int *win_keyval);
OMPI_DECLSPEC int PMPI_Win_get_attr(MPI_Win win, int win_keyval,
void *attribute_val, int *flag);
OMPI_DECLSPEC int PMPI_Win_get_errhandler(MPI_Win win, MPI_Errhandler *errhandler);
OMPI_DECLSPEC int PMPI_Win_get_group(MPI_Win win, MPI_Group *group);
OMPI_DECLSPEC int PMPI_Win_get_info(MPI_Win win, MPI_Info *info_used);
OMPI_DECLSPEC int PMPI_Win_get_name(MPI_Win win, char *win_name, int *resultlen);
OMPI_DECLSPEC int PMPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_lock_all(int assert, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_post(MPI_Group group, int assert, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_set_attr(MPI_Win win, int win_keyval, void *attribute_val);
OMPI_DECLSPEC int PMPI_Win_set_errhandler(MPI_Win win, MPI_Errhandler errhandler);
OMPI_DECLSPEC int PMPI_Win_set_info(MPI_Win win, MPI_Info info);
OMPI_DECLSPEC int PMPI_Win_set_name(MPI_Win win, const char *win_name);
OMPI_DECLSPEC int PMPI_Win_shared_query(MPI_Win win, int rank, MPI_Aint *size, int *disp_unit, void *baseptr);
OMPI_DECLSPEC int PMPI_Win_start(MPI_Group group, int assert, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_sync(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_test(MPI_Win win, int *flag);
OMPI_DECLSPEC int PMPI_Win_unlock(int rank, MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_unlock_all(MPI_Win win);
OMPI_DECLSPEC int PMPI_Win_wait(MPI_Win win);
OMPI_DECLSPEC double PMPI_Wtick(void);
OMPI_DECLSPEC double PMPI_Wtime(void);

Просмотреть файл

@ -320,7 +320,10 @@ $constants->{MPI_T_ERR_CVAR_SET_NEVER} = 64;
$constants->{MPI_T_ERR_PVAR_NO_STARTSTOP} = 65;
$constants->{MPI_T_ERR_PVAR_NO_WRITE} = 66;
$constants->{MPI_T_ERR_PVAR_NO_ATOMIC} = 67;
$constants->{MPI_ERR_LASTCODE} = $constants->{MPI_T_ERR_PVAR_NO_ATOMIC};
$constants->{MPI_ERR_RMA_RANGE} = 68;
$constants->{MPI_ERR_RMA_ATTACH} = 69;
$constants->{MPI_ERR_RMA_FLAVOR} = 70;
$constants->{MPI_ERR_LASTCODE} = $constants->{MPI_ERR_RMA_FLAVOR};
$constants->{MPI_ERR_SYSRESOURCE} = -2;

Просмотреть файл

@ -227,6 +227,8 @@ enum {
OMPI_OP_BASE_FORTRAN_MINLOC,
/** Corresponds to Fortran MPI_REPLACE */
OMPI_OP_BASE_FORTRAN_REPLACE,
/** Corresponds to Fortran MPI_NO_OP */
OMPI_OP_BASE_FORTRAN_NO_OP,
/** Maximum value */
OMPI_OP_BASE_FORTRAN_OP_MAX

Просмотреть файл

@ -37,8 +37,13 @@ int ompi_osc_base_find_available(bool enable_progress_threads,
bool enable_mpi_threads);
int ompi_osc_base_select(ompi_win_t *win,
void **base,
size_t size,
int disp_unit,
ompi_communicator_t *comm,
ompi_info_t *info,
ompi_communicator_t *comm);
int flavor,
int *model);
int ompi_osc_base_finalize(void);

Просмотреть файл

@ -27,8 +27,13 @@
int
ompi_osc_base_select(ompi_win_t *win,
ompi_info_t *info,
ompi_communicator_t *comm)
void **base,
size_t size,
int disp_unit,
ompi_communicator_t *comm,
ompi_info_t *info,
int flavor,
int *model)
{
opal_list_item_t *item;
ompi_osc_base_component_t *best_component = NULL;
@ -45,7 +50,7 @@ ompi_osc_base_select(ompi_win_t *win,
ompi_osc_base_component_t *component = (ompi_osc_base_component_t*)
((mca_base_component_list_item_t*) item)->cli_component;
priority = component->osc_query(win, info, comm);
priority = component->osc_query(win, base, size, disp_unit, comm, info, flavor);
if (priority < 0) continue;
if (priority > best_priority) {
best_component = component;
@ -55,5 +60,5 @@ ompi_osc_base_select(ompi_win_t *win,
if (NULL == best_component) return OMPI_ERR_NOT_SUPPORTED;
return best_component->osc_select(win, info, comm);
return best_component->osc_select(win, base, size, disp_unit, comm, info, flavor, model);
}

Просмотреть файл

@ -239,3 +239,65 @@ ompi_osc_base_process_op(void *outbuf,
return OMPI_SUCCESS;
}
int
ompi_osc_base_sndrcv_op(void *origin,
int32_t origin_count,
struct ompi_datatype_t *origin_dt,
void *target,
int32_t target_count,
struct ompi_datatype_t *target_dt,
ompi_op_t *op)
{
if (ompi_datatype_is_predefined(origin_dt) && origin_dt == target_dt) {
ompi_op_reduce(op, origin, target, origin_count, origin_dt);
} else {
ompi_osc_base_convertor_t recv_convertor;
opal_convertor_t send_convertor;
struct iovec iov;
uint32_t iov_count = 1;
size_t max_data;
int completed, length;
struct opal_convertor_master_t master = {NULL, 0, 0, 0, {0, }, NULL};
/* initialize send convertor */
OBJ_CONSTRUCT(&send_convertor, opal_convertor_t);
opal_convertor_copy_and_prepare_for_send(ompi_proc_local()->proc_convertor,
&(origin_dt->super), origin_count, origin, 0,
&send_convertor);
/* initialize recv convertor */
OBJ_CONSTRUCT(&recv_convertor, ompi_osc_base_convertor_t);
recv_convertor.op = op;
recv_convertor.datatype = ompi_datatype_get_single_predefined_type_from_args(target_dt);
opal_convertor_copy_and_prepare_for_recv(ompi_proc_local()->proc_convertor,
&(target_dt->super), target_count,
target, 0, &recv_convertor.convertor);
memcpy(&master, recv_convertor.convertor.master, sizeof(struct opal_convertor_master_t));
master.next = recv_convertor.convertor.master;
master.pFunctions = (conversion_fct_t*) &ompi_osc_base_copy_functions;
recv_convertor.convertor.master = &master;
recv_convertor.convertor.fAdvance = opal_unpack_general;
/* copy */
iov.iov_len = length = 64 * 1024;
iov.iov_base = (IOVBASE_TYPE*)malloc( length * sizeof(char) );
completed = 0;
while(0 == completed) {
iov.iov_len = length;
iov_count = 1;
max_data = length;
completed |= opal_convertor_pack( &send_convertor, &iov, &iov_count, &max_data );
completed |= opal_convertor_unpack( &recv_convertor.convertor, &iov, &iov_count, &max_data );
}
free( iov.iov_base );
OBJ_DESTRUCT( &send_convertor );
OBJ_DESTRUCT( &recv_convertor );
}
return OMPI_SUCCESS;
}

Просмотреть файл

@ -117,4 +117,12 @@ OMPI_DECLSPEC int ompi_osc_base_process_op(void *outbuf,
int count,
ompi_op_t *op);
OMPI_DECLSPEC int ompi_osc_base_sndrcv_op(void *origin,
int32_t origin_count,
struct ompi_datatype_t *origin_dt,
void *target,
int32_t target_count,
struct ompi_datatype_t *target_dt,
ompi_op_t *op);
END_C_DECLS

Просмотреть файл

@ -49,7 +49,7 @@ struct ompi_communicator_t;
struct ompi_group_t;
struct ompi_datatype_t;
struct ompi_op_t;
struct ompi_request_t;
/* ******************************************************************** */
@ -111,9 +111,12 @@ typedef int (*ompi_osc_base_component_finalize_fn_t)(void);
* @retval >= 0 The priority of the component for this window
*/
typedef int (*ompi_osc_base_component_query_fn_t)(struct ompi_win_t *win,
void **base,
size_t size,
int disp_unit,
struct ompi_communicator_t *comm,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
int flavor);
/**
* OSC component select
@ -140,9 +143,13 @@ typedef int (*ompi_osc_base_component_query_fn_t)(struct ompi_win_t *win,
* @retval OMPI_ERROR An unspecified error occurred
*/
typedef int (*ompi_osc_base_component_select_fn_t)(struct ompi_win_t *win,
void **base,
size_t size,
int disp_unit,
struct ompi_communicator_t *comm,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
int flavor,
int *model);
/**
* OSC component interface
@ -171,6 +178,11 @@ typedef ompi_osc_base_component_2_0_0_t ompi_osc_base_component_t;
/* ******************************************************************** */
typedef int (*ompi_osc_base_module_win_shared_query_fn_t)(struct ompi_win_t *win, int rank,
size_t *size, int *disp_unit, void *baseptr);
typedef int (*ompi_osc_base_module_win_attach_fn_t)(struct ompi_win_t *win, void *base, size_t size);
typedef int (*ompi_osc_base_module_win_detach_fn_t)(struct ompi_win_t *win, void *base);
/**
* Free resources associated with win
@ -220,6 +232,80 @@ typedef int (*ompi_osc_base_module_accumulate_fn_t)(void *origin_addr,
struct ompi_op_t *op,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_compare_and_swap_fn_t)(void *origin_addr,
void *compare_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_fetch_and_op_fn_t)(void *origin_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_op_t *op,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_get_accumulate_fn_t)(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_rput_fn_t)(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
typedef int (*ompi_osc_base_module_rget_fn_t)(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
typedef int (*ompi_osc_base_module_raccumulate_fn_t)(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
typedef int (*ompi_osc_base_module_rget_accumulate_fn_t)(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
typedef int (*ompi_osc_base_module_fence_fn_t)(int assert, struct ompi_win_t *win);
@ -249,10 +335,26 @@ typedef int (*ompi_osc_base_module_lock_fn_t)(int lock_type,
int assert,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_unlock_fn_t)(int target,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_lock_all_fn_t)(int assert,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_unlock_all_fn_t)(struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_sync_fn_t)(struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_flush_fn_t)(int target,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_flush_all_fn_t)(struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_flush_local_fn_t)(int target,
struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_flush_local_all_fn_t)(struct ompi_win_t *win);
typedef int (*ompi_osc_base_module_set_info_fn_t)(struct ompi_win_t *win, struct ompi_info_t *info);
typedef int (*ompi_osc_base_module_get_info_fn_t)(struct ompi_win_t *win, struct ompi_info_t **info_used);
/* ******************************************************************** */
@ -266,47 +368,58 @@ typedef int (*ompi_osc_base_module_unlock_fn_t)(int target,
* free to create a structure that inherits this one for use as the
* module structure.
*/
struct ompi_osc_base_module_1_0_0_t {
/** Free resources associated with the window */
struct ompi_osc_base_module_3_0_0_t {
ompi_osc_base_module_win_shared_query_fn_t osc_win_shared_query;
ompi_osc_base_module_win_attach_fn_t osc_win_attach;
ompi_osc_base_module_win_detach_fn_t osc_win_detach;
ompi_osc_base_module_free_fn_t osc_free;
/** Implement MPI_PUT */
ompi_osc_base_module_put_fn_t osc_put;
/** Implement MPI_GET */
ompi_osc_base_module_get_fn_t osc_get;
/** Implement MPI_ACCUMULATE */
ompi_osc_base_module_accumulate_fn_t osc_accumulate;
ompi_osc_base_module_compare_and_swap_fn_t osc_compare_and_swap;
ompi_osc_base_module_fetch_and_op_fn_t osc_fetch_and_op;
ompi_osc_base_module_get_accumulate_fn_t osc_get_accumulate;
ompi_osc_base_module_rput_fn_t osc_rput;
ompi_osc_base_module_rget_fn_t osc_rget;
ompi_osc_base_module_raccumulate_fn_t osc_raccumulate;
ompi_osc_base_module_rget_accumulate_fn_t osc_rget_accumulate;
/** Implement MPI_WIN_FENCE */
ompi_osc_base_module_fence_fn_t osc_fence;
/* Implement MPI_WIN_START */
ompi_osc_base_module_start_fn_t osc_start;
/* Implement MPI_WIN_COMPLETE */
ompi_osc_base_module_complete_fn_t osc_complete;
/* Implement MPI_WIN_POST */
ompi_osc_base_module_post_fn_t osc_post;
/* Implement MPI_WIN_WAIT */
ompi_osc_base_module_wait_fn_t osc_wait;
/* Implement MPI_WIN_TEST */
ompi_osc_base_module_test_fn_t osc_test;
/* Implement MPI_WIN_LOCK */
ompi_osc_base_module_lock_fn_t osc_lock;
/* Implement MPI_WIN_UNLOCK */
ompi_osc_base_module_unlock_fn_t osc_unlock;
ompi_osc_base_module_lock_all_fn_t osc_lock_all;
ompi_osc_base_module_unlock_all_fn_t osc_unlock_all;
ompi_osc_base_module_sync_fn_t osc_sync;
ompi_osc_base_module_flush_fn_t osc_flush;
ompi_osc_base_module_flush_all_fn_t osc_flush_all;
ompi_osc_base_module_flush_local_fn_t osc_flush_local;
ompi_osc_base_module_flush_local_all_fn_t osc_flush_local_all;
ompi_osc_base_module_set_info_fn_t osc_set_info;
ompi_osc_base_module_get_info_fn_t osc_get_info;
};
typedef struct ompi_osc_base_module_1_0_0_t ompi_osc_base_module_1_0_0_t;
typedef ompi_osc_base_module_1_0_0_t ompi_osc_base_module_t;
typedef struct ompi_osc_base_module_3_0_0_t ompi_osc_base_module_3_0_0_t;
typedef ompi_osc_base_module_3_0_0_t ompi_osc_base_module_t;
/* ******************************************************************** */
/** Macro for use in components that are of type osc */
#define OMPI_OSC_BASE_VERSION_2_0_0 \
#define OMPI_OSC_BASE_VERSION_3_0_0 \
MCA_BASE_VERSION_2_0_0, \
"osc", 2, 0, 0
"osc", 3, 0, 0
/* ******************************************************************** */

43
ompi/mca/osc/portals4/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,43 @@
#
# Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
EXTRA_DIST =
portals4_sources = \
osc_portals4.h \
osc_portals4_comm.c \
osc_portals4_component.c \
osc_portals4_active_target.c \
osc_portals4_passive_target.c \
osc_portals4_request.c
AM_CPPFLAGS = $(osc_portals4_CPPFLAGS)
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if MCA_BUILD_ompi_osc_portals4_DSO
component_noinst =
component_install = mca_osc_portals4.la
else
component_noinst = libmca_osc_portals4.la
component_install =
endif
mcacomponentdir = $(pkglibdir)
mcacomponent_LTLIBRARIES = $(component_install)
mca_osc_portals4_la_SOURCES = $(portals4_sources)
mca_osc_portals4_la_LIBADD = $(osc_portals4_LIBS)
mca_osc_portals4_la_LDFLAGS = -module -avoid-version $(osc_portals4_LDFLAGS)
noinst_LTLIBRARIES = $(component_noinst)
libmca_osc_portals4_la_SOURCES = $(portals4_sources)
libmca_osc_portals4_la_LIBADD = $(osc_portals4_LIBS)
libmca_osc_portals4_la_LDFLAGS = -module -avoid-version $(osc_portals4_LDFLAGS)

42
ompi/mca/osc/portals4/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,42 @@
# -*- shell-script -*-
#
# Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# MCA_ompi_osc_portals4_POST_CONFIG(will_build)
# ----------------------------------------
# Only require the tag if we're actually going to be built
AC_DEFUN([MCA_ompi_osc_portals4_POST_CONFIG], [
AS_IF([test "$1" = "1"], [OMPI_REQUIRE_ENDPOINT_TAG([PORTALS4])])
])dnl
# MCA_osc_portals4_CONFIG(action-if-can-compile,
# [action-if-cant-compile])
# ------------------------------------------------
AC_DEFUN([MCA_ompi_osc_portals4_CONFIG],[
AC_CONFIG_FILES([ompi/mca/osc/portals4/Makefile])
OMPI_CHECK_PORTALS4([osc_portals4],
[osc_portals4_happy="yes"],
[osc_portals4_happy="no"])
AS_IF([test "$osc_portals4_happy" = "yes"],
[osc_portals4_WRAPPER_EXTRA_LDFLAGS="$osc_portals4_LDFLAGS"
osc_portals4_WRAPPER_EXTRA_LIBS="$osc_portals4_LIBS"
$1],
[$2])
# need to propogate CPPFLAGS to all of OMPI
AS_IF([test "$DIRECT_osc" = "portals4"],
[CPPFLAGS="$CPPFLAGS $osc_portals4_CPPFLAGS"])
# substitute in the things needed to build portals4
AC_SUBST([osc_portals4_CPPFLAGS])
AC_SUBST([osc_portals4_LDFLAGS])
AC_SUBST([osc_portals4_LIBS])
])dnl

338
ompi/mca/osc/portals4/osc_portals4.h Обычный файл
Просмотреть файл

@ -0,0 +1,338 @@
/*
* Copyright (c) 2011-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_PORTALS4_PORTALS4_H
#define OSC_PORTALS4_PORTALS4_H
#include <portals4.h>
#include "ompi/class/ompi_free_list.h"
#include "ompi/group/group.h"
#include "ompi/communicator/communicator.h"
#define OSC_PORTALS4_MB_DATA 0x0000000000000000ULL
#define OSC_PORTALS4_MB_CONTROL 0x1000000000000000ULL
/* Component structure. There is one of these per process, per process lifetime.
*
* Currently, the Portals 4 one-sided implementation only uses a
* matching interface for all communication. There are plans for
* using a non-matching interface for a few windows (they each need
* their own PTE, which is a precious resource). In anticipation of
* that, we initialize the network interfaces and keep them in the
* component structure (for win create), but then also keep a handle
* copy in the window module, so that we can use the right structures
* once we add the non-matching support.
*
* The sizes are kept in the component structure because we can only
* find them during PtlNIInit, and it would be poor to do that for
* every window creation. Again, the window module has a copy of the
* max sizes, but tweaked to match the window configuration (ie,
* there's one atomic size, instead of an ordered and unordered size,
* since we know the ordering constraints during window creation).
*/
struct ompi_osc_portals4_component_t {
ompi_osc_base_component_t super;
ptl_handle_ni_t matching_ni_h;
ptl_handle_eq_t matching_eq_h;
ptl_pt_index_t matching_pt_idx;
ptl_size_t matching_atomic_max;
ptl_size_t matching_fetch_atomic_max;
ptl_size_t matching_atomic_ordered_size;
ompi_free_list_t requests; /* request free list for the r* communication variants */
};
typedef struct ompi_osc_portals4_component_t ompi_osc_portals4_component_t;
OMPI_DECLSPEC extern ompi_osc_portals4_component_t mca_osc_portals4_component;
/* Data about me exposed to remote peers. Used in generalized active
target and passive target synchronization. */
struct ompi_osc_portals4_node_state_t {
volatile int32_t post_count;
volatile int32_t complete_count;
volatile uint64_t lock;
};
typedef struct ompi_osc_portals4_node_state_t ompi_osc_portals4_node_state_t;
#define LOCK_ILLEGAL (0x4000000000000000ULL)
#define LOCK_UNLOCKED (0x0000000000000000ULL)
#define LOCK_EXCLUSIVE (0x0000000100000000ULL)
/* Module structure. There is one of these per window */
struct ompi_osc_portals4_module_t {
ompi_osc_base_module_t super;
void *free_after; /* if non-null, this pointer should be free()ed when window destroyed */
struct ompi_communicator_t *comm; /* communicator which backs this window (unique to this window) */
int disp_unit; /* if -1, have to look at disp_units */
int *disp_units; /* array (possibly NULL!) of displacement units, per peer */
ptl_handle_ni_t ni_h; /* network interface used by this window */
ptl_pt_index_t pt_idx; /* portal table index used by this window (this will be same across window) */
ptl_handle_ct_t ct_h; /* Counting event handle used for completion in this window */
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
ptl_handle_md_t *md_h; /* memory descriptor describing all of memory used by this window */
ptl_handle_md_t *req_md_h; /* memory descriptor with event completion used by this window */
#else
ptl_handle_md_t md_h[1]; /* memory descriptor describing all of memory used by this window */
ptl_handle_md_t req_md_h[1]; /* memory descriptor with event completion used by this window */
#endif
ptl_handle_me_t data_me_h; /* data match list entry (MB are CID | OSC_PORTALS4_MB_DATA) */
ptl_handle_me_t control_me_h; /* match list entry for control data (node_state_t). Match bits are (CID | OSC_PORTALS4_MB_CONTROL). */
int64_t opcount;
ptl_match_bits_t match_bits; /* match bits for module. Same as cid for comm in most cases. */
ptl_size_t atomic_max; /* max size of atomic messages. Will guarantee ordering IF ordering requested */
ptl_size_t fetch_atomic_max; /* max size of fetchatomic messages. Will guarantee ordering IF ordering requested */
/* variable containing specified value. Needed for atomic
increments so they can be non-blocking */
int32_t zero;
int32_t one;
ompi_group_t *start_group;
ompi_group_t *post_group;
opal_list_t outstanding_locks;
/* things that are remotely accessible */
ompi_osc_portals4_node_state_t state;
};
typedef struct ompi_osc_portals4_module_t ompi_osc_portals4_module_t;
static inline size_t
get_displacement(ompi_osc_portals4_module_t *module,
int target)
{
if (-1 == module->disp_unit) {
return module->disp_units[target];
} else {
return module->disp_unit;
}
}
/*
* See note in ompi/mtl/portals4/mtl_portals4.h for how we deal with
* platforms that don't allow us to crate an MD that covers all of
* memory.
*/
static inline void
ompi_osc_portals4_get_md(const void *ptr, const ptl_handle_md_t *array,
ptl_handle_md_t *md_h, void **base_ptr)
{
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
int mask = (1ULL << (OMPI_PORTALS4_MAX_VA_SIZE - OMPI_PORTALS4_MAX_MD_SIZE + 1)) - 1;
int which = (((uintptr_t) ptr) >> (OMPI_PORTALS4_MAX_MD_SIZE - 1)) & mask;
*md_h = array[which];
*base_ptr = (void*) (which * (1ULL << (OMPI_PORTALS4_MAX_MD_SIZE - 1)));
#else
*md_h = array[0];
*base_ptr = 0;
#endif
}
static inline int
ompi_osc_portals4_get_num_mds(void)
{
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
return (1 << (OMPI_PORTALS4_MAX_VA_SIZE - OMPI_PORTALS4_MAX_MD_SIZE + 1));
#else
return 1;
#endif
}
int ompi_osc_portals4_attach(struct ompi_win_t *win, void *base, size_t len);
int ompi_osc_portals4_detach(struct ompi_win_t *win, void *base);
int ompi_osc_portals4_free(struct ompi_win_t *win);
int ompi_osc_portals4_put(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_portals4_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_portals4_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_portals4_compare_and_swap(void *origin_addr,
void *compare_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_win_t *win);
int ompi_osc_portals4_fetch_and_op(void *origin_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_portals4_get_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_portals4_rput(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_portals4_rget(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_portals4_raccumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_portals4_rget_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_portals4_fence(int assert, struct ompi_win_t *win);
int ompi_osc_portals4_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_portals4_complete(struct ompi_win_t *win);
int ompi_osc_portals4_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_portals4_wait(struct ompi_win_t *win);
int ompi_osc_portals4_test(struct ompi_win_t *win,
int *flag);
int ompi_osc_portals4_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win);
int ompi_osc_portals4_unlock(int target,
struct ompi_win_t *win);
int ompi_osc_portals4_lock_all(int assert,
struct ompi_win_t *win);
int ompi_osc_portals4_unlock_all(struct ompi_win_t *win);
int ompi_osc_portals4_sync(struct ompi_win_t *win);
int ompi_osc_portals4_flush(int target,
struct ompi_win_t *win);
int ompi_osc_portals4_flush_all(struct ompi_win_t *win);
int ompi_osc_portals4_flush_local(int target,
struct ompi_win_t *win);
int ompi_osc_portals4_flush_local_all(struct ompi_win_t *win);
int ompi_osc_portals4_set_info(struct ompi_win_t *win, struct ompi_info_t *info);
int ompi_osc_portals4_get_info(struct ompi_win_t *win, struct ompi_info_t **info_used);
static inline int
ompi_osc_portals4_complete_all(ompi_osc_portals4_module_t *module)
{
int ret;
ptl_ct_event_t event;
ret = PtlCTWait(module->ct_h, module->opcount, &event);
if (PTL_OK != ret || 0 != event.failure) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: flush_all ct failure: ret=%d, failure=%d\n",
__FILE__, __LINE__, ret, (int) event.failure);
event.success = event.failure = 0;
PtlCTSet(module->ct_h, event);
module->opcount = 0;
}
assert(event.success == (size_t) module->opcount);
PtlAtomicSync();
return ret;
}
static inline ptl_process_t
ompi_osc_portals4_get_peer(ompi_osc_portals4_module_t *module, int rank)
{
ompi_proc_t *proc = ompi_comm_peer_lookup(module->comm, rank);
return *((ptl_process_t*) proc->proc_endpoints[OMPI_PROC_ENDPOINT_TAG_PORTALS4]);
}
static inline ptl_process_t
ompi_osc_portals4_get_peer_group(struct ompi_group_t *group, int rank)
{
ompi_proc_t *proc = ompi_group_get_proc_ptr(group, rank);
return *((ptl_process_t*) proc->proc_endpoints[OMPI_PROC_ENDPOINT_TAG_PORTALS4]);
}
#endif

Просмотреть файл

@ -0,0 +1,192 @@
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_portals4.h"
#include "ompi/mca/mtl/portals4/mtl_portals4_endpoint.h"
int
ompi_osc_portals4_fence(int assert, struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
int comm_ret, ret;
comm_ret = ompi_osc_portals4_complete_all(module);
ret = module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
return (OMPI_SUCCESS == comm_ret) ? ret : comm_ret;
}
int
ompi_osc_portals4_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
if (0 == (assert & MPI_MODE_NOCHECK)) {
int size;
OBJ_RETAIN(group);
module->start_group = group;
size = ompi_group_size(module->start_group);
while (module->state.post_count != size) opal_progress();
} else {
module->start_group = NULL;
}
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_complete(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
int ret, i, size;
ptl_handle_md_t md_h;
void *base;
ret = ompi_osc_portals4_complete_all(module);
if (ret != OMPI_SUCCESS) return ret;
if (NULL != module->start_group) {
module->state.post_count = 0;
PtlAtomicSync();
ompi_osc_portals4_get_md(&module->one, module->md_h, &md_h, &base);
size = ompi_group_size(module->start_group);
for (i = 0 ; i < size ; ++i) {
ret = PtlAtomic(md_h,
(ptl_size_t) ((char*) &module->one - (char*) base),
sizeof(module->one),
PTL_ACK_REQ,
ompi_osc_portals4_get_peer_group(module->start_group, i),
module->pt_idx,
module->match_bits | OSC_PORTALS4_MB_CONTROL,
offsetof(ompi_osc_portals4_node_state_t, complete_count),
NULL,
0,
PTL_SUM,
PTL_INT32_T);
if (ret != OMPI_SUCCESS) return ret;
OPAL_THREAD_ADD64(&module->opcount, 1);
}
ret = ompi_osc_portals4_complete_all(module);
if (ret != OMPI_SUCCESS) return ret;
OBJ_RELEASE(module->start_group);
module->start_group = NULL;
}
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
int ret, i, size;
ptl_handle_md_t md_h;
void *base;
if (0 == (assert & MPI_MODE_NOCHECK)) {
OBJ_RETAIN(group);
module->post_group = group;
module->state.complete_count = 0;
PtlAtomicSync();
ompi_osc_portals4_get_md(&module->one, module->md_h, &md_h, &base);
size = ompi_group_size(module->post_group);
for (i = 0 ; i < size ; ++i) {
ret = PtlAtomic(md_h,
(ptl_size_t) ((char*) &module->one - (char*) base),
sizeof(module->one),
PTL_ACK_REQ,
ompi_osc_portals4_get_peer_group(module->post_group, i),
module->pt_idx,
module->match_bits | OSC_PORTALS4_MB_CONTROL,
offsetof(ompi_osc_portals4_node_state_t, post_count),
NULL,
0,
PTL_SUM,
PTL_INT32_T);
if (ret != OMPI_SUCCESS) return ret;
OPAL_THREAD_ADD64(&module->opcount, 1);
}
} else {
module->post_group = NULL;
}
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_wait(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
if (NULL != module->post_group) {
int size = ompi_group_size(module->post_group);
while (module->state.complete_count != size) opal_progress();
OBJ_RELEASE(module->post_group);
module->post_group = NULL;
}
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_test(struct ompi_win_t *win,
int *flag)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
if (NULL != module->post_group) {
int size = ompi_group_size(module->post_group);
if (module->state.complete_count == size) {
OBJ_RELEASE(module->post_group);
module->post_group = NULL;
*flag = 1;
}
} else {
*flag = 0;
}
return OMPI_SUCCESS;
}

1152
ompi/mca/osc/portals4/osc_portals4_comm.c Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,716 @@
/*
* Copyright (c) 2011-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "ompi/request/request.h"
#include "ompi/class/ompi_free_list.h"
#include "osc_portals4.h"
#include "osc_portals4_request.h"
static int component_open(void);
static int component_register(void);
static int component_init(bool enable_progress_threads, bool enable_mpi_threads);
static int component_finalize(void);
static int component_query(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor);
static int component_select(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor, int *model);
ompi_osc_portals4_component_t mca_osc_portals4_component = {
{ /* ompi_osc_base_component_t */
{ /* ompi_base_component_t */
OMPI_OSC_BASE_VERSION_3_0_0,
"portals4",
OMPI_MAJOR_VERSION, /* MCA component major version */
OMPI_MINOR_VERSION, /* MCA component minor version */
OMPI_RELEASE_VERSION, /* MCA component release version */
component_open,
NULL,
NULL,
component_register
},
{ /* mca_base_component_data */
/* The component is not checkpoint ready */
MCA_BASE_METADATA_PARAM_NONE
},
component_init,
component_query,
component_select,
component_finalize
}
};
ompi_osc_portals4_module_t ompi_osc_portals4_module_template = {
{
NULL, /* shared_query */
ompi_osc_portals4_attach,
ompi_osc_portals4_detach,
ompi_osc_portals4_free,
ompi_osc_portals4_put,
ompi_osc_portals4_get,
ompi_osc_portals4_accumulate,
ompi_osc_portals4_compare_and_swap,
ompi_osc_portals4_fetch_and_op,
ompi_osc_portals4_get_accumulate,
ompi_osc_portals4_rput,
ompi_osc_portals4_rget,
ompi_osc_portals4_raccumulate,
ompi_osc_portals4_rget_accumulate,
ompi_osc_portals4_fence,
ompi_osc_portals4_start,
ompi_osc_portals4_complete,
ompi_osc_portals4_post,
ompi_osc_portals4_wait,
ompi_osc_portals4_test,
ompi_osc_portals4_lock,
ompi_osc_portals4_unlock,
ompi_osc_portals4_lock_all,
ompi_osc_portals4_unlock_all,
ompi_osc_portals4_sync,
ompi_osc_portals4_flush,
ompi_osc_portals4_flush_all,
ompi_osc_portals4_flush_local,
ompi_osc_portals4_flush_local_all,
ompi_osc_portals4_set_info,
ompi_osc_portals4_get_info
}
};
/* look up parameters for configuring this window. The code first
looks in the info structure passed by the user, then through mca
parameters. */
static bool
check_config_value_bool(char *key, ompi_info_t *info)
{
char *value_string;
int value_len, ret, flag, param;
const bool *flag_value;
bool result;
ret = ompi_info_get_valuelen(info, key, &value_len, &flag);
if (OMPI_SUCCESS != ret) goto info_not_found;
if (flag == 0) goto info_not_found;
value_len++;
value_string = (char*)malloc(sizeof(char) * value_len + 1); /* Should malloc 1 char for NUL-termination */
if (NULL == value_string) goto info_not_found;
ret = ompi_info_get(info, key, value_len, value_string, &flag);
if (OMPI_SUCCESS != ret) {
free(value_string);
goto info_not_found;
}
assert(flag != 0);
ret = ompi_info_value_to_bool(value_string, &result);
free(value_string);
if (OMPI_SUCCESS != ret) goto info_not_found;
return result;
info_not_found:
param = mca_base_var_find("ompi", "osc", "portals4", key);
if (0 > param) return false;
ret = mca_base_var_get_value(param, &flag_value, NULL, NULL);
if (OMPI_SUCCESS != ret) return false;
return flag_value[0];
}
static bool
check_config_value_equal(char *key, ompi_info_t *info, char *value)
{
char *value_string;
int value_len, ret, flag, param;
const bool *flag_value;
bool result = false;
ret = ompi_info_get_valuelen(info, key, &value_len, &flag);
if (OMPI_SUCCESS != ret) goto info_not_found;
if (flag == 0) goto info_not_found;
value_len++;
value_string = (char*)malloc(sizeof(char) * value_len + 1); /* Should malloc 1 char for NUL-termination */
if (NULL == value_string) goto info_not_found;
ret = ompi_info_get(info, key, value_len, value_string, &flag);
if (OMPI_SUCCESS != ret) {
free(value_string);
goto info_not_found;
}
assert(flag != 0);
if (0 == strcmp(value_string, value)) result = true;
free(value_string);
return result;
info_not_found:
param = mca_base_var_find("ompi", "osc", "portals4", key);
if (0 > param) return false;
ret = mca_base_var_get_value(param, &flag_value, NULL, NULL);
if (OMPI_SUCCESS != ret) return false;
if (0 == strcmp(value_string, value)) result = true;
return result;
}
static int
progress_callback(void)
{
int ret, count = 0;
ptl_event_t ev;
ompi_osc_portals4_request_t *req;
int32_t ops;
while (true) {
ret = PtlEQGet(mca_osc_portals4_component.matching_eq_h, &ev);
if (PTL_OK == ret) {
goto process;
} else if (PTL_EQ_DROPPED == ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlEQGet reported dropped event",
__FILE__, __LINE__);
goto process;
} else if (PTL_EQ_EMPTY) {
return 0;
} else {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlEQGet failed: %d\n",
__FILE__, __LINE__, ret);
return 0;
}
process:
if (ev.ni_fail_type != PTL_OK) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: event failure: %d %d",
__FILE__, __LINE__, ev.type, ev.ni_fail_type);
return 0;
}
count++;
if (NULL != ev.user_ptr) {
/* can't disable send events, but they don't count in ops */
if (ev.type == PTL_EVENT_SEND) continue;
req = (ompi_osc_portals4_request_t*) ev.user_ptr;
opal_atomic_add_size_t(&req->super.req_status._ucount, ev.mlength);
ops = opal_atomic_add_32(&req->ops_committed, 1);
if (ops == req->ops_expected) {
OPAL_THREAD_LOCK(&ompi_request_lock);
ompi_request_complete(&req->super, true);
OPAL_THREAD_UNLOCK(&ompi_request_lock);
}
}
}
return count;
}
static int
component_open(void)
{
return OMPI_SUCCESS;
}
static int
component_register(void)
{
bool ompi_osc_portals4_no_locks = false;
(void) mca_base_component_var_register(&mca_osc_portals4_component.super.osc_version,
"no_locks",
"Enable optimizations available only if MPI_LOCK is "
"not used. "
"Info key of same name overrides this value.",
MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
OPAL_INFO_LVL_9,
MCA_BASE_VAR_SCOPE_READONLY,
&ompi_osc_portals4_no_locks);
return OMPI_SUCCESS;
}
static int
component_init(bool enable_progress_threads, bool enable_mpi_threads)
{
int ret;
ptl_ni_limits_t actual;
ret = PtlInit();
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlInit failed: %d\n",
__FILE__, __LINE__, ret);
return OMPI_ERROR;
}
ret = PtlNIInit(PTL_IFACE_DEFAULT,
PTL_NI_PHYSICAL | PTL_NI_MATCHING,
PTL_PID_ANY,
NULL,
&actual,
&mca_osc_portals4_component.matching_ni_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlNIInit failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
/* BWB: FIX ME: Need to make sure our ID matches with the MTL... */
mca_osc_portals4_component.matching_atomic_max = actual.max_atomic_size;
mca_osc_portals4_component.matching_fetch_atomic_max = actual.max_fetch_atomic_size;
mca_osc_portals4_component.matching_atomic_ordered_size =
MAX(actual.max_waw_ordered_size, actual.max_war_ordered_size);
ret = PtlEQAlloc(mca_osc_portals4_component.matching_ni_h,
4096,
&mca_osc_portals4_component.matching_eq_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlEQAlloc failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
ret = PtlPTAlloc(mca_osc_portals4_component.matching_ni_h,
0,
mca_osc_portals4_component.matching_eq_h,
4,
&mca_osc_portals4_component.matching_pt_idx);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlPTAlloc failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
OBJ_CONSTRUCT(&mca_osc_portals4_component.requests, ompi_free_list_t);
ret = ompi_free_list_init(&mca_osc_portals4_component.requests,
sizeof(ompi_osc_portals4_request_t),
OBJ_CLASS(ompi_osc_portals4_request_t),
8,
0,
8,
NULL);
if (OMPI_SUCCESS != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: ompi_free_list_init failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
ret = opal_progress_register(progress_callback);
if (OMPI_SUCCESS != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: opal_progress_register failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
return OMPI_SUCCESS;
}
static int
component_finalize(void)
{
PtlNIFini(mca_osc_portals4_component.matching_ni_h);
return OMPI_SUCCESS;
}
static int
component_query(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor)
{
if (MPI_WIN_FLAVOR_SHARED == flavor) return -1;
return 20;
}
static int
component_select(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor, int *model)
{
ompi_osc_portals4_module_t *module = NULL;
int ret = OMPI_ERROR;
int tmp;
ptl_md_t md;
ptl_me_t me;
char *name;
if (MPI_WIN_FLAVOR_SHARED == flavor) return OMPI_ERR_NOT_SUPPORTED;
/* create module structure */
module = (ompi_osc_portals4_module_t*)
calloc(1, sizeof(ompi_osc_portals4_module_t));
if (NULL == module) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
/* fill in the function pointer part */
memcpy(module, &ompi_osc_portals4_module_template,
sizeof(ompi_osc_base_module_t));
/* fill in our part */
if (MPI_WIN_FLAVOR_ALLOCATE == flavor) {
module->free_after = *base = malloc(size);
if (NULL == *base) goto error;
} else {
module->free_after = NULL;
}
ret = ompi_comm_dup(comm, &module->comm);
if (OMPI_SUCCESS != ret) goto error;
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"portals4 component creating window with id %d",
ompi_comm_get_cid(module->comm));
asprintf(&name, "portals4 window %d", ompi_comm_get_cid(module->comm));
ompi_win_set_name(win, name);
free(name);
/* share everyone's displacement units. Only do an allgather if
strictly necessary, since it requires O(p) state. */
tmp = disp_unit;
ret = module->comm->c_coll.coll_bcast(&tmp, 1, MPI_INT, 0,
module->comm,
module->comm->c_coll.coll_bcast_module);
if (OMPI_SUCCESS != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: MPI_Bcast failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
tmp = (tmp == disp_unit) ? 1 : 0;
ret = module->comm->c_coll.coll_allreduce(MPI_IN_PLACE, &tmp, 1, MPI_INT, MPI_LAND,
module->comm, module->comm->c_coll.coll_allreduce_module);
if (OMPI_SUCCESS != ret) goto error;
if (tmp == 1) {
module->disp_unit = disp_unit;
module->disp_units = NULL;
} else {
module->disp_unit = -1;
module->disp_units = malloc(sizeof(int) * ompi_comm_size(module->comm));
ret = module->comm->c_coll.coll_allgather(&disp_unit, 1, MPI_INT,
module->disp_units, 1, MPI_INT,
module->comm,
module->comm->c_coll.coll_allgather_module);
if (OMPI_SUCCESS != ret) goto error;
}
module->ni_h = mca_osc_portals4_component.matching_ni_h;
module->pt_idx = mca_osc_portals4_component.matching_pt_idx;
ret = PtlCTAlloc(module->ni_h, &(module->ct_h));
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlCTAlloc failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
{
int i;
int num_mds = ompi_mtl_portals4_get_num_mds();
ptl_size_t size = 1ULL << OMPI_PORTALS4_MAX_MD_SIZE;
ptl_size_t offset_unit = (1ULL << OMPI_PORTALS4_MAX_MD_SIZE) / 2;
module->md_h = malloc(sizeof(ptl_handle_md_t) * num_mds);
if (NULL == module->md_h) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto error;
}
for (i = 0 ; i < num_mds ; ++i) {
module->md_h[i] = PTL_INVALID_HANDLE;
}
module->req_md_h = malloc(sizeof(ptl_handle_md_t) * num_mds);
if (NULL == module->req_md_h) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto error;
}
for (i = 0 ; i < num_mds ; ++i) {
module->req_md_h[i] = PTL_INVALID_HANDLE;
}
for (i = 0 ; i < num_mds ; ++i) {
md.start = (char*) (offset_unit * i);
md.length = (i - 1 == num_mds) ? size / 2 : size;
md.options = PTL_MD_EVENT_SUCCESS_DISABLE | PTL_MD_EVENT_CT_REPLY | PTL_MD_EVENT_CT_ACK;
md.eq_handle = mca_osc_portals4_component.matching_eq_h;
md.ct_handle = module->ct_h;
ret = PtlMDBind(module->ni_h, &md, &module->md_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMDBind failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
md.options = PTL_MD_EVENT_CT_REPLY | PTL_MD_EVENT_CT_ACK;
md.eq_handle = mca_osc_portals4_component.matching_eq_h;
md.ct_handle = module->ct_h;
ret = PtlMDBind(module->ni_h, &md, &module->req_md_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMDBind failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
}
#else
md.start = 0;
md.length = PTL_SIZE_MAX;
md.options = PTL_MD_EVENT_SUCCESS_DISABLE | PTL_MD_EVENT_CT_REPLY | PTL_MD_EVENT_CT_ACK;
md.eq_handle = mca_osc_portals4_component.matching_eq_h;
md.ct_handle = module->ct_h;
ret = PtlMDBind(module->ni_h, &md, &module->md_h[0]);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMDBind failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
md.start = 0;
md.length = PTL_SIZE_MAX;
md.options = PTL_MD_EVENT_CT_REPLY | PTL_MD_EVENT_CT_ACK;
md.eq_handle = mca_osc_portals4_component.matching_eq_h;
md.ct_handle = module->ct_h;
ret = PtlMDBind(module->ni_h, &md, &module->req_md_h[0]);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMDBind failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
#endif
if (MPI_WIN_FLAVOR_DYNAMIC == flavor) {
me.start = 0;
me.length = SIZE_MAX;
} else {
me.start = *base;
me.length = size;
}
me.ct_handle = PTL_CT_NONE;
me.uid = PTL_UID_ANY;
me.options = PTL_ME_OP_PUT | PTL_ME_OP_GET | PTL_ME_NO_TRUNCATE | PTL_ME_EVENT_SUCCESS_DISABLE;
me.match_id.phys.nid = PTL_NID_ANY;
me.match_id.phys.pid = PTL_PID_ANY;
me.match_bits = module->comm->c_contextid;
me.ignore_bits = 0;
ret = PtlMEAppend(module->ni_h,
module->pt_idx,
&me,
PTL_PRIORITY_LIST,
NULL,
&module->data_me_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMEAppend failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
me.start = &module->state;
me.length = sizeof(module->state);
me.ct_handle = PTL_CT_NONE;
me.uid = PTL_UID_ANY;
me.options = PTL_ME_OP_PUT | PTL_ME_OP_GET | PTL_ME_NO_TRUNCATE | PTL_ME_EVENT_SUCCESS_DISABLE;
me.match_id.phys.nid = PTL_NID_ANY;
me.match_id.phys.pid = PTL_PID_ANY;
me.match_bits = module->comm->c_contextid | OSC_PORTALS4_MB_CONTROL;
me.ignore_bits = 0;
ret = PtlMEAppend(module->ni_h,
module->pt_idx,
&me,
PTL_PRIORITY_LIST,
NULL,
&module->control_me_h);
if (PTL_OK != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: PtlMEAppend failed: %d\n",
__FILE__, __LINE__, ret);
goto error;
}
module->opcount = 0;
module->match_bits = module->comm->c_contextid;
module->atomic_max = (check_config_value_equal("accumulate_ordering", info, "none")) ?
mca_osc_portals4_component.matching_atomic_max :
MIN(mca_osc_portals4_component.matching_atomic_max,
mca_osc_portals4_component.matching_atomic_ordered_size);
module->fetch_atomic_max = (check_config_value_equal("accumulate_ordering", info, "none")) ?
mca_osc_portals4_component.matching_fetch_atomic_max :
MIN(mca_osc_portals4_component.matching_fetch_atomic_max,
mca_osc_portals4_component.matching_atomic_ordered_size);
module->zero = 0;
module->one = 1;
module->start_group = NULL;
module->post_group = NULL;
module->state.post_count = 0;
module->state.complete_count = 0;
if (check_config_value_bool("no_locks", info)) {
module->state.lock = LOCK_ILLEGAL;
} else {
module->state.lock = LOCK_UNLOCKED;
}
OBJ_CONSTRUCT(&module->outstanding_locks, opal_list_t);
#if OPAL_ASSEMBLY_ARCH == OMPI_AMD64 || OPAL_ASSEMBLY_ARCH == IA32
*model = MPI_WIN_UNIFIED;
#else
*model = MPI_WIN_SEPARATE;
#endif
win->w_osc_module = &module->super;
PtlAtomicSync();
/* Make sure that everyone's ready to receive. */
module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
return OMPI_SUCCESS;
error:
/* BWB: FIX ME: This is all wrong... */
if (0 != module->ct_h) PtlCTFree(module->ct_h);
if (0 != module->data_me_h) PtlMEUnlink(module->data_me_h);
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
/* BWB: FIX ME */
#else
if (0 != module->req_md_h) PtlMDRelease(module->req_md_h[0]);
if (0 != module->md_h) PtlMDRelease(module->md_h[0]);
#endif
if (NULL != module->comm) ompi_comm_free(&module->comm);
if (NULL != module) free(module);
return ret;
}
int
ompi_osc_portals4_attach(struct ompi_win_t *win, void *base, size_t len)
{
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_detach(struct ompi_win_t *win, void *base)
{
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_free(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
int ret = OMPI_SUCCESS;
/* synchronize */
module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
/* cleanup */
PtlMEUnlink(module->data_me_h);
#if OMPI_PORTALS4_MAX_MD_SIZE < OMPI_PORTALS4_MAX_VA_SIZE
/* BWB: FIX ME */
#else
PtlMDRelease(module->md_h[0]);
PtlMDRelease(module->req_md_h[0]);
#endif
PtlCTFree(module->ct_h);
if (NULL != module->disp_units) free(module->disp_units);
ompi_comm_free(&module->comm);
if (NULL != module->free_after) free(module->free_after);
if (!opal_list_is_empty(&module->outstanding_locks)) {
ret = MPI_ERR_RMA_SYNC;
}
OBJ_DESTRUCT(&module->outstanding_locks);
free(module);
return ret;
}
int
ompi_osc_portals4_set_info(struct ompi_win_t *win, struct ompi_info_t *info)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
/* enforce collectiveness... */
return module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
}
int
ompi_osc_portals4_get_info(struct ompi_win_t *win, struct ompi_info_t **info_used)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
ompi_info_t *info = OBJ_NEW(ompi_info_t);
if (NULL == info) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
ompi_info_set(info, "no_locks", (module->state.lock == LOCK_ILLEGAL) ? "true" : "false");
if (module->atomic_max < mca_osc_portals4_component.matching_atomic_max) {
ompi_info_set(info, "accumulate_ordering", "none");
} else {
ompi_info_set(info, "accumulate_ordering", "rar,war,raw,waw");
}
*info_used = info;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,413 @@
/*
* Copyright (c) 2011-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_portals4.h"
#include "ompi/mca/mtl/portals4/mtl_portals4_endpoint.h"
enum locktype_t {
lock_nocheck,
lock_exclusive,
lock_shared
};
struct ompi_osc_portals4_outstanding_lock_t {
opal_list_item_t super;
int target;
enum locktype_t lock_type;
};
typedef struct ompi_osc_portals4_outstanding_lock_t ompi_osc_portals4_outstanding_lock_t;
OBJ_CLASS_INSTANCE(ompi_osc_portals4_outstanding_lock_t, opal_list_item_t,
NULL, NULL);
static inline int
lk_cas64(ompi_osc_portals4_module_t *module,
int target,
int64_t write_val,
int64_t comp_val,
int64_t *result_val)
{
int ret;
size_t offset = offsetof(ompi_osc_portals4_node_state_t, lock);
ptl_handle_md_t result_md_h, write_md_h;
void *result_base, *write_base;
opal_atomic_add_64(&module->opcount, 1);
ompi_osc_portals4_get_md(result_val, module->md_h, &result_md_h, &result_base);
ompi_osc_portals4_get_md(&write_val, module->md_h, &write_md_h, &write_base);
ret = PtlSwap(result_md_h,
(char*) result_val - (char*) result_base,
write_md_h,
(char*) write_val - (char*) write_base,
sizeof(int64_t),
ompi_osc_portals4_get_peer(module, target),
module->pt_idx,
module->match_bits | OSC_PORTALS4_MB_CONTROL,
offset,
NULL,
0,
&comp_val,
PTL_CSWAP,
PTL_INT64_T);
if (OMPI_SUCCESS != ret) {
return ret;
}
ret = ompi_osc_portals4_complete_all(module);
return ret;
}
static inline int
lk_write64(ompi_osc_portals4_module_t *module,
int target,
int64_t write_val)
{
int ret;
size_t offset = offsetof(ompi_osc_portals4_node_state_t, lock);
ptl_handle_md_t md_h;
void *base;
opal_atomic_add_64(&module->opcount, 1);
ompi_osc_portals4_get_md(&write_val, module->md_h, &md_h, &base);
ret = PtlPut(md_h,
(char*) &write_val - (char*) base,
sizeof(int64_t),
PTL_ACK_REQ,
ompi_osc_portals4_get_peer(module, target),
module->pt_idx,
module->match_bits | OSC_PORTALS4_MB_CONTROL,
offset,
NULL,
0);
if (OMPI_SUCCESS != ret) {
return ret;
}
ret = ompi_osc_portals4_complete_all(module);
return ret;
}
static inline int
lk_add64(ompi_osc_portals4_module_t *module,
int target,
int64_t write_val,
int64_t *result_val)
{
int ret;
size_t offset = offsetof(ompi_osc_portals4_node_state_t, lock);
ptl_handle_md_t result_md_h, write_md_h;
void *result_base, *write_base;
opal_atomic_add_64(&module->opcount, 1);
ompi_osc_portals4_get_md(result_val, module->md_h, &result_md_h, &result_base);
ompi_osc_portals4_get_md(&write_val, module->md_h, &write_md_h, &write_base);
ret = PtlFetchAtomic(result_md_h,
(char*) &result_val - (char*) result_base,
write_md_h,
(char*) &write_val - (char*) write_base,
sizeof(int64_t),
ompi_osc_portals4_get_peer(module, target),
module->pt_idx,
module->match_bits | OSC_PORTALS4_MB_CONTROL,
offset,
NULL,
0,
PTL_SUM,
PTL_INT64_T);
if (OMPI_SUCCESS != ret) {
return ret;
}
ret = ompi_osc_portals4_complete_all(module);
return ret;
}
static inline int
start_exclusive(ompi_osc_portals4_module_t *module,
int target)
{
int64_t result;
int ret;
while (true) {
ret = lk_cas64(module, target, LOCK_EXCLUSIVE, 0, &result);
if (OMPI_SUCCESS != ret) return ret;
if (LOCK_ILLEGAL == (LOCK_ILLEGAL & result)) return MPI_ERR_RMA_SYNC;
if (0 == result) break;
}
return OMPI_SUCCESS;
}
static inline int
end_exclusive(ompi_osc_portals4_module_t *module,
int target)
{
int ret;
ret = lk_write64(module, target, LOCK_UNLOCKED);
return ret;
}
static inline int
start_shared(ompi_osc_portals4_module_t *module,
int target)
{
int64_t result;
int ret;
while (true) {
ret = lk_add64(module, target, 1, &result);
if (OMPI_SUCCESS != ret) return ret;
if (result > (int64_t)LOCK_EXCLUSIVE) {
if (LOCK_ILLEGAL == (LOCK_ILLEGAL & result)) return MPI_ERR_RMA_SYNC;
ret = lk_add64(module, target, -1, &result);
if (OMPI_SUCCESS != ret) return ret;
} else {
break;
}
}
return OMPI_SUCCESS;
}
static inline int
end_shared(ompi_osc_portals4_module_t *module,
int target)
{
int64_t result;
int ret;
ret = lk_add64(module, target, -1, &result);
return ret;
}
int
ompi_osc_portals4_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
ompi_osc_portals4_outstanding_lock_t* lock;
int ret;
lock = OBJ_NEW(ompi_osc_portals4_outstanding_lock_t);
lock->target = target;
if (0 == (assert & MPI_MODE_NOCHECK)) {
if (MPI_LOCK_EXCLUSIVE == lock_type) {
lock->lock_type = lock_exclusive;
ret = start_exclusive(module, target);
} else {
lock->lock_type = lock_shared;
ret = start_shared(module, target);
}
} else {
lock->lock_type = lock_nocheck;
ret = OMPI_SUCCESS;
}
if (OMPI_SUCCESS == ret) {
opal_list_append(&module->outstanding_locks, &lock->super);
} else {
OBJ_RELEASE(lock);
}
return ret;
}
int
ompi_osc_portals4_unlock(int target,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
ompi_osc_portals4_outstanding_lock_t *lock = NULL, *item;
int ret;
OPAL_LIST_FOREACH(item, &module->outstanding_locks,
ompi_osc_portals4_outstanding_lock_t) {
if (item->target == target) {
lock = item;
break;
}
}
if (NULL != item) {
opal_list_remove_item(&module->outstanding_locks, &lock->super);
} else {
return MPI_ERR_RMA_SYNC;
}
ret = ompi_osc_portals4_complete_all(module);
if (ret != OMPI_SUCCESS) return ret;
if (lock->lock_type == lock_exclusive) {
ret = end_exclusive(module, target);
} else if (lock->lock_type == lock_shared) {
ret = end_shared(module, target);
} else {
ret = OMPI_SUCCESS;
}
OBJ_RELEASE(lock);
return ret;
}
int
ompi_osc_portals4_lock_all(int assert,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
ompi_osc_portals4_outstanding_lock_t* lock;
int ret = OMPI_SUCCESS;
lock = OBJ_NEW(ompi_osc_portals4_outstanding_lock_t);
lock->target = -1;
if (0 == (assert & MPI_MODE_NOCHECK)) {
int i, comm_size;
lock->lock_type = lock_shared;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret |= start_shared(module, i);
}
} else {
lock->lock_type = lock_nocheck;
ret = OMPI_SUCCESS;
}
if (OMPI_SUCCESS == ret) {
opal_list_append(&module->outstanding_locks, &lock->super);
} else {
OBJ_RELEASE(lock);
}
return ret;
}
int
ompi_osc_portals4_unlock_all(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
ompi_osc_portals4_outstanding_lock_t *lock = NULL, *item;
int ret;
OPAL_LIST_FOREACH(item, &module->outstanding_locks,
ompi_osc_portals4_outstanding_lock_t) {
if (item->target == -1) {
lock = item;
break;
}
}
if (NULL != item) {
opal_list_remove_item(&module->outstanding_locks, &lock->super);
} else {
return MPI_ERR_RMA_SYNC;
}
ret = ompi_osc_portals4_complete_all(module);
if (ret != OMPI_SUCCESS) return ret;
if (lock->lock_type == lock_shared) {
int i, comm_size;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret |= end_shared(module, i);
}
}
OBJ_RELEASE(lock);
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_sync(struct ompi_win_t *win)
{
/* Not sure this is strictly necessary, but why not? */
opal_atomic_mb();
PtlAtomicSync();
return OMPI_SUCCESS;
}
int
ompi_osc_portals4_flush(int target,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
return ompi_osc_portals4_complete_all(module);
}
int
ompi_osc_portals4_flush_all(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
return ompi_osc_portals4_complete_all(module);
}
int
ompi_osc_portals4_flush_local(int target,
struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
return ompi_osc_portals4_complete_all(module);
}
int
ompi_osc_portals4_flush_local_all(struct ompi_win_t *win)
{
ompi_osc_portals4_module_t *module =
(ompi_osc_portals4_module_t*) win->w_osc_module;
return ompi_osc_portals4_complete_all(module);
}

Просмотреть файл

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/request/request.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_portals4.h"
#include "osc_portals4_request.h"
static int
request_cancel(struct ompi_request_t *request, int complete)
{
return MPI_ERR_REQUEST;
}
static int
request_free(struct ompi_request_t **ompi_req)
{
ompi_osc_portals4_request_t *request =
(ompi_osc_portals4_request_t*) *ompi_req;
if (true != request->super.req_complete) {
return MPI_ERR_REQUEST;
}
OMPI_OSC_PORTALS4_REQUEST_RETURN(request);
*ompi_req = MPI_REQUEST_NULL;
return OMPI_SUCCESS;
}
static
void
request_construct(ompi_osc_portals4_request_t *request)
{
request->super.req_type = OMPI_REQUEST_WIN;
request->super.req_status._cancelled = 0;
request->super.req_free = request_free;
request->super.req_cancel = request_cancel;
}
OBJ_CLASS_INSTANCE(ompi_osc_portals4_request_t,
ompi_request_t,
request_construct,
NULL);

Просмотреть файл

@ -0,0 +1,46 @@
/*
* Copyright (c) 2011-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_PORTALS4_REQUEST_H
#define OSC_PORTALS4_REQUEST_H
#include "ompi/request/request.h"
struct ompi_osc_portals4_request_t {
ompi_request_t super;
int32_t ops_expected;
volatile int32_t ops_committed;
};
typedef struct ompi_osc_portals4_request_t ompi_osc_portals4_request_t;
OBJ_CLASS_DECLARATION(ompi_osc_portals4_request_t);
#define OMPI_OSC_PORTALS4_REQUEST_ALLOC(win, req) \
do { \
ompi_free_list_item_t *item; \
OMPI_FREE_LIST_WAIT_MT(&mca_osc_portals4_component.requests, \
item); \
req = (ompi_osc_portals4_request_t*) item; \
OMPI_REQUEST_INIT(&req->super, false); \
req->super.req_mpi_object.win = win; \
req->super.req_complete = false; \
req->super.req_state = OMPI_REQUEST_ACTIVE; \
req->ops_expected = 0; \
req->ops_committed = 0; \
} while (0)
#define OMPI_OSC_PORTALS4_REQUEST_RETURN(req) \
do { \
OMPI_REQUEST_FINI(&request->super); \
OMPI_FREE_LIST_RETURN_MT(&mca_osc_portals4_component.requests, \
(ompi_free_list_item_t*) req); \
} while (0)
#endif

Просмотреть файл

@ -1,55 +0,0 @@
#
# 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-2009 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
pt2pt_sources = \
osc_pt2pt.h \
osc_pt2pt.c \
osc_pt2pt_buffer.h \
osc_pt2pt_buffer.c \
osc_pt2pt_comm.c \
osc_pt2pt_component.c \
osc_pt2pt_data_move.h \
osc_pt2pt_data_move.c \
osc_pt2pt_header.h \
osc_pt2pt_longreq.h \
osc_pt2pt_longreq.c \
osc_pt2pt_replyreq.h \
osc_pt2pt_replyreq.c \
osc_pt2pt_sendreq.h \
osc_pt2pt_sendreq.c \
osc_pt2pt_sync.c
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if MCA_BUILD_ompi_osc_pt2pt_DSO
component_noinst =
component_install = mca_osc_pt2pt.la
else
component_noinst = libmca_osc_pt2pt.la
component_install =
endif
mcacomponentdir = $(ompilibdir)
mcacomponent_LTLIBRARIES = $(component_install)
mca_osc_pt2pt_la_SOURCES = $(pt2pt_sources)
mca_osc_pt2pt_la_LDFLAGS = -module -avoid-version
noinst_LTLIBRARIES = $(component_noinst)
libmca_osc_pt2pt_la_SOURCES = $(pt2pt_sources)
libmca_osc_pt2pt_la_LDFLAGS = -module -avoid-version

Просмотреть файл

@ -1,81 +0,0 @@
/*
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_pt2pt.h"
#include "osc_pt2pt_sendreq.h"
#include "ompi/mca/osc/base/base.h"
#include "opal/threads/mutex.h"
#include "ompi/win/win.h"
#include "ompi/communicator/communicator.h"
#include "ompi/request/request.h"
#include "mpi.h"
int
ompi_osc_pt2pt_module_free(ompi_win_t *win)
{
int ret = OMPI_SUCCESS;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"pt2pt component destroying window with id %d",
ompi_comm_get_cid(module->p2p_comm));
/* finish with a barrier */
if (ompi_group_size(win->w_group) > 1) {
ret = module->p2p_comm->c_coll.coll_barrier(module->p2p_comm,
module->p2p_comm->c_coll.coll_barrier_module);
}
win->w_osc_module = NULL;
OBJ_DESTRUCT(&module->p2p_unlocks_pending);
OBJ_DESTRUCT(&module->p2p_locks_pending);
OBJ_DESTRUCT(&module->p2p_copy_pending_sendreqs);
OBJ_DESTRUCT(&module->p2p_pending_sendreqs);
OBJ_DESTRUCT(&module->p2p_acc_lock);
OBJ_DESTRUCT(&module->p2p_cond);
OBJ_DESTRUCT(&module->p2p_lock);
if (NULL != module->p2p_sc_remote_ranks) {
free(module->p2p_sc_remote_ranks);
}
if (NULL != module->p2p_sc_remote_active_ranks) {
free(module->p2p_sc_remote_active_ranks);
}
if (NULL != module->p2p_fence_coll_counts) {
free(module->p2p_fence_coll_counts);
}
if (NULL != module->p2p_copy_num_pending_sendreqs) {
free(module->p2p_copy_num_pending_sendreqs);
}
if (NULL != module->p2p_num_pending_sendreqs) {
free(module->p2p_num_pending_sendreqs);
}
if (NULL != module->p2p_comm) ompi_comm_free(&module->p2p_comm);
#if OPAL_ENABLE_DEBUG
memset(module, 0, sizeof(ompi_osc_base_module_t));
#endif
if (NULL != module) free(module);
return ret;
}

Просмотреть файл

@ -1,253 +0,0 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2006 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_PT2PT_H
#define OMPI_OSC_PT2PT_H
#include "ompi_config.h"
#include "opal/class/opal_list.h"
#include "opal/class/opal_free_list.h"
#include "opal/class/opal_hash_table.h"
#include "opal/threads/threads.h"
#include "ompi/win/win.h"
#include "ompi/communicator/communicator.h"
#include "ompi/request/request.h"
#include "ompi/mca/osc/osc.h"
BEGIN_C_DECLS
#define CONTROL_MSG_TAG (-200)
struct ompi_osc_pt2pt_component_t {
/** Extend the basic osc component interface */
ompi_osc_base_component_t super;
/** max size of eager message */
unsigned long long p2p_c_eager_size;
/** free list of ompi_osc_pt2pt_sendreq_t structures */
opal_free_list_t p2p_c_sendreqs;
/** free list of ompi_osc_pt2pt_replyreq_t structures */
opal_free_list_t p2p_c_replyreqs;
/** free list of ompi_osc_pt2pt_longreq_t structures */
opal_free_list_t p2p_c_longreqs;
/** free list for eager / control meessages */
opal_free_list_t p2p_c_buffers;
};
typedef struct ompi_osc_pt2pt_component_t ompi_osc_pt2pt_component_t;
struct ompi_osc_pt2pt_module_t {
/** Extend the basic osc module interface */
ompi_osc_base_module_t super;
/** lock access to data structures in the current module */
opal_mutex_t p2p_lock;
/** condition variable for access to current module */
opal_condition_t p2p_cond;
/** lock for "atomic" window updates from reductions */
opal_mutex_t p2p_acc_lock;
/** pointer back to window */
ompi_win_t *p2p_win;
/** communicator created with this window */
ompi_communicator_t *p2p_comm;
/** list of ompi_osc_pt2pt_sendreq_t structures, and includes all
requests for this access epoch that have not already been
started. p2p_lock must be held when modifying this field. */
opal_list_t p2p_pending_sendreqs;
/** list of unsigned int counters for the number of requests to a
particular rank in p2p_comm for this access epoc. p2p_lock
must be held when modifying this field */
unsigned int *p2p_num_pending_sendreqs;
/** For MPI_Fence synchronization, the number of messages to send
in epoch. For Start/Complete, the number of updates for this
Complete. For lock, the number of
messages waiting for completion on on the origin side. Not
protected by p2p_lock - must use atomic counter operations. */
int32_t p2p_num_pending_out;
/** For MPI_Fence synchronization, the number of expected incoming
messages. For Post/Wait, the number of expected updates from
complete. For lock, the number of messages on the passive side
we are waiting for. Not protected by p2p_lock - must use
atomic counter operations. */
int32_t p2p_num_pending_in;
/** Number of "ping" messages from the remote post group we've
received */
int32_t p2p_num_post_msgs;
/** Number of "count" messages from the remote complete group
we've received */
int32_t p2p_num_complete_msgs;
/** cyclic counter for a unique tag for long messages. Not
protected by the p2p_lock - must use create_send_tag() to
create a send tag */
volatile int32_t p2p_tag_counter;
opal_list_t p2p_copy_pending_sendreqs;
unsigned int *p2p_copy_num_pending_sendreqs;
/* ********************* FENCE data ************************ */
/* an array of <sizeof(p2p_comm)> ints, each containing the value
1. */
int *p2p_fence_coll_counts;
/* ********************* PWSC data ************************ */
struct ompi_group_t *p2p_pw_group;
struct ompi_group_t *p2p_sc_group;
bool *p2p_sc_remote_active_ranks;
int *p2p_sc_remote_ranks;
/* ********************* LOCK data ************************ */
int32_t p2p_lock_status; /* one of 0, MPI_LOCK_EXCLUSIVE, MPI_LOCK_SHARED */
int32_t p2p_shared_count;
opal_list_t p2p_locks_pending;
opal_list_t p2p_unlocks_pending;
int32_t p2p_lock_received_ack;
};
typedef struct ompi_osc_pt2pt_module_t ompi_osc_pt2pt_module_t;
OMPI_MODULE_DECLSPEC extern ompi_osc_pt2pt_component_t mca_osc_pt2pt_component;
/**
* Helper macro for grabbing the module structure from a window instance
*/
#define P2P_MODULE(win) ((ompi_osc_pt2pt_module_t*) win->w_osc_module)
/*
* Component functions
*/
int ompi_osc_pt2pt_component_init(bool enable_progress_threads,
bool enable_mpi_threads);
int ompi_osc_pt2pt_component_finalize(void);
int ompi_osc_pt2pt_component_query(struct ompi_win_t *win,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
int ompi_osc_pt2pt_component_select(struct ompi_win_t *win,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
/* helper function that properly sets up request handling */
int ompi_osc_pt2pt_component_irecv(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int src,
int tag,
struct ompi_communicator_t *comm,
struct ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *data);
int ompi_osc_pt2pt_component_isend(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int dest,
int tag,
struct ompi_communicator_t *comm,
struct ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *data);
/*
* Module interface function types
*/
int ompi_osc_pt2pt_module_free(struct ompi_win_t *win);
int ompi_osc_pt2pt_module_put(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_fence(int assert, struct ompi_win_t *win);
int ompi_osc_pt2pt_module_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_complete(struct ompi_win_t *win);
int ompi_osc_pt2pt_module_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_wait(struct ompi_win_t *win);
int ompi_osc_pt2pt_module_test(struct ompi_win_t *win,
int *flag);
int ompi_osc_pt2pt_module_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win);
int ompi_osc_pt2pt_module_unlock(int target,
struct ompi_win_t *win);
/*
* passive side sync interface functions
*/
int ompi_osc_pt2pt_passive_lock(ompi_osc_pt2pt_module_t *module,
int32_t origin,
int32_t lock_type);
int ompi_osc_pt2pt_passive_unlock(ompi_osc_pt2pt_module_t *module,
int32_t origin,
int32_t count);
int ompi_osc_pt2pt_passive_unlock_complete(ompi_osc_pt2pt_module_t *module);
END_C_DECLS
#endif /* OMPI_OSC_PT2PT_H */

Просмотреть файл

@ -1,43 +0,0 @@
/*
* 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-2006 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2008 Sun Microsystems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "opal/class/opal_free_list.h"
#include "opal/types.h"
#include "osc_pt2pt_buffer.h"
static void ompi_osc_pt2pt_buffer_construct(ompi_osc_pt2pt_buffer_t *buf)
{
/* adjust payload location to account for alignment issues */
buf->payload = (void* )(((char*) buf) +
sizeof(ompi_osc_pt2pt_buffer_t) +
(sizeof(ompi_osc_pt2pt_buffer_t) % sizeof(ompi_ptr_t)));
}
static void ompi_osc_pt2pt_buffer_destruct(ompi_osc_pt2pt_buffer_t *buf)
{
buf->payload = NULL;
}
OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_buffer_t, opal_free_list_item_t,
ompi_osc_pt2pt_buffer_construct,
ompi_osc_pt2pt_buffer_destruct);

Просмотреть файл

@ -1,38 +0,0 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2006 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-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_PT2PT_BUFFER_H
#define OMPI_OSC_PT2PT_BUFFER_H
#include "opal/class/opal_free_list.h"
#include "ompi/request/request.h"
BEGIN_C_DECLS
struct ompi_osc_pt2pt_buffer_t {
ompi_free_list_item_t super;
ompi_request_t *request;
void *data;
void *payload;
size_t len;
};
typedef struct ompi_osc_pt2pt_buffer_t ompi_osc_pt2pt_buffer_t;
OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_buffer_t);
END_C_DECLS
#endif

Просмотреть файл

@ -1,202 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "mpi.h"
#include <stdio.h>
#include "opal/class/opal_list.h"
#include "opal/threads/mutex.h"
#include "osc_pt2pt.h"
#include "osc_pt2pt_sendreq.h"
#include "osc_pt2pt_header.h"
#include "osc_pt2pt_data_move.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/op/op.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
static int
enqueue_sendreq(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_sendreq_t *sendreq)
{
OPAL_THREAD_LOCK(&(module->p2p_lock));
opal_list_append(&(module->p2p_pending_sendreqs),
(opal_list_item_t*) sendreq);
module->p2p_num_pending_sendreqs[sendreq->req_target_rank]++;
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_accumulate(void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target, OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op, ompi_win_t *win)
{
int ret;
ompi_osc_pt2pt_sendreq_t *sendreq;
if ((OMPI_WIN_STARTED & ompi_win_get_mode(win)) &&
(!P2P_MODULE(win)->p2p_sc_remote_active_ranks[target])) {
return MPI_ERR_RMA_SYNC;
}
if (OMPI_WIN_FENCE & ompi_win_get_mode(win)) {
/* well, we're definitely in an access epoch now */
ompi_win_set_mode(win, OMPI_WIN_FENCE | OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
/* shortcut 0 count case */
if (0 == origin_count || 0 == target_count) {
return OMPI_SUCCESS;
}
/* create sendreq */
ret = ompi_osc_pt2pt_sendreq_alloc_init(OMPI_OSC_PT2PT_ACC,
origin_addr,
origin_count,
origin_dt,
target,
target_disp,
target_count,
target_dt,
P2P_MODULE(win),
&sendreq);
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_noaccess,
&sendreq->req_origin_convertor);
);
if (OMPI_SUCCESS != ret) return ret;
sendreq->req_op_id = op->o_f_to_c_index;
/* enqueue sendreq */
ret = enqueue_sendreq(P2P_MODULE(win), sendreq);
return ret;
}
int
ompi_osc_pt2pt_module_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
ompi_win_t *win)
{
int ret;
ompi_osc_pt2pt_sendreq_t *sendreq;
if ((OMPI_WIN_STARTED & ompi_win_get_mode(win)) &&
(!P2P_MODULE(win)->p2p_sc_remote_active_ranks[target])) {
return MPI_ERR_RMA_SYNC;
}
if (OMPI_WIN_FENCE & ompi_win_get_mode(win)) {
/* well, we're definitely in an access epoch now */
ompi_win_set_mode(win, OMPI_WIN_FENCE | OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
/* shortcut 0 count case */
if (0 == origin_count || 0 == target_count) {
return OMPI_SUCCESS;
}
/* create sendreq */
ret = ompi_osc_pt2pt_sendreq_alloc_init(OMPI_OSC_PT2PT_GET,
origin_addr,
origin_count,
origin_dt,
target,
target_disp,
target_count,
target_dt,
P2P_MODULE(win),
&sendreq);
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_noaccess,
&sendreq->req_origin_convertor);
);
if (OMPI_SUCCESS != ret) return ret;
/* enqueue sendreq */
ret = enqueue_sendreq(P2P_MODULE(win), sendreq);
return ret;
}
int
ompi_osc_pt2pt_module_put(void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target, OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt, ompi_win_t *win)
{
int ret;
ompi_osc_pt2pt_sendreq_t *sendreq;
if ((OMPI_WIN_STARTED & ompi_win_get_mode(win)) &&
(!P2P_MODULE(win)->p2p_sc_remote_active_ranks[target])) {
return MPI_ERR_RMA_SYNC;
}
if (OMPI_WIN_FENCE & ompi_win_get_mode(win)) {
/* well, we're definitely in an access epoch now */
ompi_win_set_mode(win, OMPI_WIN_FENCE | OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
/* shortcut 0 count case */
if (0 == origin_count || 0 == target_count) {
return OMPI_SUCCESS;
}
/* create sendreq */
ret = ompi_osc_pt2pt_sendreq_alloc_init(OMPI_OSC_PT2PT_PUT,
origin_addr,
origin_count,
origin_dt,
target,
target_disp,
target_count,
target_dt,
P2P_MODULE(win),
&sendreq);
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_noaccess,
&sendreq->req_origin_convertor);
);
if (OMPI_SUCCESS != ret) return ret;
/* enqueue sendreq */
ret = enqueue_sendreq(P2P_MODULE(win), sendreq);
return ret;
}

Просмотреть файл

@ -1,661 +0,0 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2010 The University of Tennessee and The University
* of Tennessee Research Foundation. 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2008 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2006-2008 University of Houston. All rights reserved.
* Copyright (c) 2010 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <string.h>
#include "osc_pt2pt.h"
#include "osc_pt2pt_sendreq.h"
#include "osc_pt2pt_replyreq.h"
#include "osc_pt2pt_header.h"
#include "osc_pt2pt_data_move.h"
#include "osc_pt2pt_buffer.h"
#include "opal/threads/mutex.h"
#include "ompi/info/info.h"
#include "ompi/communicator/communicator.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "ompi/mca/pml/pml.h"
static int component_register(void);
static int component_fragment_cb(ompi_request_t *request);
ompi_osc_pt2pt_component_t mca_osc_pt2pt_component = {
{ /* ompi_osc_base_component_t */
{ /* ompi_base_component_t */
OMPI_OSC_BASE_VERSION_2_0_0,
"pt2pt",
OMPI_MAJOR_VERSION, /* MCA component major version */
OMPI_MINOR_VERSION, /* MCA component minor version */
OMPI_RELEASE_VERSION, /* MCA component release version */
NULL,
NULL,
NULL,
component_register
},
{ /* mca_base_component_data */
MCA_BASE_METADATA_PARAM_CHECKPOINT
},
ompi_osc_pt2pt_component_init,
ompi_osc_pt2pt_component_query,
ompi_osc_pt2pt_component_select,
ompi_osc_pt2pt_component_finalize
}
};
ompi_osc_pt2pt_module_t ompi_osc_pt2pt_module_template = {
{
ompi_osc_pt2pt_module_free,
ompi_osc_pt2pt_module_put,
ompi_osc_pt2pt_module_get,
ompi_osc_pt2pt_module_accumulate,
ompi_osc_pt2pt_module_fence,
ompi_osc_pt2pt_module_start,
ompi_osc_pt2pt_module_complete,
ompi_osc_pt2pt_module_post,
ompi_osc_pt2pt_module_wait,
ompi_osc_pt2pt_module_test,
ompi_osc_pt2pt_module_lock,
ompi_osc_pt2pt_module_unlock,
}
};
static int
component_register(void)
{
mca_osc_pt2pt_component.p2p_c_eager_size = 16 * 1024;
(void) mca_base_component_var_register(&mca_osc_pt2pt_component.super.osc_version,
"eager_limit",
"Max size of eagerly sent data",
MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG,
NULL, 0, 0, OPAL_INFO_LVL_9,
MCA_BASE_VAR_SCOPE_READONLY,
&mca_osc_pt2pt_component.p2p_c_eager_size);
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_component_init(bool enable_progress_threads,
bool enable_mpi_threads)
{
size_t aligned_size;
OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_sendreqs, opal_free_list_t);
opal_free_list_init(&mca_osc_pt2pt_component.p2p_c_sendreqs,
sizeof(ompi_osc_pt2pt_sendreq_t),
OBJ_CLASS(ompi_osc_pt2pt_sendreq_t),
1, -1, 1);
OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_replyreqs, opal_free_list_t);
opal_free_list_init(&mca_osc_pt2pt_component.p2p_c_replyreqs,
sizeof(ompi_osc_pt2pt_replyreq_t),
OBJ_CLASS(ompi_osc_pt2pt_replyreq_t),
1, -1, 1);
OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_longreqs, opal_free_list_t);
opal_free_list_init(&mca_osc_pt2pt_component.p2p_c_longreqs,
sizeof(ompi_osc_pt2pt_longreq_t),
OBJ_CLASS(ompi_osc_pt2pt_longreq_t),
1, -1, 1);
/* adjust size to be multiple of ompi_ptr_t to avoid alignment issues*/
aligned_size = sizeof(ompi_osc_pt2pt_buffer_t) +
(sizeof(ompi_osc_pt2pt_buffer_t) % sizeof(ompi_ptr_t)) +
mca_osc_pt2pt_component.p2p_c_eager_size;
OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_buffers, opal_free_list_t);
opal_free_list_init(&mca_osc_pt2pt_component.p2p_c_buffers,
aligned_size,
OBJ_CLASS(ompi_osc_pt2pt_buffer_t),
1, -1, 1);
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_component_finalize(void)
{
OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_buffers);
OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_longreqs);
OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_replyreqs);
OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_sendreqs);
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_component_query(ompi_win_t *win,
ompi_info_t *info,
ompi_communicator_t *comm)
{
/* we can always run - return a low priority */
return 5;
}
int
ompi_osc_pt2pt_component_select(ompi_win_t *win,
ompi_info_t *info,
ompi_communicator_t *comm)
{
ompi_osc_pt2pt_module_t *module = NULL;
int ret, i;
ompi_osc_pt2pt_buffer_t *buffer = NULL;
opal_free_list_item_t *item = NULL;
char *tmp = NULL;
/* create module structure */
module = (ompi_osc_pt2pt_module_t*)
calloc(1, sizeof(ompi_osc_pt2pt_module_t));
if (NULL == module) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
/* fill in the function pointer part */
memcpy(module, &ompi_osc_pt2pt_module_template,
sizeof(ompi_osc_base_module_t));
/* initialize the p2p part */
OBJ_CONSTRUCT(&(module->p2p_lock), opal_mutex_t);
OBJ_CONSTRUCT(&(module->p2p_cond), opal_condition_t);
OBJ_CONSTRUCT(&(module->p2p_acc_lock), opal_mutex_t);
OBJ_CONSTRUCT(&module->p2p_pending_sendreqs, opal_list_t);
OBJ_CONSTRUCT(&(module->p2p_copy_pending_sendreqs), opal_list_t);
OBJ_CONSTRUCT(&(module->p2p_locks_pending), opal_list_t);
OBJ_CONSTRUCT(&(module->p2p_unlocks_pending), opal_list_t);
module->p2p_win = win;
ret = ompi_comm_dup(comm, &(module->p2p_comm));
if (ret != OMPI_SUCCESS) goto cleanup;
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"pt2pt component creating window with id %d",
ompi_comm_get_cid(module->p2p_comm));
asprintf(&tmp, "%d", ompi_comm_get_cid(module->p2p_comm));
ompi_win_set_name(win, tmp);
free(tmp);
module->p2p_num_pending_sendreqs = (unsigned int*)
malloc(sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));
if (NULL == module->p2p_num_pending_sendreqs) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto cleanup;
}
memset(module->p2p_num_pending_sendreqs, 0,
sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));
module->p2p_num_pending_out = 0;
module->p2p_num_pending_in = 0;
module->p2p_num_post_msgs = 0;
module->p2p_num_complete_msgs = 0;
module->p2p_tag_counter = 0;
module->p2p_copy_num_pending_sendreqs = (unsigned int*)
malloc(sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));
if (NULL == module->p2p_copy_num_pending_sendreqs) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto cleanup;
}
memset(module->p2p_num_pending_sendreqs, 0,
sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));
/* fence data */
module->p2p_fence_coll_counts = (int*)
malloc(sizeof(int) * ompi_comm_size(module->p2p_comm));
if (NULL == module->p2p_fence_coll_counts) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto cleanup;
}
for (i = 0 ; i < ompi_comm_size(module->p2p_comm) ; ++i) {
module->p2p_fence_coll_counts[i] = 1;
}
/* pwsc data */
module->p2p_pw_group = NULL;
module->p2p_sc_group = NULL;
module->p2p_sc_remote_active_ranks = (bool*)
malloc(sizeof(bool) * ompi_comm_size(module->p2p_comm));
if (NULL == module->p2p_sc_remote_active_ranks) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto cleanup;
}
module->p2p_sc_remote_ranks = (int*)
malloc(sizeof(int) * ompi_comm_size(module->p2p_comm));
if (NULL == module->p2p_sc_remote_ranks) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto cleanup;
}
/* lock data */
module->p2p_lock_status = 0;
module->p2p_shared_count = 0;
module->p2p_lock_received_ack = 0;
/* fill in window information */
win->w_osc_module = (ompi_osc_base_module_t*) module;
/* sync memory - make sure all initialization completed */
opal_atomic_mb();
/* start up receive for protocol headers */
OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_buffers,
item, ret);
if (OMPI_SUCCESS != ret) goto cleanup;
buffer = (ompi_osc_pt2pt_buffer_t*) item;
buffer->data = (void*) module;
ret = ompi_osc_pt2pt_component_irecv(buffer->payload,
mca_osc_pt2pt_component.p2p_c_eager_size,
MPI_BYTE,
MPI_ANY_SOURCE,
CONTROL_MSG_TAG,
module->p2p_comm,
&(buffer->request),
component_fragment_cb,
buffer);
if (OMPI_SUCCESS != ret) goto cleanup;
return OMPI_SUCCESS;
cleanup:
OBJ_DESTRUCT(&module->p2p_unlocks_pending);
OBJ_DESTRUCT(&module->p2p_locks_pending);
OBJ_DESTRUCT(&module->p2p_copy_pending_sendreqs);
OBJ_DESTRUCT(&module->p2p_pending_sendreqs);
OBJ_DESTRUCT(&module->p2p_acc_lock);
OBJ_DESTRUCT(&module->p2p_cond);
OBJ_DESTRUCT(&module->p2p_lock);
if (NULL != buffer) {
OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_buffers, item);
}
if (NULL != module->p2p_sc_remote_ranks) {
free(module->p2p_sc_remote_ranks);
}
if (NULL != module->p2p_sc_remote_active_ranks) {
free(module->p2p_sc_remote_active_ranks);
}
if (NULL != module->p2p_fence_coll_counts) {
free(module->p2p_fence_coll_counts);
}
if (NULL != module->p2p_copy_num_pending_sendreqs) {
free(module->p2p_copy_num_pending_sendreqs);
}
if (NULL != module->p2p_num_pending_sendreqs) {
free(module->p2p_num_pending_sendreqs);
}
if (NULL != module->p2p_comm) ompi_comm_free(&module->p2p_comm);
#if OPAL_ENABLE_DEBUG
memset(module, 0, sizeof(ompi_osc_base_module_t));
#endif
if (NULL != module) free(module);
return ret;
}
/* dispatch for callback on message completion */
static int
component_fragment_cb(ompi_request_t *request)
{
int ret;
ompi_osc_pt2pt_buffer_t *buffer;
ompi_osc_pt2pt_module_t *module;
if (request->req_status._cancelled) {
opal_output_verbose(5, ompi_osc_base_framework.framework_output,
"pt2pt request was canceled");
return OMPI_ERR_NOT_AVAILABLE;
}
buffer = (ompi_osc_pt2pt_buffer_t*) request->req_complete_cb_data;
module = (ompi_osc_pt2pt_module_t*) buffer->data;
assert(request->req_status._ucount >= (int) sizeof(ompi_osc_pt2pt_base_header_t));
/* handle message */
switch (((ompi_osc_pt2pt_base_header_t*) buffer->payload)->hdr_type) {
case OMPI_OSC_PT2PT_HDR_PUT:
{
/* get our header and payload */
ompi_osc_pt2pt_send_header_t *header =
(ompi_osc_pt2pt_send_header_t*) buffer->payload;
void *payload = (void*) (header + 1);
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_SEND_HDR_NTOH(*header);
}
#endif
if (!ompi_win_exposure_epoch(module->p2p_win)) {
if (OMPI_WIN_FENCE & ompi_win_get_mode(module->p2p_win)) {
ompi_win_set_mode(module->p2p_win,
OMPI_WIN_FENCE |
OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
}
ret = ompi_osc_pt2pt_sendreq_recv_put(module, header, payload);
}
break;
case OMPI_OSC_PT2PT_HDR_ACC:
{
/* get our header and payload */
ompi_osc_pt2pt_send_header_t *header =
(ompi_osc_pt2pt_send_header_t*) buffer->payload;
void *payload = (void*) (header + 1);
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_SEND_HDR_NTOH(*header);
}
#endif
if (!ompi_win_exposure_epoch(module->p2p_win)) {
if (OMPI_WIN_FENCE & ompi_win_get_mode(module->p2p_win)) {
ompi_win_set_mode(module->p2p_win,
OMPI_WIN_FENCE |
OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
}
/* receive into temporary buffer */
ret = ompi_osc_pt2pt_sendreq_recv_accum(module, header, payload);
}
break;
case OMPI_OSC_PT2PT_HDR_GET:
{
/* get our header and payload */
ompi_osc_pt2pt_send_header_t *header =
(ompi_osc_pt2pt_send_header_t*) buffer->payload;
void *payload = (void*) (header + 1);
ompi_datatype_t *datatype;
ompi_osc_pt2pt_replyreq_t *replyreq;
ompi_proc_t *proc;
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_SEND_HDR_NTOH(*header);
}
#endif
if (!ompi_win_exposure_epoch(module->p2p_win)) {
if (OMPI_WIN_FENCE & ompi_win_get_mode(module->p2p_win)) {
ompi_win_set_mode(module->p2p_win,
OMPI_WIN_FENCE |
OMPI_WIN_ACCESS_EPOCH |
OMPI_WIN_EXPOSE_EPOCH);
}
}
/* create or get a pointer to our datatype */
proc = ompi_comm_peer_lookup( module->p2p_comm, header->hdr_origin );
datatype = ompi_osc_base_datatype_create(proc, &payload);
if (NULL == datatype) {
opal_output(ompi_osc_base_framework.framework_output,
"Error recreating datatype. Aborting.");
ompi_mpi_abort(module->p2p_comm, 1, false);
}
/* create replyreq sendreq */
ret = ompi_osc_pt2pt_replyreq_alloc_init(module,
header->hdr_origin,
header->hdr_origin_sendreq,
header->hdr_target_disp,
header->hdr_target_count,
datatype,
&replyreq);
/* send replyreq */
ompi_osc_pt2pt_replyreq_send(module, replyreq);
/* sendreq does the right retain, so we can release safely */
OBJ_RELEASE(datatype);
}
break;
case OMPI_OSC_PT2PT_HDR_REPLY:
{
ompi_osc_pt2pt_reply_header_t *header =
(ompi_osc_pt2pt_reply_header_t*) buffer->payload;
void *payload = (void*) (header + 1);
ompi_osc_pt2pt_sendreq_t *sendreq;
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_REPLY_HDR_NTOH(*header);
}
#endif
/* get original sendreq pointer */
sendreq = (ompi_osc_pt2pt_sendreq_t*) header->hdr_origin_sendreq.pval;
module = sendreq->req_module;
/* receive data */
ompi_osc_pt2pt_replyreq_recv(module, sendreq, header, payload);
}
break;
case OMPI_OSC_PT2PT_HDR_POST:
{
int32_t count;
OPAL_THREAD_LOCK(&module->p2p_lock);
count = (module->p2p_num_post_msgs -= 1);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
if (count == 0) opal_condition_broadcast(&module->p2p_cond);
}
break;
case OMPI_OSC_PT2PT_HDR_COMPLETE:
{
ompi_osc_pt2pt_control_header_t *header =
(ompi_osc_pt2pt_control_header_t*) buffer->payload;
int32_t count;
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_CONTROL_HDR_NTOH(*header);
}
#endif
/* we've heard from one more place, and have value reqs to
process */
OPAL_THREAD_LOCK(&module->p2p_lock);
count = (module->p2p_num_complete_msgs -= 1);
count += (module->p2p_num_pending_in += header->hdr_value[0]);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
if (count == 0) opal_condition_broadcast(&module->p2p_cond);
}
break;
case OMPI_OSC_PT2PT_HDR_LOCK_REQ:
{
ompi_osc_pt2pt_control_header_t *header =
(ompi_osc_pt2pt_control_header_t*) buffer->payload;
int32_t count;
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_CONTROL_HDR_NTOH(*header);
}
#endif
if (header->hdr_value[1] > 0) {
ompi_osc_pt2pt_passive_lock(module, header->hdr_value[0],
header->hdr_value[1]);
} else {
OPAL_THREAD_LOCK(&module->p2p_lock);
count = (module->p2p_lock_received_ack += 1);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
if (count != 0) opal_condition_broadcast(&module->p2p_cond);
}
}
break;
case OMPI_OSC_PT2PT_HDR_UNLOCK_REQ:
{
ompi_osc_pt2pt_control_header_t *header =
(ompi_osc_pt2pt_control_header_t*) buffer->payload;
#if !defined(WORDS_BIGENDIAN) && OPAL_ENABLE_HETEROGENEOUS_SUPPORT
if (header->hdr_base.hdr_flags & OMPI_OSC_PT2PT_HDR_FLAG_NBO) {
OMPI_OSC_PT2PT_CONTROL_HDR_NTOH(*header);
}
#endif
ompi_osc_pt2pt_passive_unlock(module, header->hdr_value[0],
header->hdr_value[1]);
}
break;
case OMPI_OSC_PT2PT_HDR_UNLOCK_REPLY:
{
int32_t count;
OPAL_THREAD_LOCK(&module->p2p_lock);
count = (module->p2p_num_pending_out -= 1);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
if (count == 0) opal_condition_broadcast(&module->p2p_cond);
}
break;
default:
opal_output_verbose(5, ompi_osc_base_framework.framework_output,
"received one-sided packet for with unknown type");
}
ompi_request_free(&request);
ret = ompi_osc_pt2pt_component_irecv(buffer->payload,
mca_osc_pt2pt_component.p2p_c_eager_size,
MPI_BYTE,
MPI_ANY_SOURCE,
CONTROL_MSG_TAG,
module->p2p_comm,
&buffer->request,
component_fragment_cb,
buffer);
return ret;
}
int
ompi_osc_pt2pt_component_irecv(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int src,
int tag,
struct ompi_communicator_t *comm,
ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *cbdata)
{
int ret;
bool missed_callback;
ompi_request_complete_fn_t tmp;
ret = MCA_PML_CALL(irecv(buf, count, datatype,
src, tag, comm, request));
if (OMPI_SUCCESS != ret) return ret;
/* lock the giant request mutex to update the callback data so
that the PML can't mark the request as complete while we're
updating the callback data, which means we can
deterministically ensure the callback is only fired once and
that we didn't miss it. */
OPAL_THREAD_LOCK(&ompi_request_lock);
(*request)->req_complete_cb = callback;
(*request)->req_complete_cb_data = cbdata;
missed_callback = (*request)->req_complete;
OPAL_THREAD_UNLOCK(&ompi_request_lock);
if (missed_callback) {
tmp = (*request)->req_complete_cb;
(*request)->req_complete_cb = NULL;
tmp(*request);
}
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_component_isend(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int dest,
int tag,
struct ompi_communicator_t *comm,
ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *cbdata)
{
int ret;
bool missed_callback;
ompi_request_complete_fn_t tmp;
ret = MCA_PML_CALL(isend(buf, count, datatype,
dest, tag, MCA_PML_BASE_SEND_STANDARD, comm, request));
if (OMPI_SUCCESS != ret) return ret;
/* lock the giant request mutex to update the callback data so
that the PML can't mark the request as complete while we're
updating the callback data, which means we can
deterministically ensure the callback is only fired once and
that we didn't miss it. */
OPAL_THREAD_LOCK(&ompi_request_lock);
(*request)->req_complete_cb = callback;
(*request)->req_complete_cb_data = cbdata;
missed_callback = (*request)->req_complete;
OPAL_THREAD_UNLOCK(&ompi_request_lock);
if (missed_callback) {
tmp = (*request)->req_complete_cb;
(*request)->req_complete_cb = NULL;
tmp(*request);
}
return OMPI_SUCCESS;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,55 +0,0 @@
/*
* 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$
*/
#ifndef OMPI_MCA_OSC_PT2PT_DATA_MOVE_H
#define OMPI_MCA_OSC_PT2PT_DATA_MOVE_H
#include "osc_pt2pt_sendreq.h"
#include "osc_pt2pt_replyreq.h"
/* send a sendreq (the request from the origin for a Put, Get, or
Accumulate, including the payload for Put and Accumulate) */
int ompi_osc_pt2pt_sendreq_send(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_sendreq_t *sendreq);
/* send a replyreq (the request from the target of a Get, with the
payload for the origin */
int ompi_osc_pt2pt_replyreq_send(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_replyreq_t *replyreq);
/* receive the target side of a sendreq for a put, directly into the user's window */
int ompi_osc_pt2pt_sendreq_recv_put(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_send_header_t *header,
void *payload);
/* receive the target side of a sendreq for an accumulate, possibly
using a temproart buffer, then calling the reduction functions */
int ompi_osc_pt2pt_sendreq_recv_accum(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_send_header_t *header,
void *payload);
/* receive the origin side of a replyreq (the reply part of an
MPI_Get), directly into the user's window */
int ompi_osc_pt2pt_replyreq_recv(ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_sendreq_t *sendreq,
ompi_osc_pt2pt_reply_header_t *header,
void *payload);
int ompi_osc_pt2pt_control_send(ompi_osc_pt2pt_module_t *module,
ompi_proc_t *proc,
uint8_t type, int32_t value0, int32_t value1);
#endif

Просмотреть файл

@ -1,134 +0,0 @@
/*
* 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 (c) 2006-2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_MCA_OSC_PT2PT_HDR_H
#define OMPI_MCA_OSC_PT2PT_HDR_H
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include "opal/types.h"
#define OMPI_OSC_PT2PT_HDR_PUT 0x0001
#define OMPI_OSC_PT2PT_HDR_ACC 0x0002
#define OMPI_OSC_PT2PT_HDR_GET 0x0003
#define OMPI_OSC_PT2PT_HDR_REPLY 0x0004
#define OMPI_OSC_PT2PT_HDR_POST 0x0005
#define OMPI_OSC_PT2PT_HDR_COMPLETE 0x0006
#define OMPI_OSC_PT2PT_HDR_LOCK_REQ 0x0007
#define OMPI_OSC_PT2PT_HDR_UNLOCK_REQ 0x0008
#define OMPI_OSC_PT2PT_HDR_UNLOCK_REPLY 0x0009
#define OMPI_OSC_PT2PT_HDR_FLAG_NBO 0x0001
struct ompi_osc_pt2pt_base_header_t {
uint8_t hdr_type;
uint8_t hdr_flags;
#if OPAL_ENABLE_HETEROGENEOUS_SUPPORT
uint8_t padding[2];
#endif
};
typedef struct ompi_osc_pt2pt_base_header_t ompi_osc_pt2pt_base_header_t;
#define OMPI_OSC_PT2PT_BASE_HDR_NTOH(h)
#define OMPI_OSC_PT2PT_BASE_HDR_HTON(h)
struct ompi_osc_pt2pt_send_header_t {
ompi_osc_pt2pt_base_header_t hdr_base;
int32_t hdr_origin;
ompi_ptr_t hdr_origin_sendreq;
int32_t hdr_origin_tag;
uint64_t hdr_target_disp;
int32_t hdr_target_count;
int32_t hdr_target_op;
int32_t hdr_msg_length; /* 0 if payload is not included */
};
typedef struct ompi_osc_pt2pt_send_header_t ompi_osc_pt2pt_send_header_t;
#define OMPI_OSC_PT2PT_SEND_HDR_HTON(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_HTON((hdr).hdr_base) \
(hdr).hdr_origin = htonl((hdr).hdr_origin); \
(hdr).hdr_origin_tag = htonl((hdr).hdr_origin_tag); \
(hdr).hdr_target_disp = hton64((hdr).hdr_target_disp); \
(hdr).hdr_target_count = htonl((hdr).hdr_target_count); \
(hdr).hdr_target_op = htonl((hdr).hdr_target_op); \
(hdr).hdr_msg_length = htonl((hdr).hdr_msg_length); \
} while (0)
#define OMPI_OSC_PT2PT_SEND_HDR_NTOH(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_NTOH((hdr).hdr_base) \
(hdr).hdr_origin = ntohl((hdr).hdr_origin); \
(hdr).hdr_origin_tag = ntohl((hdr).hdr_origin_tag); \
(hdr).hdr_target_disp = ntoh64((hdr).hdr_target_disp); \
(hdr).hdr_target_count = ntohl((hdr).hdr_target_count); \
(hdr).hdr_target_op = ntohl((hdr).hdr_target_op); \
(hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_pt2pt_reply_header_t {
ompi_osc_pt2pt_base_header_t hdr_base;
int32_t hdr_target_tag;
ompi_ptr_t hdr_origin_sendreq;
int32_t hdr_msg_length;
};
typedef struct ompi_osc_pt2pt_reply_header_t ompi_osc_pt2pt_reply_header_t;
#define OMPI_OSC_PT2PT_REPLY_HDR_HTON(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_HTON((hdr).hdr_base) \
(hdr).hdr_target_tag = htonl((hdr).hdr_target_tag); \
(hdr).hdr_msg_length = htonl((hdr).hdr_msg_length); \
} while (0)
#define OMPI_OSC_PT2PT_REPLY_HDR_NTOH(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_NTOH((hdr).hdr_base) \
(hdr).hdr_target_tag = ntohl((hdr).hdr_target_tag); \
(hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_pt2pt_control_header_t {
ompi_osc_pt2pt_base_header_t hdr_base;
int32_t hdr_value[2];
};
typedef struct ompi_osc_pt2pt_control_header_t ompi_osc_pt2pt_control_header_t;
#define OMPI_OSC_PT2PT_CONTROL_HDR_HTON(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_HTON((hdr).hdr_base) \
(hdr).hdr_value[0] = htonl((hdr).hdr_value[0]); \
(hdr).hdr_value[1] = htonl((hdr).hdr_value[1]); \
} while (0)
#define OMPI_OSC_PT2PT_CONTROL_HDR_NTOH(hdr) \
do { \
OMPI_OSC_PT2PT_BASE_HDR_NTOH((hdr).hdr_base) \
(hdr).hdr_value[0] = ntohl((hdr).hdr_value[0]); \
(hdr).hdr_value[1] = ntohl((hdr).hdr_value[1]); \
} while (0)
#endif /* OMPI_MCA_OSC_PT2PT_HDR_H */

Просмотреть файл

@ -1,23 +0,0 @@
/*
* 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$
*/
#include "ompi_config.h"
#include "osc_pt2pt_longreq.h"
OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_longreq_t, opal_free_list_item_t,
NULL, NULL);

Просмотреть файл

@ -1,64 +0,0 @@
/*
* 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$
*/
#ifndef OSC_PT2PT_LONGREQ_H
#define OSC_PT2PT_LONGREQ_H
#include "opal/class/opal_free_list.h"
#include "osc_pt2pt.h"
struct ompi_osc_pt2pt_longreq_t {
opal_free_list_item_t super;
struct ompi_request_t *req_pml_request; /* PML request */
union {
struct ompi_osc_pt2pt_sendreq_t *req_sendreq;
struct ompi_osc_pt2pt_replyreq_t *req_replyreq;
struct ompi_osc_pt2pt_send_header_t *req_sendhdr;
} req_basereq;
/* This may not always be filled in... */
struct ompi_osc_pt2pt_module_t *req_module;
struct ompi_op_t *req_op;
struct ompi_datatype_t *req_datatype;
};
typedef struct ompi_osc_pt2pt_longreq_t ompi_osc_pt2pt_longreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_longreq_t);
static inline int
ompi_osc_pt2pt_longreq_alloc(ompi_osc_pt2pt_longreq_t **longreq)
{
opal_free_list_item_t *item;
int ret;
OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_longreqs,
item, ret);
*longreq = (ompi_osc_pt2pt_longreq_t*) item;
return ret;
}
static inline int
ompi_osc_pt2pt_longreq_free(ompi_osc_pt2pt_longreq_t *longreq)
{
OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_longreqs,
&longreq->super);
return OMPI_SUCCESS;
}
#endif

Просмотреть файл

@ -1,80 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_pt2pt_replyreq.h"
#include "opal/class/opal_list.h"
#include "opal/datatype/opal_convertor.h"
int
ompi_osc_pt2pt_replyreq_alloc_init(ompi_osc_pt2pt_module_t *module,
int origin,
ompi_ptr_t origin_request,
OPAL_PTRDIFF_TYPE target_displacement,
int target_count,
struct ompi_datatype_t *datatype,
ompi_osc_pt2pt_replyreq_t **replyreq)
{
int ret;
void *target_addr = (unsigned char*) module->p2p_win->w_baseptr +
(target_displacement * module->p2p_win->w_disp_unit);
/* allocate a replyreq */
ret = ompi_osc_pt2pt_replyreq_alloc(module,
origin,
replyreq);
if (OMPI_SUCCESS != ret) return ret;
/* initialize local side of replyreq */
ret = ompi_osc_pt2pt_replyreq_init_target(*replyreq,
target_addr,
target_count,
datatype);
if (OMPI_SUCCESS != ret) {
ompi_osc_pt2pt_replyreq_free(*replyreq);
return ret;
}
/* initialize remote side of replyreq */
ret = ompi_osc_pt2pt_replyreq_init_origin(*replyreq,
origin_request);
if (OMPI_SUCCESS != ret) {
ompi_osc_pt2pt_replyreq_free(*replyreq);
return ret;
}
return OMPI_SUCCESS;
}
static void ompi_osc_pt2pt_replyreq_construct(ompi_osc_pt2pt_replyreq_t *replyreq)
{
OBJ_CONSTRUCT(&(replyreq->rep_target_convertor), opal_convertor_t);
}
static void ompi_osc_pt2pt_replyreq_destruct(ompi_osc_pt2pt_replyreq_t *replyreq)
{
OBJ_DESTRUCT(&(replyreq->rep_target_convertor));
}
OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_replyreq_t, opal_list_item_t,
ompi_osc_pt2pt_replyreq_construct,
ompi_osc_pt2pt_replyreq_destruct);

Просмотреть файл

@ -1,143 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_PT2PT_REPLYREQ_H
#define OMPI_OSC_PT2PT_REPLYREQ_H
#include "osc_pt2pt.h"
#include "osc_pt2pt_longreq.h"
#include "opal/types.h"
#include "opal/class/opal_list.h"
#include "ompi/datatype/ompi_datatype.h"
#include "opal/datatype/opal_convertor.h"
#include "ompi/communicator/communicator.h"
#include "ompi/proc/proc.h"
#include "ompi/memchecker.h"
struct ompi_osc_pt2pt_replyreq_t {
opal_list_item_t super;
/** pointer to the module that created the replyreq */
ompi_osc_pt2pt_module_t *rep_module;
/** Datatype for the target side of the operation */
struct ompi_datatype_t *rep_target_datatype;
/** Convertor for the target. Always setup for send. */
opal_convertor_t rep_target_convertor;
/** packed size of message on the target side */
size_t rep_target_bytes_packed;
/** rank in module's communicator for origin of operation */
int rep_origin_rank;
/** pointer to the proc structure for the origin of the operation */
ompi_proc_t *rep_origin_proc;
ompi_ptr_t rep_origin_sendreq;
};
typedef struct ompi_osc_pt2pt_replyreq_t ompi_osc_pt2pt_replyreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_replyreq_t);
/** allocate and populate a replyreq structure. datatype is
RETAINed for the life of the replyreq */
int
ompi_osc_pt2pt_replyreq_alloc_init(ompi_osc_pt2pt_module_t *module,
int origin,
ompi_ptr_t origin_request,
OPAL_PTRDIFF_TYPE target_displacement,
int target_count,
struct ompi_datatype_t *datatype,
ompi_osc_pt2pt_replyreq_t **replyreq);
static inline int
ompi_osc_pt2pt_replyreq_alloc(ompi_osc_pt2pt_module_t *module,
int origin_rank,
ompi_osc_pt2pt_replyreq_t **replyreq)
{
int ret;
opal_free_list_item_t *item;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, origin_rank );
/* BWB - FIX ME - is this really the right return code? */
if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE;
OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_replyreqs,
item, ret);
if (OMPI_SUCCESS != ret) return ret;
*replyreq = (ompi_osc_pt2pt_replyreq_t*) item;
(*replyreq)->rep_module = module;
(*replyreq)->rep_origin_rank = origin_rank;
(*replyreq)->rep_origin_proc = proc;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_replyreq_init_target(ompi_osc_pt2pt_replyreq_t *replyreq,
void *target_addr,
int target_count,
struct ompi_datatype_t *target_dt)
{
OBJ_RETAIN(target_dt);
replyreq->rep_target_datatype = target_dt;
opal_convertor_copy_and_prepare_for_send(replyreq->rep_origin_proc->proc_convertor,
&(target_dt->super),
target_count,
target_addr,
0,
&(replyreq->rep_target_convertor));
opal_convertor_get_packed_size(&replyreq->rep_target_convertor,
&replyreq->rep_target_bytes_packed);
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_replyreq_init_origin(ompi_osc_pt2pt_replyreq_t *replyreq,
ompi_ptr_t origin_request)
{
replyreq->rep_origin_sendreq = origin_request;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_replyreq_free(ompi_osc_pt2pt_replyreq_t *replyreq)
{
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_defined,
&replyreq->rep_target_convertor);
);
opal_convertor_cleanup(&replyreq->rep_target_convertor);
OBJ_RELEASE(replyreq->rep_target_datatype);
OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_replyreqs,
(opal_list_item_t*) replyreq);
return OMPI_SUCCESS;
}
#endif /* OMPI_OSC_PT2PT_REPLYREQ_H */

Просмотреть файл

@ -1,85 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_pt2pt_sendreq.h"
#include "opal/datatype/opal_convertor.h"
int
ompi_osc_pt2pt_sendreq_alloc_init(ompi_osc_pt2pt_req_type_t req_type,
void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_sendreq_t **sendreq)
{
int ret;
/* allocate a sendreq */
ret = ompi_osc_pt2pt_sendreq_alloc(module, target,
sendreq);
if (OMPI_SUCCESS != ret) return ret;
/* initialize local side of sendreq */
ret = ompi_osc_pt2pt_sendreq_init_origin(*sendreq,
req_type,
origin_addr,
origin_count,
origin_dt);
if (OMPI_SUCCESS != ret) {
ompi_osc_pt2pt_sendreq_free(*sendreq);
return ret;
}
/* initialize remote side of sendreq */
ret = ompi_osc_pt2pt_sendreq_init_target(*sendreq,
target_disp,
target_count,
target_dt);
if (OMPI_SUCCESS != ret) {
ompi_osc_pt2pt_sendreq_free(*sendreq);
return ret;
}
return OMPI_SUCCESS;
}
static void ompi_osc_pt2pt_sendreq_construct(ompi_osc_pt2pt_sendreq_t *req)
{
req->super.req_type = OMPI_REQUEST_WIN;
req->super.req_free = NULL;
req->super.req_cancel = NULL;
OBJ_CONSTRUCT(&(req->req_origin_convertor), opal_convertor_t);
}
static void ompi_osc_pt2pt_sendreq_destruct(ompi_osc_pt2pt_sendreq_t *req)
{
OBJ_DESTRUCT(&(req->req_origin_convertor));
}
OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_sendreq_t, ompi_request_t,
ompi_osc_pt2pt_sendreq_construct,
ompi_osc_pt2pt_sendreq_destruct);

Просмотреть файл

@ -1,180 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_PT2PT_SENDREQ_H
#define OMPI_OSC_PT2PT_SENDREQ_H
#include "osc_pt2pt.h"
#include "osc_pt2pt_longreq.h"
#include "opal/class/opal_list.h"
#include "ompi/datatype/ompi_datatype.h"
#include "opal/datatype/opal_convertor.h"
#include "ompi/communicator/communicator.h"
#include "ompi/proc/proc.h"
#include "ompi/memchecker.h"
typedef enum {
OMPI_OSC_PT2PT_GET,
OMPI_OSC_PT2PT_ACC,
OMPI_OSC_PT2PT_PUT
} ompi_osc_pt2pt_req_type_t;
struct ompi_osc_pt2pt_sendreq_t {
ompi_request_t super;
/** type of sendreq (from ompi_osc_pt2pt_req_type_t) */
ompi_osc_pt2pt_req_type_t req_type;
/** pointer to the module that created the sendreq */
ompi_osc_pt2pt_module_t *req_module;
/** Datatype for the origin side of the operation */
struct ompi_datatype_t *req_origin_datatype;
/** Convertor for the origin side of the operation. Setup for
either send (Put / Accumulate) or receive (Get) */
opal_convertor_t req_origin_convertor;
/** packed size of message on the origin side */
size_t req_origin_bytes_packed;
/** rank in module's communicator for target of operation */
int req_target_rank;
/** pointer to the proc structure for the target of the operation */
ompi_proc_t *req_target_proc;
/** displacement on target */
OPAL_PTRDIFF_TYPE req_target_disp;
/** datatype count on target */
int req_target_count;
/** datatype on target */
struct ompi_datatype_t *req_target_datatype;
/** op index on the target */
int req_op_id;
};
typedef struct ompi_osc_pt2pt_sendreq_t ompi_osc_pt2pt_sendreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_sendreq_t);
/** allocate and populate a sendreq structure. Both datatypes are
RETAINed for the life of the sendreq */
int
ompi_osc_pt2pt_sendreq_alloc_init(ompi_osc_pt2pt_req_type_t req_type,
void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
ompi_osc_pt2pt_module_t *module,
ompi_osc_pt2pt_sendreq_t **sendreq);
static inline int
ompi_osc_pt2pt_sendreq_alloc(ompi_osc_pt2pt_module_t *module,
int target_rank,
ompi_osc_pt2pt_sendreq_t **sendreq)
{
int ret;
opal_free_list_item_t *item;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, target_rank );
/* BWB - FIX ME - is this really the right return code? */
if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE;
OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_sendreqs,
item, ret);
if (OMPI_SUCCESS != ret) return ret;
*sendreq = (ompi_osc_pt2pt_sendreq_t*) item;
(*sendreq)->req_module = module;
(*sendreq)->req_target_rank = target_rank;
(*sendreq)->req_target_proc = proc;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_sendreq_init_origin(ompi_osc_pt2pt_sendreq_t *sendreq,
ompi_osc_pt2pt_req_type_t req_type,
void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt)
{
OBJ_RETAIN(origin_dt);
sendreq->req_origin_datatype = origin_dt;
sendreq->req_type = req_type;
if (req_type != OMPI_OSC_PT2PT_GET) {
opal_convertor_copy_and_prepare_for_send(sendreq->req_target_proc->proc_convertor,
&(origin_dt->super),
origin_count,
origin_addr,
0,
&(sendreq->req_origin_convertor));
opal_convertor_get_packed_size(&sendreq->req_origin_convertor,
&sendreq->req_origin_bytes_packed);
} else {
opal_convertor_copy_and_prepare_for_recv(sendreq->req_target_proc->proc_convertor,
&(origin_dt->super),
origin_count,
origin_addr,
0,
&(sendreq->req_origin_convertor));
opal_convertor_get_packed_size(&sendreq->req_origin_convertor,
&sendreq->req_origin_bytes_packed);
}
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_sendreq_init_target(ompi_osc_pt2pt_sendreq_t *sendreq,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype)
{
OBJ_RETAIN(target_datatype);
sendreq->req_target_disp = target_disp;
sendreq->req_target_count = target_count;
sendreq->req_target_datatype = target_datatype;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_pt2pt_sendreq_free(ompi_osc_pt2pt_sendreq_t *sendreq)
{
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_defined,
&sendreq->req_origin_convertor);
);
opal_convertor_cleanup(&sendreq->req_origin_convertor);
OBJ_RELEASE(sendreq->req_target_datatype);
OBJ_RELEASE(sendreq->req_origin_datatype);
OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_sendreqs,
(opal_list_item_t*) sendreq);
return OMPI_SUCCESS;
}
#endif /* OMPI_OSC_PT2PT_SENDREQ_H */

Просмотреть файл

@ -1,698 +0,0 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2013 The University of Tennessee and The University
* of Tennessee Research Foundation. 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 (c) 2012 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_pt2pt.h"
#include "osc_pt2pt_sendreq.h"
#include "osc_pt2pt_header.h"
#include "osc_pt2pt_data_move.h"
#include "mpi.h"
#include "opal/runtime/opal_progress.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/mca/osc/base/base.h"
/* Must hold module's lock before calling... */
static inline void
ompi_osc_pt2pt_flip_sendreqs(ompi_osc_pt2pt_module_t *module)
{
unsigned int *tmp;
tmp = module->p2p_copy_num_pending_sendreqs;
module->p2p_copy_num_pending_sendreqs =
module->p2p_num_pending_sendreqs;
module->p2p_num_pending_sendreqs = tmp;
memset(module->p2p_num_pending_sendreqs, 0,
sizeof(unsigned int) * ompi_comm_size(module->p2p_comm));
/* Copy in all the pending requests */
opal_list_join(&module->p2p_copy_pending_sendreqs,
opal_list_get_end(&module->p2p_copy_pending_sendreqs),
&module->p2p_pending_sendreqs);
}
int
ompi_osc_pt2pt_module_fence(int assert, ompi_win_t *win)
{
unsigned int incoming_reqs;
int ret = OMPI_SUCCESS, i;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
int num_outgoing = 0;
if (0 != (assert & MPI_MODE_NOPRECEDE)) {
/* check that the user didn't lie to us - since NOPRECEDED
must be specified by all processes if it is specified by
any process, if we see this it is safe to assume that there
are no pending operations anywhere needed to close out this
epoch. No need to lock, since it's a lookup and any
pending modification of the pending_sendreqs during this
time is an erroneous program. */
if (0 != opal_list_get_size(&(module->p2p_pending_sendreqs))) {
return MPI_ERR_RMA_SYNC;
}
} else {
opal_list_item_t *item;
/* "atomically" copy all the data we're going to be modifying
into the copy... */
OPAL_THREAD_LOCK(&(module->p2p_lock));
ompi_osc_pt2pt_flip_sendreqs(module);
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
num_outgoing = opal_list_get_size(&(module->p2p_copy_pending_sendreqs));
/* find out how much data everyone is going to send us. */
ret = module->p2p_comm->
c_coll.coll_reduce_scatter(module->p2p_copy_num_pending_sendreqs,
&incoming_reqs,
module->p2p_fence_coll_counts,
MPI_UNSIGNED,
MPI_SUM,
module->p2p_comm,
module->p2p_comm->c_coll.coll_reduce_scatter_module);
if (OMPI_SUCCESS != ret) {
/* put the stupid data back for the user. This is not
cheap, but the user lost his data if we don't. */
OPAL_THREAD_LOCK(&(module->p2p_lock));
opal_list_join(&module->p2p_pending_sendreqs,
opal_list_get_end(&module->p2p_pending_sendreqs),
&module->p2p_copy_pending_sendreqs);
for (i = 0 ; i < ompi_comm_size(module->p2p_comm) ; ++i) {
module->p2p_num_pending_sendreqs[i] +=
module->p2p_copy_num_pending_sendreqs[i];
}
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
return ret;
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"fence: waiting on %d in and %d out",
module->p2p_num_pending_in,
module->p2p_num_pending_out));
/* try to start all the requests. We've copied everything we
need out of pending_sendreqs, so don't need the lock
here */
while (NULL !=
(item = opal_list_remove_first(&(module->p2p_copy_pending_sendreqs)))) {
ompi_osc_pt2pt_sendreq_t *req =
(ompi_osc_pt2pt_sendreq_t*) item;
ret = ompi_osc_pt2pt_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_output_verbose(5, ompi_osc_base_framework.framework_output,
"complete: failure in starting sendreq (%d). Will try later.",
ret);
opal_list_append(&(module->p2p_copy_pending_sendreqs), item);
} else if (OMPI_SUCCESS != ret) {
return ret;
}
}
OPAL_THREAD_LOCK(&module->p2p_lock);
/* possible we've already received a couple in messages, so
add however many we're going to wait for */
module->p2p_num_pending_in += incoming_reqs;
module->p2p_num_pending_out += num_outgoing;
/* now we know how many things we're waiting for - wait for them... */
while (module->p2p_num_pending_in > 0 ||
0 != module->p2p_num_pending_out) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
OPAL_THREAD_UNLOCK(&module->p2p_lock);
}
/* all transfers are done - back to the real world we go */
if (0 == (assert & MPI_MODE_NOSUCCEED)) {
ompi_win_set_mode(win, OMPI_WIN_FENCE);
} else {
ompi_win_set_mode(win, 0);
}
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_start(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int i, ret = OMPI_SUCCESS;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
OPAL_THREAD_LOCK(&(module->p2p_lock));
if (NULL != module->p2p_sc_group) {
OPAL_THREAD_UNLOCK(&module->p2p_lock);
ret = MPI_ERR_RMA_SYNC;
goto cleanup;
}
module->p2p_sc_group = group;
/* possible we've already received a couple in messages, so
add however many we're going to wait for */
module->p2p_num_post_msgs += ompi_group_size(module->p2p_sc_group);
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
memset(module->p2p_sc_remote_active_ranks, 0,
sizeof(bool) * ompi_comm_size(module->p2p_comm));
/* for each process in the specified group, find it's rank in our
communicator, store those indexes, and set the true / false in
the active ranks table */
for (i = 0 ; i < ompi_group_size(group) ; i++) {
int comm_rank = -1, j;
/* find the rank in the communicator associated with this windows */
for (j = 0 ; j < ompi_comm_size(module->p2p_comm) ; ++j) {
if (ompi_group_peer_lookup(module->p2p_sc_group, i) ==
ompi_comm_peer_lookup(module->p2p_comm, j)) {
comm_rank = j;
break;
}
}
if (comm_rank == -1) {
ret = MPI_ERR_RMA_SYNC;
goto cleanup;
}
module->p2p_sc_remote_active_ranks[comm_rank] = true;
module->p2p_sc_remote_ranks[i] = comm_rank;
}
/* Set our mode to access w/ start */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_STARTED);
return OMPI_SUCCESS;
cleanup:
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return ret;
}
int
ompi_osc_pt2pt_module_complete(ompi_win_t *win)
{
int i;
int ret = OMPI_SUCCESS;
ompi_group_t *group;
opal_list_item_t *item;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
/* wait for all the post messages */
OPAL_THREAD_LOCK(&module->p2p_lock);
while (0 != module->p2p_num_post_msgs) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
ompi_osc_pt2pt_flip_sendreqs(module);
/* for each process in group, send a control message with number
of updates coming, then start all the requests */
for (i = 0 ; i < ompi_group_size(module->p2p_sc_group) ; ++i) {
int comm_rank = module->p2p_sc_remote_ranks[i];
module->p2p_num_pending_out +=
module->p2p_copy_num_pending_sendreqs[comm_rank];
}
OPAL_THREAD_UNLOCK(&module->p2p_lock);
for (i = 0 ; i < ompi_group_size(module->p2p_sc_group) ; ++i) {
int comm_rank = module->p2p_sc_remote_ranks[i];
ret = ompi_osc_pt2pt_control_send(module,
ompi_group_peer_lookup(module->p2p_sc_group, i),
OMPI_OSC_PT2PT_HDR_COMPLETE,
module->p2p_copy_num_pending_sendreqs[comm_rank],
0);
assert(ret == OMPI_SUCCESS);
}
/* try to start all the requests. We've copied everything we
need out of pending_sendreqs, so don't need the lock
here */
while (NULL !=
(item = opal_list_remove_first(&(module->p2p_copy_pending_sendreqs)))) {
ompi_osc_pt2pt_sendreq_t *req =
(ompi_osc_pt2pt_sendreq_t*) item;
ret = ompi_osc_pt2pt_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_output_verbose(5, ompi_osc_base_framework.framework_output,
"complete: failure in starting sendreq (%d). Will try later.",
ret);
opal_list_append(&(module->p2p_copy_pending_sendreqs), item);
} else if (OMPI_SUCCESS != ret) {
return ret;
}
}
/* wait for all the requests */
OPAL_THREAD_LOCK(&module->p2p_lock);
while (0 != module->p2p_num_pending_out) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
group = module->p2p_sc_group;
module->p2p_sc_group = NULL;
OPAL_THREAD_UNLOCK(&module->p2p_lock);
/* remove WIN_POSTED from our mode */
ompi_win_remove_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_STARTED);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return ret;
}
int
ompi_osc_pt2pt_module_post(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int i;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
OPAL_THREAD_LOCK(&(module->p2p_lock));
assert(NULL == module->p2p_pw_group);
module->p2p_pw_group = group;
/* Set our mode to expose w/ post */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
/* list how many complete counters we're still waiting on */
module->p2p_num_complete_msgs +=
ompi_group_size(module->p2p_pw_group);
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
/* send a hello counter to everyone in group */
for (i = 0 ; i < ompi_group_size(module->p2p_pw_group) ; ++i) {
ompi_osc_pt2pt_control_send(module,
ompi_group_peer_lookup(group, i),
OMPI_OSC_PT2PT_HDR_POST, 1, 0);
}
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_wait(ompi_win_t *win)
{
ompi_group_t *group;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
OPAL_THREAD_LOCK(&module->p2p_lock);
while (0 != (module->p2p_num_pending_in) ||
0 != (module->p2p_num_complete_msgs)) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
group = module->p2p_pw_group;
module->p2p_pw_group = NULL;
OPAL_THREAD_UNLOCK(&module->p2p_lock);
ompi_win_remove_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_test(ompi_win_t *win,
int *flag)
{
ompi_group_t *group;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
#if !OMPI_ENABLE_PROGRESS_THREADS
opal_progress();
#endif
if (0 != (module->p2p_num_pending_in) ||
0 != (module->p2p_num_complete_msgs)) {
*flag = 0;
return OMPI_SUCCESS;
}
*flag = 1;
ompi_win_remove_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
OPAL_THREAD_LOCK(&(module->p2p_lock));
group = module->p2p_pw_group;
module->p2p_pw_group = NULL;
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return OMPI_SUCCESS;
}
struct ompi_osc_pt2pt_pending_lock_t {
opal_list_item_t super;
ompi_proc_t *proc;
int32_t lock_type;
};
typedef struct ompi_osc_pt2pt_pending_lock_t ompi_osc_pt2pt_pending_lock_t;
OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_pending_lock_t, opal_list_item_t,
NULL, NULL);
int
ompi_osc_pt2pt_module_lock(int lock_type,
int target,
int assert,
ompi_win_t *win)
{
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, target );
assert(lock_type != 0);
/* set our mode on the window */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_LOCK_ACCESS);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: sending lock request to %d",
ompi_comm_rank(module->p2p_comm),
target));
/* generate a lock request */
ompi_osc_pt2pt_control_send(module,
proc,
OMPI_OSC_PT2PT_HDR_LOCK_REQ,
ompi_comm_rank(module->p2p_comm),
lock_type);
if (ompi_comm_rank(module->p2p_comm) == target) {
/* If we're trying to lock locally, have to wait to actually
acquire the lock */
OPAL_THREAD_LOCK(&module->p2p_lock);
while (module->p2p_lock_received_ack == 0) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
OPAL_THREAD_UNLOCK(&module->p2p_lock);
}
/* return */
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_module_unlock(int target,
ompi_win_t *win)
{
int32_t out_count;
opal_list_item_t *item;
int ret;
ompi_osc_pt2pt_module_t *module = P2P_MODULE(win);
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, target );
OPAL_THREAD_LOCK(&module->p2p_lock);
while (0 == module->p2p_lock_received_ack) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
module->p2p_lock_received_ack -= 1;
/* start all the requests */
ompi_osc_pt2pt_flip_sendreqs(module);
/* try to start all the requests. We've copied everything we need
out of pending_sendreqs, so don't need the lock here */
out_count = opal_list_get_size(&(module->p2p_copy_pending_sendreqs));
/* we want to send all the requests, plus we wait for one more
completion event for the control message ack from the unlocker
saying we're done */
module->p2p_num_pending_out += (out_count + 1);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
/* send the unlock request */
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: sending unlock request to %d with %d requests",
ompi_comm_rank(module->p2p_comm), target,
out_count));
ompi_osc_pt2pt_control_send(module,
proc,
OMPI_OSC_PT2PT_HDR_UNLOCK_REQ,
ompi_comm_rank(module->p2p_comm),
out_count);
while (NULL !=
(item = opal_list_remove_first(&(module->p2p_copy_pending_sendreqs)))) {
ompi_osc_pt2pt_sendreq_t *req =
(ompi_osc_pt2pt_sendreq_t*) item;
ret = ompi_osc_pt2pt_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_output_verbose(5, ompi_osc_base_framework.framework_output,
"complete: failure in starting sendreq (%d). Will try later.",
ret);
opal_list_append(&(module->p2p_copy_pending_sendreqs), item);
} else if (OMPI_SUCCESS != ret) {
return ret;
}
}
/* wait for all the requests */
OPAL_THREAD_LOCK(&module->p2p_lock);
while (0 != module->p2p_num_pending_out) {
opal_condition_wait(&module->p2p_cond, &module->p2p_lock);
}
OPAL_THREAD_UNLOCK(&module->p2p_lock);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: finished unlock to %d",
ompi_comm_rank(module->p2p_comm), target));
/* set our mode on the window */
ompi_win_remove_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_LOCK_ACCESS);
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_passive_lock(ompi_osc_pt2pt_module_t *module,
int32_t origin,
int32_t lock_type)
{
bool send_ack = false;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, origin );
ompi_osc_pt2pt_pending_lock_t *new_pending;
OPAL_THREAD_LOCK(&(module->p2p_lock));
if (lock_type == MPI_LOCK_EXCLUSIVE) {
if (module->p2p_lock_status == 0) {
module->p2p_lock_status = MPI_LOCK_EXCLUSIVE;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: setting lock status to EXCLUSIVE (from %d)",
ompi_comm_rank(module->p2p_comm), origin));
ompi_win_append_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
send_ack = true;
} else {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: queuing lock request from %d (type=%d)",
ompi_comm_rank(module->p2p_comm), origin, lock_type));
new_pending = OBJ_NEW(ompi_osc_pt2pt_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = lock_type;
opal_list_append(&(module->p2p_locks_pending), &(new_pending->super));
}
} else if (lock_type == MPI_LOCK_SHARED) {
if (module->p2p_lock_status != MPI_LOCK_EXCLUSIVE) {
module->p2p_lock_status = MPI_LOCK_SHARED;
module->p2p_shared_count++;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: setting lock status to SHARED (from %d), count %d",
ompi_comm_rank(module->p2p_comm), origin, module->p2p_shared_count));
ompi_win_append_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
send_ack = true;
} else {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: queuing lock request from %d (type=%d)",
ompi_comm_rank(module->p2p_comm), origin, lock_type));
new_pending = OBJ_NEW(ompi_osc_pt2pt_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = lock_type;
opal_list_append(&(module->p2p_locks_pending), &(new_pending->super));
}
}
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
if (send_ack) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: sending lock ack to %d",
ompi_comm_rank(module->p2p_comm), origin));
ompi_osc_pt2pt_control_send(module, proc,
OMPI_OSC_PT2PT_HDR_LOCK_REQ,
ompi_comm_rank(module->p2p_comm),
OMPI_SUCCESS);
}
return OMPI_SUCCESS;
}
int
ompi_osc_pt2pt_passive_unlock(ompi_osc_pt2pt_module_t *module,
int32_t origin,
int32_t count)
{
ompi_proc_t *proc = ompi_comm_peer_lookup( module->p2p_comm, origin );
ompi_osc_pt2pt_pending_lock_t *new_pending = NULL;
assert(module->p2p_lock_status != 0);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: received unlock request from %d with %d requests\n",
ompi_comm_rank(module->p2p_comm),
origin, count));
new_pending = OBJ_NEW(ompi_osc_pt2pt_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = 0;
OPAL_THREAD_LOCK(&(module->p2p_lock));
module->p2p_num_pending_in += count;
opal_list_append(&module->p2p_unlocks_pending, &(new_pending->super));
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
return ompi_osc_pt2pt_passive_unlock_complete(module);
}
int
ompi_osc_pt2pt_passive_unlock_complete(ompi_osc_pt2pt_module_t *module)
{
ompi_osc_pt2pt_pending_lock_t *new_pending = NULL;
opal_list_t copy_unlock_acks;
if (module->p2p_num_pending_in != 0) return OMPI_SUCCESS;
OPAL_THREAD_LOCK(&(module->p2p_lock));
if (module->p2p_num_pending_in != 0) {
OPAL_THREAD_UNLOCK(&module->p2p_lock);
return OMPI_SUCCESS;
}
if (module->p2p_lock_status == MPI_LOCK_EXCLUSIVE) {
ompi_win_remove_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
module->p2p_lock_status = 0;
} else {
module->p2p_shared_count -= opal_list_get_size(&module->p2p_unlocks_pending);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: decrementing shared count to %d",
ompi_comm_rank(module->p2p_comm),
module->p2p_shared_count));
if (module->p2p_shared_count == 0) {
ompi_win_remove_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
module->p2p_lock_status = 0;
}
}
OBJ_CONSTRUCT(&copy_unlock_acks, opal_list_t);
/* copy over any unlocks that have been satisfied (possibly
multiple if SHARED) */
opal_list_join(&copy_unlock_acks,
opal_list_get_end(&copy_unlock_acks),
&module->p2p_unlocks_pending);
OPAL_THREAD_UNLOCK(&module->p2p_lock);
/* issue whichever unlock acks we should issue */
while (NULL != (new_pending = (ompi_osc_pt2pt_pending_lock_t*)
opal_list_remove_first(&copy_unlock_acks))) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: sending unlock ack to proc %d",
ompi_comm_rank(module->p2p_comm),
new_pending->proc->proc_name.vpid));
ompi_osc_pt2pt_control_send(module,
new_pending->proc,
OMPI_OSC_PT2PT_HDR_UNLOCK_REPLY,
OMPI_SUCCESS, OMPI_SUCCESS);
OBJ_RELEASE(new_pending);
}
OBJ_DESTRUCT(&copy_unlock_acks);
/* if we were really unlocked, see if we have another lock request
we can satisfy */
OPAL_THREAD_LOCK(&module->p2p_lock);
if (0 == module->p2p_lock_status) {
new_pending = (ompi_osc_pt2pt_pending_lock_t*)
opal_list_remove_first(&(module->p2p_locks_pending));
if (NULL != new_pending) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"%d: sending lock ack to proc %d",
ompi_comm_rank(module->p2p_comm),
new_pending->proc->proc_name.vpid));
ompi_win_append_mode(module->p2p_win, OMPI_WIN_EXPOSE_EPOCH);
/* set lock state and generate a lock request */
module->p2p_lock_status = new_pending->lock_type;
if (MPI_LOCK_SHARED == new_pending->lock_type) {
module->p2p_shared_count++;
}
}
} else {
new_pending = NULL;
}
OPAL_THREAD_UNLOCK(&(module->p2p_lock));
if (NULL != new_pending) {
ompi_osc_pt2pt_control_send(module,
new_pending->proc,
OMPI_OSC_PT2PT_HDR_LOCK_REQ,
ompi_comm_rank(module->p2p_comm),
OMPI_SUCCESS);
OBJ_RELEASE(new_pending);
}
return OMPI_SUCCESS;
}

Просмотреть файл

@ -15,22 +15,21 @@
# $HEADER$
#
pt2pt_sources = \
rdma_sources = \
osc_rdma.h \
osc_rdma.c \
osc_rdma_comm.c \
osc_rdma_component.c \
osc_rdma_data_move.h \
osc_rdma_data_move.c \
osc_rdma_frag.h \
osc_rdma_frag.c \
osc_rdma_header.h \
osc_rdma_longreq.h \
osc_rdma_longreq.c \
osc_rdma_obj_convert.h \
osc_rdma_replyreq.h \
osc_rdma_replyreq.c \
osc_rdma_sendreq.h \
osc_rdma_sendreq.c \
osc_rdma_sync.c
osc_rdma_request.h \
osc_rdma_request.c \
osc_rdma_active_target.c \
osc_rdma_passive_target.c
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
@ -46,9 +45,9 @@ endif
mcacomponentdir = $(ompilibdir)
mcacomponent_LTLIBRARIES = $(component_install)
mca_osc_rdma_la_SOURCES = $(pt2pt_sources)
mca_osc_rdma_la_SOURCES = $(rdma_sources)
mca_osc_rdma_la_LDFLAGS = -module -avoid-version
noinst_LTLIBRARIES = $(component_noinst)
libmca_osc_rdma_la_SOURCES = $(pt2pt_sources)
libmca_osc_rdma_la_SOURCES = $(rdma_sources)
libmca_osc_rdma_la_LDFLAGS = -module -avoid-version

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
@ -7,8 +8,9 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Los Alamos National Security, LLC. All rights
* Copyright (c) 2007-2014 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -19,7 +21,6 @@
#include "ompi_config.h"
#include "osc_rdma.h"
#include "osc_rdma_sendreq.h"
#include "opal/threads/mutex.h"
#include "ompi/win/win.h"
@ -30,108 +31,81 @@
int
ompi_osc_rdma_module_free(ompi_win_t *win)
ompi_osc_rdma_attach(struct ompi_win_t *win, void *base, size_t len)
{
int ret = OMPI_SUCCESS;
int i;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"rdma component destroying window with id %d",
ompi_comm_get_cid(module->m_comm));
/* finish with a barrier */
if (ompi_group_size(win->w_group) > 1) {
ret = module->m_comm->c_coll.coll_barrier(module->m_comm,
module->m_comm->c_coll.coll_barrier_module);
}
/* remove from component information */
OPAL_THREAD_LOCK(&mca_osc_rdma_component.c_lock);
opal_hash_table_remove_value_uint32(&mca_osc_rdma_component.c_modules,
ompi_comm_get_cid(module->m_comm));
OPAL_THREAD_UNLOCK(&mca_osc_rdma_component.c_lock);
win->w_osc_module = NULL;
OBJ_DESTRUCT(&module->m_unlocks_pending);
OBJ_DESTRUCT(&module->m_locks_pending);
OBJ_DESTRUCT(&module->m_queued_sendreqs);
OBJ_DESTRUCT(&module->m_copy_pending_sendreqs);
OBJ_DESTRUCT(&module->m_pending_sendreqs);
OBJ_DESTRUCT(&module->m_acc_lock);
OBJ_DESTRUCT(&module->m_cond);
OBJ_DESTRUCT(&module->m_lock);
if (NULL != module->m_sc_remote_ranks) {
free(module->m_sc_remote_ranks);
}
if (NULL != module->m_sc_remote_active_ranks) {
free(module->m_sc_remote_active_ranks);
}
if (NULL != module->m_pending_buffers) {
free(module->m_pending_buffers);
}
if (NULL != module->m_fence_coll_counts) {
free(module->m_fence_coll_counts);
}
if (NULL != module->m_copy_num_pending_sendreqs) {
free(module->m_copy_num_pending_sendreqs);
}
if (NULL != module->m_num_pending_sendreqs) {
free(module->m_num_pending_sendreqs);
}
if (NULL != module->m_peer_info) {
for (i = 0 ; i < ompi_comm_size(module->m_comm) ; ++i) {
ompi_osc_rdma_peer_info_free(&module->m_peer_info[i]);
}
free(module->m_peer_info);
}
if (NULL != module->m_comm) ompi_comm_free(&module->m_comm);
if (NULL != module) free(module);
return ret;
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_peer_info_free(ompi_osc_rdma_peer_info_t *peer_info)
ompi_osc_rdma_detach(struct ompi_win_t *win, void *base)
{
int i;
if (NULL != peer_info->peer_btls) {
free(peer_info->peer_btls);
}
if (NULL != peer_info->local_descriptors) {
for (i = 0 ; i < peer_info->local_num_btls ; ++i) {
if (NULL != peer_info->local_descriptors[i]) {
mca_bml_base_btl_t *bml_btl = peer_info->local_btls[i];
mca_btl_base_module_t* btl = bml_btl->btl;
btl->btl_free(btl, peer_info->local_descriptors[i]);
}
}
free(peer_info->local_descriptors);
}
if (NULL != peer_info->local_registrations) {
for (i = 0 ; i < peer_info->local_num_btls ; ++i) {
if (NULL != peer_info->local_registrations[i]) {
mca_mpool_base_module_t *module =
peer_info->local_registrations[i]->mpool;
module->mpool_deregister(module,
peer_info->local_registrations[i]);
}
}
free(peer_info->local_registrations);
}
if (NULL != peer_info->local_btls) {
free(peer_info->local_btls);
}
memset(peer_info, 0, sizeof(ompi_osc_rdma_peer_info_t));
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_free(ompi_win_t *win)
{
int ret = OMPI_SUCCESS;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
opal_list_item_t *item;
assert (NULL != module);
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"rdma component destroying window with id %d",
ompi_comm_get_cid(module->comm));
/* finish with a barrier */
if (ompi_group_size(win->w_group) > 1) {
ret = module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
}
/* remove from component information */
OPAL_THREAD_LOCK(&mca_osc_rdma_component.lock);
opal_hash_table_remove_value_uint32(&mca_osc_rdma_component.modules,
ompi_comm_get_cid(module->comm));
OPAL_THREAD_UNLOCK(&mca_osc_rdma_component.lock);
win->w_osc_module = NULL;
OBJ_DESTRUCT(&module->outstanding_locks);
OBJ_DESTRUCT(&module->locks_pending);
OBJ_DESTRUCT(&module->acc_lock);
OBJ_DESTRUCT(&module->cond);
OBJ_DESTRUCT(&module->lock);
/* it is erroneous to close a window with active operations on it so we should
* probably produce an error here instead of cleaning up */
while (NULL != (item = opal_list_remove_first (&module->pending_acc))) {
OBJ_RELEASE(item);
}
OBJ_DESTRUCT(&module->pending_acc);
osc_rdma_request_gc_clean (module);
assert (0 == opal_list_get_size (&module->request_gc));
OBJ_DESTRUCT(&module->request_gc);
if (NULL != module->peers) {
free(module->peers);
}
if (NULL != module->passive_eager_send_active) free(module->passive_eager_send_active);
if (NULL != module->passive_incoming_frag_count) free(module->passive_incoming_frag_count);
if (NULL != module->passive_incoming_frag_signal_count) free(module->passive_incoming_frag_signal_count);
if (NULL != module->epoch_outgoing_frag_count) free(module->epoch_outgoing_frag_count);
if (NULL != module->incomming_buffer) free (module->incomming_buffer);
if (NULL != module->comm) ompi_comm_free(&module->comm);
if (NULL != module->free_after) free(module->free_after);
if (NULL != module->frag_request) {
module->frag_request->req_complete_cb = NULL;
ompi_request_cancel (module->frag_request);
}
free (module);
return ret;
}

Просмотреть файл

@ -1,19 +1,21 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2006 The Trustees of the University of Tennessee.
* All rights reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2007-2014 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
*
* Additional copyrights may follow
*
*
* $HEADER$
*/
@ -28,234 +30,194 @@
#include "ompi/win/win.h"
#include "ompi/communicator/communicator.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/request/request.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/btl/btl.h"
#include "ompi/mca/bml/bml.h"
#include "ompi/memchecker.h"
#include "osc_rdma_header.h"
BEGIN_C_DECLS
struct ompi_osc_rdma_buffer_t {
mca_btl_base_descriptor_t* descriptor;
size_t remain_len;
mca_bml_base_btl_t *bml_btl;
};
typedef struct ompi_osc_rdma_buffer_t ompi_osc_rdma_buffer_t;
struct ompi_osc_rdma_frag_t;
struct ompi_osc_rdma_component_t {
/** Extend the basic osc component interface */
ompi_osc_base_component_t super;
/** lock access to datastructures in the component structure */
opal_mutex_t c_lock;
/** lock access to modules */
opal_mutex_t lock;
/** List of ompi_osc_rdma_module_ts currently in existance.
Needed so that received fragments can be dispatched to the
correct module */
opal_hash_table_t c_modules;
/** cid -> module mapping */
opal_hash_table_t modules;
/** Lock for request management */
opal_mutex_t c_request_lock;
/** module count */
int module_count;
/** Condition variable for request management */
opal_condition_t c_request_cond;
/** free list of ompi_osc_rdma_sendreq_t structures */
opal_free_list_t c_sendreqs;
/** free list of ompi_osc_rdma_replyreq_t structures */
opal_free_list_t c_replyreqs;
/** free list of ompi_osc_rdma_longreq_t structures */
opal_free_list_t c_longreqs;
/** free list of ompi_osc_rdma_frag_t structures */
opal_free_list_t frags;
bool c_btl_registered;
/** Free list of requests */
ompi_free_list_t requests;
uint32_t c_sequence_number;
/** RDMA component buffer size */
unsigned int buffer_size;
/** List of operations that need to be processed */
opal_list_t pending_operations;
/** Is the progress function enabled? */
bool progress_enable;
};
typedef struct ompi_osc_rdma_component_t ompi_osc_rdma_component_t;
struct ompi_osc_rdma_btl_t {
uint8_t peer_seg[MCA_BTL_SEG_MAX_SIZE];
mca_bml_base_btl_t *bml_btl;
int rdma_order;
int32_t num_sent;
struct ompi_osc_rdma_peer_t {
/** Pointer to the current send fragment for each outgoing target */
struct ompi_osc_rdma_frag_t *active_frag;
/** Number of acks pending. New requests can not be sent out if there are
* acks pending (to fulfill the ordering constraints of accumulate) */
uint32_t num_acks_pending;
};
typedef struct ompi_osc_rdma_btl_t ompi_osc_rdma_btl_t;
struct ompi_osc_rdma_peer_info_t {
uint64_t peer_base;
uint64_t peer_len;
int peer_num_btls;
volatile int peer_index_btls;
ompi_osc_rdma_btl_t *peer_btls;
int local_num_btls;
mca_bml_base_btl_t **local_btls;
mca_mpool_base_registration_t **local_registrations;
mca_btl_base_descriptor_t **local_descriptors;
};
typedef struct ompi_osc_rdma_peer_info_t ompi_osc_rdma_peer_info_t;
struct ompi_osc_rdma_setup_info_t {
volatile int32_t num_btls_callin;
int32_t num_btls_expected;
volatile int32_t num_btls_outgoing;
opal_list_t *outstanding_btl_requests;
};
typedef struct ompi_osc_rdma_setup_info_t ompi_osc_rdma_setup_info_t;
typedef struct ompi_osc_rdma_peer_t ompi_osc_rdma_peer_t;
#define SEQ_INVALID 0xFFFFFFFFFFFFFFFFULL
/** Module structure. Exactly one of these is associated with each
RDMA window */
struct ompi_osc_rdma_module_t {
/** Extend the basic osc module interface */
ompi_osc_base_module_t super;
uint32_t m_sequence_number;
/** window should have accumulate ordering... */
bool accumulate_ordering;
/** lock access to data structures in the current module */
opal_mutex_t m_lock;
/** pointer to free on cleanup (may be NULL) */
void *free_after;
/** condition variable for access to current module */
opal_condition_t m_cond;
/** Base pointer for local window */
void *baseptr;
/** lock for "atomic" window updates from reductions */
opal_mutex_t m_acc_lock;
/** communicator created with this window. This is the cid used
in the component's modules mapping. */
ompi_communicator_t *comm;
/** pointer back to window */
ompi_win_t *m_win;
/** Local displacement unit. */
int disp_unit;
/** communicator created with this window */
ompi_communicator_t *m_comm;
/** Mutex lock protecting module data */
opal_mutex_t lock;
/** list of ompi_osc_rdma_sendreq_t structures, and includes all
requests for this access epoch that have not already been
started. m_lock must be held when modifying this field. */
opal_list_t m_pending_sendreqs;
/** condition variable associated with lock */
opal_condition_t cond;
/** list of unsigned int counters for the number of requests to a
particular rank in m_comm for this access epoc. m_lock
must be held when modifying this field */
unsigned int *m_num_pending_sendreqs;
/** lock for atomic window updates from reductions */
opal_mutex_t acc_lock;
/** For MPI_Fence synchronization, the number of messages to send
in epoch. For Start/Complete, the number of updates for this
Complete. For lock, the number of
messages waiting for completion on on the origin side. Not
protected by m_lock - must use atomic counter operations. */
int32_t m_num_pending_out;
/** peer data */
ompi_osc_rdma_peer_t *peers;
/** For MPI_Fence synchronization, the number of expected incoming
messages. For Post/Wait, the number of expected updates from
complete. For lock, the number of messages on the passive side
we are waiting for. Not protected by m_lock - must use
atomic counter operations. */
int32_t m_num_pending_in;
/** Nmber of communication fragments started for this epoch, by
peer. Not in peer data to make fence more manageable. */
int32_t *epoch_outgoing_frag_count;
/** List of full communication buffers queued to be sent. Should
be maintained in order (at least in per-target order). */
opal_list_t queued_frags;
/** cyclic counter for a unique tage for long messages. */
int tag_counter;
/* Number of outgoing fragments that have completed since the
begining of time */
int32_t outgoing_frag_count;
/* Next outgoing fragment count at which we want a signal on cond */
int32_t outgoing_frag_signal_count;
/* Number of incoming fragments that have completed since the
begining of time */
int32_t active_incoming_frag_count;
/* Next incoming buffer count at which we want a signal on cond */
int32_t active_incoming_frag_signal_count;
int32_t *passive_incoming_frag_count;
int32_t *passive_incoming_frag_signal_count;
/* Number of flush ack requests send since beginning of time */
uint64_t flush_ack_requested_count;
/* Number of flush ack replies received since beginning of
time. cond should be signalled on every flush reply
received. */
uint64_t flush_ack_received_count;
/** True if the access epoch is a passive target access epoch */
bool passive_target_access_epoch;
/** start sending data eagerly */
bool active_eager_send_active;
bool *passive_eager_send_active;
/* ********************* PWSC data ************************ */
struct ompi_group_t *pw_group;
struct ompi_group_t *sc_group;
/** Number of "ping" messages from the remote post group we've
received */
int32_t m_num_post_msgs;
int32_t num_post_msgs;
/** Number of "count" messages from the remote complete group
we've received */
int32_t m_num_complete_msgs;
/** cyclic counter for a unique tage for long messages. Not
protected by the m_lock - must use create_send_tag() to
create a send tag */
volatile int32_t m_tag_counter;
opal_list_t m_copy_pending_sendreqs;
unsigned int *m_copy_num_pending_sendreqs;
opal_list_t m_queued_sendreqs;
/** start sending data eagerly */
bool m_eager_send_active;
bool m_eager_send_ok;
/* RDMA data */
bool m_use_rdma;
bool m_rdma_wait_completion;
ompi_osc_rdma_setup_info_t *m_setup_info;
ompi_osc_rdma_peer_info_t *m_peer_info;
int32_t m_rdma_num_pending;
/*** buffering ***/
bool m_use_buffers;
ompi_osc_rdma_buffer_t *m_pending_buffers;
/* ********************* FENCE data ************************ */
/* an array of <sizeof(m_comm)> ints, each containing the value
1. */
int *m_fence_coll_counts;
/* ********************* PWSC data ************************ */
struct ompi_group_t *m_pw_group;
struct ompi_group_t *m_sc_group;
bool *m_sc_remote_active_ranks;
int *m_sc_remote_ranks;
int32_t num_complete_msgs;
/* ********************* LOCK data ************************ */
int32_t m_lock_status; /* one of 0, MPI_LOCK_EXCLUSIVE, MPI_LOCK_SHARED */
int32_t m_shared_count;
opal_list_t m_locks_pending;
opal_list_t m_unlocks_pending;
int32_t m_lock_received_ack;
/** Status of the local window lock. One of 0 (unlocked),
MPI_LOCK_EXCLUSIVE, or MPI_LOCK_SHARED. */
int lock_status;
/** number of peers who hold a shared lock on the local window */
int32_t shared_count;
/** target side list of lock requests we couldn't satisfy yet */
opal_list_t locks_pending;
/** origin side list of locks currently outstanding */
opal_list_t outstanding_locks;
uint64_t lock_serial_number;
unsigned char *incomming_buffer;
ompi_request_t *frag_request;
opal_list_t request_gc;
/* enforce accumulate semantics */
opal_atomic_lock_t accumulate_lock;
opal_list_t pending_acc;
};
typedef struct ompi_osc_rdma_module_t ompi_osc_rdma_module_t;
OMPI_MODULE_DECLSPEC extern ompi_osc_rdma_component_t mca_osc_rdma_component;
struct ompi_osc_rdma_pending_t {
opal_list_item_t super;
ompi_osc_rdma_module_t *module;
int source;
ompi_osc_rdma_header_t header;
};
typedef struct ompi_osc_rdma_pending_t ompi_osc_rdma_pending_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_pending_t);
#define GET_MODULE(win) ((ompi_osc_rdma_module_t*) win->w_osc_module)
/*
* Component functions
*/
int ompi_osc_rdma_component_init(bool enable_progress_threads,
bool enable_mpi_threads);
int ompi_osc_rdma_attach(struct ompi_win_t *win, void *base, size_t len);
int ompi_osc_rdma_detach(struct ompi_win_t *win, void *base);
int ompi_osc_rdma_component_finalize(void);
int ompi_osc_rdma_free(struct ompi_win_t *win);
int ompi_osc_rdma_component_query(struct ompi_win_t *win,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
int ompi_osc_rdma_component_select(struct ompi_win_t *win,
struct ompi_info_t *info,
struct ompi_communicator_t *comm);
/* helper function that properly sets up request handling */
int ompi_osc_rdma_component_irecv(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int src,
int tag,
struct ompi_communicator_t *comm,
struct ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *data);
int ompi_osc_rdma_component_isend(void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int dest,
int tag,
struct ompi_communicator_t *comm,
struct ompi_request_t **request,
ompi_request_complete_fn_t callback,
void *data);
int ompi_osc_rdma_peer_info_free(ompi_osc_rdma_peer_info_t *peer_info);
/*
* Module interface function types
*/
int ompi_osc_rdma_module_free(struct ompi_win_t *win);
int ompi_osc_rdma_module_put(void *origin_addr,
int ompi_osc_rdma_put(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
@ -264,7 +226,7 @@ int ompi_osc_rdma_module_put(void *origin_addr,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_rdma_module_accumulate(void *origin_addr,
int ompi_osc_rdma_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
@ -274,7 +236,7 @@ int ompi_osc_rdma_module_accumulate(void *origin_addr,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_rdma_module_get(void *origin_addr,
int ompi_osc_rdma_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
@ -283,43 +245,418 @@ int ompi_osc_rdma_module_get(void *origin_addr,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_rdma_module_fence(int assert, struct ompi_win_t *win);
int ompi_osc_rdma_compare_and_swap(void *origin_addr,
void *compare_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_win_t *win);
int ompi_osc_rdma_module_start(struct ompi_group_t *group,
int assert,
int ompi_osc_rdma_fetch_and_op(void *origin_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_rdma_module_complete(struct ompi_win_t *win);
int ompi_osc_rdma_module_post(struct ompi_group_t *group,
int ompi_osc_rdma_get_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_rdma_rput(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_rdma_rget(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_rdma_raccumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_rdma_rget_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_rdma_fence(int assert, struct ompi_win_t *win);
/* received a post message */
int osc_rdma_incomming_post (ompi_osc_rdma_module_t *module);
int ompi_osc_rdma_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_rdma_complete(struct ompi_win_t *win);
int ompi_osc_rdma_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_rdma_module_wait(struct ompi_win_t *win);
int ompi_osc_rdma_wait(struct ompi_win_t *win);
int ompi_osc_rdma_module_test(struct ompi_win_t *win,
int ompi_osc_rdma_test(struct ompi_win_t *win,
int *flag);
int ompi_osc_rdma_module_lock(int lock_type,
int ompi_osc_rdma_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win);
int ompi_osc_rdma_module_unlock(int target,
int ompi_osc_rdma_unlock(int target,
struct ompi_win_t *win);
/*
* passive side sync interface functions
int ompi_osc_rdma_lock_all(int assert,
struct ompi_win_t *win);
int ompi_osc_rdma_unlock_all(struct ompi_win_t *win);
int ompi_osc_rdma_sync(struct ompi_win_t *win);
int ompi_osc_rdma_flush(int target,
struct ompi_win_t *win);
int ompi_osc_rdma_flush_all(struct ompi_win_t *win);
int ompi_osc_rdma_flush_local(int target,
struct ompi_win_t *win);
int ompi_osc_rdma_flush_local_all(struct ompi_win_t *win);
int ompi_osc_rdma_set_info(struct ompi_win_t *win, struct ompi_info_t *info);
int ompi_osc_rdma_get_info(struct ompi_win_t *win, struct ompi_info_t **info_used);
int ompi_osc_rdma_component_irecv(ompi_osc_rdma_module_t *module,
void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int src,
int tag,
struct ompi_communicator_t *comm);
int ompi_osc_rdma_component_isend(ompi_osc_rdma_module_t *module,
void *buf,
size_t count,
struct ompi_datatype_t *datatype,
int dest,
int tag,
struct ompi_communicator_t *comm);
/**
* ompi_osc_rdma_progress_pending_acc:
*
* @short Progress one pending accumulation or compare and swap operation.
*
* @param[in] module - OSC RDMA module
*
* @long If the accumulation lock can be aquired progress one pending
* accumulate or compare and swap operation.
*/
int ompi_osc_rdma_passive_lock(ompi_osc_rdma_module_t *module,
int32_t origin,
int32_t lock_type);
int ompi_osc_rdma_progress_pending_acc (ompi_osc_rdma_module_t *module);
int ompi_osc_rdma_passive_unlock(ompi_osc_rdma_module_t *module,
int32_t origin,
int32_t count);
int ompi_osc_rdma_passive_unlock_complete(ompi_osc_rdma_module_t *module);
/**
* mark_incoming_completion:
*
* @short Increment incoming completeion count.
*
* @param[in] module - OSC RDMA module
* @param[in] source - Passive target source or MPI_PROC_NULL (active target)
*
* @long This function incremements either the passive or active incoming counts.
* If the count reaches the signal count we signal the module's condition.
* This function uses atomics if necessary so it is not necessary to hold
* the module lock before calling this function.
*/
static inline void mark_incoming_completion (ompi_osc_rdma_module_t *module, int source)
{
if (MPI_PROC_NULL == source) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"mark_incoming_completion marking active incomming complete. count = %d",
(int) module->active_incoming_frag_count + 1));
OPAL_THREAD_ADD32(&module->active_incoming_frag_count, 1);
if (module->active_incoming_frag_count >= module->active_incoming_frag_signal_count) {
opal_condition_broadcast(&module->cond);
}
} else {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"mark_incoming_completion marking passive incomming complete. source = %d, count = %d",
source, (int) module->passive_incoming_frag_count[source] + 1));
OPAL_THREAD_ADD32(module->passive_incoming_frag_count + source, 1);
if (module->passive_incoming_frag_count[source] >= module->passive_incoming_frag_signal_count[source]) {
opal_condition_broadcast(&module->cond);
}
}
}
/**
* mark_outgoing_completion:
*
* @short Increment outgoing count.
*
* @param[in] module - OSC RDMA module
*
* @long This function is used to signal that an outgoing send is complete. It
* incrememnts only the outgoing fragment count and signals the module
* condition the fragment count is >= the signal count. This function
* uses atomics if necessary so it is not necessary to hold the module
* lock before calling this function.
*/
static inline void mark_outgoing_completion (ompi_osc_rdma_module_t *module)
{
OPAL_THREAD_ADD32(&module->outgoing_frag_count, 1);
if (module->outgoing_frag_count >= module->outgoing_frag_signal_count) {
opal_condition_broadcast(&module->cond);
}
}
/**
* ompi_osc_signal_outgoing:
*
* @short Increment outgoing signal counters.
*
* @param[in] module - OSC RDMA module
* @param[in] target - Passive target rank or MPI_PROC_NULL (active target)
* @param[in] count - Number of outgoing messages to signal.
*
* @long This function uses atomics if necessary so it is not necessary to hold
* the module lock before calling this function.
*/
static inline void ompi_osc_signal_outgoing (ompi_osc_rdma_module_t *module, int target, int count)
{
OPAL_THREAD_ADD32(&module->outgoing_frag_signal_count, count);
if (MPI_PROC_NULL != target) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_signal_outgoing_passive: target = %d, count = %d, total = %d", target,
count, module->epoch_outgoing_frag_count[target] + count));
OPAL_THREAD_ADD32(module->epoch_outgoing_frag_count + target, count);
}
}
/**
* osc_rdma_copy_on_recv:
*
* @short Helper function. Copies data from source to target through the
* convertor.
*
* @param[in] target - destination for the data
* @param[in] source - packed data
* @param[in] source_len - length of source buffer
* @param[in] proc - proc that packed the source data
* @param[in] count - count of datatype items
* @param[in] datatype - datatype used for unpacking
*
* @long This functions unpacks data from the source buffer into the target
* buffer. The copy is done with a convertor generated from proc,
* datatype, and count.
*/
static inline void osc_rdma_copy_on_recv (void *target, void *source, size_t source_len, ompi_proc_t *proc,
int count, ompi_datatype_t *datatype)
{
opal_convertor_t convertor;
uint32_t iov_count = 1;
struct iovec iov;
size_t max_data;
/* create convertor */
OBJ_CONSTRUCT(&convertor, opal_convertor_t);
/* initialize convertor */
opal_convertor_copy_and_prepare_for_recv(proc->proc_convertor, &datatype->super, count, target,
0, &convertor);
iov.iov_len = source_len;
iov.iov_base = (IOVBASE_TYPE *) source;
max_data = iov.iov_len;
MEMCHECKER(memchecker_convertor_call(&opal_memchecker_base_mem_defined, &convertor));
opal_convertor_unpack (&convertor, &iov, &iov_count, &max_data);
MEMCHECKER(memchecker_convertor_call(&opal_memchecker_base_mem_noaccess, &convertor));
OBJ_DESTRUCT(&convertor);
}
/**
* osc_rdma_copy_for_send:
*
* @short: Helper function. Copies data from source to target through the
* convertor.
*
* @param[in] target - destination for the packed data
* @param[in] target_len - length of the target buffer
* @param[in] source - original data
* @param[in] proc - proc this data will be sent to
* @param[in] count - count of datatype items
* @param[in] datatype - datatype used for packing
*
* @long This functions packs data from the source buffer into the target
* buffer. The copy is done with a convertor generated from proc,
* datatype, and count.
*/
static inline void osc_rdma_copy_for_send (void *target, size_t target_len, void *source, ompi_proc_t *proc,
int count, ompi_datatype_t *datatype)
{
opal_convertor_t convertor;
uint32_t iov_count = 1;
struct iovec iov;
size_t max_data;
OBJ_CONSTRUCT(&convertor, opal_convertor_t);
opal_convertor_copy_and_prepare_for_send(proc->proc_convertor, &datatype->super,
count, source, 0, &convertor);
iov.iov_len = target_len;
iov.iov_base = (IOVBASE_TYPE *) target;
opal_convertor_pack(&convertor, &iov, &iov_count, &max_data);
OBJ_DESTRUCT(&convertor);
}
/**
* osc_rdma_request_gc_clean:
*
* @short Release finished PML requests.
*
* @param[in] module - OSC RDMA module
*
* @long This function exists because it is not possible to free a PML request
* from a request completion callback. We instead put the request on the
* module's garbage collection list and release it at a later time.
*/
static inline void osc_rdma_request_gc_clean (ompi_osc_rdma_module_t *module)
{
ompi_request_t *request;
while (NULL != (request = (ompi_request_t *) opal_list_remove_first (&module->request_gc))) {
ompi_request_free (&request);
}
}
#define OSC_RDMA_FRAG_TAG 0x10000
#define OSC_RDMA_FRAG_MASK 0x0ffff
/**
* get_tag:
*
* @short Get a send/recv tag for large memory operations.
*
* @param[in] module - OSC RDMA module
*
* @long This function aquires a 16-bit tag for use with large memory operations. The
* tag will be odd or even depending on if this is in a passive target access
* or not.
*/
static inline int get_tag(ompi_osc_rdma_module_t *module)
{
/* the LSB of the tag is used be the receiver to determine if the
message is a passive or active target (ie, where to mark
completion). */
int tmp = module->tag_counter + !!(module->passive_target_access_epoch);
module->tag_counter = (module->tag_counter + 2) & OSC_RDMA_FRAG_MASK;
return tmp;
}
/**
* ompi_osc_rdma_accumulate_lock:
*
* @short Internal function that spins until the accumulation lock has
* been aquired.
*
* @param[in] module - OSC RDMA module
*
* @returns 0
*
* @long This functions blocks until the accumulation lock has been aquired. This
* behavior is only acceptable from a user-level call as blocking in a
* callback may cause deadlock. If a callback needs the accumulate lock and
* it is not available it should be placed on the pending_acc list of the
* module. It will be released by ompi_osc_rdma_accumulate_unlock().
*/
static inline int ompi_osc_rdma_accumulate_lock (ompi_osc_rdma_module_t *module)
{
while (opal_atomic_trylock (&module->accumulate_lock)) {
opal_progress ();
}
return 0;
}
/**
* ompi_osc_rdma_accumulate_trylock:
*
* @short Try to aquire the accumulation lock.
*
* @param[in] module - OSC RDMA module
*
* @returns 0 if the accumulation lock was aquired
* @returns 1 if the lock was not available
*
* @long This function will try to aquire the accumulation lock. This function
* is safe to call from a callback.
*/
static inline int ompi_osc_rdma_accumulate_trylock (ompi_osc_rdma_module_t *module)
{
return opal_atomic_trylock (&module->accumulate_lock);
}
/**
* ompi_osc_rdma_accumulate_unlock:
*
* @short Unlock the accumulation lock and release a pending accumulation operation.
*
* @param[in] module - OSC RDMA module
*
* @long This function unlocks the accumulation lock and release a single pending
* accumulation operation if one exists. This function may be called recursively.
*/
static inline void ompi_osc_rdma_accumulate_unlock (ompi_osc_rdma_module_t *module)
{
opal_atomic_unlock (&module->accumulate_lock);
if (0 != opal_list_get_size (&module->pending_acc)) {
ompi_osc_rdma_progress_pending_acc (module);
}
}
END_C_DECLS

414
ompi/mca/osc/rdma/osc_rdma_active_target.c Обычный файл
Просмотреть файл

@ -0,0 +1,414 @@
/*
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_rdma.h"
#include "osc_rdma_header.h"
#include "osc_rdma_data_move.h"
#include "osc_rdma_frag.h"
#include "mpi.h"
#include "opal/runtime/opal_progress.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/mca/osc/base/base.h"
static int*
get_comm_ranks(ompi_osc_rdma_module_t *module,
ompi_group_t *sub_group)
{
int *ranks1 = NULL, *ranks2 = NULL;
bool success = false;
int i, ret;
ranks1 = malloc(sizeof(int) * ompi_group_size(sub_group));
if (NULL == ranks1) goto cleanup;
ranks2 = malloc(sizeof(int) * ompi_group_size(sub_group));
if (NULL == ranks2) goto cleanup;
for (i = 0 ; i < ompi_group_size(sub_group) ; ++i) {
ranks1[i] = i;
}
ret = ompi_group_translate_ranks(sub_group,
ompi_group_size(sub_group),
ranks1,
module->comm->c_local_group,
ranks2);
if (OMPI_SUCCESS != ret) goto cleanup;
success = true;
cleanup:
if (NULL != ranks1) free(ranks1);
if (!success) {
if (NULL != ranks2) free(ranks2);
ranks2 = NULL;
}
return ranks2;
}
int
ompi_osc_rdma_fence(int assert, ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
uint32_t incoming_reqs;
int ret = OMPI_SUCCESS;
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: fence start"));
/* short-circuit the noprecede case */
if (0 != (assert & MPI_MODE_NOPRECEDE)) {
ret = module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: fence end (short circuit)"));
return ret;
}
/* try to start all the requests. */
ret = ompi_osc_rdma_frag_flush_all(module);
if (OMPI_SUCCESS != ret) goto cleanup;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: fence done sending"));
/* find out how much data everyone is going to send us. */
ret = module->comm->c_coll.coll_reduce_scatter_block (module->epoch_outgoing_frag_count,
&incoming_reqs, 1, MPI_UINT32_T,
MPI_SUM, module->comm,
module->comm->c_coll.coll_reduce_scatter_block_module);
if (OMPI_SUCCESS != ret) goto cleanup;
OPAL_THREAD_LOCK(&module->lock);
bzero(module->epoch_outgoing_frag_count,
sizeof(uint32_t) * ompi_comm_size(module->comm));
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: fence expects %d requests",
incoming_reqs));
/* set our complete condition for incoming requests */
module->active_incoming_frag_signal_count += incoming_reqs;
/* wait for completion */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count ||
module->active_incoming_frag_count < module->active_incoming_frag_signal_count) {
opal_condition_wait(&module->cond, &module->lock);
}
ret = OMPI_SUCCESS;
if (0 == (assert & MPI_MODE_NOSUCCEED)) {
module->active_eager_send_active = true;
}
cleanup:
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: fence end: %d", ret));
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int
ompi_osc_rdma_start(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int ret = OMPI_SUCCESS;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_start entering..."));
/* save the group */
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
OPAL_THREAD_LOCK(&module->lock);
/* ensure we're not already in a start */
if (NULL != module->sc_group) {
ret = MPI_ERR_RMA_SYNC;
goto cleanup;
}
module->sc_group = group;
/* disable eager sends until we've receved the proper number of
post messages, at which time we know all our peers are ready to
receive messages. */
module->active_eager_send_active = false;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"num_post_msgs = %d", module->num_post_msgs));
/* possible we've already received a couple in messages, so
add however many we're going to wait for */
module->num_post_msgs -= ompi_group_size(module->sc_group);
/* if we've already received all the post messages, we can eager
send. Otherwise, eager send will be enabled when
numb_post_messages reaches 0 */
if (0 == module->num_post_msgs) {
module->active_eager_send_active = true;
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_start complete"));
OPAL_THREAD_UNLOCK(&module->lock);
return OMPI_SUCCESS;
cleanup:
OPAL_THREAD_UNLOCK(&module->lock);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return ret;
}
int
ompi_osc_rdma_complete(ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_header_complete_t complete_req;
int ret = OMPI_SUCCESS;
int i;
int *ranks = NULL;
ompi_group_t *group;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_complete entering..."));
ranks = get_comm_ranks(module, module->sc_group);
if (NULL == ranks) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
OPAL_THREAD_LOCK(&module->lock);
/* wait for all the post messages */
while (0 != module->num_post_msgs) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"waiting for post messages. num_post_msgs = %d", module->num_post_msgs));
opal_condition_wait(&module->cond, &module->lock);
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_complete sending complete message"));
/* for each process in group, send a control message with number
of updates coming, then start all the requests. Note that the
control send is processed as another message in a fragment, so
this might get queued until the flush_all (which is fine).
At the same time, clean out the outgoing count for the next
round. */
OPAL_THREAD_UNLOCK(&module->lock);
for (i = 0 ; i < ompi_group_size(module->sc_group) ; ++i) {
complete_req.base.type = OMPI_OSC_RDMA_HDR_TYPE_COMPLETE;
complete_req.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
complete_req.frag_count = module->epoch_outgoing_frag_count[ranks[i]];
module->epoch_outgoing_frag_count[ranks[i]] = 0;
ret = ompi_osc_rdma_control_send(module,
ranks[i],
&complete_req,
sizeof(ompi_osc_rdma_header_complete_t));
if (OMPI_SUCCESS != ret) goto cleanup;
}
OPAL_THREAD_LOCK(&module->lock);
/* start all requests */
ret = ompi_osc_rdma_frag_flush_all(module);
if (OMPI_SUCCESS != ret) goto cleanup;
/* wait for outgoing requests to complete. Don't wait for incoming, as
we're only completing the access epoch, not the exposure epoch */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count) {
opal_condition_wait(&module->cond, &module->lock);
}
/* phase 1 cleanup group */
group = module->sc_group;
module->sc_group = NULL;
/* unlock here, as group cleanup can take a while... */
OPAL_THREAD_UNLOCK(&(module->lock));
/* phase 2 cleanup group */
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_complete complete"));
free (ranks);
return OMPI_SUCCESS;
cleanup:
if (NULL != ranks) free(ranks);
OPAL_THREAD_UNLOCK(&(module->lock));
return ret;
}
int
ompi_osc_rdma_post(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int *ranks;
int ret = OMPI_SUCCESS;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_header_post_t post_req;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_post entering..."));
/* save the group */
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
OPAL_THREAD_LOCK(&(module->lock));
/* ensure we're not already in a post */
if (NULL != module->pw_group) {
OPAL_THREAD_UNLOCK(&(module->lock));
return MPI_ERR_RMA_SYNC;
}
module->pw_group = group;
/* Update completion counter. Can't have received any completion
messages yet; complete won't send a completion header until
we've sent a post header. */
module->num_complete_msgs = -ompi_group_size(module->pw_group);
OPAL_THREAD_UNLOCK(&(module->lock));
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"sending post messages"));
ranks = get_comm_ranks(module, module->pw_group);
if (NULL == ranks) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* send a hello counter to everyone in group */
for (int i = 0 ; i < ompi_group_size(module->pw_group) ; ++i) {
post_req.base.type = OMPI_OSC_RDMA_HDR_TYPE_POST;
post_req.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
post_req.windx = ompi_comm_get_cid(module->comm);
/* we don't want to send any data, since we're the exposure
epoch only, so use an unbuffered send */
ret = ompi_osc_rdma_control_send_unbuffered(module, ranks[i], &post_req,
sizeof(ompi_osc_rdma_header_post_t));
if (OMPI_SUCCESS != ret) {
break;
}
}
free (ranks);
return ret;
}
int
ompi_osc_rdma_wait(ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_group_t *group;
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_wait entering..."));
OPAL_THREAD_LOCK(&module->lock);
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_wait active_incoming_frag_count = %d, active_incoming_frag_signal_count = %d, num_complete_msgs = %d",
(int) module->active_incoming_frag_count, (int) module->active_incoming_frag_count, module->num_complete_msgs));
while (0 != module->num_complete_msgs ||
module->active_incoming_frag_count < module->active_incoming_frag_signal_count) {
opal_condition_wait(&module->cond, &module->lock);
}
group = module->pw_group;
module->pw_group = NULL;
OPAL_THREAD_UNLOCK(&module->lock);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_wait complete"));
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_test(ompi_win_t *win,
int *flag)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_group_t *group;
int ret = OMPI_SUCCESS;
#if !OMPI_ENABLE_PROGRESS_THREADS
opal_progress();
#endif
OPAL_THREAD_LOCK(&(module->lock));
if (0 != module->num_complete_msgs ||
module->active_incoming_frag_count < module->active_incoming_frag_signal_count) {
*flag = 0;
ret = OMPI_SUCCESS;
goto cleanup;
} else {
*flag = 1;
group = module->pw_group;
module->pw_group = NULL;
OPAL_THREAD_UNLOCK(&(module->lock));
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return OMPI_SUCCESS;
}
cleanup:
OPAL_THREAD_UNLOCK(&(module->lock));
return ret;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
@ -7,6 +8,9 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -17,46 +21,125 @@
#ifndef OMPI_MCA_OSC_RDMA_DATA_MOVE_H
#define OMPI_MCA_OSC_RDMA_DATA_MOVE_H
#include "osc_rdma_sendreq.h"
#include "osc_rdma_replyreq.h"
/* send a sendreq (the request from the origin for a Put, Get, or
Accumulate, including the payload for Put and Accumulate) */
int ompi_osc_rdma_sendreq_send(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_sendreq_t *sendreq);
/* send a replyreq (the request from the target of a Get, with the
payload for the origin */
int ompi_osc_rdma_replyreq_send(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_replyreq_t *replyreq);
/* receive the target side of a sendreq for a put, directly into the user's window */
int ompi_osc_rdma_sendreq_recv_put(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_send_header_t *header,
void **payload);
/* receive the target side of a sendreq for an accumulate, possibly
using a temproart buffer, then calling the reduction functions */
int ompi_osc_rdma_sendreq_recv_accum(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_send_header_t *header,
void **payload);
/* receive the origin side of a replyreq (the reply part of an
MPI_Get), directly into the user's window */
int ompi_osc_rdma_replyreq_recv(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_sendreq_t *sendreq,
ompi_osc_rdma_reply_header_t *header,
void **payload);
#include "osc_rdma_header.h"
int ompi_osc_rdma_control_send(ompi_osc_rdma_module_t *module,
ompi_proc_t *proc,
uint8_t type,
int32_t value0, int32_t value1);
int target,
void *data,
size_t len);
int ompi_osc_rdma_rdma_ack_send(ompi_osc_rdma_module_t *module,
ompi_proc_t *proc,
ompi_osc_rdma_btl_t *rdma_btl);
/**
* ompi_osc_rdma_control_send_unbuffered:
*
* @short Send an unbuffered control message to a peer.
*
* @param[in] module - OSC RDMA module
* @param[in] target - Target rank
* @param[in] data - Data to send
* @param[in] len - Length of data
*
* @long Directly send a control message. This does not allocate a
* fragment, so should only be used when sending other messages would
* be erroneous (such as complete messages, when there may be queued
* transactions from an overlapping post that has already heard back
* from its peer). The buffer specified by data will be available
* when this call returns.
*/
int ompi_osc_rdma_control_send_unbuffered (ompi_osc_rdma_module_t *module,
int target, void *data, size_t len);
int ompi_osc_rdma_flush(ompi_osc_rdma_module_t *module);
/**
* ompi_osc_rdma_isend_w_cb:
*
* @short Post a non-blocking send with a specified callback.
*
* @param[in] ptr - Source buffer. Will be available when the callback fires
* @param[in] count - Number of elements to send
* @param[in] datatype - Datatype of elements
* @param[in] source - Ranks to send data to
* @param[in] tag - Tag to use
* @param[in] comm - Communicator for communicating with rank
* @param[in] cb - Function to call when the request is complete
* @param[in] ctx - Context to store in new request for callback
*
* @long This function posts a new send request. Upon completion the function cb will
* be called with the associated request. The context specified in ctx will be stored in
* the req_completion_cb_data member of the ompi_request_t for use by the callback.
*/
int ompi_osc_rdma_isend_w_cb (void *ptr, int count, ompi_datatype_t *datatype, int target, int tag,
ompi_communicator_t *comm, ompi_request_complete_fn_t cb, void *ctx);
/**
* ompi_osc_rdma_irecv_w_cb:
*
* @short Post a non-blocking receive with a specified callback.
*
* @param[inout] ptr - Destination for incoming data
* @param[in] count - Number of elements to receive
* @param[in] datatype - Datatype of elements
* @param[in] source - Ranks to receive data from
* @param[in] tag - Tag to use
* @param[in] comm - Communicator for communicating with rank
* @param[in] request_out - Location to store new receive request (may be NULL)
* @param[in] cb - Function to call when the request is complete
* @param[in] ctx - Context to store in new request for callback
*
* @long This function posts a new request and stores the request in request_out if
* provided. Upon completion the function cb will be called with the associated
* request. The context specified in ctx will be stored in the req_completion_cb_data
* member of the ompi_request_t for use by the callback.
*/
int ompi_osc_rdma_irecv_w_cb (void *ptr, int count, ompi_datatype_t *datatype, int source, int tag,
ompi_communicator_t *comm, ompi_request_t **request_out,
ompi_request_complete_fn_t cb, void *ctx);
int ompi_osc_rdma_process_lock(ompi_osc_rdma_module_t* module,
int source,
struct ompi_osc_rdma_header_lock_t* lock_header);
void ompi_osc_rdma_process_lock_ack(ompi_osc_rdma_module_t* module,
struct ompi_osc_rdma_header_lock_ack_t* lock_header);
int ompi_osc_rdma_process_unlock(ompi_osc_rdma_module_t* module,
int source,
struct ompi_osc_rdma_header_unlock_t* lock_header);
int ompi_osc_rdma_process_flush (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_flush_t *flush_header);
/**
* ompi_osc_rdma_process_unlock_ack:
*
* @short Process an incomming unlock acknowledgement.
*
* @param[in] module - OSC RDMA module
* @param[in] source - Source rank
* @param[in] unlock_ack_header - Incoming unlock ack header
*/
void ompi_osc_rdma_process_unlock_ack (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_unlock_ack_t *unlock_ack_header);
/**
* ompi_osc_rdma_process_flush_ack:
*
* @short Process an incomming flush acknowledgement.
*
* @param[in] module - OSC RDMA module
* @param[in] source - Source rank
* @param[in] flush_ack_header - Incoming flush ack header
*/
void ompi_osc_rdma_process_flush_ack (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_flush_ack_t *flush_ack_header);
/**
* ompi_osc_rdma_frag_start_receive:
*
* @short Start receiving fragments on the OSC module.
*
* @param[in] module - OSC module
*
* @long This function starts receiving eager fragments on the module. The current
* implementation uses the pml to transfer eager fragments.
*/
int ompi_osc_rdma_frag_start_receive (ompi_osc_rdma_module_t *module);
#endif

213
ompi/mca/osc/rdma/osc_rdma_frag.c Обычный файл
Просмотреть файл

@ -0,0 +1,213 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "opal/class/opal_list.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/pml/pml.h"
#include "osc_rdma.h"
#include "osc_rdma_frag.h"
#include "osc_rdma_data_move.h"
static void ompi_osc_rdma_frag_constructor (ompi_osc_rdma_frag_t *frag){
frag->buffer = malloc (mca_osc_rdma_component.buffer_size + sizeof (ompi_osc_rdma_frag_header_t));
assert (frag->buffer);
}
static void ompi_osc_rdma_frag_destructor (ompi_osc_rdma_frag_t *frag) {
if (NULL != frag->buffer) {
free (frag->buffer);
}
}
OBJ_CLASS_INSTANCE(ompi_osc_rdma_frag_t, opal_list_item_t,
ompi_osc_rdma_frag_constructor, ompi_osc_rdma_frag_destructor);
static int frag_send_cb (ompi_request_t *request)
{
ompi_osc_rdma_frag_t *frag =
(ompi_osc_rdma_frag_t*) request->req_complete_cb_data;
ompi_osc_rdma_module_t *module = frag->module;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag_send complete to %d, frag = %p, request = %p",
frag->target, (void *) frag, (void *) request));
mark_outgoing_completion(module);
OPAL_FREE_LIST_RETURN(&mca_osc_rdma_component.frags, &frag->super);
/* put this request on the garbage colletion list */
opal_list_append (&module->request_gc, (opal_list_item_t *) request);
return OMPI_SUCCESS;
}
static int
frag_send(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_frag_t *frag)
{
int count;
count = (int)((uintptr_t) frag->top - (uintptr_t) frag->buffer);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag_send called to %d, frag = %p, count = %d",
frag->target, (void *) frag, count));
return ompi_osc_rdma_isend_w_cb (frag->buffer, count, MPI_BYTE, frag->target, OSC_RDMA_FRAG_TAG,
module->comm, frag_send_cb, frag);
}
int
ompi_osc_rdma_frag_start(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_frag_t *frag)
{
int ret;
assert(0 == frag->pending);
assert(module->peers[frag->target].active_frag != frag);
/* we need to signal now that a frag is outgoing to ensure the count sent
* with the unlock message is correct */
ompi_osc_signal_outgoing (module, frag->target, 1);
/* if eager sends are not active, can't send yet, so buffer and
get out... */
if (module->passive_target_access_epoch) {
if (!module->passive_eager_send_active[frag->target]) {
opal_list_append(&module->queued_frags, &frag->super);
return OMPI_SUCCESS;
}
} else {
if (!module->active_eager_send_active) {
opal_list_append(&module->queued_frags, &frag->super);
return OMPI_SUCCESS;
}
}
ret = frag_send(module, frag);
opal_condition_broadcast(&module->cond);
return ret;
}
int
ompi_osc_rdma_frag_flush_target(ompi_osc_rdma_module_t *module, int target)
{
int ret = OMPI_SUCCESS;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush target begin"));
/* flush the active frag */
if (NULL != module->peers[target].active_frag) {
ompi_osc_rdma_frag_t *frag = module->peers[target].active_frag;
if (0 != frag->pending) {
/* communication going on while synchronizing; this is a bug */
return MPI_ERR_RMA_SYNC;
}
module->peers[target].active_frag = NULL;
ret = ompi_osc_rdma_frag_start(module, frag);
if (OMPI_SUCCESS != ret) return ret;
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush target finished active frag"));
/* walk through the pending list and send */
ompi_osc_rdma_frag_t *frag, *next;
OPAL_LIST_FOREACH_SAFE(frag, next, &module->queued_frags, ompi_osc_rdma_frag_t) {
if (frag->target == target) {
opal_list_remove_item(&module->queued_frags, &frag->super);
ret = frag_send(module, frag);
if (OMPI_SUCCESS != ret) return ret;
}
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush target finished"));
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_frag_flush_all(ompi_osc_rdma_module_t *module)
{
int ret = OMPI_SUCCESS;
int i;
ompi_osc_rdma_frag_t *frag, *next;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush all begin"));
/* flush the active frag */
for (i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
if (NULL != module->peers[i].active_frag) {
ompi_osc_rdma_frag_t *frag = module->peers[i].active_frag;
if (0 != frag->pending) {
/* communication going on while synchronizing; this is a bug */
return MPI_ERR_RMA_SYNC;
}
module->peers[i].active_frag = NULL;
ret = ompi_osc_rdma_frag_start(module, frag);
if (OMPI_SUCCESS != ret) return ret;
}
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush all finished active frag"));
/* try to start all the queued frags */
OPAL_LIST_FOREACH_SAFE(frag, next, &module->queued_frags, ompi_osc_rdma_frag_t) {
opal_list_remove_item(&module->queued_frags, &frag->super);
ret = frag_send(module, frag);
if (OMPI_SUCCESS != ret) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: failure for frag send: %d", ret));
return ret;
}
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: frag flush all done"));
return OMPI_SUCCESS;
}
int osc_rdma_incomming_post (ompi_osc_rdma_module_t *module)
{
OPAL_THREAD_LOCK(&module->lock);
module->num_post_msgs++;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"received post message. num_post_msgs = %d", module->num_post_msgs));
if (0 == module->num_post_msgs) {
module->active_eager_send_active = true;
}
opal_condition_broadcast (&module->cond);
OPAL_THREAD_UNLOCK(&module->lock);
return OMPI_SUCCESS;
}

131
ompi/mca/osc/rdma/osc_rdma_frag.h Обычный файл
Просмотреть файл

@ -0,0 +1,131 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_RDMA_FRAG_H
#define OSC_RDMA_FRAG_H
#include "ompi/communicator/communicator.h"
#include "osc_rdma_header.h"
#include "osc_rdma_request.h"
/** Communication buffer for packing messages */
struct ompi_osc_rdma_frag_t {
opal_list_item_t super;
/* target rank of buffer */
int target;
unsigned char *buffer;
/* space remaining in buffer */
size_t remain_len;
/* start of unused space */
char *top;
/* Number of operations which have started writing into the frag, but not yet completed doing so */
int pending;
ompi_osc_rdma_frag_header_t *header;
ompi_osc_rdma_module_t *module;
};
typedef struct ompi_osc_rdma_frag_t ompi_osc_rdma_frag_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_frag_t);
extern int ompi_osc_rdma_frag_start(ompi_osc_rdma_module_t *module, ompi_osc_rdma_frag_t *buffer);
extern int ompi_osc_rdma_frag_flush_target(ompi_osc_rdma_module_t *module, int target);
extern int ompi_osc_rdma_frag_flush_all(ompi_osc_rdma_module_t *module);
/*
* Note: module lock must be held during this operation
*/
static inline int ompi_osc_rdma_frag_alloc(ompi_osc_rdma_module_t *module, int target,
size_t request_len, ompi_osc_rdma_frag_t **buffer,
char **ptr)
{
ompi_osc_rdma_frag_t *curr = module->peers[target].active_frag;
int ret;
if (request_len > mca_osc_rdma_component.buffer_size) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
if (NULL == curr || curr->remain_len < request_len) {
opal_free_list_item_t *item;
if (NULL != curr) {
curr->remain_len = 0;
/* If there's something pending, the pending finish will
start the buffer. Otherwise, we need to start it now. */
if (0 == curr->pending) {
module->peers[target].active_frag = NULL;
ret = ompi_osc_rdma_frag_start(module, curr);
}
}
OPAL_FREE_LIST_GET(&mca_osc_rdma_component.frags,
item, ret);
if (OMPI_SUCCESS != ret) return ret;
curr = module->peers[target].active_frag =
(ompi_osc_rdma_frag_t*) item;
curr->target = target;
curr->header = (ompi_osc_rdma_frag_header_t*) curr->buffer;
curr->top = (char*) (curr->header + 1);
curr->remain_len = mca_osc_rdma_component.buffer_size;
curr->module = module;
curr->pending = 0;
curr->header->base.type = OMPI_OSC_RDMA_HDR_TYPE_FRAG;
curr->header->base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
if (module->passive_target_access_epoch) {
curr->header->base.flags |= OMPI_OSC_RDMA_HDR_FLAG_PASSIVE_TARGET;
}
curr->header->source = ompi_comm_rank(module->comm);
curr->header->num_ops = 0;
curr->header->windx = ompi_comm_get_cid(module->comm);
if (curr->remain_len < request_len) {
return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
}
}
*ptr = curr->top;
*buffer = curr;
curr->top += request_len;
curr->remain_len -= request_len;
curr->pending++;
curr->header->num_ops++;
return OMPI_SUCCESS;
}
/*
* Note: module lock must be held for this operation
*/
static inline int
ompi_osc_rdma_frag_finish(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_frag_t* buffer)
{
int ret = OMPI_SUCCESS;
buffer->pending--;
if (0 == buffer->pending && 0 == buffer->remain_len) {
ret = ompi_osc_rdma_frag_start(module, buffer);
}
return ret;
}
#endif

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
@ -7,14 +8,15 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Los Alamos National Security, LLC. All rights
* Copyright (c) 2007-2014 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
*
* Additional copyrights may follow
*
*
* $HEADER$
*/
@ -27,144 +29,169 @@
#include "opal/types.h"
/* Note -- 0x05 to 0x0C are of control_hdr type */
#define OMPI_OSC_RDMA_HDR_PUT 0x01
#define OMPI_OSC_RDMA_HDR_ACC 0x02
#define OMPI_OSC_RDMA_HDR_GET 0x03
#define OMPI_OSC_RDMA_HDR_REPLY 0x04
#define OMPI_OSC_RDMA_HDR_POST 0x05
#define OMPI_OSC_RDMA_HDR_COMPLETE 0x06
#define OMPI_OSC_RDMA_HDR_LOCK_REQ 0x07
#define OMPI_OSC_RDMA_HDR_UNLOCK_REQ 0x08
#define OMPI_OSC_RDMA_HDR_UNLOCK_REPLY 0x09
#define OMPI_OSC_RDMA_HDR_RDMA_COMPLETE 0x0A
#define OMPI_OSC_RDMA_HDR_MULTI_END 0x0B
#define OMPI_OSC_RDMA_HDR_RDMA_INFO 0x0C
#define OMPI_OSC_RDMA_HDR_FLAG_ALIGN_MASK 0x0F
#define OMPI_OSC_RDMA_HDR_FLAG_NBO 0x10
#define OMPI_OSC_RDMA_HDR_FLAG_MULTI 0x20
struct ompi_osc_rdma_base_header_t {
uint8_t hdr_type;
/* eventually, this will include endian information */
uint8_t hdr_flags;
enum ompi_osc_rdma_hdr_type_t {
OMPI_OSC_RDMA_HDR_TYPE_PUT = 0x01,
OMPI_OSC_RDMA_HDR_TYPE_PUT_LONG = 0x02,
OMPI_OSC_RDMA_HDR_TYPE_ACC = 0x03,
OMPI_OSC_RDMA_HDR_TYPE_ACC_LONG = 0x04,
OMPI_OSC_RDMA_HDR_TYPE_GET = 0x05,
OMPI_OSC_RDMA_HDR_TYPE_CSWAP = 0x06,
OMPI_OSC_RDMA_HDR_TYPE_CSWAP_LONG = 0x07,
OMPI_OSC_RDMA_HDR_TYPE_GET_ACC = 0x08,
OMPI_OSC_RDMA_HDR_TYPE_GET_ACC_LONG = 0x09,
OMPI_OSC_RDMA_HDR_TYPE_COMPLETE = 0x10,
OMPI_OSC_RDMA_HDR_TYPE_POST = 0x11,
OMPI_OSC_RDMA_HDR_TYPE_LOCK_REQ = 0x12,
OMPI_OSC_RDMA_HDR_TYPE_LOCK_ACK = 0x13,
OMPI_OSC_RDMA_HDR_TYPE_UNLOCK_REQ = 0x14,
OMPI_OSC_RDMA_HDR_TYPE_UNLOCK_ACK = 0x15,
OMPI_OSC_RDMA_HDR_TYPE_FLUSH_REQ = 0x16,
OMPI_OSC_RDMA_HDR_TYPE_FLUSH_ACK = 0x17,
OMPI_OSC_RDMA_HDR_TYPE_FRAG = 0x20,
};
typedef struct ompi_osc_rdma_base_header_t ompi_osc_rdma_base_header_t;
typedef enum ompi_osc_rdma_hdr_type_t ompi_osc_rdma_hdr_type_t;
#define OMPI_OSC_RDMA_BASE_HDR_NTOH(h)
#define OMPI_OSC_RDMA_BASE_HDR_HTON(h)
#define OMPI_OSC_RDMA_HDR_FLAG_NBO 0x01
#define OMPI_OSC_RDMA_HDR_FLAG_VALID 0x02
#define OMPI_OSC_RDMA_HDR_FLAG_PASSIVE_TARGET 0x04
struct ompi_osc_rdma_send_header_t {
ompi_osc_rdma_base_header_t hdr_base;
uint16_t hdr_windx;
int32_t hdr_origin;
ompi_ptr_t hdr_origin_sendreq;
int32_t hdr_origin_tag;
uint64_t hdr_target_disp;
int32_t hdr_target_count;
int32_t hdr_target_op;
int32_t hdr_msg_length; /* 0 if payload is not included */
struct ompi_osc_rdma_header_base_t {
/** fragment type. 8 bits */
uint8_t type;
/** fragment flags. 8 bits */
uint8_t flags;
};
typedef struct ompi_osc_rdma_send_header_t ompi_osc_rdma_send_header_t;
typedef struct ompi_osc_rdma_header_base_t ompi_osc_rdma_header_base_t;
#define OMPI_OSC_RDMA_SEND_HDR_HTON(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_HTON((hdr).hdr_base) \
(hdr).hdr_windx = htons((hdr).hdr_windx); \
(hdr).hdr_origin = htonl((hdr).hdr_origin); \
(hdr).hdr_origin_tag = htonl((hdr).hdr_origin_tag); \
(hdr).hdr_target_disp = hton64((hdr).hdr_target_disp); \
(hdr).hdr_target_count = htonl((hdr).hdr_target_count); \
(hdr).hdr_target_op = htonl((hdr).hdr_target_op); \
(hdr).hdr_msg_length = htonl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_rdma_header_put_t {
ompi_osc_rdma_header_base_t base;
#define OMPI_OSC_RDMA_SEND_HDR_NTOH(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_NTOH((hdr).hdr_base) \
(hdr).hdr_windx = ntohs((hdr).hdr_windx); \
(hdr).hdr_origin = ntohl((hdr).hdr_origin); \
(hdr).hdr_origin_tag = ntohl((hdr).hdr_origin_tag); \
(hdr).hdr_target_disp = ntoh64((hdr).hdr_target_disp); \
(hdr).hdr_target_count = ntohl((hdr).hdr_target_count); \
(hdr).hdr_target_op = ntohl((hdr).hdr_target_op); \
(hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_rdma_reply_header_t {
ompi_osc_rdma_base_header_t hdr_base;
ompi_ptr_t hdr_origin_sendreq;
int32_t hdr_target_tag;
int32_t hdr_msg_length;
uint16_t tag;
uint32_t count;
uint64_t len;
uint64_t displacement;
};
typedef struct ompi_osc_rdma_reply_header_t ompi_osc_rdma_reply_header_t;
typedef struct ompi_osc_rdma_header_put_t ompi_osc_rdma_header_put_t;
#define OMPI_OSC_RDMA_REPLY_HDR_HTON(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_HTON((hdr).hdr_base) \
(hdr).hdr_target_tag = htonl((hdr).hdr_target_tag); \
(hdr).hdr_msg_length = htonl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_rdma_header_acc_t {
ompi_osc_rdma_header_base_t base;
#define OMPI_OSC_RDMA_REPLY_HDR_NTOH(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_NTOH((hdr).hdr_base) \
(hdr).hdr_target_tag = ntohl((hdr).hdr_target_tag); \
(hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \
} while (0)
struct ompi_osc_rdma_control_header_t {
ompi_osc_rdma_base_header_t hdr_base;
int16_t hdr_windx;
int32_t hdr_value[2];
uint16_t tag;
uint32_t count;
uint64_t len;
uint64_t displacement;
uint32_t op;
};
typedef struct ompi_osc_rdma_control_header_t ompi_osc_rdma_control_header_t;
typedef struct ompi_osc_rdma_header_acc_t ompi_osc_rdma_header_acc_t;
#define OMPI_OSC_RDMA_CONTROL_HDR_HTON(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_HTON((hdr).hdr_base); \
(hdr).hdr_windx = htons((hdr).hdr_windx); \
(hdr).hdr_value[0] = htonl((hdr).hdr_value[0]); \
(hdr).hdr_value[1] = htonl((hdr).hdr_value[1]); \
} while (0)
struct ompi_osc_rdma_header_get_t {
ompi_osc_rdma_header_base_t base;
#define OMPI_OSC_RDMA_CONTROL_HDR_NTOH(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_NTOH((hdr).hdr_base); \
(hdr).hdr_windx = ntohs((hdr).hdr_windx); \
(hdr).hdr_value[0] = ntohl((hdr).hdr_value[0]); \
(hdr).hdr_value[1] = ntohl((hdr).hdr_value[1]); \
} while (0)
struct ompi_osc_rdma_rdma_info_header_t {
ompi_osc_rdma_base_header_t hdr_base;
int16_t hdr_windx;
int32_t hdr_origin;
uint16_t tag;
uint32_t count;
uint64_t len;
uint64_t displacement;
};
typedef struct ompi_osc_rdma_rdma_info_header_t ompi_osc_rdma_rdma_info_header_t;
typedef struct ompi_osc_rdma_header_get_t ompi_osc_rdma_header_get_t;
#define OMPI_OSC_RDMA_RDMA_INFO_HDR_HTON(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_HTON((hdr).hdr_base); \
(hdr).hdr_windx = htons((hdr).hdr_windx); \
(hdr).hdr_origin = htonl((hdr).hdr_origin); \
} while (0)
struct ompi_osc_rdma_header_complete_t {
ompi_osc_rdma_header_base_t base;
int frag_count;
};
typedef struct ompi_osc_rdma_header_complete_t ompi_osc_rdma_header_complete_t;
#define OMPI_OSC_RDMA_RDMA_INFO_HDR_NTOH(hdr) \
do { \
OMPI_OSC_RDMA_BASE_HDR_NTOH((hdr).hdr_base); \
(hdr).hdr_windx = ntohs((hdr).hdr_windx); \
(hdr).hdr_origin = ntohl((hdr).hdr_origin); \
} while (0)
struct ompi_osc_rdma_header_get_acc_t {
ompi_osc_rdma_header_base_t base;
int16_t tag;
uint32_t count;
uint64_t len;
uint64_t displacement;
uint32_t op;
};
typedef struct ompi_osc_rdma_header_get_acc_t ompi_osc_rdma_header_get_acc_t;
struct ompi_osc_rdma_header_cswap_t {
ompi_osc_rdma_header_base_t base;
int16_t tag;
uint32_t len;
uint64_t displacement;
};
typedef struct ompi_osc_rdma_header_cswap_t ompi_osc_rdma_header_cswap_t;
struct ompi_osc_rdma_header_post_t {
ompi_osc_rdma_header_base_t base;
uint16_t windx;
};
typedef struct ompi_osc_rdma_header_post_t ompi_osc_rdma_header_post_t;
struct ompi_osc_rdma_header_lock_t {
ompi_osc_rdma_header_base_t base;
int32_t lock_type;
uint64_t serial_number;
};
typedef struct ompi_osc_rdma_header_lock_t ompi_osc_rdma_header_lock_t;
struct ompi_osc_rdma_header_lock_ack_t {
ompi_osc_rdma_header_base_t base;
uint16_t windx;
uint32_t source;
uint64_t serial_number;
};
typedef struct ompi_osc_rdma_header_lock_ack_t ompi_osc_rdma_header_lock_ack_t;
struct ompi_osc_rdma_header_unlock_t {
ompi_osc_rdma_header_base_t base;
int32_t lock_type;
uint32_t frag_count;
};
typedef struct ompi_osc_rdma_header_unlock_t ompi_osc_rdma_header_unlock_t;
struct ompi_osc_rdma_header_unlock_ack_t {
ompi_osc_rdma_header_base_t base;
};
typedef struct ompi_osc_rdma_header_unlock_ack_t ompi_osc_rdma_header_unlock_ack_t;
struct ompi_osc_rdma_header_flush_t {
ompi_osc_rdma_header_base_t base;
uint32_t frag_count;
uint64_t serial_number;
};
typedef struct ompi_osc_rdma_header_flush_t ompi_osc_rdma_header_flush_t;
struct ompi_osc_rdma_header_flush_ack_t {
ompi_osc_rdma_header_base_t base;
uint64_t serial_number;
};
typedef struct ompi_osc_rdma_header_flush_ack_t ompi_osc_rdma_header_flush_ack_t;
struct ompi_osc_rdma_frag_header_t {
ompi_osc_rdma_header_base_t base;
uint16_t windx; /* cid of communicator backing window (our window id) */
uint32_t source; /* rank in window of source process */
uint16_t num_ops; /* number of operations in this buffer */
};
typedef struct ompi_osc_rdma_frag_header_t ompi_osc_rdma_frag_header_t;
union ompi_osc_rdma_header_t {
ompi_osc_rdma_header_base_t base;
ompi_osc_rdma_header_put_t put;
ompi_osc_rdma_header_acc_t acc;
ompi_osc_rdma_header_get_t get;
ompi_osc_rdma_header_complete_t complete;
ompi_osc_rdma_header_get_acc_t get_acc;
ompi_osc_rdma_header_cswap_t cswap;
ompi_osc_rdma_header_post_t post;
ompi_osc_rdma_header_lock_t lock;
ompi_osc_rdma_header_lock_ack_t lock_ack;
ompi_osc_rdma_header_unlock_t unlock;
ompi_osc_rdma_header_unlock_ack_t unlock_ack;
ompi_osc_rdma_header_flush_t flush;
ompi_osc_rdma_header_flush_ack_t flush_ack;
ompi_osc_rdma_frag_header_t frag;
};
typedef union ompi_osc_rdma_header_t ompi_osc_rdma_header_t;
#endif /* OMPI_MCA_OSC_RDMA_HDR_H */

Просмотреть файл

@ -1,25 +0,0 @@
/*
* 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$
*/
#include "ompi_config.h"
#include "osc_rdma_longreq.h"
OBJ_CLASS_INSTANCE(ompi_osc_rdma_longreq_t, opal_free_list_item_t,
NULL, NULL);

Просмотреть файл

@ -1,70 +0,0 @@
/*
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_RDMA_LONGREQ_H
#define OSC_RDMA_LONGREQ_H
#include "osc_rdma.h"
#include "opal/class/opal_free_list.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/request/request.h"
#include "ompi/op/op.h"
struct ompi_osc_rdma_longreq_t {
opal_free_list_item_t super;
ompi_request_t *request;
union {
struct ompi_osc_rdma_sendreq_t *req_sendreq;
struct ompi_osc_rdma_replyreq_t *req_replyreq;
struct ompi_osc_rdma_send_header_t *req_sendhdr;
} req_basereq;
/* warning - this doesn't always have a sane value */
ompi_osc_rdma_module_t *req_module;
/* for long receives, to avoid a longrecvreq type */
struct ompi_op_t *req_op;
struct ompi_datatype_t *req_datatype;
};
typedef struct ompi_osc_rdma_longreq_t ompi_osc_rdma_longreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_longreq_t);
static inline int
ompi_osc_rdma_longreq_alloc(ompi_osc_rdma_longreq_t **longreq)
{
opal_free_list_item_t *item;
int ret;
OPAL_FREE_LIST_GET(&mca_osc_rdma_component.c_longreqs,
item, ret);
*longreq = (ompi_osc_rdma_longreq_t*) item;
return ret;
}
static inline int
ompi_osc_rdma_longreq_free(ompi_osc_rdma_longreq_t *longreq)
{
OPAL_FREE_LIST_RETURN(&mca_osc_rdma_component.c_longreqs,
&longreq->super.super);
return OMPI_SUCCESS;
}
#endif

Просмотреть файл

@ -10,6 +10,7 @@
* Copyright (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -31,11 +32,11 @@ ompi_osc_rdma_windx_to_module(uint32_t windx)
ompi_osc_rdma_module_t *module;
/* find the right module and dispatch */
OPAL_THREAD_LOCK(&mca_osc_rdma_component.c_lock);
ret = opal_hash_table_get_value_uint32(&mca_osc_rdma_component.c_modules,
OPAL_THREAD_LOCK(&mca_osc_rdma_component.lock);
ret = opal_hash_table_get_value_uint32(&mca_osc_rdma_component.modules,
windx,
(void**) (&module));
OPAL_THREAD_UNLOCK(&mca_osc_rdma_component.c_lock);
OPAL_THREAD_UNLOCK(&mca_osc_rdma_component.lock);
if (OMPI_SUCCESS != ret) {
opal_output(0, "Could not translate windx %d to a local MPI_Win instance",
windx);

919
ompi/mca/osc/rdma/osc_rdma_passive_target.c Обычный файл
Просмотреть файл

@ -0,0 +1,919 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* 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 (c) 2007-2014 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_rdma.h"
#include "osc_rdma_header.h"
#include "osc_rdma_data_move.h"
#include "osc_rdma_frag.h"
#include "mpi.h"
#include "opal/runtime/opal_progress.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/mca/osc/base/base.h"
#include "opal/include/opal_stdint.h"
/* target-side tracking of a lock request */
struct ompi_osc_rdma_pending_lock_t {
opal_list_item_t super;
int peer;
int lock_type;
uint64_t serial_number;
};
typedef struct ompi_osc_rdma_pending_lock_t ompi_osc_rdma_pending_lock_t;
OBJ_CLASS_INSTANCE(ompi_osc_rdma_pending_lock_t, opal_list_item_t,
NULL, NULL);
/* origin-side tracking of a lock request */
struct ompi_osc_rdma_outstanding_lock_t {
opal_list_item_t super;
int target;
int32_t lock_acks_received;
int32_t unlock_acks_received;
int32_t flush_acks_received;
uint64_t serial_number;
int32_t type;
};
typedef struct ompi_osc_rdma_outstanding_lock_t ompi_osc_rdma_outstanding_lock_t;
OBJ_CLASS_INSTANCE(ompi_osc_rdma_outstanding_lock_t, opal_list_item_t,
NULL, NULL);
static int ompi_osc_activate_next_lock (ompi_osc_rdma_module_t *module);
static inline int queue_lock (ompi_osc_rdma_module_t *module, int requestor,
int lock_type, uint64_t serial_number);
/**
* Find the first outstanding lock to a target.
*
* @param[in] module - OSC RDMA module
* @param[in] target - Target rank
*
* @returns an outstanding lock on success
*
* This function traverses the outstanding_locks list in the module
* looking for a lock that matches target. The caller must hold the
* module lock.
*/
static inline ompi_osc_rdma_outstanding_lock_t *find_outstanding_lock (ompi_osc_rdma_module_t *module, int target)
{
ompi_osc_rdma_outstanding_lock_t *lock;
OPAL_LIST_FOREACH(lock, &module->outstanding_locks, ompi_osc_rdma_outstanding_lock_t) {
if (lock->target == target) {
return lock;
}
}
return NULL;
}
static inline ompi_osc_rdma_outstanding_lock_t *find_outstanding_lock_by_serial (ompi_osc_rdma_module_t *module, uint64_t serial_number)
{
ompi_osc_rdma_outstanding_lock_t *lock;
OPAL_LIST_FOREACH(lock, &module->outstanding_locks, ompi_osc_rdma_outstanding_lock_t) {
if (lock->serial_number == serial_number) {
return lock;
}
}
return NULL;
}
static inline int ompi_osc_rdma_lock_self (ompi_osc_rdma_module_t *module, ompi_osc_rdma_outstanding_lock_t *lock)
{
const int my_rank = ompi_comm_rank (module->comm);
if ((MPI_LOCK_SHARED == lock->type && MPI_LOCK_EXCLUSIVE != module->lock_status) ||
(MPI_LOCK_EXCLUSIVE == lock->type && 0 == module->lock_status)) {
/* we can aquire the lock immediately */
module->lock_status = lock->type;
if (MPI_LOCK_SHARED == lock->type) {
module->shared_count++;
}
lock->lock_acks_received = 1;
} else {
/* queue the lock */
queue_lock (module, my_rank, lock->type, lock->serial_number);
}
/* If locking local, can't be non-blocking according to the
standard. We need to wait for the ack here. */
while (0 == lock->lock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"local lock aquired"));
return OMPI_SUCCESS;
}
static inline void ompi_osc_rdma_unlock_self (ompi_osc_rdma_module_t *module, ompi_osc_rdma_outstanding_lock_t *lock)
{
if (!(MPI_LOCK_SHARED == lock->type && 0 == --module->shared_count)) {
module->lock_status = 0;
ompi_osc_activate_next_lock (module);
}
/* need to ensure we make progress */
opal_progress();
lock->unlock_acks_received++;
}
static inline int ompi_osc_rdma_lock_remote (ompi_osc_rdma_module_t *module, int target, ompi_osc_rdma_outstanding_lock_t *lock)
{
ompi_osc_rdma_header_lock_t lock_req;
int ret;
/* generate a lock request */
lock_req.base.type = OMPI_OSC_RDMA_HDR_TYPE_LOCK_REQ;
lock_req.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID | OMPI_OSC_RDMA_HDR_FLAG_PASSIVE_TARGET;
lock_req.lock_type = lock->type;
lock_req.serial_number = lock->serial_number;
ret = ompi_osc_rdma_control_send (module, target, &lock_req, sizeof (lock_req));
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
return ret;
}
/* make sure the request gets sent, so we can start eager sending... */
ret = ompi_osc_rdma_frag_flush_target (module, target);
return ret;
}
static inline int ompi_osc_rdma_unlock_remote (ompi_osc_rdma_module_t *module, int target, ompi_osc_rdma_outstanding_lock_t *lock)
{
ompi_osc_rdma_header_unlock_t unlock_req;
unlock_req.base.type = OMPI_OSC_RDMA_HDR_TYPE_UNLOCK_REQ;
unlock_req.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID | OMPI_OSC_RDMA_HDR_FLAG_PASSIVE_TARGET;
unlock_req.frag_count = module->epoch_outgoing_frag_count[target];
unlock_req.lock_type = lock->type;
/* send control message with unlock request and count */
return ompi_osc_rdma_control_send (module, target, &unlock_req, sizeof (unlock_req));
}
int ompi_osc_rdma_lock(int lock_type, int target, int assert, ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_outstanding_lock_t *lock;
int ret = OMPI_SUCCESS;
assert(module->epoch_outgoing_frag_count[target] == 0);
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: lock %d %d", target, lock_type));
/* delay all eager sends until we've heard back.. */
OPAL_THREAD_LOCK(&module->lock);
module->passive_eager_send_active[target] = false;
module->passive_target_access_epoch = true;
/* create lock item */
lock = OBJ_NEW(ompi_osc_rdma_outstanding_lock_t);
if (OPAL_UNLIKELY(NULL == lock)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
lock->target = target;
lock->lock_acks_received = 0;
lock->unlock_acks_received = 0;
lock->serial_number = module->lock_serial_number++;
lock->type = lock_type;
opal_list_append(&module->outstanding_locks, &lock->super);
if (0 == (assert & MPI_MODE_NOCHECK)) {
if (ompi_comm_rank (module->comm) != target) {
ret = ompi_osc_rdma_lock_remote (module, target, lock);
} else {
ret = ompi_osc_rdma_lock_self (module, lock);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
goto exit_error;
}
} else {
lock->lock_acks_received = 1;
}
OPAL_THREAD_UNLOCK(&module->lock);
return OMPI_SUCCESS;
exit_error:
OPAL_THREAD_UNLOCK(&module->lock);
opal_list_remove_item(&module->outstanding_locks, &lock->super);
OBJ_RELEASE(lock);
/* return */
return ret;
}
int ompi_osc_rdma_unlock(int target, ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_outstanding_lock_t *lock = NULL;
int ret = OMPI_SUCCESS;
OPAL_THREAD_LOCK(&module->lock);
lock = find_outstanding_lock (module, target);
if (OPAL_UNLIKELY(NULL == lock)) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_unlock: target %d is not locked in window %s",
target, win->w_name));
OPAL_THREAD_LOCK(&module->lock);
return MPI_ERR_RMA_SYNC;
}
if (ompi_comm_rank (module->comm) != target) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: unlock %d, lock_acks_received = %d", target,
lock->lock_acks_received));
/* wait until ack has arrived from target */
while (0 == lock->lock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
ret = ompi_osc_rdma_unlock_remote (module, target, lock);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
goto cleanup;
}
/* start all sendreqs to target */
ret = ompi_osc_rdma_frag_flush_target(module, target);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
goto cleanup;
}
/* wait for all the requests and the unlock ack (meaning remote completion) */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count ||
0 == lock->unlock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_unlock: unlock of %d complete", target));
} else {
ompi_osc_rdma_unlock_self (module, lock);
}
module->passive_eager_send_active[target] = false;
module->epoch_outgoing_frag_count[target] = 0;
module->passive_target_access_epoch = false;
/* delete the lock */
opal_list_remove_item (&module->outstanding_locks, &lock->super);
OBJ_RELEASE(lock);
cleanup:
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int ompi_osc_rdma_lock_all(int assert, struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int ret, my_rank = ompi_comm_rank (module->comm);
ompi_osc_rdma_outstanding_lock_t *lock;
/* delay all eager sends until we've heard back.. */
OPAL_THREAD_LOCK(&module->lock);
for (int i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
module->passive_eager_send_active[i] = false;
}
module->passive_target_access_epoch = true;
/* create lock item */
lock = OBJ_NEW(ompi_osc_rdma_outstanding_lock_t);
lock->target = -1;
lock->lock_acks_received = 0;
lock->unlock_acks_received = 0;
lock->serial_number = module->lock_serial_number++;
opal_list_append(&module->outstanding_locks, &lock->super);
/* if nocheck is not specified, send a lock request to everyone
and wait for the local response */
if (0 != (assert & MPI_MODE_NOCHECK)) {
ret = ompi_osc_rdma_lock_self (module, lock);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
goto exit_error;
}
for (int i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
if (my_rank == i) {
continue;
}
ret = ompi_osc_rdma_lock_remote (module, i, lock);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
opal_list_remove_item(&module->outstanding_locks, &lock->super);
}
}
} else {
lock->lock_acks_received = ompi_comm_size(module->comm);
}
OPAL_THREAD_UNLOCK(&module->lock);
return OMPI_SUCCESS;
exit_error:
OPAL_THREAD_UNLOCK(&module->lock);
opal_list_remove_item(&module->outstanding_locks, &lock->super);
OBJ_RELEASE(lock);
/* return */
return ret;
}
int ompi_osc_rdma_unlock_all (struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int my_rank = ompi_comm_rank (module->comm);
ompi_osc_rdma_outstanding_lock_t *lock;
int ret;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_unlock_all entering..."));
OPAL_THREAD_LOCK(&module->lock);
lock = find_outstanding_lock (module, -1);
if (OPAL_UNLIKELY(NULL == lock)) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_unlock_all: not locked in window %s",
win->w_name));
OPAL_THREAD_LOCK(&module->lock);
return MPI_ERR_RMA_SYNC;
}
/* wait for lock acks */
while (ompi_comm_size(module->comm) != lock->lock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
/* send unlock messages to all of my peers */
for (int i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
if (my_rank == i) {
continue;
}
ret = ompi_osc_rdma_unlock_remote (module, i, lock);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
goto cleanup;
}
}
/* unlock myself */
ompi_osc_rdma_unlock_self (module, lock);
/* start all sendreqs to target */
ret = ompi_osc_rdma_frag_flush_all(module);
if (OMPI_SUCCESS != ret) goto cleanup;
/* wait for all the requests and the unlock ack (meaning remote completion) */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count ||
ompi_comm_size(module->comm) != lock->unlock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
/* reset all fragment counters */
memset (module->epoch_outgoing_frag_count, 0, ompi_comm_size(module->comm) * sizeof (module->epoch_outgoing_frag_count[0]));
memset (module->passive_eager_send_active, 0, ompi_comm_size(module->comm) * module->passive_eager_send_active[0]);
opal_list_remove_item (&module->outstanding_locks, &lock->super);
OBJ_RELEASE(lock);
module->passive_target_access_epoch = false;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_unlock_all complete"));
cleanup:
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int ompi_osc_rdma_sync (struct ompi_win_t *win)
{
opal_progress();
return OMPI_SUCCESS;
}
static int ompi_osc_rdma_flush_lock (ompi_osc_rdma_module_t *module, ompi_osc_rdma_outstanding_lock_t *lock,
int target)
{
ompi_osc_rdma_header_flush_t flush_req;
int peer_count, ret, flush_count;
int my_rank = ompi_comm_rank (module->comm);
if (-1 == lock->target) {
peer_count = ompi_comm_size(module->comm) - 1;
} else {
peer_count = 1;
}
/* wait until ack has arrived from target, since we need to be
able to eager send before we can transfer all the data... */
while (peer_count > lock->lock_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
lock->flush_acks_received = 0;
flush_req.base.type = OMPI_OSC_RDMA_HDR_TYPE_FLUSH_REQ;
flush_req.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID | OMPI_OSC_RDMA_HDR_FLAG_PASSIVE_TARGET;
flush_req.serial_number = lock->serial_number;
if (-1 == target) {
flush_count = ompi_comm_size(module->comm);
for (int i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
if (i == my_rank) {
continue;
}
flush_req.frag_count = module->epoch_outgoing_frag_count[i];
/* send control message with flush request and count */
ret = ompi_osc_rdma_control_send (module, i, &flush_req, sizeof (flush_req));
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
return ret;
}
}
} else {
flush_req.frag_count = module->epoch_outgoing_frag_count[target];
flush_count = 1;
/* send control message with flush request and count */
ret = ompi_osc_rdma_control_send (module, target, &flush_req, sizeof (flush_req));
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
return ret;
}
}
/* start all sendreqs to target */
ret = ompi_osc_rdma_frag_flush_all (module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
return ret;
}
/* wait for all the requests and the flush ack (meaning remote completion) */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count ||
flush_count != lock->flush_acks_received) {
opal_condition_wait(&module->cond, &module->lock);
}
if (-1 == target) {
memset (module->epoch_outgoing_frag_count, 0, peer_count * sizeof (module->epoch_outgoing_frag_count[0]));
} else {
module->epoch_outgoing_frag_count[target] = 0;
}
return OMPI_SUCCESS;
}
int ompi_osc_rdma_flush (int target, struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_outstanding_lock_t *lock;
int ret;
assert (0 <= target);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_flush starting..."));
if (ompi_comm_rank (module->comm) == target) {
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"calling opal_progress. incoming complete = %d",
module->frag_request->req_complete));
opal_progress ();
return OMPI_SUCCESS;
}
OPAL_THREAD_LOCK(&module->lock);
lock = find_outstanding_lock (module, target);
if (NULL == lock) {
lock = find_outstanding_lock (module, -1);
}
if (OPAL_UNLIKELY(NULL == lock)) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_flush: target %d is not locked in window %s",
target, win->w_name));
OPAL_THREAD_LOCK(&module->lock);
return MPI_ERR_RMA_SYNC;
}
ret = ompi_osc_rdma_flush_lock (module, lock, target);
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int ompi_osc_rdma_flush_all (struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_osc_rdma_outstanding_lock_t *lock;
int ret = OMPI_SUCCESS;
if (OPAL_UNLIKELY(0 == opal_list_get_size (&module->outstanding_locks))) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_flush_all: no targets are locked in window %s",
win->w_name));
return MPI_ERR_RMA_SYNC;
}
OPAL_THREAD_LOCK(&module->lock);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_flush_all entering..."));
/* flush all locks */
OPAL_LIST_FOREACH(lock, &module->outstanding_locks, ompi_osc_rdma_outstanding_lock_t) {
ret = ompi_osc_rdma_flush_lock (module, lock, lock->target);
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
break;
}
}
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_flush_all complete"));
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int ompi_osc_rdma_flush_local (int target, struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int ret;
OPAL_THREAD_LOCK(&module->lock);
ret = ompi_osc_rdma_frag_flush_target(module, target);
if (OMPI_SUCCESS != ret) goto cleanup;
/* wait for all the requests */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count) {
opal_condition_wait(&module->cond, &module->lock);
}
cleanup:
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
int ompi_osc_rdma_flush_local_all (struct ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int ret = OMPI_SUCCESS;
OPAL_THREAD_LOCK(&module->lock);
ret = ompi_osc_rdma_frag_flush_all(module);
if (OMPI_SUCCESS != ret) goto cleanup;
/* wait for all the requests */
while (module->outgoing_frag_count != module->outgoing_frag_signal_count) {
opal_condition_wait(&module->cond, &module->lock);
}
cleanup:
OPAL_THREAD_UNLOCK(&module->lock);
return ret;
}
/* target side operation to acknowledge to initiator side that the
lock is now held by the initiator */
static inline int activate_lock (ompi_osc_rdma_module_t *module, int requestor,
uint64_t serial_number)
{
ompi_osc_rdma_outstanding_lock_t *lock;
if (ompi_comm_rank (module->comm) != requestor) {
ompi_osc_rdma_header_lock_ack_t lock_ack;
lock_ack.base.type = OMPI_OSC_RDMA_HDR_TYPE_LOCK_ACK;
lock_ack.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
lock_ack.source = ompi_comm_rank(module->comm);
lock_ack.windx = ompi_comm_get_cid(module->comm);
lock_ack.serial_number = serial_number;
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: sending lock to %d", requestor));
/* we don't want to send any data, since we're the exposure
epoch only, so use an unbuffered send */
return ompi_osc_rdma_control_send_unbuffered (module, requestor, &lock_ack, sizeof (lock_ack));
}
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: releasing local lock"));
lock = find_outstanding_lock (module, requestor);
if (NULL == lock) {
lock = find_outstanding_lock (module, -1);
if (OPAL_UNLIKELY(NULL == lock)) {
OPAL_OUTPUT_VERBOSE((5, ompi_osc_base_framework.framework_output,
"lock could not be located"));
}
}
lock->lock_acks_received = 1;
opal_condition_broadcast (&module->cond);
return OMPI_SUCCESS;
}
/* target side operation to create a pending lock request for a lock
request that could not be satisfied */
static inline int queue_lock (ompi_osc_rdma_module_t *module, int requestor,
int lock_type, uint64_t serial_number)
{
ompi_osc_rdma_pending_lock_t *pending =
OBJ_NEW(ompi_osc_rdma_pending_lock_t);
if (NULL == pending) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
pending->peer = requestor;
pending->lock_type = lock_type;
pending->serial_number = serial_number;
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: queueing lock request from %d", requestor));
opal_list_append(&module->locks_pending, &pending->super);
return OMPI_SUCCESS;
}
static int ompi_osc_activate_next_lock (ompi_osc_rdma_module_t *module) {
/* release any other pending locks we can */
ompi_osc_rdma_pending_lock_t *pending_lock, *next;
int ret = OMPI_SUCCESS;
OPAL_LIST_FOREACH_SAFE(pending_lock, next, &module->locks_pending,
ompi_osc_rdma_pending_lock_t) {
if (MPI_LOCK_SHARED == pending_lock->lock_type) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_activate_next_lock: release pending lock of type MPI_LOCK_SHARED to peer %d\n",
pending_lock->peer));
/* acquire shared lock */
module->lock_status = MPI_LOCK_SHARED;
module->shared_count++;
ret = activate_lock(module, pending_lock->peer, pending_lock->serial_number);
opal_list_remove_item (&module->locks_pending, &pending_lock->super);
OBJ_RELEASE(pending_lock);
} else {
if (0 == module->lock_status) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_activate_next_lock: release pending lock of type MPI_LOCK_EXCLUSIVE to peer %d\n",
pending_lock->peer));
/* acquire exclusive lock */
module->lock_status = MPI_LOCK_EXCLUSIVE;
ret = activate_lock(module, pending_lock->peer, pending_lock->serial_number);
opal_list_remove_item (&module->locks_pending, &pending_lock->super);
OBJ_RELEASE(pending_lock);
}
/* if the lock was acquired (ie, status was 0), then
we're done. If the lock was not acquired, we're
also done, because all the shared locks have to
finish first */
break;
}
if (OMPI_SUCCESS != ret) {
break;
}
}
return ret;
}
/* target side function called when the initiator sends a lock
request. Lock will either be activated and acknowledged or
queued. */
int ompi_osc_rdma_process_lock (ompi_osc_rdma_module_t* module, int source,
ompi_osc_rdma_header_lock_t* lock_header)
{
int ret;
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_process_lock: processing lock request from %d. current lock state = %d, shared_count = %d",
source, module->lock_status, module->shared_count));
if (MPI_LOCK_SHARED == lock_header->lock_type) {
if (module->lock_status != MPI_LOCK_EXCLUSIVE) {
/* acquire shared lock */
module->lock_status = MPI_LOCK_SHARED;
module->shared_count++;
ret = activate_lock(module, source, lock_header->serial_number);
} else {
/* lock not available, queue */
ret = queue_lock(module, source, lock_header->lock_type, lock_header->serial_number);
}
} else {
if (0 == module->lock_status) {
/* acquire exclusive lock */
module->lock_status = MPI_LOCK_EXCLUSIVE;
ret = activate_lock(module, source, lock_header->serial_number);
} else {
/* lock not available, queue */
ret = queue_lock(module, source, lock_header->lock_type, lock_header->serial_number);
}
}
return ret;
}
/* initiator-side function called when the target acks the lock
request. */
void ompi_osc_rdma_process_lock_ack (ompi_osc_rdma_module_t *module,
ompi_osc_rdma_header_lock_ack_t *lock_ack_header)
{
ompi_osc_rdma_outstanding_lock_t *lock, *next;
OPAL_LIST_FOREACH_SAFE(lock, next, &module->outstanding_locks, ompi_osc_rdma_outstanding_lock_t) {
if (lock->serial_number == lock_ack_header->serial_number) {
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
"osc rdma: lock ack %d", lock_ack_header->source));
lock->lock_acks_received++;
module->passive_eager_send_active[lock_ack_header->source] = true;
return;
}
}
opal_output(ompi_osc_base_framework.framework_output,
"osc rdma: lock ack %d, %ld for unfindable lock request",
lock_ack_header->source, (unsigned long) lock_ack_header->serial_number);
}
void ompi_osc_rdma_process_flush_ack (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_flush_ack_t *flush_ack_header) {
ompi_osc_rdma_outstanding_lock_t *lock;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_process_unlock_ack: processing flush ack from %d for lock %" PRIu64,
source, flush_ack_header->serial_number));
/* NTH: need to verify that this will work as expected */
lock = find_outstanding_lock_by_serial (module, flush_ack_header->serial_number);
assert (NULL != lock);
lock->flush_acks_received++;
opal_condition_broadcast(&module->cond);
}
void ompi_osc_rdma_process_unlock_ack (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_unlock_ack_t *unlock_ack_header) {
ompi_osc_rdma_outstanding_lock_t *lock;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_process_unlock_ack: processing unlock ack from %d",
source));
/* NTH: need to verify that this will work as expected */
lock = find_outstanding_lock (module, source);
if (NULL == lock) {
lock = find_outstanding_lock(module, -1);
assert (NULL != lock);
}
lock->unlock_acks_received++;
}
/**
* Process an unlock request.
*
* @param[in] module - OSC RDMA module
* @param[in] source - Source rank
* @param[in] unlock_header - Incomming unlock header
*
* This functions is the target-side functio for handling an unlock
* request. Once all pending operations from the target are complete
* this functions sends an unlock acknowledgement then attempts to
* active a pending lock if the lock becomes free.
*/
int ompi_osc_rdma_process_unlock (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_unlock_t *unlock_header)
{
ompi_osc_rdma_header_unlock_ack_t unlock_ack;
int ret;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_process_unlock entering (finished %d/%d)...",
module->passive_incoming_frag_count[source],
module->passive_incoming_frag_signal_count[source]));
/* we cannot block when processing an incomming request */
if (module->passive_incoming_frag_signal_count[source] !=
module->passive_incoming_frag_count[source]) {
return OMPI_ERR_WOULD_BLOCK;
}
unlock_ack.base.type = OMPI_OSC_RDMA_HDR_TYPE_UNLOCK_ACK;
unlock_ack.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
ret = ompi_osc_rdma_control_send_unbuffered (module, source, &unlock_ack, sizeof (unlock_ack));
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
return ret;
}
module->passive_incoming_frag_signal_count[source] = 0;
module->passive_incoming_frag_count[source] = 0;
OPAL_THREAD_LOCK(&module->lock);
if (unlock_header->lock_type == MPI_LOCK_EXCLUSIVE || 0 == --module->shared_count) {
module->lock_status = 0;
ompi_osc_activate_next_lock (module);
}
OPAL_THREAD_UNLOCK(&module->lock);
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"osc rdma: finished processing unlock fragment"));
return ret;
}
int ompi_osc_rdma_process_flush (ompi_osc_rdma_module_t *module, int source,
ompi_osc_rdma_header_flush_t *flush_header)
{
ompi_osc_rdma_header_flush_ack_t flush_ack;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"ompi_osc_rdma_process_flush entering (finished %d/%d)...",
module->passive_incoming_frag_count[source],
module->passive_incoming_frag_signal_count[source]));
/* we cannot block when processing an incomming request */
if (module->passive_incoming_frag_signal_count[source] !=
module->passive_incoming_frag_count[source]) {
return OMPI_ERR_WOULD_BLOCK;
}
module->passive_incoming_frag_signal_count[source] = 0;
module->passive_incoming_frag_count[source] = 0;
flush_ack.base.type = OMPI_OSC_RDMA_HDR_TYPE_FLUSH_ACK;
flush_ack.base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
flush_ack.serial_number = flush_header->serial_number;
return ompi_osc_rdma_control_send_unbuffered (module, source, &flush_ack, sizeof (flush_ack));
}

65
ompi/mca/osc/rdma/osc_rdma_pending_frag.h Обычный файл
Просмотреть файл

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*
* Pending frags are fragments that have been received on the target,
* but can not yet be processed (because ordering is turned on).
* Because receive memory descriptors are precious resources, rather
* than keeping a descriptor until the right sequence number, we
* instead malloc a buffer (as part of the pending frag) and copy the
* message.
*/
#ifndef OSC_RDMA_PENDING_FRAG_H
#define OSC_RDMA_PENDING_FRAG_H
/** Incoming fragment that has to be queued */
struct ompi_osc_rdma_pending_frag_t {
opal_list_item_t super;
/* This is a pointer to the top of the fragment (which is always
the header). Save as a header to make the casting a bit less
onerous during sequence number lookups. */
ompi_osc_rdma_frag_header_t *header;
};
typedef struct ompi_osc_rdma_pending_frag_t ompi_osc_rdma_pending_frag_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_pending_frag_t);
/*
* Note: module lock must be held during this operation
*/
static inline ompi_osc_rdma_pending_frag_t*
ompi_osc_rdma_pending_frag_create(ompi_osc_rdma_module_t *module,
void *ptr,
size_t size)
{
size_t total_size = sizeof(ompi_osc_rdma_pending_frag_t) + size;
ompi_osc_rdma_pending_frag_t *ret =
(ompi_osc_rdma_pending_frag_t*) malloc(total_size);
if (NULL == ret) return NULL;
OBJ_CONSTRUCT(&ret, ompi_osc_rdma_pending_frag_t);
memcpy(ret->header, ptr, size);
return ret;
}
/*
* Note: module lock must be held for this operation
*/
static inline int
ompi_osc_rdma_pending_frag_destroy(ompi_osc_rdma_module_t *module,
ompi_osc_rdma_pending_frag_t* frag)
{
OBJ_DESTRUCT(&frag);
free(frag);
return OMPI_SUCCESS;
}
#endif

Просмотреть файл

@ -1,80 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_rdma_replyreq.h"
#include "opal/class/opal_list.h"
#include "opal/datatype/opal_convertor.h"
int
ompi_osc_rdma_replyreq_alloc_init(ompi_osc_rdma_module_t *module,
int origin,
ompi_ptr_t origin_request,
OPAL_PTRDIFF_TYPE target_displacement,
int target_count,
struct ompi_datatype_t *datatype,
ompi_osc_rdma_replyreq_t **replyreq)
{
int ret;
void *target_addr = (unsigned char*) module->m_win->w_baseptr +
(target_displacement * module->m_win->w_disp_unit);
/* allocate a replyreq */
ret = ompi_osc_rdma_replyreq_alloc(module,
origin,
replyreq);
if (OMPI_SUCCESS != ret) return ret;
/* initialize local side of replyreq */
ret = ompi_osc_rdma_replyreq_init_target(*replyreq,
target_addr,
target_count,
datatype);
if (OMPI_SUCCESS != ret) {
ompi_osc_rdma_replyreq_free(*replyreq);
return ret;
}
/* initialize remote side of replyreq */
ret = ompi_osc_rdma_replyreq_init_origin(*replyreq,
origin_request);
if (OMPI_SUCCESS != ret) {
ompi_osc_rdma_replyreq_free(*replyreq);
return ret;
}
return OMPI_SUCCESS;
}
static void ompi_osc_rdma_replyreq_construct(ompi_osc_rdma_replyreq_t *replyreq)
{
OBJ_CONSTRUCT(&(replyreq->rep_target_convertor), opal_convertor_t);
}
static void ompi_osc_rdma_replyreq_destruct(ompi_osc_rdma_replyreq_t *replyreq)
{
OBJ_DESTRUCT(&(replyreq->rep_target_convertor));
}
OBJ_CLASS_INSTANCE(ompi_osc_rdma_replyreq_t, opal_list_item_t,
ompi_osc_rdma_replyreq_construct,
ompi_osc_rdma_replyreq_destruct);

Просмотреть файл

@ -1,144 +0,0 @@
/*
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_RDMA_REPLYREQ_H
#define OMPI_OSC_RDMA_REPLYREQ_H
#include "osc_rdma.h"
#include "osc_rdma_longreq.h"
#include "opal/class/opal_list.h"
#include "ompi/datatype/ompi_datatype.h"
#include "opal/datatype/opal_convertor.h"
#include "ompi/communicator/communicator.h"
#include "ompi/proc/proc.h"
#include "ompi/memchecker.h"
struct ompi_osc_rdma_replyreq_t {
opal_list_item_t super;
/** pointer to the module that created the replyreq */
ompi_osc_rdma_module_t *rep_module;
/** Datatype for the target side of the operation */
struct ompi_datatype_t *rep_target_datatype;
/** Convertor for the target. Always setup for send. */
opal_convertor_t rep_target_convertor;
/** packed size of message on the target side */
size_t rep_target_bytes_packed;
/** rank in module's communicator for origin of operation */
int rep_origin_rank;
/** pointer to the proc structure for the origin of the operation */
ompi_proc_t *rep_origin_proc;
ompi_ptr_t rep_origin_sendreq;
};
typedef struct ompi_osc_rdma_replyreq_t ompi_osc_rdma_replyreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_replyreq_t);
/** allocate and populate a replyreq structure. datatype is
RETAINed for the life of the replyreq */
int
ompi_osc_rdma_replyreq_alloc_init(ompi_osc_rdma_module_t *module,
int origin,
ompi_ptr_t origin_request,
OPAL_PTRDIFF_TYPE target_displacement,
int target_count,
struct ompi_datatype_t *datatype,
ompi_osc_rdma_replyreq_t **replyreq);
static inline int
ompi_osc_rdma_replyreq_alloc(ompi_osc_rdma_module_t *module,
int origin_rank,
ompi_osc_rdma_replyreq_t **replyreq)
{
int ret;
opal_free_list_item_t *item;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, origin_rank );
/* BWB - FIX ME - is this really the right return code? */
if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE;
OPAL_FREE_LIST_GET(&mca_osc_rdma_component.c_replyreqs,
item, ret);
if (OMPI_SUCCESS != ret) return ret;
*replyreq = (ompi_osc_rdma_replyreq_t*) item;
(*replyreq)->rep_module = module;
(*replyreq)->rep_origin_rank = origin_rank;
(*replyreq)->rep_origin_proc = proc;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_replyreq_init_target(ompi_osc_rdma_replyreq_t *replyreq,
void *target_addr,
int target_count,
struct ompi_datatype_t *target_dt)
{
OBJ_RETAIN(target_dt);
replyreq->rep_target_datatype = target_dt;
opal_convertor_copy_and_prepare_for_send(replyreq->rep_origin_proc->proc_convertor,
&(target_dt->super),
target_count,
target_addr,
0,
&(replyreq->rep_target_convertor));
opal_convertor_get_packed_size(&replyreq->rep_target_convertor,
&replyreq->rep_target_bytes_packed);
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_replyreq_init_origin(ompi_osc_rdma_replyreq_t *replyreq,
ompi_ptr_t origin_request)
{
replyreq->rep_origin_sendreq = origin_request;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_replyreq_free(ompi_osc_rdma_replyreq_t *replyreq)
{
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_defined,
&replyreq->rep_target_convertor);
);
opal_convertor_cleanup(&replyreq->rep_target_convertor);
OBJ_RELEASE(replyreq->rep_target_datatype);
OPAL_FREE_LIST_RETURN(&mca_osc_rdma_component.c_replyreqs,
(opal_list_item_t*) replyreq);
return OMPI_SUCCESS;
}
#endif /* OMPI_OSC_RDMA_REPLYREQ_H */

56
ompi/mca/osc/rdma/osc_rdma_request.c Обычный файл
Просмотреть файл

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011-2012 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/request/request.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_rdma.h"
#include "osc_rdma_request.h"
static int
request_cancel(struct ompi_request_t *request, int complete)
{
return MPI_ERR_REQUEST;
}
static int
request_free(struct ompi_request_t **ompi_req)
{
ompi_osc_rdma_request_t *request =
(ompi_osc_rdma_request_t*) *ompi_req;
if (true != request->super.req_complete) {
return MPI_ERR_REQUEST;
}
OMPI_OSC_RDMA_REQUEST_RETURN(request);
*ompi_req = MPI_REQUEST_NULL;
return OMPI_SUCCESS;
}
static
void
request_construct(ompi_osc_rdma_request_t *request)
{
request->super.req_type = OMPI_REQUEST_WIN;
request->super.req_status._cancelled = 0;
request->super.req_free = request_free;
request->super.req_cancel = request_cancel;
}
OBJ_CLASS_INSTANCE(ompi_osc_rdma_request_t,
ompi_request_t,
request_construct,
NULL);

74
ompi/mca/osc/rdma/osc_rdma_request.h Обычный файл
Просмотреть файл

@ -0,0 +1,74 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_RDMA_REQUEST_H
#define OMPI_OSC_RDMA_REQUEST_H
#include "osc_rdma.h"
#include "ompi/request/request.h"
#include "opal/util/output.h"
struct ompi_osc_rdma_request_t {
ompi_request_t super;
int type;
void *origin_addr;
int origin_count;
struct ompi_datatype_t *origin_dt;
ompi_osc_rdma_module_t* module;
int outstanding_requests;
bool internal;
};
typedef struct ompi_osc_rdma_request_t ompi_osc_rdma_request_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_request_t);
/* REQUEST_ALLOC is only called from "top-level" functions (rdma_rput,
rdma_rget, etc.), so it's ok to spin here... */
#define OMPI_OSC_RDMA_REQUEST_ALLOC(win, req) \
do { \
ompi_free_list_item_t *item; \
do { \
OMPI_FREE_LIST_GET_MT(&mca_osc_rdma_component.requests, item); \
if (NULL == item) { \
opal_progress(); \
} \
} while (NULL == item); \
req = (ompi_osc_rdma_request_t*) item; \
OMPI_REQUEST_INIT(&req->super, false); \
req->super.req_mpi_object.win = win; \
req->super.req_complete = false; \
req->super.req_state = OMPI_REQUEST_ACTIVE; \
req->module = GET_MODULE(win); \
req->internal = false; \
} while (0)
#define OMPI_OSC_RDMA_REQUEST_RETURN(req) \
do { \
OMPI_REQUEST_FINI(&(req)->super); \
OMPI_FREE_LIST_RETURN_MT(&mca_osc_rdma_component.requests, \
(ompi_free_list_item_t *) (req)); \
} while (0)
static inline void ompi_osc_rdma_request_complete (ompi_osc_rdma_request_t *request, int mpi_error)
{
if (!request->internal) {
request->super.req_status.MPI_ERROR = mpi_error;
/* mark the request complete at the mpi level */
ompi_request_complete (&request->super, true);
} else {
OMPI_OSC_RDMA_REQUEST_RETURN (request);
}
}
#endif /* OMPI_OSC_RDMA_REQUEST_H */

Просмотреть файл

@ -1,84 +0,0 @@
/*
* 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 (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_rdma_sendreq.h"
#include "opal/datatype/opal_convertor.h"
int
ompi_osc_rdma_sendreq_alloc_init(ompi_osc_rdma_req_type_t req_type,
void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target, OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
ompi_osc_rdma_module_t *module,
ompi_osc_rdma_sendreq_t **sendreq)
{
int ret;
/* allocate a sendreq */
ret = ompi_osc_rdma_sendreq_alloc(module, target,
sendreq);
if (OMPI_SUCCESS != ret) return ret;
/* initialize local side of sendreq */
ret = ompi_osc_rdma_sendreq_init_origin(*sendreq,
req_type,
origin_addr,
origin_count,
origin_dt);
if (OMPI_SUCCESS != ret) {
ompi_osc_rdma_sendreq_free(*sendreq);
return ret;
}
/* initialize remote side of sendreq */
ret = ompi_osc_rdma_sendreq_init_target(*sendreq,
target_disp,
target_count,
target_dt);
if (OMPI_SUCCESS != ret) {
ompi_osc_rdma_sendreq_free(*sendreq);
return ret;
}
return OMPI_SUCCESS;
}
static void ompi_osc_rdma_sendreq_construct(ompi_osc_rdma_sendreq_t *req)
{
req->super.req_type = OMPI_REQUEST_WIN;
req->super.req_free = NULL;
req->super.req_cancel = NULL;
OBJ_CONSTRUCT(&(req->req_origin_convertor), opal_convertor_t);
}
static void ompi_osc_rdma_sendreq_destruct(ompi_osc_rdma_sendreq_t *req)
{
OBJ_DESTRUCT(&(req->req_origin_convertor));
}
OBJ_CLASS_INSTANCE(ompi_osc_rdma_sendreq_t, ompi_request_t,
ompi_osc_rdma_sendreq_construct,
ompi_osc_rdma_sendreq_destruct);

Просмотреть файл

@ -1,188 +0,0 @@
/*
* 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 (c) 2007 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_OSC_RDMA_SENDREQ_H
#define OMPI_OSC_RDMA_SENDREQ_H
#include "osc_rdma.h"
#include "osc_rdma_longreq.h"
#include "opal/class/opal_list.h"
#include "ompi/datatype/ompi_datatype.h"
#include "opal/datatype/opal_convertor.h"
#include "ompi/communicator/communicator.h"
#include "ompi/proc/proc.h"
#include "ompi/memchecker.h"
typedef enum {
OMPI_OSC_RDMA_GET,
OMPI_OSC_RDMA_ACC,
OMPI_OSC_RDMA_PUT
} ompi_osc_rdma_req_type_t;
struct ompi_osc_rdma_sendreq_t {
ompi_request_t super;
int req_refcount;
/** type of sendreq (from ompi_osc_rdma_req_type_t) */
ompi_osc_rdma_req_type_t req_type;
/** pointer to the module that created the sendreq */
ompi_osc_rdma_module_t *req_module;
/** Datatype for the origin side of the operation */
struct ompi_datatype_t *req_origin_datatype;
/** Convertor for the origin side of the operation. Setup for
either send (Put / Accumulate) or receive (Get) */
opal_convertor_t req_origin_convertor;
/** packed size of message on the origin side */
size_t req_origin_bytes_packed;
/** rank in module's communicator for target of operation */
int req_target_rank;
/** pointer to the proc structure for the target of the operation */
ompi_proc_t *req_target_proc;
/** displacement on target */
OPAL_PTRDIFF_TYPE req_target_disp;
/** datatype count on target */
int req_target_count;
/** datatype on target */
struct ompi_datatype_t *req_target_datatype;
/** op index on the target */
int req_op_id;
uint8_t remote_segs[MCA_BTL_SEG_MAX_SIZE];
};
typedef struct ompi_osc_rdma_sendreq_t ompi_osc_rdma_sendreq_t;
OBJ_CLASS_DECLARATION(ompi_osc_rdma_sendreq_t);
/** allocate and populate a sendreq structure. Both datatypes are
RETAINed for the life of the sendreq */
int
ompi_osc_rdma_sendreq_alloc_init(ompi_osc_rdma_req_type_t req_type,
void *origin_addr, int origin_count,
struct ompi_datatype_t *origin_dt,
int target, OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
ompi_osc_rdma_module_t *module,
ompi_osc_rdma_sendreq_t **sendreq);
static inline int
ompi_osc_rdma_sendreq_alloc(ompi_osc_rdma_module_t *module,
int target_rank,
ompi_osc_rdma_sendreq_t **sendreq)
{
int ret;
opal_free_list_item_t *item;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, target_rank );
/* BWB - FIX ME - is this really the right return code? */
if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE;
OPAL_FREE_LIST_GET(&mca_osc_rdma_component.c_sendreqs,
item, ret);
if (OMPI_SUCCESS != ret) return ret;
*sendreq = (ompi_osc_rdma_sendreq_t*) item;
(*sendreq)->req_module = module;
(*sendreq)->req_target_rank = target_rank;
(*sendreq)->req_target_proc = proc;
(*sendreq)->req_refcount = 1;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_sendreq_init_origin(ompi_osc_rdma_sendreq_t *sendreq,
ompi_osc_rdma_req_type_t req_type,
void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt)
{
OBJ_RETAIN(origin_dt);
sendreq->req_origin_datatype = origin_dt;
sendreq->req_type = req_type;
if (req_type != OMPI_OSC_RDMA_GET) {
opal_convertor_copy_and_prepare_for_send(sendreq->req_target_proc->proc_convertor,
&(origin_dt->super),
origin_count,
origin_addr,
0,
&(sendreq->req_origin_convertor));
opal_convertor_get_packed_size(&sendreq->req_origin_convertor,
&sendreq->req_origin_bytes_packed);
} else {
opal_convertor_copy_and_prepare_for_recv(sendreq->req_target_proc->proc_convertor,
&(origin_dt->super),
origin_count,
origin_addr,
0,
&(sendreq->req_origin_convertor));
opal_convertor_get_packed_size(&sendreq->req_origin_convertor,
&sendreq->req_origin_bytes_packed);
}
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_sendreq_init_target(ompi_osc_rdma_sendreq_t *sendreq,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_datatype)
{
OBJ_RETAIN(target_datatype);
sendreq->req_target_disp = target_disp;
sendreq->req_target_count = target_count;
sendreq->req_target_datatype = target_datatype;
return OMPI_SUCCESS;
}
static inline int
ompi_osc_rdma_sendreq_free(ompi_osc_rdma_sendreq_t *sendreq)
{
if (0 == (--sendreq->req_refcount)) {
MEMCHECKER(
memchecker_convertor_call(&opal_memchecker_base_mem_defined,
&sendreq->req_origin_convertor);
);
opal_convertor_cleanup(&sendreq->req_origin_convertor);
OBJ_RELEASE(sendreq->req_target_datatype);
OBJ_RELEASE(sendreq->req_origin_datatype);
OPAL_FREE_LIST_RETURN(&mca_osc_rdma_component.c_sendreqs,
(opal_list_item_t*) sendreq);
}
return OMPI_SUCCESS;
}
#endif /* OMPI_OSC_RDMA_SENDREQ_H */

Просмотреть файл

@ -1,788 +0,0 @@
/*
* 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 (c) 2007-2012 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "osc_rdma.h"
#include "osc_rdma_sendreq.h"
#include "osc_rdma_longreq.h"
#include "osc_rdma_header.h"
#include "osc_rdma_data_move.h"
#include "mpi.h"
#include "opal/runtime/opal_progress.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/mca/osc/base/base.h"
/* Must hold module's lock before calling... */
static inline void
ompi_osc_rdma_flip_sendreqs(ompi_osc_rdma_module_t *module)
{
unsigned int *tmp;
tmp = module->m_copy_num_pending_sendreqs;
module->m_copy_num_pending_sendreqs =
module->m_num_pending_sendreqs;
module->m_num_pending_sendreqs = tmp;
memset(module->m_num_pending_sendreqs, 0,
sizeof(unsigned int) * ompi_comm_size(module->m_comm));
/* Copy in all the pending requests */
opal_list_join(&module->m_copy_pending_sendreqs,
opal_list_get_end(&module->m_copy_pending_sendreqs),
&module->m_pending_sendreqs);
}
int
ompi_osc_rdma_module_fence(int assert, ompi_win_t *win)
{
unsigned int incoming_reqs;
int ret = OMPI_SUCCESS, i, len, started_send;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int num_outgoing = 0;
if (0 != (assert & MPI_MODE_NOPRECEDE)) {
/* check that the user didn't lie to us - since NOPRECEDED
must be specified by all processes if it is specified by
any process, if we see this it is safe to assume that there
are no pending operations anywhere needed to close out this
epoch. */
if (0 != opal_list_get_size(&(module->m_pending_sendreqs))) {
return MPI_ERR_RMA_SYNC;
}
} else {
/* "atomically" copy all the data we're going to be modifying
into the copy... */
OPAL_THREAD_LOCK(&module->m_lock);
ompi_osc_rdma_flip_sendreqs(module);
OPAL_THREAD_UNLOCK(&module->m_lock);
num_outgoing = opal_list_get_size(&(module->m_copy_pending_sendreqs));
/* find out how much data everyone is going to send us. Need
to have the lock during this period so that we have a sane
view of the number of sendreqs */
ret = module->m_comm->
c_coll.coll_reduce_scatter(module->m_copy_num_pending_sendreqs,
&incoming_reqs,
module->m_fence_coll_counts,
MPI_UNSIGNED,
MPI_SUM,
module->m_comm,
module->m_comm->c_coll.coll_reduce_scatter_module);
if (OMPI_SUCCESS != ret) {
/* put the stupid data back for the user. This is not
cheap, but the user lost his data if we don't. */
OPAL_THREAD_LOCK(&(module->m_lock));
opal_list_join(&module->m_pending_sendreqs,
opal_list_get_end(&module->m_pending_sendreqs),
&module->m_copy_pending_sendreqs);
for (i = 0 ; i < ompi_comm_size(module->m_comm) ; ++i) {
module->m_num_pending_sendreqs[i] +=
module->m_copy_num_pending_sendreqs[i];
}
OPAL_THREAD_UNLOCK(&(module->m_lock));
return ret;
}
/* try to start all the requests. We've copied everything we
need out of pending_sendreqs, so don't need the lock
here */
len = opal_list_get_size(&(module->m_copy_pending_sendreqs));
started_send = 0;
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"fence: trying to start %d reqs",
len));
for (i = 0 ; i < len ; ++i) {
ompi_osc_rdma_sendreq_t *req = (ompi_osc_rdma_sendreq_t*)
opal_list_remove_first(&(module->m_copy_pending_sendreqs));
ret = ompi_osc_rdma_sendreq_send(module, req);
if (OMPI_SUCCESS != ret) {
opal_list_append(&(module->m_copy_pending_sendreqs), (opal_list_item_t*)req);
} else {
started_send = 1;
}
}
/* we need to start at least one send, so that the callback
will restart the rest. */
while (0 == started_send && len != 0) {
opal_progress();
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"fence: restarting %d reqs", len));
len = opal_list_get_size(&(module->m_copy_pending_sendreqs));
for (i = 0 ; i < len ; ++i) {
ompi_osc_rdma_sendreq_t *req = (ompi_osc_rdma_sendreq_t*)
opal_list_remove_first(&(module->m_copy_pending_sendreqs));
ret = ompi_osc_rdma_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_list_append(&(module->m_copy_pending_sendreqs), (opal_list_item_t*)req);
} else if (OMPI_SUCCESS != ret) {
return ret;
} else {
started_send = 1;
}
}
}
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"fence: done with initial start"));
if (module->m_use_rdma) {
if (module->m_rdma_wait_completion) {
OPAL_THREAD_LOCK(&module->m_lock);
while (module->m_rdma_num_pending != 0) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
OPAL_THREAD_UNLOCK(&module->m_lock);
}
for (i = 0 ; i < ompi_comm_size(module->m_comm) ; ++i) {
int j;
for (j = 0 ; j < module->m_peer_info[i].peer_num_btls ; ++j) {
if (module->m_peer_info[i].peer_btls[j].num_sent > 0) {
ret = ompi_osc_rdma_rdma_ack_send(module,
ompi_comm_peer_lookup(module->m_comm, i),
&(module->m_peer_info[i].peer_btls[j]));
if (OPAL_LIKELY(OMPI_SUCCESS == ret)) {
module->m_peer_info[i].peer_btls[j].num_sent = 0;
} else {
return ret;
}
}
}
}
}
ompi_osc_rdma_flush(module);
OPAL_THREAD_LOCK(&module->m_lock);
/* if some requests couldn't be started, push into the
"queued" list, where we will try to restart them later. */
if (opal_list_get_size(&module->m_copy_pending_sendreqs)) {
opal_list_join(&module->m_queued_sendreqs,
opal_list_get_end(&module->m_queued_sendreqs),
&module->m_copy_pending_sendreqs);
}
/* possible we've already received a couple in messages, so
atomicall add however many we're going to wait for */
module->m_num_pending_in += incoming_reqs;
module->m_num_pending_out += num_outgoing;
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"fence: waiting on %d in and %d out, now %d, %d",
incoming_reqs,
num_outgoing,
module->m_num_pending_in,
module->m_num_pending_out));
/* now we know how many things we're waiting for - wait for them... */
while (module->m_num_pending_in > 0 ||
0 != module->m_num_pending_out) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
OPAL_THREAD_UNLOCK(&module->m_lock);
}
/* all transfers are done - back to the real world we go */
if (0 == (assert & MPI_MODE_NOSUCCEED)) {
ompi_win_set_mode(win, OMPI_WIN_FENCE);
} else {
ompi_win_set_mode(win, 0);
}
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_module_start(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int i, ret = OMPI_SUCCESS;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
int32_t count;
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
module->m_eager_send_active = false;
OPAL_THREAD_LOCK(&module->m_lock);
if (NULL != module->m_sc_group) {
OPAL_THREAD_UNLOCK(&module->m_lock);
ret = MPI_ERR_RMA_SYNC;
goto clean;
}
module->m_sc_group = group;
/* possible we've already received a couple in messages, so
add however many we're going to wait for */
count = (module->m_num_post_msgs += ompi_group_size(module->m_sc_group));
OPAL_THREAD_UNLOCK(&(module->m_lock));
memset(module->m_sc_remote_active_ranks, 0,
sizeof(bool) * ompi_comm_size(module->m_comm));
/* for each process in the specified group, find it's rank in our
communicator, store those indexes, and set the true / false in
the active ranks table */
for (i = 0 ; i < ompi_group_size(group) ; i++) {
int comm_rank = -1, j;
/* find the rank in the communicator associated with this windows */
for (j = 0 ; j < ompi_comm_size(module->m_comm) ; ++j) {
if (ompi_group_peer_lookup(module->m_sc_group, i) ==
ompi_comm_peer_lookup(module->m_comm, j)) {
comm_rank = j;
break;
}
}
if (comm_rank == -1) {
ret = MPI_ERR_RMA_SYNC;
goto clean;
}
module->m_sc_remote_active_ranks[comm_rank] = true;
module->m_sc_remote_ranks[i] = comm_rank;
}
/* Set our mode to access w/ start */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_STARTED);
if (count == 0) {
module->m_eager_send_active = module->m_eager_send_ok;
}
return OMPI_SUCCESS;
clean:
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return ret;
}
int
ompi_osc_rdma_module_complete(ompi_win_t *win)
{
int i, j;
int ret = OMPI_SUCCESS;
ompi_group_t *group;
opal_list_item_t *item;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
/* wait for all the post messages */
OPAL_THREAD_LOCK(&module->m_lock);
while (0 != module->m_num_post_msgs) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
ompi_osc_rdma_flip_sendreqs(module);
/* for each process in group, send a control message with number
of updates coming, then start all the requests */
module->m_num_pending_out +=
(int32_t) opal_list_get_size(&module->m_copy_pending_sendreqs);
OPAL_THREAD_UNLOCK(&module->m_lock);
for (i = 0 ; i < ompi_group_size(module->m_sc_group) ; ++i) {
int comm_rank = module->m_sc_remote_ranks[i];
if (module->m_use_rdma) {
if (module->m_rdma_wait_completion) {
OPAL_THREAD_LOCK(&module->m_lock);
while (module->m_rdma_num_pending != 0) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
OPAL_THREAD_UNLOCK(&module->m_lock);
}
for (j = 0 ; j < module->m_peer_info[comm_rank].peer_num_btls ; ++j) {
if (module->m_peer_info[comm_rank].peer_btls[j].num_sent > 0) {
ret = ompi_osc_rdma_rdma_ack_send(module,
ompi_group_peer_lookup(module->m_sc_group, i),
&(module->m_peer_info[comm_rank].peer_btls[j]));
if (OPAL_LIKELY(OMPI_SUCCESS == ret)) {
module->m_peer_info[comm_rank].peer_btls[j].num_sent = 0;
} else {
return ret;
}
}
}
}
ret = ompi_osc_rdma_control_send(module,
ompi_group_peer_lookup(module->m_sc_group, i),
OMPI_OSC_RDMA_HDR_COMPLETE,
module->m_copy_num_pending_sendreqs[comm_rank],
0);
assert(ret == OMPI_SUCCESS);
}
/* try to start all the requests. We've copied everything we
need out of pending_sendreqs, so don't need the lock
here */
while (NULL !=
(item = opal_list_remove_first(&(module->m_copy_pending_sendreqs)))) {
ompi_osc_rdma_sendreq_t *req =
(ompi_osc_rdma_sendreq_t*) item;
ret = ompi_osc_rdma_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_list_append(&(module->m_copy_pending_sendreqs), item);
break;
} else if (OMPI_SUCCESS != ret) {
return ret;
}
}
ompi_osc_rdma_flush(module);
OPAL_THREAD_LOCK(&module->m_lock);
/* if some requests couldn't be started, push into the
"queued" list, where we will try to restart them later. */
if (opal_list_get_size(&module->m_copy_pending_sendreqs)) {
opal_list_join(&module->m_queued_sendreqs,
opal_list_get_end(&module->m_queued_sendreqs),
&module->m_copy_pending_sendreqs);
}
/* wait for all the requests */
while (0 != module->m_num_pending_out) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
group = module->m_sc_group;
module->m_sc_group = NULL;
OPAL_THREAD_UNLOCK(&(module->m_lock));
/* remove WIN_POSTED from our mode */
ompi_win_remove_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_STARTED);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return ret;
}
int
ompi_osc_rdma_module_post(ompi_group_t *group,
int assert,
ompi_win_t *win)
{
int i;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
OBJ_RETAIN(group);
ompi_group_increment_proc_count(group);
OPAL_THREAD_LOCK(&(module->m_lock));
assert(NULL == module->m_pw_group);
module->m_pw_group = group;
/* Set our mode to expose w/ post */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
/* list how many complete counters we're still waiting on */
module->m_num_complete_msgs +=
ompi_group_size(module->m_pw_group);
OPAL_THREAD_UNLOCK(&(module->m_lock));
/* send a hello counter to everyone in group */
for (i = 0 ; i < ompi_group_size(module->m_pw_group) ; ++i) {
ompi_osc_rdma_control_send(module,
ompi_group_peer_lookup(group, i),
OMPI_OSC_RDMA_HDR_POST, 1, 0);
}
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_module_wait(ompi_win_t *win)
{
ompi_group_t *group;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
OPAL_THREAD_LOCK(&module->m_lock);
while (0 != (module->m_num_pending_in) ||
0 != (module->m_num_complete_msgs)) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
group = module->m_pw_group;
module->m_pw_group = NULL;
OPAL_THREAD_UNLOCK(&module->m_lock);
ompi_win_remove_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_module_test(ompi_win_t *win,
int *flag)
{
ompi_group_t *group;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
#if !OMPI_ENABLE_PROGRESS_THREADS
opal_progress();
#endif
if (0 != (module->m_num_pending_in) ||
0 != (module->m_num_complete_msgs)) {
*flag = 0;
return OMPI_SUCCESS;
}
*flag = 1;
OPAL_THREAD_LOCK(&(module->m_lock));
group = module->m_pw_group;
module->m_pw_group = NULL;
OPAL_THREAD_UNLOCK(&(module->m_lock));
ompi_win_remove_mode(win, OMPI_WIN_EXPOSE_EPOCH | OMPI_WIN_POSTED);
ompi_group_decrement_proc_count(group);
OBJ_RELEASE(group);
return OMPI_SUCCESS;
}
struct ompi_osc_rdma_pending_lock_t {
opal_list_item_t super;
ompi_proc_t *proc;
int32_t lock_type;
};
typedef struct ompi_osc_rdma_pending_lock_t ompi_osc_rdma_pending_lock_t;
OBJ_CLASS_INSTANCE(ompi_osc_rdma_pending_lock_t, opal_list_item_t,
NULL, NULL);
int
ompi_osc_rdma_module_lock(int lock_type,
int target,
int assert,
ompi_win_t *win)
{
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, target );
assert(lock_type != 0);
/* set our mode on the window */
ompi_win_remove_mode(win, OMPI_WIN_FENCE);
ompi_win_append_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_LOCK_ACCESS);
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"%d sending lock request to %d",
ompi_comm_rank(module->m_comm), target));
/* generate a lock request */
ompi_osc_rdma_control_send(module,
proc,
OMPI_OSC_RDMA_HDR_LOCK_REQ,
ompi_comm_rank(module->m_comm),
lock_type);
module->m_eager_send_active = false;
if (ompi_comm_rank(module->m_comm) == target) {
/* If we're trying to lock locally, have to wait to actually
acquire the lock */
OPAL_THREAD_LOCK(&module->m_lock);
while (module->m_lock_received_ack == 0) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
OPAL_THREAD_UNLOCK(&module->m_lock);
}
/* return */
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_module_unlock(int target,
ompi_win_t *win)
{
int32_t out_count;
opal_list_item_t *item;
int ret;
ompi_osc_rdma_module_t *module = GET_MODULE(win);
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, target );
OPAL_THREAD_LOCK(&module->m_lock);
while (0 == module->m_lock_received_ack) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
module->m_lock_received_ack -= 1;
/* start all the requests */
ompi_osc_rdma_flip_sendreqs(module);
/* try to start all the requests. We've copied everything we need
out of pending_sendreqs, so don't need the lock here */
out_count = opal_list_get_size(&module->m_copy_pending_sendreqs);
/* we want to send all the requests, plus we wait for one more
completion event for the control message ack from the unlocker
saying we're done */
module->m_num_pending_out += (out_count + 1);
OPAL_THREAD_UNLOCK(&module->m_lock);
/* send the unlock request */
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"%d sending unlock request to %d with %d requests",
ompi_comm_rank(module->m_comm), target,
out_count));
ompi_osc_rdma_control_send(module,
proc,
OMPI_OSC_RDMA_HDR_UNLOCK_REQ,
ompi_comm_rank(module->m_comm),
out_count);
/* try to start all the requests. We've copied everything we
need out of pending_sendreqs, so don't need the lock
here */
while (NULL !=
(item = opal_list_remove_first(&(module->m_copy_pending_sendreqs)))) {
ompi_osc_rdma_sendreq_t *req =
(ompi_osc_rdma_sendreq_t*) item;
ret = ompi_osc_rdma_sendreq_send(module, req);
if (OMPI_ERR_TEMP_OUT_OF_RESOURCE == ret) {
opal_list_append(&(module->m_copy_pending_sendreqs), item);
break;
} else if (OMPI_SUCCESS != ret) {
return ret;
}
}
ompi_osc_rdma_flush(module);
OPAL_THREAD_LOCK(&module->m_lock);
/* if some requests couldn't be started, push into the
"queued" list, where we will try to restart them later. */
if (opal_list_get_size(&module->m_copy_pending_sendreqs)) {
opal_list_join(&module->m_queued_sendreqs,
opal_list_get_end(&module->m_queued_sendreqs),
&module->m_copy_pending_sendreqs);
}
/* wait for all the requests */
while (0 != module->m_num_pending_out) {
opal_condition_wait(&module->m_cond, &module->m_lock);
}
OPAL_THREAD_UNLOCK(&module->m_lock);
/* set our mode on the window */
ompi_win_remove_mode(win, OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_LOCK_ACCESS);
module->m_eager_send_active = module->m_eager_send_ok;
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_passive_lock(ompi_osc_rdma_module_t *module,
int32_t origin,
int32_t lock_type)
{
bool send_ack = false;
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, origin );
ompi_osc_rdma_pending_lock_t *new_pending;
OPAL_THREAD_LOCK(&(module->m_lock));
if (lock_type == MPI_LOCK_EXCLUSIVE) {
if (module->m_lock_status == 0) {
module->m_lock_status = MPI_LOCK_EXCLUSIVE;
ompi_win_append_mode(module->m_win, OMPI_WIN_EXPOSE_EPOCH);
send_ack = true;
} else {
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"%d queuing lock request from %d (%d)",
ompi_comm_rank(module->m_comm),
origin, lock_type));
new_pending = OBJ_NEW(ompi_osc_rdma_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = lock_type;
opal_list_append(&(module->m_locks_pending), &(new_pending->super));
}
} else if (lock_type == MPI_LOCK_SHARED) {
if (module->m_lock_status != MPI_LOCK_EXCLUSIVE) {
module->m_lock_status = MPI_LOCK_SHARED;
module->m_shared_count++;
ompi_win_append_mode(module->m_win, OMPI_WIN_EXPOSE_EPOCH);
send_ack = true;
} else {
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"queuing lock request from %d (%d) lock_type:%d",
ompi_comm_rank(module->m_comm),
origin, lock_type));
new_pending = OBJ_NEW(ompi_osc_rdma_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = lock_type;
opal_list_append(&(module->m_locks_pending), &(new_pending->super));
}
}
OPAL_THREAD_UNLOCK(&(module->m_lock));
if (send_ack) {
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"%d sending lock ack to %d",
ompi_comm_rank(module->m_comm), origin));
ompi_osc_rdma_control_send(module, proc,
OMPI_OSC_RDMA_HDR_LOCK_REQ,
ompi_comm_rank(module->m_comm),
OMPI_SUCCESS);
}
return OMPI_SUCCESS;
}
int
ompi_osc_rdma_passive_unlock(ompi_osc_rdma_module_t *module,
int32_t origin,
int32_t count)
{
ompi_proc_t *proc = ompi_comm_peer_lookup( module->m_comm, origin );
ompi_osc_rdma_pending_lock_t *new_pending = NULL;
assert(module->m_lock_status != 0);
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"received unlock request from %d with %d requests\n",
origin, count));
new_pending = OBJ_NEW(ompi_osc_rdma_pending_lock_t);
new_pending->proc = proc;
new_pending->lock_type = 0;
OPAL_THREAD_LOCK(&(module->m_lock));
module->m_num_pending_in += count;
opal_list_append(&module->m_unlocks_pending, &(new_pending->super));
OPAL_THREAD_UNLOCK(&(module->m_lock));
return ompi_osc_rdma_passive_unlock_complete(module);
}
int
ompi_osc_rdma_passive_unlock_complete(ompi_osc_rdma_module_t *module)
{
ompi_osc_rdma_pending_lock_t *new_pending = NULL;
opal_list_t copy_unlock_acks;
if (module->m_num_pending_in != 0) return OMPI_SUCCESS;
OPAL_THREAD_LOCK(&module->m_lock);
if (module->m_num_pending_in != 0) {
OPAL_THREAD_UNLOCK(&module->m_lock);
return OMPI_SUCCESS;
}
if (module->m_lock_status == MPI_LOCK_EXCLUSIVE) {
ompi_win_remove_mode(module->m_win, OMPI_WIN_EXPOSE_EPOCH);
module->m_lock_status = 0;
} else {
module->m_shared_count -= opal_list_get_size(&module->m_unlocks_pending);
if (module->m_shared_count == 0) {
ompi_win_remove_mode(module->m_win, OMPI_WIN_EXPOSE_EPOCH);
module->m_lock_status = 0;
}
}
OBJ_CONSTRUCT(&copy_unlock_acks, opal_list_t);
/* copy over any unlocks that have been satisfied (possibly
multiple if SHARED) */
opal_list_join(&copy_unlock_acks,
opal_list_get_end(&copy_unlock_acks),
&module->m_unlocks_pending);
OPAL_THREAD_UNLOCK(&module->m_lock);
/* issue whichever unlock acks we should issue */
while (NULL != (new_pending = (ompi_osc_rdma_pending_lock_t*)
opal_list_remove_first(&copy_unlock_acks))) {
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"sending unlock reply to proc"));
ompi_osc_rdma_control_send(module,
new_pending->proc,
OMPI_OSC_RDMA_HDR_UNLOCK_REPLY,
OMPI_SUCCESS, OMPI_SUCCESS);
OBJ_RELEASE(new_pending);
}
OBJ_DESTRUCT(&copy_unlock_acks);
/* if we were really unlocked, see if we have another lock request
we can satisfy */
OPAL_THREAD_LOCK(&(module->m_lock));
if (0 == module->m_lock_status) {
new_pending = (ompi_osc_rdma_pending_lock_t*)
opal_list_remove_first(&(module->m_locks_pending));
if (NULL != new_pending) {
ompi_win_append_mode(module->m_win, OMPI_WIN_EXPOSE_EPOCH);
/* set lock state and generate a lock request */
module->m_lock_status = new_pending->lock_type;
if (MPI_LOCK_SHARED == new_pending->lock_type) {
module->m_shared_count++;
}
}
} else {
new_pending = NULL;
}
OPAL_THREAD_UNLOCK(&(module->m_lock));
if (NULL != new_pending) {
OPAL_OUTPUT_VERBOSE((40, ompi_osc_base_framework.framework_output,
"sending lock request to proc"));
ompi_osc_rdma_control_send(module,
new_pending->proc,
OMPI_OSC_RDMA_HDR_LOCK_REQ,
ompi_comm_rank(module->m_comm),
OMPI_SUCCESS);
OBJ_RELEASE(new_pending);
}
return OMPI_SUCCESS;
}

44
ompi/mca/osc/sm/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,44 @@
#
# Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
EXTRA_DIST =
sm_sources = \
osc_sm.h \
osc_sm_comm.c \
osc_sm_component.c \
osc_sm_active_target.c \
osc_sm_passive_target.c \
osc_sm_request.c \
osc_sm_request.h
AM_CPPFLAGS = $(osc_sm_CPPFLAGS)
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if MCA_BUILD_ompi_osc_sm_DSO
component_noinst =
component_install = mca_osc_sm.la
else
component_noinst = libmca_osc_sm.la
component_install =
endif
mcacomponentdir = $(pkglibdir)
mcacomponent_LTLIBRARIES = $(component_install)
mca_osc_sm_la_SOURCES = $(sm_sources)
mca_osc_sm_la_LIBADD = $(osc_sm_LIBS)
mca_osc_sm_la_LDFLAGS = -module -avoid-version $(osc_sm_LDFLAGS)
noinst_LTLIBRARIES = $(component_noinst)
libmca_osc_sm_la_SOURCES = $(sm_sources)
libmca_osc_sm_la_LIBADD = $(osc_sm_LIBS)
libmca_osc_sm_la_LDFLAGS = -module -avoid-version $(osc_sm_LDFLAGS)

243
ompi/mca/osc/sm/osc_sm.h Обычный файл
Просмотреть файл

@ -0,0 +1,243 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_SM_SM_H
#define OSC_SM_SM_H
#include "ompi/class/ompi_free_list.h"
#include "opal/mca/shmem/base/base.h"
/* data shared across all peers */
struct ompi_osc_sm_global_state_t {
int use_barrier_for_fence;
#if OPAL_HAVE_POSIX_THREADS
pthread_mutex_t mtx;
pthread_cond_t cond;
int sense;
int32_t count;
#endif
};
typedef struct ompi_osc_sm_global_state_t ompi_osc_sm_global_state_t;
/* this is data exposed to remote nodes */
struct ompi_osc_sm_lock_t {
uint32_t counter;
uint32_t write;
uint32_t read;
};
typedef struct ompi_osc_sm_lock_t ompi_osc_sm_lock_t;
struct ompi_osc_sm_node_state_t {
int32_t post_count;
int32_t complete_count;
ompi_osc_sm_lock_t lock;
opal_atomic_lock_t accumulate_lock;
};
typedef struct ompi_osc_sm_node_state_t ompi_osc_sm_node_state_t;
struct ompi_osc_sm_component_t {
ompi_osc_base_component_t super;
ompi_free_list_t requests;
};
typedef struct ompi_osc_sm_component_t ompi_osc_sm_component_t;
OMPI_DECLSPEC extern ompi_osc_sm_component_t mca_osc_sm_component;
enum ompi_osc_sm_locktype_t {
lock_none = 0,
lock_nocheck,
lock_exclusive,
lock_shared
};
struct ompi_osc_sm_module_t {
ompi_osc_base_module_t super;
struct ompi_communicator_t *comm;
int flavor;
opal_shmem_ds_t seg_ds;
void *segment_base;
bool noncontig;
size_t *sizes;
void **bases;
int *disp_units;
ompi_group_t *start_group;
ompi_group_t *post_group;
#if OPAL_HAVE_POSIX_THREADS
int my_sense;
#endif
enum ompi_osc_sm_locktype_t *outstanding_locks;
/* exposed data */
ompi_osc_sm_global_state_t *global_state;
ompi_osc_sm_node_state_t *my_node_state;
ompi_osc_sm_node_state_t *node_states;
};
typedef struct ompi_osc_sm_module_t ompi_osc_sm_module_t;
int ompi_osc_sm_shared_query(struct ompi_win_t *win, int rank, size_t *size, int *disp_unit, void *baseptr);
int ompi_osc_sm_attach(struct ompi_win_t *win, void *base, size_t len);
int ompi_osc_sm_detach(struct ompi_win_t *win, void *base);
int ompi_osc_sm_free(struct ompi_win_t *win);
int ompi_osc_sm_put(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_sm_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win);
int ompi_osc_sm_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_sm_compare_and_swap(void *origin_addr,
void *compare_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_win_t *win);
int ompi_osc_sm_fetch_and_op(void *origin_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_sm_get_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win);
int ompi_osc_sm_rput(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_sm_rget(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_sm_raccumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_sm_rget_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_datatype,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_datatype,
int target_rank,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_datatype,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **request);
int ompi_osc_sm_fence(int assert, struct ompi_win_t *win);
int ompi_osc_sm_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_sm_complete(struct ompi_win_t *win);
int ompi_osc_sm_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win);
int ompi_osc_sm_wait(struct ompi_win_t *win);
int ompi_osc_sm_test(struct ompi_win_t *win,
int *flag);
int ompi_osc_sm_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win);
int ompi_osc_sm_unlock(int target,
struct ompi_win_t *win);
int ompi_osc_sm_lock_all(int assert,
struct ompi_win_t *win);
int ompi_osc_sm_unlock_all(struct ompi_win_t *win);
int ompi_osc_sm_sync(struct ompi_win_t *win);
int ompi_osc_sm_flush(int target,
struct ompi_win_t *win);
int ompi_osc_sm_flush_all(struct ompi_win_t *win);
int ompi_osc_sm_flush_local(int target,
struct ompi_win_t *win);
int ompi_osc_sm_flush_local_all(struct ompi_win_t *win);
int ompi_osc_sm_set_info(struct ompi_win_t *win, struct ompi_info_t *info);
int ompi_osc_sm_get_info(struct ompi_win_t *win, struct ompi_info_t **info_used);
#endif

197
ompi/mca/osc/sm/osc_sm_active_target.c Обычный файл
Просмотреть файл

@ -0,0 +1,197 @@
/*
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "opal/sys/atomic.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_sm.h"
int
ompi_osc_sm_fence(int assert, struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
/* ensure all memory operations have completed */
opal_atomic_mb();
if (module->global_state->use_barrier_for_fence) {
return module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
} else {
module->my_sense = !module->my_sense;
pthread_mutex_lock(&module->global_state->mtx);
module->global_state->count--;
if (module->global_state->count == 0) {
module->global_state->count = ompi_comm_size(module->comm);
module->global_state->sense = module->my_sense;
pthread_cond_broadcast(&module->global_state->cond);
} else {
while (module->global_state->sense != module->my_sense) {
pthread_cond_wait(&module->global_state->cond, &module->global_state->mtx);
}
}
pthread_mutex_unlock(&module->global_state->mtx);
return OMPI_SUCCESS;
}
}
int
ompi_osc_sm_start(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (0 == (assert & MPI_MODE_NOCHECK)) {
int size;
OBJ_RETAIN(group);
module->start_group = group;
size = ompi_group_size(module->start_group);
while (module->my_node_state->post_count != size) {
opal_progress();
opal_atomic_mb();
}
} else {
module->start_group = NULL;
}
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_complete(struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int i, j, gsize, csize;
/* ensure all memory operations have completed */
opal_atomic_mb();
if (NULL != module->start_group) {
module->my_node_state->post_count = 0;
opal_atomic_mb();
gsize = ompi_group_size(module->start_group);
csize = ompi_comm_size(module->comm);
for (i = 0 ; i < gsize ; ++i) {
for (j = 0 ; i < csize ; ++j) {
if (ompi_group_peer_lookup(module->start_group, i) ==
ompi_comm_peer_lookup(module->comm, j)) {
opal_atomic_add_32(&module->node_states[j].complete_count, 1);
}
}
}
OBJ_RELEASE(module->start_group);
module->start_group = NULL;
}
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_post(struct ompi_group_t *group,
int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int i, j, gsize, csize;
if (0 == (assert & MPI_MODE_NOCHECK)) {
OBJ_RETAIN(group);
module->post_group = group;
module->my_node_state->complete_count = 0;
opal_atomic_mb();
gsize = ompi_group_size(module->post_group);
csize = ompi_comm_size(module->comm);
for (i = 0 ; i < gsize ; ++i) {
for (j = 0 ; i < csize ; ++j) {
if (ompi_group_peer_lookup(module->start_group, i) ==
ompi_comm_peer_lookup(module->comm, j)) {
opal_atomic_add_32(&module->node_states[j].post_count, 1);
}
}
}
} else {
module->post_group = NULL;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_wait(struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (NULL != module->post_group) {
int size = ompi_group_size(module->post_group);
while (module->my_node_state->complete_count != size) {
opal_progress();
opal_atomic_mb();
}
OBJ_RELEASE(module->post_group);
module->post_group = NULL;
}
/* ensure all memory operations have completed */
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_test(struct ompi_win_t *win,
int *flag)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (NULL != module->post_group) {
int size = ompi_group_size(module->post_group);
if (module->my_node_state->complete_count == size) {
OBJ_RELEASE(module->post_group);
module->post_group = NULL;
*flag = 1;
}
} else {
opal_atomic_mb();
*flag = 0;
}
/* ensure all memory operations have completed */
opal_atomic_mb();
return OMPI_SUCCESS;
}

451
ompi/mca/osc/sm/osc_sm_comm.c Обычный файл
Просмотреть файл

@ -0,0 +1,451 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_sm.h"
#include "osc_sm_request.h"
int
ompi_osc_sm_rput(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **ompi_req)
{
int ret;
ompi_osc_sm_request_t *request;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"rput: 0x%lx, %d, %s, %d, %d, %d, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
(unsigned long) win));
OMPI_OSC_SM_REQUEST_ALLOC(win, request);
if (NULL == request) return OMPI_ERR_OUT_OF_RESOURCE;
*ompi_req = &request->super;
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
ret = ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
if (OMPI_SUCCESS != ret) {
OMPI_OSC_SM_REQUEST_RETURN(request);
return ret;
}
OMPI_OSC_SM_REQUEST_COMPLETE(request);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_rget(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win,
struct ompi_request_t **ompi_req)
{
int ret;
ompi_osc_sm_request_t *request;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"rget: 0x%lx, %d, %s, %d, %d, %d, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
(unsigned long) win));
OMPI_OSC_SM_REQUEST_ALLOC(win, request);
if (NULL == request) return OMPI_ERR_OUT_OF_RESOURCE;
*ompi_req = &request->super;
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
ret = ompi_datatype_sndrcv(remote_address, target_count, target_dt,
origin_addr, origin_count, origin_dt);
if (OMPI_SUCCESS != ret) {
OMPI_OSC_SM_REQUEST_RETURN(request);
return ret;
}
OMPI_OSC_SM_REQUEST_COMPLETE(request);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_raccumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **ompi_req)
{
int ret;
ompi_osc_sm_request_t *request;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"raccumulate: 0x%lx, %d, %s, %d, %d, %d, %s, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
op->o_name,
(unsigned long) win));
OMPI_OSC_SM_REQUEST_ALLOC(win, request);
if (NULL == request) return OMPI_ERR_OUT_OF_RESOURCE;
*ompi_req = &request->super;
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
opal_atomic_lock(&module->node_states[target].accumulate_lock);
if (op == &ompi_mpi_op_replace.op) {
ret = ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
} else {
ret = ompi_osc_base_sndrcv_op(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt,
op);
}
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
OMPI_OSC_SM_REQUEST_COMPLETE(request);
return ret;
}
int
ompi_osc_sm_rget_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_dt,
int target,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win,
struct ompi_request_t **ompi_req)
{
int ret;
ompi_osc_sm_request_t *request;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"rget_accumulate: 0x%lx, %d, %s, %d, %d, %d, %s, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
op->o_name,
(unsigned long) win));
OMPI_OSC_SM_REQUEST_ALLOC(win, request);
if (NULL == request) return OMPI_ERR_OUT_OF_RESOURCE;
*ompi_req = &request->super;
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
opal_atomic_lock(&module->node_states[target].accumulate_lock);
ret = ompi_datatype_sndrcv(remote_address, target_count, target_dt,
result_addr, result_count, result_dt);
if (OMPI_SUCCESS != ret || op == &ompi_mpi_op_no_op.op) goto done;
if (op == &ompi_mpi_op_replace.op) {
return ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
} else {
ret = ompi_osc_base_sndrcv_op(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt,
op);
}
done:
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
OMPI_OSC_SM_REQUEST_COMPLETE(request);
return ret;
}
int
ompi_osc_sm_put(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win)
{
int ret;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"put: 0x%lx, %d, %s, %d, %d, %d, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
ret = ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
return ret;
}
int
ompi_osc_sm_get(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_win_t *win)
{
int ret;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"get: 0x%lx, %d, %s, %d, %d, %d, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
ret = ompi_datatype_sndrcv(remote_address, target_count, target_dt,
origin_addr, origin_count, origin_dt);
return ret;
}
int
ompi_osc_sm_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win)
{
int ret;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"accumulate: 0x%lx, %d, %s, %d, %d, %d, %s, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
op->o_name,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
opal_atomic_lock(&module->node_states[target].accumulate_lock);
if (op == &ompi_mpi_op_replace.op) {
ret = ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
} else {
ret = ompi_osc_base_sndrcv_op(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt,
op);
}
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
return ret;
}
int
ompi_osc_sm_get_accumulate(void *origin_addr,
int origin_count,
struct ompi_datatype_t *origin_dt,
void *result_addr,
int result_count,
struct ompi_datatype_t *result_dt,
int target,
MPI_Aint target_disp,
int target_count,
struct ompi_datatype_t *target_dt,
struct ompi_op_t *op,
struct ompi_win_t *win)
{
int ret;
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"get_accumulate: 0x%lx, %d, %s, %d, %d, %d, %s, %s, 0x%lx",
(unsigned long) origin_addr, origin_count,
origin_dt->name, target, (int) target_disp,
target_count, target_dt->name,
op->o_name,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
opal_atomic_lock(&module->node_states[target].accumulate_lock);
ret = ompi_datatype_sndrcv(remote_address, target_count, target_dt,
result_addr, result_count, result_dt);
if (OMPI_SUCCESS != ret || op == &ompi_mpi_op_no_op.op) goto done;
if (op == &ompi_mpi_op_replace.op) {
return ompi_datatype_sndrcv(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt);
} else {
ret = ompi_osc_base_sndrcv_op(origin_addr, origin_count, origin_dt,
remote_address, target_count, target_dt,
op);
}
done:
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
return ret;
}
int
ompi_osc_sm_compare_and_swap(void *origin_addr,
void *compare_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
size_t size;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"compare_and_swap: 0x%lx, %s, %d, %d, 0x%lx",
(unsigned long) origin_addr,
dt->name, target, (int) target_disp,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
ompi_datatype_type_size(dt, &size);
opal_atomic_lock(&module->node_states[target].accumulate_lock);
/* fetch */
ompi_datatype_copy_content_same_ddt(dt, 1, (char*) result_addr, (char*) remote_address);
/* compare */
if (0 == memcmp(result_addr, compare_addr, size)) {
/* set */
ompi_datatype_copy_content_same_ddt(dt, 1, (char*) remote_address, (char*) origin_addr);
}
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_fetch_and_op(void *origin_addr,
void *result_addr,
struct ompi_datatype_t *dt,
int target,
OPAL_PTRDIFF_TYPE target_disp,
struct ompi_op_t *op,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
void *remote_address;
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
"fetch_and_op: 0x%lx, %s, %d, %d, %s, 0x%lx",
(unsigned long) origin_addr,
dt->name, target, (int) target_disp,
op->o_name,
(unsigned long) win));
remote_address = ((char*) (module->bases[target])) + module->disp_units[target] * target_disp;
opal_atomic_lock(&module->node_states[target].accumulate_lock);
/* fetch */
ompi_datatype_copy_content_same_ddt(dt, 1, (char*) result_addr, (char*) remote_address);
if (op == &ompi_mpi_op_no_op.op) goto done;
/* op */
if (op == &ompi_mpi_op_replace.op) {
ompi_datatype_copy_content_same_ddt(dt, 1, (char*) remote_address, (char*) origin_addr);
} else {
ompi_op_reduce(op, origin_addr, remote_address, 1, dt);
}
done:
opal_atomic_unlock(&module->node_states[target].accumulate_lock);
return OMPI_SUCCESS;;
}

510
ompi/mca/osc/sm/osc_sm_component.c Обычный файл
Просмотреть файл

@ -0,0 +1,510 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "ompi/request/request.h"
#include "ompi/class/ompi_free_list.h"
#include "osc_sm.h"
#include "osc_sm_request.h"
static int component_open(void);
static int component_init(bool enable_progress_threads, bool enable_mpi_threads);
static int component_finalize(void);
static int component_query(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor);
static int component_select(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor, int *model);
ompi_osc_sm_component_t mca_osc_sm_component = {
{ /* ompi_osc_base_component_t */
{ /* ompi_base_component_t */
OMPI_OSC_BASE_VERSION_3_0_0,
"sm",
OMPI_MAJOR_VERSION, /* MCA component major version */
OMPI_MINOR_VERSION, /* MCA component minor version */
OMPI_RELEASE_VERSION, /* MCA component release version */
component_open,
NULL
},
{ /* mca_base_component_data */
/* The component is not checkpoint ready */
MCA_BASE_METADATA_PARAM_NONE
},
component_init,
component_query,
component_select,
component_finalize
}
};
ompi_osc_sm_module_t ompi_osc_sm_module_template = {
{
ompi_osc_sm_shared_query,
ompi_osc_sm_attach,
ompi_osc_sm_detach,
ompi_osc_sm_free,
ompi_osc_sm_put,
ompi_osc_sm_get,
ompi_osc_sm_accumulate,
ompi_osc_sm_compare_and_swap,
ompi_osc_sm_fetch_and_op,
ompi_osc_sm_get_accumulate,
ompi_osc_sm_rput,
ompi_osc_sm_rget,
ompi_osc_sm_raccumulate,
ompi_osc_sm_rget_accumulate,
ompi_osc_sm_fence,
ompi_osc_sm_start,
ompi_osc_sm_complete,
ompi_osc_sm_post,
ompi_osc_sm_wait,
ompi_osc_sm_test,
ompi_osc_sm_lock,
ompi_osc_sm_unlock,
ompi_osc_sm_lock_all,
ompi_osc_sm_unlock_all,
ompi_osc_sm_sync,
ompi_osc_sm_flush,
ompi_osc_sm_flush_all,
ompi_osc_sm_flush_local,
ompi_osc_sm_flush_local_all,
ompi_osc_sm_set_info,
ompi_osc_sm_get_info
}
};
static int
component_open(void)
{
return OMPI_SUCCESS;
}
static int
component_init(bool enable_progress_threads, bool enable_mpi_threads)
{
int ret;
ret = ompi_free_list_init(&mca_osc_sm_component.requests,
sizeof(ompi_request_t),
OBJ_CLASS(ompi_request_t),
0,
0,
8,
NULL);
if (OMPI_SUCCESS != ret) {
opal_output_verbose(1, ompi_osc_base_framework.framework_output,
"%s:%d: ompi_free_list_init failed: %d\n",
__FILE__, __LINE__, ret);
return ret;
}
return OMPI_SUCCESS;
}
static int
component_finalize(void)
{
/* clean up requests free list */
return OMPI_SUCCESS;
}
static int
check_win_ok(ompi_communicator_t *comm, int flavor)
{
int i;
if (! (MPI_WIN_FLAVOR_SHARED == flavor
|| MPI_WIN_FLAVOR_ALLOCATE == flavor) ) {
return -1;
}
for (i = 0 ; i < ompi_comm_size(comm) ; ++i) {
if (!OPAL_PROC_ON_LOCAL_NODE(ompi_comm_peer_lookup(comm, i)->proc_flags)) {
return -1;
}
}
return 0;
}
static int
component_query(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor)
{
if (0 != check_win_ok(comm, flavor)) return -1;
return 100;
}
static int
component_select(struct ompi_win_t *win, void **base, size_t size, int disp_unit,
struct ompi_communicator_t *comm, struct ompi_info_t *info,
int flavor, int *model)
{
ompi_osc_sm_module_t *module = NULL;
int ret = OMPI_ERROR;
if (0 != check_win_ok(comm, flavor)) return OMPI_ERR_NOT_SUPPORTED;
/* create module structure */
module = (ompi_osc_sm_module_t*)
calloc(1, sizeof(ompi_osc_sm_module_t));
if (NULL == module) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
/* fill in the function pointer part */
memcpy(module, &ompi_osc_sm_module_template,
sizeof(ompi_osc_base_module_t));
/* need our communicator for collectives in next phase */
ret = ompi_comm_dup(comm, &module->comm);
if (OMPI_SUCCESS != ret) goto error;
module->flavor = flavor;
/* create the segment */
if (1 == ompi_comm_size(comm)) {
module->segment_base = NULL;
module->sizes = malloc(sizeof(size_t));
if (NULL == module->sizes) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->bases = malloc(sizeof(void*));
if (NULL == module->bases) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->sizes[0] = size;
module->bases[0] = malloc(size);
if (NULL == module->bases[0]) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->global_state = malloc(sizeof(ompi_osc_sm_global_state_t));
if (NULL == module->global_state) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->node_states = malloc(sizeof(ompi_osc_sm_node_state_t));
if (NULL == module->node_states) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
} else {
char *data_file;
int *rbuf;
int total, i, flag;
size_t pagesize;
size_t state_size;
OPAL_OUTPUT_VERBOSE((1, ompi_osc_base_framework.framework_output,
"allocating shared memory region of size %ld\n", (long) size));
#ifdef HAVE_GETPAGESIZE
pagesize = getpagesize();
#else
pagesize = 4096;
#endif
rbuf = malloc(sizeof(int) * ompi_comm_size(module->comm));
if (NULL == rbuf) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->noncontig = false;
if (OMPI_SUCCESS != ompi_info_get_bool(info, "alloc_shared_noncontig",
&module->noncontig, &flag)) {
goto error;
}
if (module->noncontig) {
total = ((size - 1) / pagesize + 1) * pagesize;
} else {
total = size;
}
ret = module->comm->c_coll.coll_allgather(&total, 1, MPI_INT,
rbuf, 1, MPI_INT,
module->comm,
module->comm->c_coll.coll_allgather_module);
if (OMPI_SUCCESS != ret) return ret;
total = 0;
for (i = 0 ; i < ompi_comm_size(comm) ; ++i) {
total += rbuf[i];
}
if (asprintf(&data_file, "%s"OPAL_PATH_SEP"shared_window_%d.%s",
orte_process_info.job_session_dir,
ompi_comm_get_cid(comm),
orte_process_info.nodename) < 0) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* user opal/shmem directly to create a shared memory segment */
state_size = sizeof(ompi_osc_sm_global_state_t) + sizeof(ompi_osc_sm_node_state_t) * ompi_comm_size(module->comm);
if (0 == ompi_comm_rank (module->comm)) {
ret = opal_shmem_segment_create (&module->seg_ds, data_file, total + pagesize + state_size);
if (OPAL_SUCCESS != ret) {
goto error;
}
}
ret = module->comm->c_coll.coll_bcast (&module->seg_ds, sizeof (module->seg_ds), MPI_BYTE, 0,
module->comm, module->comm->c_coll.coll_bcast_module);
if (OMPI_SUCCESS != ret) {
goto error;
}
module->segment_base = opal_shmem_segment_attach (&module->seg_ds);
if (NULL == module->segment_base) {
goto error;
}
module->sizes = malloc(sizeof(size_t) * ompi_comm_size(module->comm));
if (NULL == module->sizes) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->bases = malloc(sizeof(void*) * ompi_comm_size(module->comm));
if (NULL == module->bases) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
module->global_state = (ompi_osc_sm_global_state_t *) (module->segment_base);
module->node_states = (ompi_osc_sm_node_state_t *) (module->global_state + 1);
for (i = 0, total = state_size ; i < ompi_comm_size(comm) ; ++i) {
module->sizes[i] = rbuf[i];
module->bases[i] = ((char *) module->segment_base) + total;
total += rbuf[i];
}
free(rbuf);
}
/* initialize my state shared */
module->my_node_state = &module->node_states[ompi_comm_rank(module->comm)];
*base = module->bases[ompi_comm_rank(module->comm)];
module->my_node_state->post_count = 0;
module->my_node_state->complete_count = 0;
bzero(&module->my_node_state->lock, sizeof(ompi_osc_sm_lock_t));
opal_atomic_init(&module->my_node_state->accumulate_lock, OPAL_ATOMIC_UNLOCKED);
/* share everyone's displacement units. */
module->disp_units = malloc(sizeof(int) * ompi_comm_size(module->comm));
ret = module->comm->c_coll.coll_allgather(&disp_unit, 1, MPI_INT,
module->disp_units, 1, MPI_INT,
module->comm,
module->comm->c_coll.coll_allgather_module);
if (OMPI_SUCCESS != ret) goto error;
module->start_group = NULL;
module->post_group = NULL;
/* initialize synchronization code */
module->my_sense = 1;
module->outstanding_locks = malloc(sizeof(enum ompi_osc_sm_locktype_t) * ompi_comm_size(module->comm));
if (NULL == module->outstanding_locks) {
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
goto error;
}
bzero(module->outstanding_locks, sizeof(enum ompi_osc_sm_locktype_t) * ompi_comm_size(module->comm));
if (0 == ompi_comm_rank(module->comm)) {
#if OPAL_HAVE_POSIX_THREADS
pthread_mutexattr_t mattr;
pthread_condattr_t cattr;
bool blocking_fence;
int flag;
if (OMPI_SUCCESS != ompi_info_get_bool(info, "blocking_fence",
&blocking_fence, &flag)) {
goto error;
}
if (blocking_fence) {
ret = pthread_mutexattr_init(&mattr);
ret = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
if (ret != 0) {
module->global_state->use_barrier_for_fence = 1;
} else {
ret = pthread_mutex_init(&module->global_state->mtx, &mattr);
if (ret != 0) {
module->global_state->use_barrier_for_fence = 1;
} else {
pthread_condattr_init(&cattr);
pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
ret = pthread_cond_init(&module->global_state->cond, &cattr);
if (ret != 0) return OMPI_ERROR;
pthread_condattr_destroy(&cattr);
}
}
module->global_state->use_barrier_for_fence = 0;
module->global_state->sense = module->my_sense;
module->global_state->count = ompi_comm_size(module->comm);
pthread_mutexattr_destroy(&mattr);
} else {
module->global_state->use_barrier_for_fence = 1;
}
#else
module->global_state->use_barrier_for_fence = 1;
#endif
}
ret = module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
if (OMPI_SUCCESS != ret) goto error;
*model = MPI_WIN_UNIFIED;
win->w_osc_module = &module->super;
return OMPI_SUCCESS;
error:
if (NULL != module->comm) ompi_comm_free(&module->comm);
if (NULL != module) free(module);
return ret;
}
int
ompi_osc_sm_shared_query(struct ompi_win_t *win, int rank, size_t *size, int *disp_unit, void *baseptr)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (module->flavor != MPI_WIN_FLAVOR_SHARED) {
return MPI_ERR_WIN;
}
if (MPI_PROC_NULL != rank) {
*size = module->sizes[rank];
*((void**) baseptr) = module->bases[rank];
*disp_unit = module->disp_units[rank];
} else {
int i = 0;
*size = 0;
*((void**) baseptr) = NULL;
*disp_unit = 0;
for (i = 0 ; i < ompi_comm_size(module->comm) ; ++i) {
if (0 != module->sizes[i]) {
*size = module->sizes[i];
*((void**) baseptr) = module->bases[i];
*disp_unit = module->disp_units[i];
break;
}
}
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_attach(struct ompi_win_t *win, void *base, size_t len)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (module->flavor != MPI_WIN_FLAVOR_DYNAMIC) {
return MPI_ERR_RMA_ATTACH;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_detach(struct ompi_win_t *win, void *base)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
if (module->flavor != MPI_WIN_FLAVOR_DYNAMIC) {
return MPI_ERR_RMA_ATTACH;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_free(struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
/* synchronize */
module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
/* free memory */
if (NULL == module->segment_base) {
free(module->node_states);
free(module->global_state);
free(module->bases[0]);
free(module->bases);
free(module->sizes);
} else {
opal_shmem_segment_detach (&module->seg_ds);
}
/* cleanup */
ompi_comm_free(&module->comm);
free(module);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_set_info(struct ompi_win_t *win, struct ompi_info_t *info)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
/* enforce collectiveness... */
return module->comm->c_coll.coll_barrier(module->comm,
module->comm->c_coll.coll_barrier_module);
}
int
ompi_osc_sm_get_info(struct ompi_win_t *win, struct ompi_info_t **info_used)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
ompi_info_t *info = OBJ_NEW(ompi_info_t);
if (NULL == info) return OMPI_ERR_TEMP_OUT_OF_RESOURCE;
if (module->flavor == MPI_WIN_FLAVOR_SHARED) {
ompi_info_set(info, "blocking_fence",
(1 == module->global_state->use_barrier_for_fence) ? "true" : "false");
ompi_info_set(info, "alloc_shared_noncontig",
(module->noncontig) ? "true" : "false");
}
*info_used = info;
return OMPI_SUCCESS;
}

241
ompi/mca/osc/sm/osc_sm_passive_target.c Обычный файл
Просмотреть файл

@ -0,0 +1,241 @@
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_sm.h"
static inline uint32_t
lk_fetch_add32(ompi_osc_sm_module_t *module,
int target,
size_t offset,
uint32_t delta)
{
return opal_atomic_add_32((int32_t*) ((char*) &module->node_states[target].lock + offset),
delta);
}
static inline void
lk_add32(ompi_osc_sm_module_t *module,
int target,
size_t offset,
uint32_t delta)
{
opal_atomic_add_32((int32_t*) ((char*) &module->node_states[target].lock + offset),
delta);
}
static inline uint32_t
lk_fetch32(ompi_osc_sm_module_t *module,
int target,
size_t offset)
{
__sync_synchronize();
return (uint32_t) *((char*) &module->node_states[target].lock + offset);
}
static inline int
start_exclusive(ompi_osc_sm_module_t *module,
int target)
{
uint32_t me = lk_fetch_add32(module, target,
offsetof(ompi_osc_sm_lock_t, counter), 1);
while (me != lk_fetch32(module, target,
offsetof(ompi_osc_sm_lock_t, write))) {
opal_progress();
}
return OMPI_SUCCESS;
}
static inline int
end_exclusive(ompi_osc_sm_module_t *module,
int target)
{
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, write), 1);
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, read), 1);
return OMPI_SUCCESS;
}
static inline int
start_shared(ompi_osc_sm_module_t *module,
int target)
{
uint32_t me = lk_fetch_add32(module, target,
offsetof(ompi_osc_sm_lock_t, counter), 1);
while (me != lk_fetch32(module, target,
offsetof(ompi_osc_sm_lock_t, read))) {
opal_progress();
}
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, read), 1);
return OMPI_SUCCESS;
}
static inline int
end_shared(ompi_osc_sm_module_t *module,
int target)
{
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, write), 1);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret;
if (lock_none != module->outstanding_locks[target]) {
return MPI_ERR_RMA_SYNC;
}
if (0 == (assert & MPI_MODE_NOCHECK)) {
if (MPI_LOCK_EXCLUSIVE == lock_type) {
module->outstanding_locks[target] = lock_exclusive;
ret = start_exclusive(module, target);
} else {
module->outstanding_locks[target] = lock_shared;
ret = start_shared(module, target);
}
} else {
module->outstanding_locks[target] = lock_nocheck;
ret = OMPI_SUCCESS;
}
return ret;
}
int
ompi_osc_sm_unlock(int target,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret;
/* ensure all memory operations have completed */
opal_atomic_mb();
if (module->outstanding_locks[target] == lock_nocheck) {
ret = OMPI_SUCCESS;
} else if (module->outstanding_locks[target] == lock_exclusive) {
ret = end_exclusive(module, target);
} else if (module->outstanding_locks[target] == lock_shared) {
ret = end_shared(module, target);
} else {
ret = MPI_ERR_RMA_SYNC;
}
return ret;
}
int
ompi_osc_sm_lock_all(int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret, i, comm_size;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret = ompi_osc_sm_lock(MPI_LOCK_SHARED, i, assert, win);
if (OMPI_SUCCESS != ret) return ret;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_unlock_all(struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret, i, comm_size;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret = ompi_osc_sm_unlock(i, win);
if (OMPI_SUCCESS != ret) return ret;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_sync(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush(int target,
struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_all(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_local(int target,
struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_local_all(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}

56
ompi/mca/osc/sm/osc_sm_request.c Обычный файл
Просмотреть файл

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/request/request.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_sm.h"
#include "osc_sm_request.h"
static int
request_cancel(struct ompi_request_t *request, int complete)
{
return MPI_ERR_REQUEST;
}
static int
request_free(struct ompi_request_t **ompi_req)
{
ompi_osc_sm_request_t *request =
(ompi_osc_sm_request_t*) *ompi_req;
if (true != request->super.req_complete) {
return MPI_ERR_REQUEST;
}
OMPI_OSC_SM_REQUEST_RETURN(request);
*ompi_req = MPI_REQUEST_NULL;
return OMPI_SUCCESS;
}
static
void
request_construct(ompi_osc_sm_request_t *request)
{
request->super.req_type = OMPI_REQUEST_WIN;
request->super.req_status._cancelled = 0;
request->super.req_free = request_free;
request->super.req_cancel = request_cancel;
}
OBJ_CLASS_INSTANCE(ompi_osc_sm_request_t,
ompi_request_t,
request_construct,
NULL);

55
ompi/mca/osc/sm/osc_sm_request.h Обычный файл
Просмотреть файл

@ -0,0 +1,55 @@
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OSC_SM_REQUEST_H
#define OSC_SM_REQUEST_H
#include "ompi/request/request.h"
struct ompi_osc_sm_request_t {
ompi_request_t super;
};
typedef struct ompi_osc_sm_request_t ompi_osc_sm_request_t;
OBJ_CLASS_DECLARATION(ompi_osc_sm_request_t);
/* REQUEST_ALLOC is only called from "top-level" functions (sm_rput,
sm_rget, etc.), so it's ok to spin here... */
#define OMPI_OSC_SM_REQUEST_ALLOC(win, req) \
do { \
ompi_free_list_item_t *item = NULL; \
do { \
OMPI_FREE_LIST_GET_MT(&mca_osc_sm_component.requests, item); \
if (NULL == item) { \
opal_progress(); \
} \
} while (NULL == item); \
req = (ompi_osc_sm_request_t*) item; \
OMPI_REQUEST_INIT(&req->super, false); \
req->super.req_mpi_object.win = win; \
req->super.req_complete = false; \
req->super.req_state = OMPI_REQUEST_ACTIVE; \
req->super.req_status._ucount = 0; \
} while (0)
#define OMPI_OSC_SM_REQUEST_RETURN(req) \
do { \
OMPI_REQUEST_FINI(&request->super); \
OMPI_FREE_LIST_RETURN_MT(&mca_osc_sm_component.requests, \
(ompi_free_list_item_t*) req); \
} while (0)
#define OMPI_OSC_SM_REQUEST_COMPLETE(req) \
do { \
OPAL_THREAD_LOCK(&ompi_request_lock); \
ompi_request_complete(&req->super, true); \
OPAL_THREAD_UNLOCK(&ompi_request_lock); \
} while (0)
#endif

Просмотреть файл

@ -8,6 +8,7 @@
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2010-2012 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow

Просмотреть файл

@ -140,6 +140,7 @@ libmpi_c_mpi_la_SOURCES = \
comm_split.c \
comm_split_type.c \
comm_test_inter.c \
compare_and_swap.c \
dims_create.c \
errhandler_c2f.c \
errhandler_create.c \
@ -150,6 +151,7 @@ libmpi_c_mpi_la_SOURCES = \
error_class.c \
error_string.c \
exscan.c \
fetch_and_op.c \
iexscan.c \
finalize.c \
finalized.c \
@ -162,6 +164,7 @@ libmpi_c_mpi_la_SOURCES = \
get_count.c \
get_elements.c \
get_elements_x.c \
get_accumulate.c \
get_library_version.c \
get_processor_name.c \
get_version.c \
@ -243,6 +246,7 @@ libmpi_c_mpi_la_SOURCES = \
probe.c \
publish_name.c \
query_thread.c \
raccumulate.c \
recv_init.c \
recv.c \
reduce.c \
@ -256,6 +260,9 @@ libmpi_c_mpi_la_SOURCES = \
request_f2c.c \
request_free.c \
request_get_status.c \
rget.c \
rget_accumulate.c \
rput.c \
rsend_init.c \
rsend.c \
scan.c \
@ -336,29 +343,44 @@ libmpi_c_mpi_la_SOURCES = \
accumulate.c \
get.c \
put.c \
win_allocate.c \
win_allocate_shared.c \
win_attach.c \
win_c2f.c \
win_call_errhandler.c \
win_complete.c \
win_create_errhandler.c \
win_create_keyval.c \
win_create.c \
win_create_dynamic.c \
win_delete_attr.c \
win_detach.c \
win_f2c.c \
win_fence.c \
win_flush.c \
win_flush_all.c \
win_flush_local.c \
win_flush_local_all.c \
win_free_keyval.c \
win_free.c \
win_get_attr.c \
win_get_errhandler.c \
win_get_group.c \
win_get_info.c \
win_get_name.c \
win_lock.c \
win_lock_all.c \
win_post.c \
win_set_attr.c \
win_set_errhandler.c \
win_set_info.c \
win_set_name.c \
win_shared_query.c \
win_sync.c \
win_start.c \
win_test.c \
win_unlock.c \
win_unlock_all.c \
win_wait.c
if OMPI_PROVIDE_MPI_FILE_INTERFACE

Просмотреть файл

@ -52,7 +52,7 @@ int MPI_Accumulate(const void *origin_addr, int origin_count, MPI_Datatype origi
MEMCHECKER(
memchecker_datatype(origin_datatype);
memchecker_datatype(target_datatype);
memchecker_call(&opal_memchecker_base_isdefined, origin_addr, origin_count, origin_datatype);
memchecker_call(&opal_memchecker_base_isdefined, (void *) origin_addr, origin_count, origin_datatype);
);
if (MPI_PARAM_CHECK) {
@ -67,12 +67,10 @@ int MPI_Accumulate(const void *origin_addr, int origin_count, MPI_Datatype origi
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (MPI_OP_NULL == op) {
} else if (MPI_OP_NULL == op || MPI_NO_OP == op) {
rc = MPI_ERR_OP;
} else if (!ompi_op_is_intrinsic(op)) {
rc = MPI_ERR_OP;
} else if (!ompi_win_comm_allowed(win)) {
rc = MPI_ERR_RMA_SYNC;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
@ -86,7 +84,7 @@ int MPI_Accumulate(const void *origin_addr, int origin_count, MPI_Datatype origi
for other reduction operators, we don't require such
behavior, as checking for it is expensive here and we don't
care in implementation.. */
if (op != &ompi_mpi_op_replace.op) {
if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
ompi_datatype_t *op_check_dt, *origin_check_dt;
char *msg;

72
ompi/mpi/c/compare_and_swap.c Обычный файл
Просмотреть файл

@ -0,0 +1,72 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/datatype/ompi_datatype.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Compare_and_swap = PMPI_Compare_and_swap
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Compare_and_swap";
int MPI_Compare_and_swap(void *origin_addr, void *compare_addr, void *result_addr,
MPI_Datatype datatype, int target_rank, MPI_Aint target_disp, MPI_Win win)
{
int rc;
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, datatype, 1);
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) return MPI_SUCCESS;
OPAL_CR_ENTER_LIBRARY();
rc = win->w_osc_module->osc_compare_and_swap(origin_addr, compare_addr, result_addr,
datatype, target_rank, target_disp, win);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

72
ompi/mpi/c/fetch_and_op.c Обычный файл
Просмотреть файл

@ -0,0 +1,72 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/datatype/ompi_datatype.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Fetch_and_op = PMPI_Fetch_and_op
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Fetch_and_op";
int MPI_Fetch_and_op(void *origin_addr, void *result_addr, MPI_Datatype datatype,
int target_rank, MPI_Aint target_disp, MPI_Op op, MPI_Win win)
{
int rc;
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, datatype, 1);
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) return MPI_SUCCESS;
OPAL_CR_ENTER_LIBRARY();
rc = win->w_osc_module->osc_fetch_and_op(origin_addr, result_addr, datatype,
target_rank, target_disp, op, win);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

Просмотреть файл

@ -56,8 +56,6 @@ int MPI_Get(void *origin_addr, int origin_count,
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (!ompi_win_comm_allowed(win)) {
rc = MPI_ERR_RMA_SYNC;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {

149
ompi/mpi/c/get_accumulate.c Обычный файл
Просмотреть файл

@ -0,0 +1,149 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2009 Sun Microsystmes, Inc. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/op/op.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/datatype/ompi_datatype_internal.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Get_accumulate = PMPI_Get_accumulate
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Get_accumlate";
int MPI_Get_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win)
{
int rc;
ompi_win_t *ompi_win = (ompi_win_t*) win;
MEMCHECKER(
memchecker_datatype(origin_datatype);
memchecker_datatype(target_datatype);
memchecker_call(&opal_memchecker_base_isdefined, (void *) origin_addr, origin_count, origin_datatype);
);
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (origin_count < 0 || target_count < 0) {
rc = MPI_ERR_COUNT;
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (MPI_OP_NULL == op) {
rc = MPI_ERR_OP;
} else if (!ompi_op_is_intrinsic(op)) {
rc = MPI_ERR_OP;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
/* the origin datatype is meaningless when using MPI_OP_NO_OP */
if (&ompi_mpi_op_no_op.op != op) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
} else {
rc = OMPI_SUCCESS;
}
if (OMPI_SUCCESS == rc) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
}
if (OMPI_SUCCESS == rc) {
/* While technically the standard probably requires that the
datatypes used with MPI_REPLACE conform to all the rules
for other reduction operators, we don't require such
behavior, as checking for it is expensive here and we don't
care in implementation.. */
if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
ompi_datatype_t *op_check_dt, *origin_check_dt;
char *msg;
/* GET_ACCUMULATE, unlike REDUCE, can use with derived
datatypes with predefinied operations, with some
restrictions outlined in MPI-2:6.3.4. The derived
datatype must be composed entierly from one predefined
datatype (so you can do all the construction you want,
but at the bottom, you can only use one datatype, say,
MPI_INT). If the datatype at the target isn't
predefined, then make sure it's composed of only one
datatype, and check that datatype against
ompi_op_is_valid(). */
origin_check_dt = ompi_datatype_get_single_predefined_type_from_args(origin_datatype);
op_check_dt = ompi_datatype_get_single_predefined_type_from_args(target_datatype);
if( !((origin_check_dt == op_check_dt) & (NULL != op_check_dt)) ) {
OMPI_ERRHANDLER_RETURN(MPI_ERR_ARG, win, MPI_ERR_ARG, FUNC_NAME);
}
/* check to make sure primitive type is valid for
reduction. Should do this on the target, but
then can't get the errcode back for this
call */
if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
free(msg);
return ret;
}
}
}
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) {
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
/* XXX -- TODO: do not cast away the const */
rc = ompi_win->w_osc_module->osc_get_accumulate((void *) origin_addr,
origin_count,
origin_datatype,
result_addr,
result_count,
result_datatype,
target_rank,
target_disp,
target_count,
target_datatype,
op, win);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

Просмотреть файл

@ -122,6 +122,7 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
pcomm_split.c \
pcomm_split_type.c \
pcomm_test_inter.c \
pcompare_and_swap.c \
pdims_create.c \
perrhandler_c2f.c \
perrhandler_create.c \
@ -132,6 +133,7 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
perror_class.c \
perror_string.c \
pexscan.c \
pfetch_and_op.c \
piexscan.c \
pfinalize.c \
pfinalized.c \
@ -144,6 +146,7 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
pget_count.c \
pget_elements.c \
pget_elements_x.c \
pget_accumulate.c \
pget_library_version.c \
pget_processor_name.c \
pget_version.c \
@ -225,6 +228,7 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
pprobe.c \
ppublish_name.c \
pquery_thread.c \
praccumulate.c \
precv_init.c \
precv.c \
preduce.c \
@ -238,6 +242,9 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
prequest_f2c.c \
prequest_free.c \
prequest_get_status.c \
prget.c \
prget_accumulate.c \
prput.c \
prsend_init.c \
prsend.c \
pscan.c \
@ -318,29 +325,44 @@ nodist_libmpi_c_pmpi_la_SOURCES = \
paccumulate.c \
pget.c \
pput.c \
pwin_allocate.c \
pwin_allocate_shared.c \
pwin_attach.c \
pwin_c2f.c \
pwin_call_errhandler.c \
pwin_complete.c \
pwin_create_errhandler.c \
pwin_create_keyval.c \
pwin_create.c \
pwin_create_dynamic.c \
pwin_delete_attr.c \
pwin_detach.c \
pwin_f2c.c \
pwin_fence.c \
pwin_flush.c \
pwin_flush_all.c \
pwin_flush_local.c \
pwin_flush_local_all.c \
pwin_free_keyval.c \
pwin_free.c \
pwin_get_attr.c \
pwin_get_errhandler.c \
pwin_get_group.c \
pwin_get_info.c \
pwin_get_name.c \
pwin_lock.c \
pwin_lock_all.c \
pwin_post.c \
pwin_set_attr.c \
pwin_set_errhandler.c \
pwin_set_info.c \
pwin_set_name.c \
pwin_shared_query.c \
pwin_start.c \
pwin_sync.c \
pwin_test.c \
pwin_unlock.c \
pwin_unlock_all.c \
pwin_wait.c
if OMPI_PROVIDE_MPI_FILE_INTERFACE

Просмотреть файл

@ -108,6 +108,7 @@
#define MPI_Comm_split PMPI_Comm_split
#define MPI_Comm_split_type PMPI_Comm_split_type
#define MPI_Comm_test_inter PMPI_Comm_test_inter
#define MPI_Compare_and_swap PMPI_Compare_and_swap
#define MPI_Dims_create PMPI_Dims_create
#define MPI_Errhandler_c2f PMPI_Errhandler_c2f
#define MPI_Errhandler_f2c PMPI_Errhandler_f2c
@ -118,6 +119,7 @@
#define MPI_Error_class PMPI_Error_class
#define MPI_Error_string PMPI_Error_string
#define MPI_Exscan PMPI_Exscan
#define MPI_Fetch_and_op PMPI_Fetch_and_op
#define MPI_Iexscan PMPI_Iexscan
#define MPI_File_c2f PMPI_File_c2f
#define MPI_File_call_errhandler PMPI_File_call_errhandler
@ -188,6 +190,7 @@
#define MPI_Get_elements PMPI_Get_elements
#define MPI_Get_elements_x PMPI_Get_elements_x
#define MPI_Get PMPI_Get
#define MPI_Get_accumulate PMPI_Get_accumulate
#define MPI_Get_library_version PMPI_Get_library_version
#define MPI_Get_processor_name PMPI_Get_processor_name
#define MPI_Get_version PMPI_Get_version
@ -272,6 +275,7 @@
#define MPI_Publish_name PMPI_Publish_name
#define MPI_Put PMPI_Put
#define MPI_Query_thread PMPI_Query_thread
#define MPI_Raccumulate PMPI_Raccumulate
#define MPI_Recv_init PMPI_Recv_init
#define MPI_Recv PMPI_Recv
#define MPI_Reduce PMPI_Reduce
@ -286,6 +290,9 @@
#define MPI_Request_f2c PMPI_Request_f2c
#define MPI_Request_free PMPI_Request_free
#define MPI_Request_get_status PMPI_Request_get_status
#define MPI_Rget PMPI_Rget
#define MPI_Rget_accumulate PMPI_Rget_accumulate
#define MPI_Rput PMPI_Rput
#define MPI_Rsend_init PMPI_Rsend_init
#define MPI_Rsend PMPI_Rsend
#define MPI_Scan PMPI_Scan
@ -361,29 +368,44 @@
#define MPI_Waitall PMPI_Waitall
#define MPI_Waitany PMPI_Waitany
#define MPI_Waitsome PMPI_Waitsome
#define MPI_Win_allocate PMPI_Win_allocate
#define MPI_Win_allocate_shared PMPI_Win_allocate_shared
#define MPI_Win_attach PMPI_Win_attach
#define MPI_Win_c2f PMPI_Win_c2f
#define MPI_Win_call_errhandler PMPI_Win_call_errhandler
#define MPI_Win_complete PMPI_Win_complete
#define MPI_Win_create_errhandler PMPI_Win_create_errhandler
#define MPI_Win_create_keyval PMPI_Win_create_keyval
#define MPI_Win_create PMPI_Win_create
#define MPI_Win_create_dynamic PMPI_Win_create_dynamic
#define MPI_Win_delete_attr PMPI_Win_delete_attr
#define MPI_Win_detach PMPI_Win_detach
#define MPI_Win_f2c PMPI_Win_f2c
#define MPI_Win_fence PMPI_Win_fence
#define MPI_Win_flush PMPI_Win_flush
#define MPI_Win_flush_all PMPI_Win_flush_all
#define MPI_Win_flush_local PMPI_Win_flush_local
#define MPI_Win_flush_local_all PMPI_Win_flush_local_all
#define MPI_Win_free_keyval PMPI_Win_free_keyval
#define MPI_Win_free PMPI_Win_free
#define MPI_Win_get_attr PMPI_Win_get_attr
#define MPI_Win_get_errhandler PMPI_Win_get_errhandler
#define MPI_Win_get_group PMPI_Win_get_group
#define MPI_Win_get_info PMPI_Win_get_info
#define MPI_Win_get_name PMPI_Win_get_name
#define MPI_Win_lock PMPI_Win_lock
#define MPI_Win_lock_all PMPI_Win_lock_all
#define MPI_Win_post PMPI_Win_post
#define MPI_Win_set_attr PMPI_Win_set_attr
#define MPI_Win_set_errhandler PMPI_Win_set_errhandler
#define MPI_Win_set_info PMPI_Win_set_info
#define MPI_Win_set_name PMPI_Win_set_name
#define MPI_Win_shared_query PMPI_Win_shared_query
#define MPI_Win_start PMPI_Win_start
#define MPI_Win_sync PMPI_Win_sync
#define MPI_Win_test PMPI_Win_test
#define MPI_Win_unlock PMPI_Win_unlock
#define MPI_Win_unlock_all PMPI_Win_unlock_all
#define MPI_Win_wait PMPI_Win_wait
#define MPI_Wtick PMPI_Wtick
#define MPI_Wtime PMPI_Wtime

Просмотреть файл

@ -59,8 +59,6 @@ int MPI_Put(const void *origin_addr, int origin_count, MPI_Datatype origin_datat
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (!ompi_win_comm_allowed(win)) {
rc = MPI_ERR_RMA_SYNC;
} else if (NULL == target_datatype ||
MPI_DATATYPE_NULL == target_datatype) {
rc = MPI_ERR_TYPE;

141
ompi/mpi/c/raccumulate.c Обычный файл
Просмотреть файл

@ -0,0 +1,141 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2009 Sun Microsystmes, Inc. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/op/op.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/datatype/ompi_datatype_internal.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Raccumulate = PMPI_Raccumulate
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Accumlate";
int MPI_Raccumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request)
{
int rc;
ompi_win_t *ompi_win = (ompi_win_t*) win;
MEMCHECKER(
memchecker_datatype(origin_datatype);
memchecker_datatype(target_datatype);
memchecker_call(&opal_memchecker_base_isdefined, origin_addr, origin_count, origin_datatype);
);
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (origin_count < 0 || target_count < 0) {
rc = MPI_ERR_COUNT;
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (MPI_OP_NULL == op || MPI_NO_OP == op) {
rc = MPI_ERR_OP;
} else if (!ompi_op_is_intrinsic(op)) {
rc = MPI_ERR_OP;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
if (OMPI_SUCCESS == rc) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
}
if (OMPI_SUCCESS == rc) {
/* While technically the standard probably requires that the
datatypes used with MPI_REPLACE conform to all the rules
for other reduction operators, we don't require such
behavior, as checking for it is expensive here and we don't
care in implementation.. */
if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
ompi_datatype_t *op_check_dt, *origin_check_dt;
char *msg;
/* RACCUMULATE, unlike REDUCE, can use with derived
datatypes with predefinied operations, with some
restrictions outlined in MPI-2:6.3.4. The derived
datatype must be composed entierly from one predefined
datatype (so you can do all the construction you want,
but at the bottom, you can only use one datatype, say,
MPI_INT). If the datatype at the target isn't
predefined, then make sure it's composed of only one
datatype, and check that datatype against
ompi_op_is_valid(). */
origin_check_dt = ompi_datatype_get_single_predefined_type_from_args(origin_datatype);
op_check_dt = ompi_datatype_get_single_predefined_type_from_args(target_datatype);
if( !((origin_check_dt == op_check_dt) & (NULL != op_check_dt)) ) {
OMPI_ERRHANDLER_RETURN(MPI_ERR_ARG, win, MPI_ERR_ARG, FUNC_NAME);
}
/* check to make sure primitive type is valid for
reduction. Should do this on the target, but
then can't get the errcode back for this
call */
if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
free(msg);
return ret;
}
}
}
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) {
*request = &ompi_request_empty;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
/* TODO: don't cast away the const */
rc = ompi_win->w_osc_module->osc_raccumulate((void*) origin_addr,
origin_count,
origin_datatype,
target_rank,
target_disp,
target_count,
target_datatype,
op, win, request);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

84
ompi/mpi/c/rget.c Обычный файл
Просмотреть файл

@ -0,0 +1,84 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2014 Los Alamos National Security, LLC. ALl rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/datatype/ompi_datatype.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Rget = PMPI_Rget
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Rget";
int MPI_Rget(void *origin_addr, int origin_count,
MPI_Datatype origin_datatype, int target_rank,
MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win, MPI_Request *request)
{
int rc;
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (origin_count < 0 || target_count < 0) {
rc = MPI_ERR_COUNT;
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
if (OMPI_SUCCESS == rc) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
}
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) {
*request = &ompi_request_empty;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
rc = win->w_osc_module->osc_rget(origin_addr, origin_count, origin_datatype,
target_rank, target_disp, target_count,
target_datatype, win, request);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

151
ompi/mpi/c/rget_accumulate.c Обычный файл
Просмотреть файл

@ -0,0 +1,151 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2009 Sun Microsystmes, Inc. All rights reserved.
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All right
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/request/request.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/op/op.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/datatype/ompi_datatype_internal.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Rget_accumulate = PMPI_Rget_accumulate
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Rget_accumlate";
int MPI_Rget_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
void *result_addr, int result_count, MPI_Datatype result_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request)
{
int rc;
ompi_win_t *ompi_win = (ompi_win_t*) win;
MEMCHECKER(
memchecker_datatype(origin_datatype);
memchecker_datatype(target_datatype);
memchecker_call(&opal_memchecker_base_isdefined, (void *) origin_addr, origin_count, origin_datatype);
);
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (origin_count < 0 || target_count < 0) {
rc = MPI_ERR_COUNT;
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (MPI_OP_NULL == op) {
rc = MPI_ERR_OP;
} else if (!ompi_op_is_intrinsic(op)) {
rc = MPI_ERR_OP;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
/* the origin datatype is meaningless when using MPI_OP_NO_OP */
if (&ompi_mpi_op_no_op.op != op) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
} else {
rc = OMPI_SUCCESS;
}
if (OMPI_SUCCESS == rc) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
}
if (OMPI_SUCCESS == rc) {
/* While technically the standard probably requires that the
datatypes used with MPI_REPLACE conform to all the rules
for other reduction operators, we don't require such
behavior, as checking for it is expensive here and we don't
care in implementation.. */
if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
ompi_datatype_t *op_check_dt, *origin_check_dt;
char *msg;
/* RGET_ACCUMULATE, unlike REDUCE, can use with derived
datatypes with predefinied operations, with some
restrictions outlined in MPI-2:6.3.4. The derived
datatype must be composed entierly from one predefined
datatype (so you can do all the construction you want,
but at the bottom, you can only use one datatype, say,
MPI_INT). If the datatype at the target isn't
predefined, then make sure it's composed of only one
datatype, and check that datatype against
ompi_op_is_valid(). */
origin_check_dt = ompi_datatype_get_single_predefined_type_from_args(origin_datatype);
op_check_dt = ompi_datatype_get_single_predefined_type_from_args(target_datatype);
if( !((origin_check_dt == op_check_dt) & (NULL != op_check_dt)) ) {
OMPI_ERRHANDLER_RETURN(MPI_ERR_ARG, win, MPI_ERR_ARG, FUNC_NAME);
}
/* check to make sure primitive type is valid for
reduction. Should do this on the target, but
then can't get the errcode back for this
call */
if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
free(msg);
return ret;
}
}
}
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) {
*request = &ompi_request_empty;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
/* TODO: do not cast away the const */
rc = ompi_win->w_osc_module->osc_rget_accumulate((void *) origin_addr,
origin_count,
origin_datatype,
result_addr,
result_count,
result_datatype,
target_rank,
target_disp,
target_count,
target_datatype,
op, win, request);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

88
ompi/mpi/c/rput.c Обычный файл
Просмотреть файл

@ -0,0 +1,88 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/datatype/ompi_datatype.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Rput = PMPI_Rput
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Rput";
int MPI_Rput(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
int target_rank, MPI_Aint target_disp, int target_count,
MPI_Datatype target_datatype, MPI_Win win, MPI_Request *request)
{
int rc;
if (MPI_PARAM_CHECK) {
rc = OMPI_SUCCESS;
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (origin_count < 0 || target_count < 0) {
rc = MPI_ERR_COUNT;
} else if (ompi_win_peer_invalid(win, target_rank) &&
(MPI_PROC_NULL != target_rank)) {
rc = MPI_ERR_RANK;
} else if (NULL == target_datatype ||
MPI_DATATYPE_NULL == target_datatype) {
rc = MPI_ERR_TYPE;
} else if ( target_disp < 0 ) {
rc = MPI_ERR_DISP;
} else {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
if (OMPI_SUCCESS == rc) {
OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
}
}
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
}
if (MPI_PROC_NULL == target_rank) {
*request = &ompi_request_empty;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
/* TODO: do not cast away the const */
rc = win->w_osc_module->osc_rput((void *) origin_addr, origin_count, origin_datatype,
target_rank, target_disp, target_count,
target_datatype, win, request);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

89
ompi/mpi/c/win_allocate.c Обычный файл
Просмотреть файл

@ -0,0 +1,89 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_allocate = PMPI_Win_allocate
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_allocate";
int MPI_Win_allocate(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win)
{
int ret = MPI_SUCCESS;
MEMCHECKER(
memchecker_comm(comm);
);
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_comm_invalid (comm)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM,
FUNC_NAME);
} else if (NULL == info || ompi_info_is_freed(info)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_INFO,
FUNC_NAME);
} else if (NULL == win) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
} else if ( size < 0 ) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_SIZE, FUNC_NAME);
} else if ( disp_unit <= 0 ) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_DISP, FUNC_NAME);
}
}
/* communicator must be an intracommunicator */
if (OMPI_COMM_IS_INTER(comm)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COMM, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = ompi_win_allocate((size_t)size, disp_unit, info,
comm, baseptr, win);
if (OMPI_SUCCESS != ret) {
*win = MPI_WIN_NULL;
OPAL_CR_EXIT_LIBRARY();
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
}
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}

87
ompi/mpi/c/win_allocate_shared.c Обычный файл
Просмотреть файл

@ -0,0 +1,87 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_allocate_shared = PMPI_Win_allocate_shared
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_allocate_shared";
int MPI_Win_allocate_shared(MPI_Aint size, int disp_unit, MPI_Info info,
MPI_Comm comm, void *baseptr, MPI_Win *win)
{
int ret = MPI_SUCCESS;
MEMCHECKER(
memchecker_comm(comm);
);
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_comm_invalid (comm)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM,
FUNC_NAME);
} else if (NULL == info || ompi_info_is_freed(info)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_INFO,
FUNC_NAME);
} else if (NULL == win) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
} else if ( size < 0 ) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_SIZE, FUNC_NAME);
}
}
/* communicator must be an intracommunicator */
if (OMPI_COMM_IS_INTER(comm)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COMM, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = ompi_win_allocate_shared((size_t)size, disp_unit, info,
comm, baseptr, win);
if (OMPI_SUCCESS != ret) {
*win = MPI_WIN_NULL;
OPAL_CR_EXIT_LIBRARY();
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
}
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}

62
ompi/mpi/c/win_attach.c Обычный файл
Просмотреть файл

@ -0,0 +1,62 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_attach = PMPI_Win_attach
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_attach";
int MPI_Win_attach(MPI_Win win, void *base, MPI_Aint size)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (NULL == base) {
ret = MPI_ERR_ARG;
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_win_attach(win, base, size);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

Просмотреть файл

@ -45,8 +45,6 @@ int MPI_Win_complete(MPI_Win win)
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (0 == (ompi_win_get_mode(win) & OMPI_WIN_STARTED)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
}
}

84
ompi/mpi/c/win_create_dynamic.c Обычный файл
Просмотреть файл

@ -0,0 +1,84 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_create_dynamic = PMPI_Win_create_dynamic
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_create_dynamic";
int MPI_Win_create_dynamic(MPI_Info info, MPI_Comm comm, MPI_Win *win)
{
int ret = MPI_SUCCESS;
MEMCHECKER(
memchecker_comm(comm);
);
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_comm_invalid (comm)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM,
FUNC_NAME);
} else if (NULL == info || ompi_info_is_freed(info)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_INFO,
FUNC_NAME);
} else if (NULL == win) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
}
}
/* communicator must be an intracommunicator */
if (OMPI_COMM_IS_INTER(comm)) {
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COMM, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create_dynamic window and return */
ret = ompi_win_create_dynamic(info, comm, win);
if (OMPI_SUCCESS != ret) {
*win = MPI_WIN_NULL;
OPAL_CR_EXIT_LIBRARY();
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME);
}
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}

62
ompi/mpi/c/win_detach.c Обычный файл
Просмотреть файл

@ -0,0 +1,62 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_detach = PMPI_Win_detach
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_detach";
int MPI_Win_detach(MPI_Win win, void *base)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (NULL == base) {
ret = MPI_ERR_ARG;
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_win_detach(win, base);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

Просмотреть файл

@ -48,10 +48,6 @@ int MPI_Win_fence(int assert, MPI_Win win)
} else if (0 != (assert & ~(MPI_MODE_NOSTORE | MPI_MODE_NOPUT |
MPI_MODE_NOPRECEDE | MPI_MODE_NOSUCCEED))) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME);
} else if (0 != (ompi_win_get_mode(win) &
(OMPI_WIN_POSTED | OMPI_WIN_STARTED))) {
/* If we're in a post or start, we can't be in a fence */
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
}
}

60
ompi/mpi/c/win_flush.c Обычный файл
Просмотреть файл

@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_flush = PMPI_Win_flush
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_flush";
int MPI_Win_flush(int rank, MPI_Win win)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_flush(rank, win);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

60
ompi/mpi/c/win_flush_all.c Обычный файл
Просмотреть файл

@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_flush_all = PMPI_Win_flush_all
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_flush_all";
int MPI_Win_flush_all(MPI_Win win)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_flush_all(win);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

60
ompi/mpi/c/win_flush_local.c Обычный файл
Просмотреть файл

@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_flush_local = PMPI_Win_flush_local
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_flush_local";
int MPI_Win_flush_local(int rank, MPI_Win win)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_flush_local(rank, win);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

60
ompi/mpi/c/win_flush_local_all.c Обычный файл
Просмотреть файл

@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2008 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 (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/info/info.h"
#include "ompi/win/win.h"
#include "ompi/memchecker.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_flush_local_all = PMPI_Win_flush_local_all
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_flush_local_all";
int MPI_Win_flush_local_all(MPI_Win win)
{
int ret = MPI_SUCCESS;
/* argument checking */
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
OMPI_ERRHANDLER_CHECK(ret, win, ret, FUNC_NAME);
}
OPAL_CR_ENTER_LIBRARY();
/* create window and return */
ret = win->w_osc_module->osc_flush_local_all(win);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

Просмотреть файл

@ -44,10 +44,6 @@ int MPI_Win_free(MPI_Win *win)
if (ompi_win_invalid(*win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (OMPI_WIN_ACCESS_EPOCH & ompi_win_get_mode(*win)) {
return OMPI_ERRHANDLER_INVOKE(*win,
MPI_ERR_RMA_SYNC,
FUNC_NAME);
}
}

48
ompi/mpi/c/win_get_info.c Обычный файл
Просмотреть файл

@ -0,0 +1,48 @@
/*
* Copyright (c) 2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_get_info = PMPI_Win_get_info
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_get_info";
int MPI_Win_get_info(MPI_Win win, MPI_Info *info_used)
{
int ret;
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
if (NULL == info_used) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ARG, FUNC_NAME);
}
}
OPAL_CR_ENTER_LIBRARY();
ret = win->w_osc_module->osc_get_info(win, info_used);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

Просмотреть файл

@ -52,8 +52,6 @@ int MPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win)
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RANK, FUNC_NAME);
} else if (0 != (assert & ~(MPI_MODE_NOCHECK))) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME);
} else if (0 != (ompi_win_get_mode(win) & OMPI_WIN_ACCESS_EPOCH)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
} else if (! ompi_win_allow_locks(win)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
}

59
ompi/mpi/c/win_lock_all.c Обычный файл
Просмотреть файл

@ -0,0 +1,59 @@
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. 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$
*/
#include "ompi_config.h"
#include <stdio.h>
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#include "ompi/mca/osc/osc.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_lock_all = PMPI_Win_lock_all
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_lock_all";
int MPI_Win_lock_all(int assert, MPI_Win win)
{
int rc;
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
} else if (0 != (assert & ~(MPI_MODE_NOCHECK))) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME);
} else if (! ompi_win_allow_locks(win)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
}
}
OPAL_CR_ENTER_LIBRARY();
rc = win->w_osc_module->osc_lock_all(assert, win);
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
}

Просмотреть файл

@ -48,8 +48,6 @@ int MPI_Win_post(MPI_Group group, int assert, MPI_Win win)
} else if (0 != (assert & ~(MPI_MODE_NOCHECK | MPI_MODE_NOSTORE |
MPI_MODE_NOPUT))) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME);
} else if (0 != (ompi_win_get_mode(win) & OMPI_WIN_EXPOSE_EPOCH)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RMA_SYNC, FUNC_NAME);
}
}

49
ompi/mpi/c/win_set_info.c Обычный файл
Просмотреть файл

@ -0,0 +1,49 @@
/*
* Copyright (c) 2013 Sandia National Laboratories. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/win/win.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Win_set_info = PMPI_Win_set_info
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Win_set_info";
int MPI_Win_set_info(MPI_Win win, MPI_Info info)
{
int ret;
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (ompi_win_invalid(win)) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
}
if (NULL == info || MPI_INFO_NULL == info ||
ompi_info_is_freed(info)) {
return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_INFO, FUNC_NAME);
}
}
OPAL_CR_ENTER_LIBRARY();
ret = win->w_osc_module->osc_set_info(win, info);
OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше