From b1d24240135d17527c4874e9154e6077b778e61f Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Sat, 28 Jan 2006 15:38:37 +0000 Subject: [PATCH] Merge in present work on the MPI-2 onesided chapter. The current code is not complete, but stable enough that it will have no impact on general development, so into the trunk it goes. Changes in this commit include: - Remove the --with option for disabling MPI-2 onesided support. It complicated code, and has no real reason for existing - add a framework osc (OneSided Communication) for encapsulating all the MPI-2 onesided functionality - Modify the MPI interface functions for the MPI-2 onesided chapter to properly call the underlying framework and do the required error checking - Created an osc component pt2pt, which is layered over the BML/BTL for communication (although it also uses the PML for long message transfers). Currently, all support functions, all communication functions (Put, Get, Accumulate), and the Fence synchronization function are implemented. The PWSC active synchronization functions and Lock/Unlock passive synchronization functions are still not implemented This commit was SVN r8836. --- config/ompi_configure_options.m4 | 55 -- include/mpi.h.in | 44 +- include/mpif.h.in | 14 +- ompi/attribute/attribute.c | 6 - ompi/attribute/attribute.h | 6 - ompi/attribute/attribute_predefined.c | 8 - ompi/errhandler/errhandler.c | 10 - ompi/errhandler/errhandler.h | 2 - ompi/errhandler/errhandler_invoke.c | 4 - ompi/errhandler/errhandler_predefined.c | 4 - ompi/errhandler/errhandler_predefined.h | 4 - ompi/info/info.c | 61 ++ ompi/info/info.h | 34 + ompi/mca/btl/btl.h | 9 +- ompi/mca/osc/Makefile.am | 39 ++ ompi/mca/osc/base/Makefile.am | 23 + ompi/mca/osc/base/base.h | 56 ++ ompi/mca/osc/base/osc_base_close.c | 59 ++ ompi/mca/osc/base/osc_base_init.c | 61 ++ ompi/mca/osc/base/osc_base_open.c | 98 +++ ompi/mca/osc/osc.h | 176 +++++ ompi/mca/osc/pt2pt/Makefile.am | 60 ++ ompi/mca/osc/pt2pt/configure.params | 18 + ompi/mca/osc/pt2pt/osc_pt2pt.c | 79 +++ ompi/mca/osc/pt2pt/osc_pt2pt.h | 209 ++++++ ompi/mca/osc/pt2pt/osc_pt2pt_comm.c | 127 ++++ ompi/mca/osc/pt2pt/osc_pt2pt_component.c | 385 +++++++++++ ompi/mca/osc/pt2pt/osc_pt2pt_data_move.c | 708 +++++++++++++++++++++ ompi/mca/osc/pt2pt/osc_pt2pt_data_move.h | 51 ++ ompi/mca/osc/pt2pt/osc_pt2pt_header.h | 135 ++++ ompi/mca/osc/pt2pt/osc_pt2pt_longreq.c | 26 + ompi/mca/osc/pt2pt/osc_pt2pt_longreq.h | 75 +++ ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.c | 97 +++ ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.h | 82 +++ ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.c | 80 +++ ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.h | 142 +++++ ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.c | 89 +++ ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.h | 177 ++++++ ompi/mca/osc/pt2pt/osc_pt2pt_sync.c | 233 +++++++ ompi/mpi/c/Makefile.am | 6 +- ompi/mpi/c/accumulate.c | 39 +- ompi/mpi/c/attr_fn.c | 2 - ompi/mpi/c/get.c | 30 +- ompi/mpi/c/profile/Makefile.am | 6 +- ompi/mpi/c/put.c | 30 +- ompi/mpi/c/win_complete.c | 17 +- ompi/mpi/c/win_create.c | 45 +- ompi/mpi/c/win_fence.c | 20 +- ompi/mpi/c/win_free.c | 19 +- ompi/mpi/c/win_get_attr.c | 12 + ompi/mpi/c/win_get_group.c | 20 +- ompi/mpi/c/win_get_name.c | 20 +- ompi/mpi/c/win_lock.c | 24 +- ompi/mpi/c/win_post.c | 20 +- ompi/mpi/c/win_set_attr.c | 2 +- ompi/mpi/c/win_set_errhandler.c | 4 - ompi/mpi/c/win_set_name.c | 20 +- ompi/mpi/c/win_start.c | 19 +- ompi/mpi/c/win_test.c | 17 +- ompi/mpi/c/win_unlock.c | 19 +- ompi/mpi/c/win_wait.c | 17 +- ompi/mpi/cxx/mpicxx.cc | 2 - ompi/mpi/cxx/win.h | 2 - ompi/mpi/cxx/win_inln.h | 2 - ompi/mpi/f77/Makefile.am | 6 +- ompi/mpi/f77/attr_fn_f.c | 6 - ompi/mpi/f77/profile/Makefile.am | 6 +- ompi/mpi/f77/win_create_keyval_f.c | 4 +- ompi/mpi/f90/Makefile.am | 7 +- ompi/request/request.h | 1 + ompi/runtime/ompi_mpi_finalize.c | 12 + ompi/runtime/ompi_mpi_init.c | 19 + ompi/tools/ompi_info/components.cc | 6 + ompi/tools/ompi_info/ompi_info.cc | 1 + ompi/win/win.c | 189 ++++++ ompi/win/win.h | 80 ++- 76 files changed, 4012 insertions(+), 285 deletions(-) create mode 100644 ompi/mca/osc/Makefile.am create mode 100644 ompi/mca/osc/base/Makefile.am create mode 100644 ompi/mca/osc/base/base.h create mode 100644 ompi/mca/osc/base/osc_base_close.c create mode 100644 ompi/mca/osc/base/osc_base_init.c create mode 100644 ompi/mca/osc/base/osc_base_open.c create mode 100644 ompi/mca/osc/osc.h create mode 100644 ompi/mca/osc/pt2pt/Makefile.am create mode 100644 ompi/mca/osc/pt2pt/configure.params create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_comm.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_component.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_data_move.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_data_move.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_header.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_longreq.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_longreq.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.c create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.h create mode 100644 ompi/mca/osc/pt2pt/osc_pt2pt_sync.c diff --git a/config/ompi_configure_options.m4 b/config/ompi_configure_options.m4 index 0294627300..b7a4300f3c 100644 --- a/config/ompi_configure_options.m4 +++ b/config/ompi_configure_options.m4 @@ -317,61 +317,6 @@ fi AM_CONDITIONAL(WANT_DEPRECATED_EXECUTABLE_NAMES, test "$WANT_DEN" = "1") - -# -# Do we want to build MPI-2 one-sided functions? Currently, they are -# empty shell functions that simply invoke an MPI exception (i.e., a -# run-time error vs. a compile/link-time error). -# -AC_MSG_CHECKING([if want MPI-2 one-sided empty shell functions]) -AC_ARG_ENABLE(mpi2-one-sided, - AC_HELP_STRING([--enable-mpi2-one-sided], - [Do we want to build empty shell functions for the MPI-2 one-sided functionality? (these functions are currently unimplemented -- all they do is invoke a run-time MPI exception)])) -if test "$enable_mpi2_one_sided" = "yes"; then - mpi2_one_sided=yes - value=1 - - # Need to set values that will be in mpif.h - - OMPI_F77_WIN_ATTR_KEYS="integer MPI_WIN_BASE, MPI_WIN_SIZE, MPI_WIN_DISP_UNIT" - OMPI_F77_WIN_ATTR_BASE_VALUE="parameter (MPI_WIN_BASE=7)" - OMPI_F77_WIN_ATTR_SIZE_VALUE="parameter (MPI_WIN_SIZE=8)" - OMPI_F77_WIN_ATTR_DISP_VALUE="parameter (MPI_WIN_DISP_UNIT=9)" - OMPI_F77_WIN_NULL_COPY_FN="external MPI_WIN_NULL_COPY_FN" - OMPI_F77_WIN_NULL_DELETE_FN="external MPI_WIN_NULL_DELETE_FN" - OMPI_F77_WIN_DUP_FN="external MPI_WIN_DUP_FN" - OMPI_F77_WIN_NULL="integer MPI_WIN_NULL" - OMPI_F77_WIN_NULL_VALUE="parameter (MPI_WIN_NULL=0)" -else - mpi2_one_sided=no - value=0 - - # Many values in mpif.h are now blank - - OMPI_F77_WIN_ATTR_KEYS= - OMPI_F77_WIN_ATTR_BASE_VALUE= - OMPI_F77_WIN_ATTR_SIZE_VALUE= - OMPI_F77_WIN_ATTR_DISP_VALUE= - OMPI_F77_WIN_NULL_COPY_FN= - OMPI_F77_WIN_NULL_DELETE_FN= - OMPI_F77_WIN_DUP_FN= - OMPI_F77_WIN_NULL= - OMPI_F77_WIN_NULL_VALUE= -fi -AC_MSG_RESULT([$mpi2_one_sided]) -AC_DEFINE_UNQUOTED(OMPI_WANT_MPI2_ONE_SIDED, $value, - [Do we want the MPI-2 one-sided functions to be compiled in or left out altogether (i.e., unlinkable)?]) -AM_CONDITIONAL(WANT_MPI2_ONE_SIDED, test "$mpi2_one_sided" = "yes") -AC_SUBST(OMPI_F77_WIN_ATTR_KEYS) -AC_SUBST(OMPI_F77_WIN_ATTR_BASE_VALUE) -AC_SUBST(OMPI_F77_WIN_ATTR_SIZE_VALUE) -AC_SUBST(OMPI_F77_WIN_ATTR_DISP_VALUE) -AC_SUBST(OMPI_F77_WIN_NULL_COPY_FN) -AC_SUBST(OMPI_F77_WIN_NULL_DELETE_FN) -AC_SUBST(OMPI_F77_WIN_DUP_FN) -AC_SUBST(OMPI_F77_WIN_NULL) -AC_SUBST(OMPI_F77_WIN_NULL_VALUE) - # # What is the max array rank that we want to support in the f90 bindings? # diff --git a/include/mpi.h.in b/include/mpi.h.in index c5b55003f8..3324463b14 100644 --- a/include/mpi.h.in +++ b/include/mpi.h.in @@ -27,10 +27,6 @@ ompi_config.h must be included before all other files, so this should be good enough */ -/* Do we want the MPI-2 one-sided functions to be compiled in or left out - altogether (i.e., unlinkable)? */ -#undef OMPI_WANT_MPI2_ONE_SIDED - /* Whether we have FORTRAN INTEGER*1 or not */ #undef OMPI_HAVE_FORTRAN_INTEGER1 @@ -150,9 +146,7 @@ typedef struct ompi_info_t *MPI_Info; typedef struct ompi_op_t *MPI_Op; typedef struct ompi_request_t *MPI_Request; typedef struct ompi_status_public_t MPI_Status; -#if OMPI_WANT_MPI2_ONE_SIDED typedef struct ompi_win_t *MPI_Win; -#endif /* * MPI_Status @@ -177,9 +171,7 @@ typedef int (MPI_Datarep_conversion_function)(void *, MPI_Datatype, int, void *, MPI_Offset, void *); typedef void (MPI_Comm_errhandler_fn)(MPI_Comm *, int *, ...); typedef void (MPI_File_errhandler_fn)(MPI_File *, int *, ...); -#if OMPI_WANT_MPI2_ONE_SIDED typedef void (MPI_Win_errhandler_fn)(MPI_Win *, int *, ...); -#endif typedef void (MPI_Handler_function)(MPI_Comm *, int *, ...); typedef void (MPI_User_function)(void *, void *, int *, MPI_Datatype *); typedef int (MPI_Comm_copy_attr_function)(MPI_Comm, int, void *, @@ -189,11 +181,9 @@ typedef int (MPI_Type_copy_attr_function)(MPI_Datatype, int, void *, void *, void *, int *); typedef int (MPI_Type_delete_attr_function)(MPI_Datatype, int, void *, void *); -#if OMPI_WANT_MPI2_ONE_SIDED typedef int (MPI_Win_copy_attr_function)(MPI_Win, int, void *, void *, void *, int *); typedef int (MPI_Win_delete_attr_function)(MPI_Win, int, void *, void *); -#endif typedef int (MPI_Grequest_query_function)(void *, MPI_Status *); typedef int (MPI_Grequest_free_function)(void *); typedef int (MPI_Grequest_cancel_function)(void *, int); @@ -256,6 +246,18 @@ typedef int (MPI_Grequest_cancel_function)(void *, int); #define MPI_MAX_DATAREP_STRING 128 +/* + * MPI-2 One-Sided Communications asserts + */ +#define MPI_MODE_NOCHECK 1 +#define MPI_MODE_NOPRECEDE 2 +#define MPI_MODE_NOPUT 4 +#define MPI_MODE_NOSTORE 8 +#define MPI_MODE_NOSUCCEED 16 + +#define MPI_LOCK_EXCLUSIVE 1 +#define MPI_LOCK_SHARED 2 + /* * Predefined attribute keyvals @@ -406,9 +408,7 @@ enum { #define MPI_OP_NULL (&ompi_mpi_op_null) #define MPI_ERRHANDLER_NULL (&ompi_mpi_errhandler_null) #define MPI_INFO_NULL (&ompi_mpi_info_null) -#if OMPI_WANT_MPI2_ONE_SIDED #define MPI_WIN_NULL ((MPI_Win) 0) -#endif #define MPI_FILE_NULL (&ompi_mpi_file_null) #define MPI_STATUS_IGNORE ((MPI_Status *) 0) @@ -443,12 +443,10 @@ enum { #define MPI_COMM_NULL_COPY_FN OMPI_C_MPI_COMM_NULL_COPY_FN #define MPI_COMM_DUP_FN OMPI_C_MPI_COMM_DUP_FN -#if OMPI_WANT_MPI2_ONE_SIDED #define MPI_WIN_NULL_DELETE_FN OMPI_C_MPI_WIN_NULL_DELETE_FN #define MPI_WIN_NULL_COPY_FN OMPI_C_MPI_WIN_NULL_COPY_FN #define MPI_WIN_DUP_FN OMPI_C_MPI_WIN_DUP_FN #endif -#endif OMPI_DECLSPEC int OMPI_C_MPI_TYPE_NULL_DELETE_FN( MPI_Datatype datatype, int type_keyval, @@ -494,7 +492,6 @@ OMPI_DECLSPEC int OMPI_C_MPI_DUP_FN( MPI_Comm comm, int comm_keyval, void* attribute_val_in, void* attribute_val_out, int* flag ); -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_DECLSPEC int OMPI_C_MPI_WIN_NULL_DELETE_FN( MPI_Win window, int win_keyval, void* attribute_val_out, @@ -509,7 +506,6 @@ OMPI_DECLSPEC int OMPI_C_MPI_WIN_DUP_FN( MPI_Win window, int win_keyval, void* attribute_val_in, void* attribute_val_out, int* flag ); -#endif /* @@ -722,11 +718,9 @@ OMPI_DECLSPEC extern MPI_Fint *MPI_F_STATUSES_IGNORE; */ OMPI_DECLSPEC int MPI_Abort(MPI_Comm comm, int errorcode); -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_DECLSPEC int MPI_Accumulate(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); -#endif OMPI_DECLSPEC int MPI_Add_error_class(int *errorclass); OMPI_DECLSPEC int MPI_Add_error_code(int errorclass, int *errorcode); OMPI_DECLSPEC int MPI_Add_error_string(int errorcode, char *string); @@ -933,12 +927,10 @@ OMPI_DECLSPEC int MPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendty OMPI_DECLSPEC int MPI_Get_address(void *location, MPI_Aint *address); OMPI_DECLSPEC int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count); OMPI_DECLSPEC int MPI_Get_elements(MPI_Status *status, MPI_Datatype datatype, int *count); -#if OMPI_WANT_MPI2_ONE_SIDED 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); -#endif OMPI_DECLSPEC int MPI_Get_processor_name(char *name, int *resultlen); OMPI_DECLSPEC int MPI_Get_version(int *version, int *subversion); OMPI_DECLSPEC int MPI_Graph_create(MPI_Comm comm_old, int nnodes, int *index, @@ -1036,11 +1028,9 @@ OMPI_DECLSPEC int MPI_Pcontrol(const int level, ...); OMPI_DECLSPEC int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status); OMPI_DECLSPEC int MPI_Publish_name(char *service_name, MPI_Info info, char *port_name); -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_DECLSPEC int MPI_Put(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); -#endif OMPI_DECLSPEC int MPI_Query_thread(int *provided); OMPI_DECLSPEC int MPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request); @@ -1200,7 +1190,6 @@ 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); -#if OMPI_WANT_MPI2_ONE_SIDED 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); @@ -1230,7 +1219,6 @@ OMPI_DECLSPEC int MPI_Win_start(MPI_Group group, int assert, 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_wait(MPI_Win win); -#endif OMPI_DECLSPEC double MPI_Wtick(void); OMPI_DECLSPEC double MPI_Wtime(void); @@ -1239,11 +1227,9 @@ OMPI_DECLSPEC double MPI_Wtime(void); * Profiling MPI API */ OMPI_DECLSPEC int PMPI_Abort(MPI_Comm comm, int errorcode); -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_DECLSPEC int PMPI_Accumulate(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); -#endif OMPI_DECLSPEC int PMPI_Add_error_class(int *errorclass); OMPI_DECLSPEC int PMPI_Add_error_code(int errorclass, int *errorcode); OMPI_DECLSPEC int PMPI_Add_error_string(int errorcode, char *string); @@ -1448,12 +1434,10 @@ OMPI_DECLSPEC int PMPI_Get_address(void *location, MPI_Aint *address); OMPI_DECLSPEC int PMPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count); OMPI_DECLSPEC int PMPI_Get_elements(MPI_Status *status, MPI_Datatype datatype, int *count); -#if OMPI_WANT_MPI2_ONE_SIDED 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); -#endif OMPI_DECLSPEC int PMPI_Get_processor_name(char *name, int *resultlen); OMPI_DECLSPEC int PMPI_Get_version(int *version, int *subversion); OMPI_DECLSPEC int PMPI_Graph_create(MPI_Comm comm_old, int nnodes, int *index, @@ -1552,11 +1536,9 @@ OMPI_DECLSPEC int PMPI_Pcontrol(const int level, ...); OMPI_DECLSPEC int PMPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status); OMPI_DECLSPEC int PMPI_Publish_name(char *service_name, MPI_Info info, char *port_name); -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_DECLSPEC int PMPI_Put(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); -#endif OMPI_DECLSPEC int PMPI_Query_thread(int *provided); OMPI_DECLSPEC int PMPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request); @@ -1716,7 +1698,6 @@ 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); -#if OMPI_WANT_MPI2_ONE_SIDED 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); @@ -1746,7 +1727,6 @@ OMPI_DECLSPEC int PMPI_Win_start(MPI_Group group, int assert, 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_wait(MPI_Win win); -#endif OMPI_DECLSPEC double PMPI_Wtick(void); OMPI_DECLSPEC double PMPI_Wtime(void); diff --git a/include/mpif.h.in b/include/mpif.h.in index 8bd46b4752..e7487544c5 100644 --- a/include/mpif.h.in +++ b/include/mpif.h.in @@ -103,7 +103,7 @@ integer MPI_MODE_DELETE_ON_CLOSE, MPI_MODE_UNIQUE_OPEN integer MPI_MODE_EXCL, MPI_MODE_APPEND, MPI_MODE_SEQUENTIAL integer MPI_DISPLACEMENT_CURRENT - @OMPI_F77_WIN_ATTR_KEYS@ + integer MPI_WIN_BASE, MPI_WIN_SIZE, MPI_WIN_DISP_UNIT parameter (MPI_ANY_SOURCE=-1) parameter (MPI_ANY_TAG=-1) @@ -127,9 +127,9 @@ parameter (MPI_APPNUM=4) parameter (MPI_LASTUSEDCODE=5) parameter (MPI_UNIVERSE_SIZE=6) - @OMPI_F77_WIN_ATTR_BASE_VALUE@ - @OMPI_F77_WIN_ATTR_SIZE_VALUE@ - @OMPI_F77_WIN_ATTR_DISP_VALUE@ + parameter (MPI_WIN_BASE=6) + parameter (MPI_WIN_SIZE=7) + parameter (MPI_WIN_DISP_UNIT=8) parameter (IMPI_CLIENT_SIZE=10) parameter (IMPI_CLIENT_COLOR=11) parameter (IMPI_HOST_SIZE=12) @@ -442,9 +442,9 @@ external MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN external MPI_TYPE_NULL_COPY_FN, MPI_TYPE_NULL_DELETE_FN external MPI_DUP_FN, MPI_COMM_DUP_FN, MPI_TYPE_DUP_FN - @OMPI_F77_WIN_NULL_COPY_FN@ - @OMPI_F77_WIN_NULL_DELETE_FN@ - @OMPI_F77_WIN_DUP_FN@ + external MPI_WIN_NULL_COPY_FN + external MPI_WIN_NULL_DELETE_FN + external MPI_WIN_DUP_FN ! ! double precision functions ! diff --git a/ompi/attribute/attribute.c b/ompi/attribute/attribute.c index 9fcbdc9335..bdb9d596ab 100644 --- a/ompi/attribute/attribute.c +++ b/ompi/attribute/attribute.c @@ -645,11 +645,9 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object, DELETE_ATTR_CALLBACKS(communicator, attr, key_item); break; -#if OMPI_WANT_MPI2_ONE_SIDED case WIN_ATTR: DELETE_ATTR_CALLBACKS(win, attr, key_item); break; -#endif case TYPE_ATTR: DELETE_ATTR_CALLBACKS(datatype, attr, key_item); @@ -865,13 +863,11 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, old_attr, new_attr); break; -#if OMPI_WANT_MPI2_ONE_SIDED case WIN_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(win, old_object, hash_value, old_attr, new_attr); break; -#endif } /* Hang this off the object's key hash */ @@ -1028,11 +1024,9 @@ static int set_value(ompi_attribute_type_t type, void *object, DELETE_ATTR_CALLBACKS(communicator, old_attr, key_item); break; -#if OMPI_WANT_MPI2_ONE_SIDED case WIN_ATTR: DELETE_ATTR_CALLBACKS(win, old_attr, key_item); break; -#endif case TYPE_ATTR: DELETE_ATTR_CALLBACKS(datatype, old_attr, key_item); diff --git a/ompi/attribute/attribute.h b/ompi/attribute/attribute.h index afd0d0ffb2..d16fb818ca 100644 --- a/ompi/attribute/attribute.h +++ b/ompi/attribute/attribute.h @@ -53,9 +53,7 @@ enum ompi_attribute_type_t { with 1 so that we can have it initialized to 0 using memset in the constructor */ TYPE_ATTR /**< The attribute belongs to datatype object */ -#if OMPI_WANT_MPI2_ONE_SIDED , WIN_ATTR /**< The attribute belongs to a win object */ -#endif }; typedef enum ompi_attribute_type_t ompi_attribute_type_t; @@ -101,15 +99,11 @@ typedef void (ompi_mpi2_fortran_delete_attr_function)(MPI_Fint *obj, union ompi_attribute_fn_ptr_union_t { MPI_Comm_delete_attr_function *attr_communicator_delete_fn; MPI_Type_delete_attr_function *attr_datatype_delete_fn; -#if OMPI_WANT_MPI2_ONE_SIDED MPI_Win_delete_attr_function *attr_win_delete_fn; -#endif MPI_Comm_copy_attr_function *attr_communicator_copy_fn; MPI_Type_copy_attr_function *attr_datatype_copy_fn; -#if OMPI_WANT_MPI2_ONE_SIDED MPI_Win_copy_attr_function *attr_win_copy_fn; -#endif /* For Fortran old MPI-1 callback functions */ diff --git a/ompi/attribute/attribute_predefined.c b/ompi/attribute/attribute_predefined.c index 3402c7ab5b..d12b1f7ed5 100644 --- a/ompi/attribute/attribute_predefined.c +++ b/ompi/attribute/attribute_predefined.c @@ -96,10 +96,8 @@ * Private functions */ static int create_comm(int target_keyval, bool want_inherit); -#if OMPI_WANT_MPI2_ONE_SIDED /* JMS for when we implement windows */ static int create_win(int target_keyval); -#endif static int set_f(int keyval, MPI_Fint value); @@ -123,12 +121,9 @@ int ompi_attr_create_predefined(void) OMPI_SUCCESS != (ret = create_comm(MPI_APPNUM, true)) || OMPI_SUCCESS != (ret = create_comm(MPI_LASTUSEDCODE, false)) || OMPI_SUCCESS != (ret = create_comm(MPI_UNIVERSE_SIZE, true)) || -#if OMPI_WANT_MPI2_ONE_SIDED - /* JMS for when we implement windows */ 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)) || -#endif #if 0 /* JMS For when we implement IMPI */ OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_CLIENT_SIZE, true)) || @@ -314,8 +309,6 @@ static int create_comm(int target_keyval, bool want_inherit) } -#if OMPI_WANT_MPI2_ONE_SIDED -/* JMS for when we implement windows */ static int create_win(int target_keyval) { int err; @@ -336,7 +329,6 @@ static int create_win(int target_keyval) } return OMPI_SUCCESS; } -#endif static int set_f(int keyval, MPI_Fint value) diff --git a/ompi/errhandler/errhandler.c b/ompi/errhandler/errhandler.c index 83e9b8ef89..59c1cb76a6 100644 --- a/ompi/errhandler/errhandler.c +++ b/ompi/errhandler/errhandler.c @@ -80,9 +80,7 @@ int ompi_errhandler_init(void) ompi_mpi_errhandler_null.eh_fortran_function = false; ompi_mpi_errhandler_null.eh_comm_fn = NULL; ompi_mpi_errhandler_null.eh_file_fn = NULL; -#if OMPI_WANT_MPI2_ONE_SIDED ompi_mpi_errhandler_null.eh_win_fn = NULL ; -#endif ompi_mpi_errhandler_null.eh_fort_fn = NULL; strncpy (ompi_mpi_errhandler_null.eh_name, "MPI_ERRHANDLER_NULL", strlen("MPI_ERRHANDLER_NULL")+1 ); @@ -95,9 +93,7 @@ int ompi_errhandler_init(void) ompi_mpi_errors_are_fatal.eh_fortran_function = false; ompi_mpi_errors_are_fatal.eh_comm_fn = ompi_mpi_errors_are_fatal_comm_handler; ompi_mpi_errors_are_fatal.eh_file_fn = ompi_mpi_errors_are_fatal_file_handler; -#if OMPI_WANT_MPI2_ONE_SIDED ompi_mpi_errors_are_fatal.eh_win_fn = ompi_mpi_errors_are_fatal_win_handler ; -#endif ompi_mpi_errors_are_fatal.eh_fort_fn = NULL; strncpy (ompi_mpi_errors_are_fatal.eh_name, "MPI_ERRORS_ARE_FATAL", strlen("MPI_ERRORS_ARE_FATAL")+1 ); @@ -109,9 +105,7 @@ int ompi_errhandler_init(void) ompi_mpi_errors_return.eh_fortran_function = false; ompi_mpi_errors_return.eh_comm_fn = ompi_mpi_errors_return_comm_handler; ompi_mpi_errors_return.eh_file_fn = ompi_mpi_errors_return_file_handler; -#if OMPI_WANT_MPI2_ONE_SIDED ompi_mpi_errors_return.eh_win_fn = ompi_mpi_errors_return_win_handler; -#endif ompi_mpi_errors_return.eh_fort_fn = NULL; strncpy (ompi_mpi_errors_return.eh_name, "MPI_ERRORS_RETURN", strlen("MPI_ERRORS_RETURN")+1 ); @@ -196,11 +190,9 @@ ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type, case (OMPI_ERRHANDLER_TYPE_FILE): new_errhandler->eh_file_fn = (MPI_File_errhandler_fn *)func; break; -#if OMPI_WANT_MPI2_ONE_SIDED case (OMPI_ERRHANDLER_TYPE_WIN): new_errhandler->eh_win_fn = (MPI_Win_errhandler_fn *)func; break; -#endif default: break; } @@ -237,9 +229,7 @@ static void ompi_errhandler_construct(ompi_errhandler_t *new_errhandler) new_errhandler->eh_fortran_function = false; new_errhandler->eh_comm_fn = NULL; -#if OMPI_WANT_MPI2_ONE_SIDED new_errhandler->eh_win_fn = NULL; -#endif new_errhandler->eh_file_fn = NULL; new_errhandler->eh_fort_fn = NULL; diff --git a/ompi/errhandler/errhandler.h b/ompi/errhandler/errhandler.h index a7a102bd89..6825df6c66 100644 --- a/ompi/errhandler/errhandler.h +++ b/ompi/errhandler/errhandler.h @@ -83,9 +83,7 @@ struct ompi_errhandler_t { /* Function pointers */ MPI_Comm_errhandler_fn *eh_comm_fn; MPI_File_errhandler_fn *eh_file_fn; -#if OMPI_WANT_MPI2_ONE_SIDED MPI_Win_errhandler_fn *eh_win_fn; -#endif ompi_errhandler_fortran_handler_fn_t *eh_fort_fn; /* index in Fortran <-> C translation array */ diff --git a/ompi/errhandler/errhandler_invoke.c b/ompi/errhandler/errhandler_invoke.c index ef0ebe639c..447002b56d 100644 --- a/ompi/errhandler/errhandler_invoke.c +++ b/ompi/errhandler/errhandler_invoke.c @@ -30,9 +30,7 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object, { MPI_Fint fortran_handle, fortran_err_code = OMPI_INT_2_FINT(err_code); ompi_communicator_t *comm; -#if OMPI_WANT_MPI2_ONE_SIDED ompi_win_t *win; -#endif ompi_file_t *file; /* If we got no errorhandler, then just invoke errors_abort */ @@ -54,7 +52,6 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object, } break; -#if OMPI_WANT_MPI2_ONE_SIDED case OMPI_ERRHANDLER_TYPE_WIN: win = (ompi_win_t *) mpi_object; if (errhandler->eh_fortran_function) { @@ -64,7 +61,6 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object, errhandler->eh_win_fn(&win, &err_code, message, NULL); } break; -#endif case OMPI_ERRHANDLER_TYPE_FILE: file = (ompi_file_t *) mpi_object; diff --git a/ompi/errhandler/errhandler_predefined.c b/ompi/errhandler/errhandler_predefined.c index 0442587381..f6fb85b5dd 100644 --- a/ompi/errhandler/errhandler_predefined.c +++ b/ompi/errhandler/errhandler_predefined.c @@ -78,7 +78,6 @@ void ompi_mpi_errors_are_fatal_file_handler(struct ompi_file_t **file, } -#if OMPI_WANT_MPI2_ONE_SIDED void ompi_mpi_errors_are_fatal_win_handler(struct ompi_win_t **win, int *error_code, ...) { @@ -95,7 +94,6 @@ void ompi_mpi_errors_are_fatal_win_handler(struct ompi_win_t **win, } backend_fatal("win", abort_comm, name, error_code, arglist); } -#endif void ompi_mpi_errors_return_comm_handler(struct ompi_communicator_t **comm, int *error_code, ...) @@ -121,7 +119,6 @@ void ompi_mpi_errors_return_file_handler(struct ompi_file_t **file, } -#if OMPI_WANT_MPI2_ONE_SIDED void ompi_mpi_errors_return_win_handler(struct ompi_win_t **win, int *error_code, ...) { @@ -132,7 +129,6 @@ void ompi_mpi_errors_return_win_handler(struct ompi_win_t **win, va_start(arglist, error_code); va_end(arglist); } -#endif static void out(char *str, char *arg) diff --git a/ompi/errhandler/errhandler_predefined.h b/ompi/errhandler/errhandler_predefined.h index 1c6e809abd..d94fcf407d 100644 --- a/ompi/errhandler/errhandler_predefined.h +++ b/ompi/errhandler/errhandler_predefined.h @@ -27,10 +27,8 @@ void ompi_mpi_errors_are_fatal_comm_handler(struct ompi_communicator_t **comm, int *error_code, ...); void ompi_mpi_errors_are_fatal_file_handler(struct ompi_file_t **file, int *error_code, ...); -#if OMPI_WANT_MPI2_ONE_SIDED void ompi_mpi_errors_are_fatal_win_handler(struct ompi_win_t **win, int *error_code, ...); -#endif /** * Handler function for MPI_ERRORS_RETURN @@ -39,10 +37,8 @@ void ompi_mpi_errors_return_comm_handler(struct ompi_communicator_t **comm, int *error_code, ...); void ompi_mpi_errors_return_file_handler(struct ompi_file_t **file, int *error_code, ...); -#if OMPI_WANT_MPI2_ONE_SIDED void ompi_mpi_errors_return_win_handler(struct ompi_win_t **win, int *error_code, ...); -#endif #endif /* OMPI_ERRHANDLER_PREDEFINED_H */ diff --git a/ompi/info/info.c b/ompi/info/info.c index ceeeea8ffe..eb48924adf 100644 --- a/ompi/info/info.c +++ b/ompi/info/info.c @@ -18,6 +18,15 @@ #include "ompi_config.h" +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + #include "ompi/include/constants.h" #include "info/info.h" #include "ompi/runtime/params.h" @@ -453,3 +462,55 @@ static ompi_info_entry_t *info_find_key (ompi_info_t *info, char *key) } return NULL; } + + +int +ompi_info_value_to_int(char *value, int *interp) +{ + long tmp; + char *endp; + + if (NULL == value || '\0' == value[0]) return OMPI_ERR_BAD_PARAM; + + errno = 0; + tmp = strtol(value, &endp, 10); + /* we found something not a number */ + if (*endp != '\0') return OMPI_ERR_BAD_PARAM; + /* underflow */ + if (tmp == 0 && errno == EINVAL) return OMPI_ERR_BAD_PARAM; + + *interp = (int) tmp; + + return OMPI_SUCCESS; +} + + +int +ompi_info_value_to_bool(char *value, bool *interp) +{ + int tmp; + + /* idiot case */ + if (NULL == value || NULL == interp) return OMPI_ERR_BAD_PARAM; + + /* is it true / false? */ + if (0 == strcmp(value, "true")) { + *interp = true; + return OMPI_SUCCESS; + } else if (0 == strcmp(value, "false")) { + *interp = false; + return OMPI_SUCCESS; + + /* is it a number? */ + } else if (OMPI_SUCCESS == ompi_info_value_to_int(value, &tmp)) { + if (tmp == 0) { + *interp = false; + } else { + *interp = true; + } + return OMPI_SUCCESS; + } + + return OMPI_ERR_BAD_PARAM; +} + diff --git a/ompi/info/info.h b/ompi/info/info.h index 9c3bb968ee..82abf0301a 100644 --- a/ompi/info/info.h +++ b/ompi/info/info.h @@ -208,6 +208,40 @@ extern "C" { * @retval MPI_ERR_ARG */ int ompi_info_get_nthkey (ompi_info_t *info, int n, char *key); + + int ompi_info_value_to_int(char *value, int *interp); + + /** + * Convert value string to boolean + * + * Convert value string \c value into a boolean, using the + * interpretation rules specified in MPI-2 Section 4.10. The + * strings "true", "false", and integer numbers can be converted + * into booleans. All others will return \c OMPI_ERR_BAD_PARAM + * + * @param value Value string for info key to interpret + * @param interp returned interpretation of the value key + * + * @retval OMPI_SUCCESS string was successfully interpreted + * @retval OMPI_ERR_BAD_PARAM string was not able to be interpreted + */ + int ompi_info_value_to_bool(char *value, bool *interp); + + /** + * Convert value string to integer + * + * Convert value string \c value into a integer, using the + * interpretation rules specified in MPI-2 Section 4.10. + * All others will return \c OMPI_ERR_BAD_PARAM + * + * @param value Value string for info key to interpret + * @param interp returned interpretation of the value key + * + * @retval OMPI_SUCCESS string was successfully interpreted + * @retval OMPI_ERR_BAD_PARAM string was not able to be interpreted + */ + int ompi_info_value_to_bool(char *value, bool *interp); + #if defined(c_plusplus) || defined(__cplusplus) } #endif diff --git a/ompi/mca/btl/btl.h b/ompi/mca/btl/btl.h index 9fac59e5e1..33b3cb91e9 100644 --- a/ompi/mca/btl/btl.h +++ b/ompi/mca/btl/btl.h @@ -129,10 +129,11 @@ struct ompi_proc_t; typedef uint8_t mca_btl_base_tag_t; /* reserved tag values */ -#define MCA_BTL_TAG_BTL 0 -#define MCA_BTL_TAG_PML 1 -#define MCA_BTL_TAG_USR 2 -#define MCA_BTL_TAG_MAX 255 /* 1 + highest allowed tag num */ +#define MCA_BTL_TAG_BTL 0 +#define MCA_BTL_TAG_PML 1 +#define MCA_BTL_TAG_OSC_PT2PT 2 +#define MCA_BTL_TAG_USR 3 +#define MCA_BTL_TAG_MAX 255 /* 1 + highest allowed tag num */ /* prefered protocol */ #define MCA_BTL_FLAGS_SEND 0x1 diff --git a/ompi/mca/osc/Makefile.am b/ompi/mca/osc/Makefile.am new file mode 100644 index 0000000000..db310bebd2 --- /dev/null +++ b/ompi/mca/osc/Makefile.am @@ -0,0 +1,39 @@ +# +# Copyright (c) 2004-2005 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$ +# + +# main library setup +noinst_LTLIBRARIES = libmca_osc.la +libmca_osc_la_SOURCES = + +# header setup +nobase_ompi_HEADERS = $(headers) +ompidir = $(includedir)/openmpi/ompi/mca/osc + +# local files +headers = osc.h +libmca_osc_la_SOURCES += $(headers) + +# Conditionally install the header files +if WANT_INSTALL_HEADERS +nobase_ompi_HEADERS += $(headers) +endif + +include base/Makefile.am + +distclean-local: + rm -f base/static-components.h diff --git a/ompi/mca/osc/base/Makefile.am b/ompi/mca/osc/base/Makefile.am new file mode 100644 index 0000000000..5cd6544db6 --- /dev/null +++ b/ompi/mca/osc/base/Makefile.am @@ -0,0 +1,23 @@ +# +# 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$ +# + +headers += \ + base/base.h + +libmca_osc_la_SOURCES += \ + base/osc_base_close.c \ + base/osc_base_open.c \ + base/osc_base_init.c diff --git a/ompi/mca/osc/base/base.h b/ompi/mca/osc/base/base.h new file mode 100644 index 0000000000..5ae12a005f --- /dev/null +++ b/ompi/mca/osc/base/base.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University. + * All rights reserved. + * Copyright (c) 2004-2005 The Trustees of the University of Tennessee. + * All rights reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +/** @file: + */ + +#ifndef OMPI_MCA_OSC_BASE_H +#define OMPI_MCA_OSC_BASE_H + +#include "datatype/datatype.h" +#include "info/info.h" +#include "communicator/communicator.h" +#include "win/win.h" +#include "opal/class/opal_list.h" + +/* + * Global functions for MCA overall collective open and close + */ +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + +/* + * function definitions + */ +OMPI_DECLSPEC int ompi_osc_base_open(void); +OMPI_DECLSPEC int ompi_osc_base_find_available(bool enable_progress_threads, + bool enable_mpi_threads); + +OMPI_DECLSPEC int ompi_osc_base_select(ompi_win_t *win, + ompi_info_t *info, + ompi_communicator_t *comm); + +OMPI_DECLSPEC int ompi_osc_base_finalize(void); +OMPI_DECLSPEC int ompi_osc_base_close(void); + + +extern opal_list_t ompi_osc_base_open_components; +extern opal_list_t ompi_osc_base_avail_components; + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif +#endif diff --git a/ompi/mca/osc/base/osc_base_close.c b/ompi/mca/osc/base/osc_base_close.c new file mode 100644 index 0000000000..818f4f2650 --- /dev/null +++ b/ompi/mca/osc/base/osc_base_close.c @@ -0,0 +1,59 @@ +/* + * 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 + +#include "mca/mca.h" +#include "mca/base/base.h" +#include "mca/osc/osc.h" +#include "mca/osc/base/base.h" +#include "opal/class/opal_list.h" + + +int +ompi_osc_base_finalize(void) +{ + opal_list_item_t* item; + + /* Finalize all available modules */ + while (NULL != + (item = opal_list_remove_first(&ompi_osc_base_avail_components))) { + ompi_osc_base_component_t *component = (ompi_osc_base_component_t*) + ((mca_base_component_list_item_t*) item)->cli_component; + component->osc_finalize(); + } + return OMPI_SUCCESS; +} + +int +ompi_osc_base_close(void) +{ + /* close all components not already closed*/ + + /* join the two lists of components */ + opal_list_join(&ompi_osc_base_open_components, + opal_list_get_end(&ompi_osc_base_open_components), + &ompi_osc_base_avail_components); + + mca_base_components_close(0, &ompi_osc_base_open_components, NULL); + + OBJ_DESTRUCT(&ompi_osc_base_open_components); + OBJ_DESTRUCT(&ompi_osc_base_avail_components); + + return OMPI_SUCCESS; +} diff --git a/ompi/mca/osc/base/osc_base_init.c b/ompi/mca/osc/base/osc_base_init.c new file mode 100644 index 0000000000..e2bf9209c7 --- /dev/null +++ b/ompi/mca/osc/base/osc_base_init.c @@ -0,0 +1,61 @@ +/* + * 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 "include/constants.h" +#include "mca/mca.h" +#include "mca/base/base.h" +#include "mca/base/mca_base_param.h" +#include "mca/osc/osc.h" +#include "mca/osc/base/base.h" +#include "datatype/datatype.h" +#include "info/info.h" +#include "communicator/communicator.h" +#include "win/win.h" + +int +ompi_osc_base_select(ompi_win_t *win, + ompi_info_t *info, + ompi_communicator_t *comm) +{ + opal_list_item_t *item; + ompi_osc_base_component_t *best_component = NULL; + int best_priority = -1, priority; + + if (opal_list_get_size(&ompi_osc_base_avail_components) <= 0) { + /* we don't have any components to support us... */ + return OMPI_ERR_NOT_SUPPORTED; + } + + for (item = opal_list_get_first(&ompi_osc_base_avail_components) ; + item != opal_list_get_end(&ompi_osc_base_avail_components) ; + item = opal_list_get_next(item)) { + 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); + if (priority < 0) continue; + if (priority > best_priority) { + best_component = component; + best_priority = priority; + } + } + + if (NULL == best_component) return OMPI_ERR_NOT_SUPPORTED; + + return best_component->osc_select(win, info, comm); +} diff --git a/ompi/mca/osc/base/osc_base_open.c b/ompi/mca/osc/base/osc_base_open.c new file mode 100644 index 0000000000..07b0dd0c1b --- /dev/null +++ b/ompi/mca/osc/base/osc_base_open.c @@ -0,0 +1,98 @@ +/* + * 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 "include/constants.h" + +#include "mca/mca.h" +#include "mca/base/base.h" +#include "mca/base/mca_base_param.h" +#include "mca/osc/osc.h" +#include "mca/osc/base/base.h" + + +/* + * The following file was created by configure. It contains extern + * statements and the definition of an array of pointers to each + * component's public mca_base_component_t struct. + */ + +#include "mca/osc/base/static-components.h" + + +opal_list_t ompi_osc_base_open_components; +opal_list_t ompi_osc_base_avail_components; + + + +/** + * Function for finding and opening either all MCA components, or the one + * that was specifically requested via a MCA parameter. + */ +int +ompi_osc_base_open(void) +{ + int ret; + + /* initialize the base code */ + OBJ_CONSTRUCT(&ompi_osc_base_open_components, opal_list_t); + OBJ_CONSTRUCT(&ompi_osc_base_avail_components, opal_list_t); + + /* Open up all available components */ + if (OMPI_SUCCESS != + (ret = mca_base_components_open("osc", 0, + mca_osc_base_static_components, + &ompi_osc_base_open_components, true))) { + return ret; + } + + /* All done */ + return OMPI_SUCCESS; +} + + +int +ompi_osc_base_find_available(bool enable_progress_threads, + bool enable_mpi_threads) +{ + opal_list_item_t *component_item, *tmp; + + for (component_item = opal_list_get_first(&ompi_osc_base_open_components) ; + component_item != opal_list_get_end(&ompi_osc_base_open_components) ; + component_item = opal_list_get_next(component_item)) { + int ret; + ompi_osc_base_component_t *component = (ompi_osc_base_component_t*) + ((mca_base_component_list_item_t*) component_item)->cli_component; + + /* see if this component is ready to run... */ + ret = component->osc_init(enable_progress_threads, enable_mpi_threads); + if (OMPI_SUCCESS != ret) { + /* leave the component in the list and move on */ + continue; + } else { + /* the component is useable on this node. put it in the + available list */ + tmp = component_item; + component_item = opal_list_remove_item(&ompi_osc_base_open_components, + component_item); + opal_list_append(&ompi_osc_base_avail_components, tmp); + } + } + + mca_base_components_close(0, &ompi_osc_base_open_components, NULL); + + return OMPI_SUCCESS; +} diff --git a/ompi/mca/osc/osc.h b/ompi/mca/osc/osc.h new file mode 100644 index 0000000000..bc1998b932 --- /dev/null +++ b/ompi/mca/osc/osc.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University. + * All rights reserved. + * Copyright (c) 2004-2005 The Trustees of the University of Tennessee. + * All rights reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +/** + * @file + * + * One Sided Communication (osc) + * + */ + +#ifndef OMPI_OSC_H +#define OMPI_OSC_H + +#include "mca/mca.h" + +struct ompi_win_t; +struct ompi_info_t; +struct ompi_communicator_t; +struct ompi_group_t; +struct ompi_datatype_t; +struct ompi_op_t; + +/* + * forward define component / module structures + */ +struct ompi_osc_base_component_1_0_0_t; +typedef struct ompi_osc_base_component_1_0_0_t ompi_osc_base_component_1_0_0_t; +typedef ompi_osc_base_component_1_0_0_t ompi_osc_base_component_t; + +struct ompi_osc_base_module_1_0_0_t; +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; + +/* + * Component interface function types + */ + +typedef int (*ompi_osc_base_component_init_fn_t)(bool enable_progress_threads, + bool enable_mpi_threads); + +typedef int (*ompi_osc_base_component_finalize_fn_t)(void); + +typedef int (*ompi_osc_base_component_query_fn_t)(struct ompi_win_t *win, + struct ompi_info_t *info, + struct ompi_communicator_t *comm); + +typedef int (*ompi_osc_base_component_select_fn_t)(struct ompi_win_t *win, + struct ompi_info_t *info, + struct ompi_communicator_t *comm); + + +/* + * Module interface function types + */ + +/** + * Free resources associated with win + * + * Free all resources associated with \c win. The component must + * provide the barrier semantics required by MPI-2 6.2.1. The caller + * will guarantee that no new calls into the module are made after the + * start of this call. It is possible that the window is locked by + * remote processes. win.w_flags will have OMPI_WIN_FREED set before + * this function is called. + */ +typedef int (*ompi_osc_base_module_free_fn_t)(struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_put_fn_t)(void *origin_addr, + int origin_count, + struct ompi_datatype_t *origin_dt, + int target, + int target_disp, + int target_count, + struct ompi_datatype_t *target_dt, + struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_get_fn_t)(void *origin_addr, + int origin_count, + struct ompi_datatype_t *origin_dt, + int target, + int target_disp, + int target_count, + struct ompi_datatype_t *target_dt, + struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_accumulate_fn_t)(void *origin_addr, + int origin_count, + struct ompi_datatype_t *origin_dt, + int target, + int target_disp, + int target_count, + struct ompi_datatype_t *target_dt, + struct ompi_op_t *op, + struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_fence_fn_t)(int assert, struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_start_fn_t)(struct ompi_group_t *group, + int assert, + struct ompi_win_t *win); +typedef int (*ompi_osc_base_module_complete_fn_t)(struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_post_fn_t)(struct ompi_group_t *group, + int assert, + struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_wait_fn_t)(struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_test_fn_t)(struct ompi_win_t *win, + int flag); + +typedef int (*ompi_osc_base_module_lock_fn_t)(int lock_type, + int target, + int assert, + struct ompi_win_t *win); + +typedef int (*ompi_osc_base_module_unlock_fn_t)(int target, + struct ompi_win_t *win); + + +/** + * osc component version and interface functions. + */ +struct ompi_osc_base_component_1_0_0_t { + mca_base_component_t osc_version; + mca_base_component_data_1_0_0_t osc_data; + ompi_osc_base_component_init_fn_t osc_init; + ompi_osc_base_component_query_fn_t osc_query; + ompi_osc_base_component_select_fn_t osc_select; + ompi_osc_base_component_finalize_fn_t osc_finalize; +}; + +/** + * osc module instance. + */ +struct ompi_osc_base_module_1_0_0_t { + ompi_osc_base_module_free_fn_t osc_free; + + ompi_osc_base_module_put_fn_t osc_put; + ompi_osc_base_module_get_fn_t osc_get; + ompi_osc_base_module_accumulate_fn_t osc_accumulate; + + ompi_osc_base_module_fence_fn_t osc_fence; + + ompi_osc_base_module_start_fn_t osc_start; + ompi_osc_base_module_complete_fn_t osc_complete; + ompi_osc_base_module_post_fn_t osc_post; + ompi_osc_base_module_wait_fn_t osc_wait; + ompi_osc_base_module_test_fn_t osc_test; + + ompi_osc_base_module_lock_fn_t osc_lock; + ompi_osc_base_module_unlock_fn_t osc_unlock; +}; + +/* + * Macro for use in components that are of type osc v1.0.0 + */ +#define OMPI_OSC_BASE_VERSION_1_0_0 \ + /* osc v1.0 is chained to MCA v1.0 */ \ + MCA_BASE_VERSION_1_0_0, \ + /* osc v1.0 */ \ + "osc", 1, 0, 0 + +#endif /* OMPI_OSC_H */ diff --git a/ompi/mca/osc/pt2pt/Makefile.am b/ompi/mca/osc/pt2pt/Makefile.am new file mode 100644 index 0000000000..fd35553ee5 --- /dev/null +++ b/ompi/mca/osc/pt2pt/Makefile.am @@ -0,0 +1,60 @@ +# +# 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$ +# + +# Use the top-level Makefile.options + +include $(top_ompi_srcdir)/config/Makefile.options + +pt2pt_sources = \ + osc_pt2pt.h \ + osc_pt2pt.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_obj_convert.h \ + osc_pt2pt_obj_convert.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__.la (for DSO builds) or libmca__.la +# (for static builds). + +if OMPI_BUILD_osc_pt2pt_DSO +component_noinst = +component_install = mca_osc_pt2pt.la +else +component_noinst = libmca_osc_pt2pt.la +component_install = +endif + +mcacomponentdir = $(libdir)/openmpi +mcacomponent_LTLIBRARIES = $(component_install) +mca_osc_pt2pt_la_SOURCES = $(pt2pt_sources) +mca_osc_pt2pt_la_LIBADD = +mca_osc_pt2pt_la_LDFLAGS = -module -avoid-version + +noinst_LTLIBRARIES = $(component_noinst) +libmca_osc_pt2pt_la_SOURCES = $(pt2pt_sources) +libmca_osc_pt2pt_la_LIBADD = +libmca_osc_pt2pt_la_LDFLAGS = -module -avoid-version diff --git a/ompi/mca/osc/pt2pt/configure.params b/ompi/mca/osc/pt2pt/configure.params new file mode 100644 index 0000000000..c6e9ce75a8 --- /dev/null +++ b/ompi/mca/osc/pt2pt/configure.params @@ -0,0 +1,18 @@ +# -*- shell-script -*- +# +# 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$ +# + +PARAM_CONFIG_FILES="Makefile" diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt.c b/ompi/mca/osc/pt2pt/osc_pt2pt.c new file mode 100644 index 0000000000..3f8abd89c4 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt.c @@ -0,0 +1,79 @@ +/* + * 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.h" +#include "osc_pt2pt_sendreq.h" + +#include "opal/threads/mutex.h" +#include "ompi/win/win.h" +#include "ompi/communicator/communicator.h" +#include "ompi/mca/btl/btl.h" +#include "mpi.h" + + +int +ompi_osc_pt2pt_module_free(ompi_win_t *win) +{ + int ret = OMPI_SUCCESS; + int i, tmp; + ompi_osc_pt2pt_module_t *module = P2P_MODULE(win); + + /* are we in an epoch? */ + if ((OMPI_WIN_ACCESS_EPOCH & win->w_flags) || + (OMPI_WIN_EXPOSE_EPOCH & win->w_flags)) { + /* finish off the epoch. More for sanity checks than anything + - could really just ignore this condition... */ + ret = ompi_osc_pt2pt_module_fence(MPI_MODE_NOPRECEDE|MPI_MODE_NOSUCCEED, win); + } + + /* finish with a barrier */ + if (ompi_group_size(win->w_group) > 1) { + ret = module->p2p_comm->c_coll.coll_barrier(module->p2p_comm); + } + + /* remove window information */ + win->w_osc_module = NULL; + + /* remove from component information */ + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + tmp = opal_hash_table_remove_value_uint32(&mca_osc_pt2pt_component.p2p_c_modules, + module->p2p_comm->c_contextid); + /* only take the output of hast_table_remove if there wasn't already an error */ + ret = (ret != OMPI_SUCCESS) ? ret : tmp; + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + + /* clean up p2p module part */ + for (i = 0 ; i < ompi_comm_size(module->p2p_comm) ; ++i) { + OBJ_DESTRUCT(&(module->p2p_pending_out_sendreqs[i])); + } + free(module->p2p_pending_out_sendreqs); + module->p2p_pending_out_sendreqs = NULL; + + ompi_comm_free(&(module->p2p_comm)); + module->p2p_comm = NULL; + + module->p2p_win = NULL; + + OBJ_DESTRUCT(&(module->p2p_long_msgs)); + OBJ_DESTRUCT(&(module->p2p_acc_lock)); + OBJ_DESTRUCT(&(module->p2p_lock)); + + free(module); + + return ret; +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt.h b/ompi/mca/osc/pt2pt/osc_pt2pt.h new file mode 100644 index 0000000000..9afd859f3c --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt.h @@ -0,0 +1,209 @@ +/* + * 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_OSC_PT2PT_H +#define OMPI_OSC_PT2PT_H + +#include "opal/class/opal_list.h" +#include "opal/class/opal_free_list.h" +#include "opal/class/opal_hash_table.h" + +#include "ompi/mca/osc/osc.h" +#include "ompi/mca/btl/btl.h" +#include "ompi/win/win.h" +#include "ompi/communicator/communicator.h" + +struct ompi_osc_pt2pt_component_t { + /** Extend the basic osc component interface */ + ompi_osc_base_component_t super; + + /** store the state of progress threads for this instance of OMPI */ + bool p2p_c_have_progress_threads; + + /** lock access to datastructures in the component structure */ + opal_mutex_t p2p_c_lock; + + /** List of ompi_osc_pt2pt_module_ts currently in existance. + Needed so that received fragments can be dispatched to the + correct module */ + opal_hash_table_t p2p_c_modules; + + /** 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; +}; +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; + + /** 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; + + /** store weather user disabled locks for this window */ + bool p2p_want_locks; + + /** array of opal_list_ts, not a pointer to one of them */ + opal_list_t *p2p_pending_out_sendreqs; + + volatile int32_t p2p_num_pending_out; + volatile int32_t p2p_num_pending_in; + + volatile int32_t p2p_tag_counter; + + /** list of outstanding long messages that must be processes + (ompi_osc_pt2pt_request_long) */ + opal_list_t p2p_long_msgs; + /** number of outstanding long messages */ + volatile int32_t p2p_num_long_msgs; +}; +typedef struct ompi_osc_pt2pt_module_t ompi_osc_pt2pt_module_t; + + +extern ompi_osc_pt2pt_component_t mca_osc_pt2pt_component; + + +/* + * Helper macro for grabbing the module structure from a window instance + */ +#if OMPI_ENABLE_DEBUG + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + +static inline ompi_osc_pt2pt_module_t* P2P_MODULE(struct ompi_win_t* win) +{ + ompi_osc_pt2pt_module_t *module = + (ompi_osc_pt2pt_module_t*) win->w_osc_module; + + assert(module->p2p_win == win); + + return module; +} + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + + +#else +#define P2P_MODULE(win) ((ompi_osc_p2p_module_t*) win->w_osc_module) +#endif + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + + +/* + * Component functions + */ +int ompi_osc_pt2pt_component_open(void); + +int ompi_osc_pt2pt_component_close(void); + +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); + + +/* + * 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, + int 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, + int 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, + int 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); + + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* OMPI_OSC_PT2PT_H */ diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_comm.c b/ompi/mca/osc/pt2pt/osc_pt2pt_comm.c new file mode 100644 index 0000000000..98fd6d7667 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_comm.c @@ -0,0 +1,127 @@ +/* + * 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.h" +#include "osc_pt2pt_sendreq.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_out_sendreqs[sendreq->req_target_rank]), + (opal_list_item_t*) sendreq); + 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, int 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; + + /* 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); + 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, + int target_disp, + int target_count, + struct ompi_datatype_t *target_dt, + ompi_win_t *win) +{ + int ret; + ompi_osc_pt2pt_sendreq_t *sendreq; + + /* 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); + 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, int target_disp, int target_count, + struct ompi_datatype_t *target_dt, ompi_win_t *win) +{ + int ret; + ompi_osc_pt2pt_sendreq_t *sendreq; + + /* 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); + if (OMPI_SUCCESS != ret) return ret; + + /* enqueue sendreq */ + ret = enqueue_sendreq(P2P_MODULE(win), sendreq); + + return ret; +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_component.c b/ompi/mca/osc/pt2pt/osc_pt2pt_component.c new file mode 100644 index 0000000000..dd42a60956 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_component.c @@ -0,0 +1,385 @@ +/* + * 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.h" +#include "osc_pt2pt_sendreq.h" +#include "osc_pt2pt_replyreq.h" +#include "osc_pt2pt_header.h" +#include "osc_pt2pt_obj_convert.h" +#include "osc_pt2pt_data_move.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/btl/btl.h" +#include "ompi/mca/bml/bml.h" +#include "ompi/mca/bml/base/base.h" + +ompi_osc_pt2pt_component_t mca_osc_pt2pt_component = { + { /* ompi_osc_base_component_t */ + { /* ompi_base_component_t */ + OMPI_OSC_BASE_VERSION_1_0_0, + "pt2pt", + 1, + 0, + 0, + NULL, + NULL + }, + { /* mca_base_component_data */ + false /* checkpointable? */ + }, + 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, + } +}; + + +void ompi_osc_pt2pt_component_fragment_cb(struct mca_btl_base_module_t *btl, + mca_btl_base_tag_t tag, + mca_btl_base_descriptor_t *descriptor, + void *cbdata); + +static bool +want_locks(ompi_info_t *info) +{ + char *val; + int vallen, ret, flag; + bool no_locks; + + ret = ompi_info_get_valuelen(info, "no_locks", &vallen, &flag); + if (OMPI_SUCCESS != ret) return true; + if (flag == 0) return true; + vallen++; + + val = malloc(sizeof(char) * vallen); + if (NULL == val) return true; + + ret = ompi_info_get(info, "no_locks", vallen, val, &flag); + if (OMPI_SUCCESS != ret) { + free(val); + return true; + } + assert(flag != 0); + ret = ompi_info_value_to_bool(val, &no_locks); + free(val); + if (OMPI_SUCCESS != ret) return true; + + return !no_locks; +} + + +int +ompi_osc_pt2pt_component_init(bool enable_progress_threads, + bool enable_mpi_threads) +{ + int ret; + + /* we can run with either threads or not threads (may not be able + to do win locks)... */ + mca_osc_pt2pt_component.p2p_c_have_progress_threads = + enable_progress_threads; + + OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_lock, opal_mutex_t); + + OBJ_CONSTRUCT(&mca_osc_pt2pt_component.p2p_c_modules, + opal_hash_table_t); + opal_hash_table_init(&mca_osc_pt2pt_component.p2p_c_modules, 2); + + 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); + + ret = mca_bml.bml_register(MCA_BTL_TAG_OSC_PT2PT, + ompi_osc_pt2pt_component_fragment_cb, + NULL); + + return ret; +} + + +int +ompi_osc_pt2pt_component_finalize(void) +{ + size_t num_modules; + + if (0 != + (num_modules = opal_hash_table_get_size(&mca_osc_pt2pt_component.p2p_c_modules))) { + opal_output(0, "WARNING: There were %d Windows created but not freed.", + num_modules); + } + + mca_bml.bml_register(MCA_BTL_TAG_OSC_PT2PT, NULL, NULL); + + 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); + OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_modules); + OBJ_DESTRUCT(&mca_osc_pt2pt_component.p2p_c_lock); + + return OMPI_SUCCESS; +} + + +int +ompi_osc_pt2pt_component_query(ompi_win_t *win, + ompi_info_t *info, + ompi_communicator_t *comm) +{ + if (!mca_osc_pt2pt_component.p2p_c_have_progress_threads) { + /* if we don't have threads, we can only run if the user + promises not to use locking by setting the no_locks key */ +#if 0 + if (want_locks(info)) { + /* once the default build of Open MPI is to use progress + threads, should enable this check again. For now, + though, we just abort when we get to the call to + MPI_Lock() */ + return -1 + } +#endif + } + + /* woo! we can run! Return priority of 10 (low) */ + return 10; +} + + +int +ompi_osc_pt2pt_component_select(ompi_win_t *win, + ompi_info_t *info, + ompi_communicator_t *comm) +{ + ompi_osc_pt2pt_module_t *module; + int ret, i; + + /* create module structure */ + module = malloc(sizeof(ompi_osc_pt2pt_module_t)); + if (NULL == module) return OMPI_ERROR; + + /* 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_acc_lock), opal_mutex_t); + + module->p2p_win = win; + + ret = ompi_comm_dup(comm, &(module->p2p_comm)); + if (ret != OMPI_SUCCESS) { + OBJ_DESTRUCT(&(module->p2p_acc_lock)); + OBJ_DESTRUCT(&(module->p2p_lock)); + free(module); + return ret; + } + + module->p2p_want_locks = want_locks(info); + if (!mca_osc_pt2pt_component.p2p_c_have_progress_threads) { + module->p2p_want_locks = false; + } + + module->p2p_pending_out_sendreqs = malloc(sizeof(opal_list_t) * + ompi_comm_size(module->p2p_comm)); + if (NULL == module) { + ompi_comm_free(&comm); + OBJ_DESTRUCT(&(module->p2p_acc_lock)); + OBJ_DESTRUCT(&(module->p2p_lock)); + free(module); + return ret; + } + for (i = 0 ; i < ompi_comm_size(module->p2p_comm) ; ++i) { + OBJ_CONSTRUCT(&(module->p2p_pending_out_sendreqs[i]), opal_list_t); + } + + module->p2p_num_pending_out = 0; + module->p2p_num_pending_in = 0; + module->p2p_tag_counter = 0; + + OBJ_CONSTRUCT(&(module->p2p_long_msgs), opal_list_t); + module->p2p_num_long_msgs = 0; + + /* update component data */ + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + opal_hash_table_set_value_uint32(&mca_osc_pt2pt_component.p2p_c_modules, + module->p2p_comm->c_contextid, + module); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + + /* fill in window information */ + win->w_osc_module = (ompi_osc_base_module_t*) module; + + /* register to receive fragment callbacks */ + ret = mca_bml.bml_register(MCA_BTL_TAG_OSC_PT2PT, + ompi_osc_pt2pt_component_fragment_cb, + NULL); + + return ret; +} + + + +/* dispatch for callback on message completion */ +void +ompi_osc_pt2pt_component_fragment_cb(struct mca_btl_base_module_t *btl, + mca_btl_base_tag_t tag, + mca_btl_base_descriptor_t *descriptor, + void *cbdata) +{ + int ret; + ompi_osc_pt2pt_module_t *module; + void *payload; + + assert(descriptor->des_dst[0].seg_len >= sizeof(ompi_osc_pt2pt_type_header_t)); + + /* handle message */ + switch (((ompi_osc_pt2pt_type_header_t*) descriptor->des_dst[0].seg_addr.pval)->hdr_type) { + case OMPI_OSC_PT2PT_HDR_PUT: + { + ompi_osc_pt2pt_send_header_t *header; + + /* get our header and payload */ + header = (ompi_osc_pt2pt_send_header_t*) + descriptor->des_dst[0].seg_addr.pval; + payload = (void*) (header + 1); + + /* get our module pointer */ + module = ompi_osc_pt2pt_windx_to_module(header->hdr_windx); + if (NULL == module) return; + + ret = ompi_osc_pt2pt_sendreq_recv_put(module, header, payload); + } + break; + + case OMPI_OSC_PT2PT_HDR_ACC: + { + ompi_osc_pt2pt_send_header_t *header; + + /* get our header and payload */ + header = (ompi_osc_pt2pt_send_header_t*) + descriptor->des_dst[0].seg_addr.pval; + payload = (void*) (header + 1); + + /* get our module pointer */ + module = ompi_osc_pt2pt_windx_to_module(header->hdr_windx); + if (NULL == module) return; + + /* receive into temporary buffer */ + ret = ompi_osc_pt2pt_sendreq_recv_accum(module, header, payload); + } + break; + + case OMPI_OSC_PT2PT_HDR_GET: + { + ompi_datatype_t *datatype; + ompi_osc_pt2pt_send_header_t *header; + ompi_osc_pt2pt_replyreq_t *replyreq; + + /* get our header and payload */ + header = (ompi_osc_pt2pt_send_header_t*) + descriptor->des_dst[0].seg_addr.pval; + payload = (void*) (header + 1); + + /* get our module pointer */ + module = ompi_osc_pt2pt_windx_to_module(header->hdr_windx); + if (NULL == module) return; + + /* create or get a pointer to our datatype */ + datatype = ompi_osc_pt2pt_datatype_create(header->hdr_target_dt_id, &payload); + + /* 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_sendreq_t *sendreq; + + /* get our header and payload */ + header = (ompi_osc_pt2pt_reply_header_t*) + descriptor->des_dst[0].seg_addr.pval; + payload = (void*) (header + 1); + + /* 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; + default: + /* BWB - FIX ME - this sucks */ + opal_output(0, "received packet for Window with unknown type"); + abort(); + } +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.c b/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.c new file mode 100644 index 0000000000..c4416aa543 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.c @@ -0,0 +1,708 @@ + +/* + * 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.h" +#include "osc_pt2pt_sendreq.h" +#include "osc_pt2pt_header.h" +#include "osc_pt2pt_data_move.h" +#include "osc_pt2pt_obj_convert.h" + +#include "opal/util/output.h" +#include "opal/include/sys/atomic.h" +#include "ompi/mca/bml/bml.h" +#include "ompi/mca/bml/base/base.h" +#include "ompi/mca/btl/btl.h" + + +static inline int32_t +create_send_tag(ompi_osc_pt2pt_module_t *module) +{ +#if OMPI_HAVE_THREAD_SUPPORT && OPAL_HAVE_ATOMIC_CMPSET_32 + int32_t new, old; + do { + oldval = module->p2p_tag_counter; + newval = (oldval + 1) % mca_pml.pml_max_tag; + } while (0 == opal_atomic_cmpset_32(&module->p2p_tag_counter, oldval, newval)); + return newval; +#elif OMPI_HAVE_THREAD_SUPPORT + int32_t ret; + /* no compare and swap - have to lock the module */ + OPAL_THREAD_LOCK(&module->p2p_lock); + module->p2p_tag_counter = (module->p2p_tag_counter + 1) % mca_pml.pml_max_tag; + ret = module->p2p_tag_counter; + OPAL_THREAD_UNLOCK(&module->p2p_lock); + return ret; +#else + module->p2p_tag_counter = (module->p2p_tag_counter + 1) % mca_pml.pml_max_tag; + return module->p2p_tag_counter; +#endif +} + + +/********************************************************************** + * + * Sending a sendreq to target + * + **********************************************************************/ +static void +ompi_osc_pt2pt_sendreq_send_long_cb(ompi_osc_pt2pt_longreq_t *longreq) +{ + ompi_osc_pt2pt_sendreq_t *sendreq = + (ompi_osc_pt2pt_sendreq_t*) longreq->req_comp_cbdata; + + OPAL_THREAD_LOCK(&(sendreq->req_module->p2p_lock)); + opal_list_remove_item(&(sendreq->req_module->p2p_long_msgs), &(longreq->super)); + sendreq->req_module->p2p_num_long_msgs--; + OPAL_THREAD_UNLOCK(&(sendreq->req_module->p2p_lock)); + + ompi_osc_pt2pt_longreq_free(longreq); + + OPAL_THREAD_ADD32(&(sendreq->req_module->p2p_num_pending_out), -1); + ompi_osc_pt2pt_sendreq_free(sendreq); +} + + +static void +ompi_osc_pt2pt_sendreq_send_cb(struct mca_btl_base_module_t* btl, + struct mca_btl_base_endpoint_t *endpoint, + struct mca_btl_base_descriptor_t* descriptor, + int status) +{ + ompi_osc_pt2pt_sendreq_t *sendreq = + (ompi_osc_pt2pt_sendreq_t*) descriptor->des_cbdata; + ompi_osc_pt2pt_send_header_t *header = + (ompi_osc_pt2pt_send_header_t*) descriptor->des_src[0].seg_addr.pval; + + if (OMPI_SUCCESS != status) { + /* requeue and return */ + /* BWB - FIX ME - figure out where to put this bad boy */ + abort(); + return; + } + + if (OMPI_OSC_PT2PT_GET != sendreq->req_type) { + /* do we need to post a send? */ + if (header->hdr_msg_length != 0) { + /* sendreq is done. Mark it as so and get out of here */ + OPAL_THREAD_ADD32(&(sendreq->req_module->p2p_num_pending_out), -1); + ompi_osc_pt2pt_sendreq_free(sendreq); + } else { + ompi_osc_pt2pt_longreq_t *longreq; + ompi_osc_pt2pt_longreq_alloc(&longreq); + + longreq->req_comp_cb = ompi_osc_pt2pt_sendreq_send_long_cb; + longreq->req_comp_cbdata = sendreq; + + mca_pml.pml_isend(sendreq->req_origin_convertor.pBaseBuf, + sendreq->req_origin_convertor.count, + sendreq->req_origin_datatype, + sendreq->req_target_rank, + header->hdr_origin_tag, + MCA_PML_BASE_SEND_STANDARD, + sendreq->req_module->p2p_comm, + &(longreq->req_pml_req)); + + /* put the send request in the waiting list */ + OPAL_THREAD_LOCK(&(sendreq->req_module->p2p_lock)); + opal_list_append(&(sendreq->req_module->p2p_long_msgs), &(longreq->super)); + sendreq->req_module->p2p_num_long_msgs++; + OPAL_THREAD_UNLOCK(&(sendreq->req_module->p2p_lock)); + } + } + + /* release the descriptor and sendreq */ + btl->btl_free(btl, descriptor); + + /* any other sendreqs to restart? */ + /* BWB - FIX ME - implement sending the next sendreq here */ +} + + +/* create the initial fragment, pack header, datatype, and payload (if + size fits) and send */ +int +ompi_osc_pt2pt_sendreq_send(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_sendreq_t *sendreq) +{ + int ret = OMPI_SUCCESS; + mca_bml_base_endpoint_t *endpoint = NULL; + mca_bml_base_btl_t *bml_btl = NULL; + mca_btl_base_descriptor_t *descriptor = NULL; + ompi_osc_pt2pt_send_header_t *header = NULL; + size_t written_data = 0; + + /* Get a BTL and a fragment to go with it */ + endpoint = (mca_bml_base_endpoint_t*) sendreq->req_target_proc->proc_pml; + bml_btl = mca_bml_base_btl_array_get_next(&endpoint->btl_eager); + descriptor = bml_btl->btl_alloc(bml_btl->btl, + bml_btl->btl_eager_limit); + if (NULL == descriptor) { + ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE; + goto cleanup; + } + + /* verify at least enough space for header */ + if (descriptor->des_src[0].seg_len < sizeof(ompi_osc_pt2pt_send_header_t)) { + ret = OMPI_ERR_OUT_OF_RESOURCE; + goto cleanup; + } + + /* setup descriptor */ + descriptor->des_cbfunc = ompi_osc_pt2pt_sendreq_send_cb; + descriptor->des_cbdata = (void*) sendreq; + descriptor->des_flags = MCA_BTL_DES_FLAGS_PRIORITY; + + /* pack header */ + header = (ompi_osc_pt2pt_send_header_t*) descriptor->des_src[0].seg_addr.pval; + written_data += sizeof(ompi_osc_pt2pt_send_header_t); + header->hdr_windx = sendreq->req_module->p2p_comm->c_contextid; + header->hdr_origin = sendreq->req_module->p2p_comm->c_my_rank; + header->hdr_origin_sendreq.pval = (void*) sendreq; + header->hdr_origin_tag = 0; + header->hdr_target_disp = sendreq->req_target_disp; + header->hdr_target_count = sendreq->req_target_count; + + switch (sendreq->req_type) { + case OMPI_OSC_PT2PT_PUT: + header->hdr_type = OMPI_OSC_PT2PT_HDR_PUT; +#if OMPI_ENABLE_MEM_DEBUG + header->hdr_target_op = 0; +#endif + break; + + case OMPI_OSC_PT2PT_ACC: + header->hdr_type = OMPI_OSC_PT2PT_HDR_ACC; + header->hdr_target_op = sendreq->req_op_id; + break; + + case OMPI_OSC_PT2PT_GET: + header->hdr_type = OMPI_OSC_PT2PT_HDR_GET; +#if OMPI_ENABLE_MEM_DEBUG + header->hdr_target_op = 0; +#endif + break; + } + + /* Set datatype id and / or pack datatype */ + if (DT_FLAG_PREDEFINED & sendreq->req_target_datatype->flags) { + header->hdr_target_dt_id = sendreq->req_target_datatype->d_f_to_c_index; + /* does not extend written_data, as nothing extra added */ + } else { + header->hdr_target_dt_id = -1; + + /* BWB - FIX ME - implement this datatype thing */ + opal_output(0, "Datatype is not predefined. aborting."); + abort(); + } + + if (OMPI_OSC_PT2PT_GET != sendreq->req_type) { + /* if sending data and it fits, pack payload */ + if (descriptor->des_src[0].seg_len >= + written_data + sendreq->req_origin_bytes_packed) { + struct iovec iov; + uint32_t iov_count = 1; + int32_t free_after; + size_t max_data = sendreq->req_origin_bytes_packed; + + iov.iov_len = max_data; + iov.iov_base = (unsigned char*) descriptor->des_src[0].seg_addr.pval + written_data; + + ret = ompi_convertor_pack(&sendreq->req_origin_convertor, &iov, &iov_count, + &max_data, &free_after); + if (ret < 0) { + ret = OMPI_ERR_FATAL; + goto cleanup; + } + + assert(max_data == sendreq->req_origin_bytes_packed); + written_data += max_data; + descriptor->des_src[0].seg_len = written_data; + + header->hdr_msg_length = sendreq->req_origin_bytes_packed; + } else { + header->hdr_msg_length = 0; + header->hdr_origin_tag = create_send_tag(module); + } + } else { + descriptor->des_src[0].seg_len = written_data; + header->hdr_msg_length = 0; + } + +#if 0 /* BWB - FIX ME */ + /* put in network byte order */ + OMPI_OSC_PT2PT_REQ_HDR_HTON(header); +#endif + + /* send fragment */ + opal_output(0, "sending sendreq of type %d to %d", + header->hdr_type, sendreq->req_target_rank); + ret = mca_bml_base_send(bml_btl, descriptor, MCA_BTL_TAG_OSC_PT2PT); + goto done; + + cleanup: + if (descriptor != NULL) { + mca_bml_base_free(bml_btl, descriptor); + } + + done: + return ret; +} + + +/********************************************************************** + * + * Sending a replyreq back to origin + * + **********************************************************************/ +static void +ompi_osc_pt2pt_replyreq_send_long_cb(ompi_osc_pt2pt_longreq_t *longreq) +{ + ompi_osc_pt2pt_replyreq_t *replyreq = + (ompi_osc_pt2pt_replyreq_t*) longreq->req_comp_cbdata; + + OPAL_THREAD_LOCK(&(replyreq->rep_module->p2p_lock)); + opal_list_remove_item(&(replyreq->rep_module->p2p_long_msgs), &(longreq->super)); + replyreq->rep_module->p2p_num_long_msgs--; + OPAL_THREAD_UNLOCK(&(replyreq->rep_module->p2p_lock)); + + ompi_osc_pt2pt_longreq_free(longreq); + + OPAL_THREAD_ADD32(&(replyreq->rep_module->p2p_num_pending_in), -1); + ompi_osc_pt2pt_replyreq_free(replyreq); +} + + +static void +ompi_osc_pt2pt_replyreq_send_cb(struct mca_btl_base_module_t* btl, + struct mca_btl_base_endpoint_t *endpoint, + struct mca_btl_base_descriptor_t* descriptor, + int status) +{ + ompi_osc_pt2pt_replyreq_t *replyreq = + (ompi_osc_pt2pt_replyreq_t*) descriptor->des_cbdata; + ompi_osc_pt2pt_reply_header_t *header = + (ompi_osc_pt2pt_reply_header_t*) descriptor->des_src[0].seg_addr.pval; + + if (OMPI_SUCCESS != status) { + /* requeue and return */ + /* BWB - FIX ME - figure out where to put this bad boy */ + abort(); + return; + } + + /* do we need to post a send? */ + if (header->hdr_msg_length != 0) { + /* sendreq is done. Mark it as so and get out of here */ + OPAL_THREAD_ADD32(&(replyreq->rep_module->p2p_num_pending_in), -1); + ompi_osc_pt2pt_replyreq_free(replyreq); + } else { + ompi_osc_pt2pt_longreq_t *longreq; + ompi_osc_pt2pt_longreq_alloc(&longreq); + + longreq->req_comp_cb = ompi_osc_pt2pt_replyreq_send_long_cb; + longreq->req_comp_cbdata = replyreq; + + mca_pml.pml_isend(replyreq->rep_target_convertor.pBaseBuf, + replyreq->rep_target_convertor.count, + replyreq->rep_target_datatype, + replyreq->rep_origin_rank, + header->hdr_target_tag, + MCA_PML_BASE_SEND_STANDARD, + replyreq->rep_module->p2p_comm, + &(longreq->req_pml_req)); + + /* put the send request in the waiting list */ + OPAL_THREAD_LOCK(&(replyreq->rep_module->p2p_lock)); + opal_list_append(&(replyreq->rep_module->p2p_long_msgs), &(longreq->super)); + replyreq->rep_module->p2p_num_long_msgs++; + OPAL_THREAD_UNLOCK(&(replyreq->rep_module->p2p_lock)); + } + + /* release the descriptor and replyreq */ + btl->btl_free(btl, descriptor); + + /* any other replyreqs to restart? */ +} + + +int +ompi_osc_pt2pt_replyreq_send(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_replyreq_t *replyreq) +{ + int ret = OMPI_SUCCESS; + mca_bml_base_endpoint_t *endpoint = NULL; + mca_bml_base_btl_t *bml_btl = NULL; + mca_btl_base_descriptor_t *descriptor = NULL; + ompi_osc_pt2pt_reply_header_t *header = NULL; + size_t written_data = 0; + + /* Get a BTL and a fragment to go with it */ + endpoint = (mca_bml_base_endpoint_t*) replyreq->rep_origin_proc->proc_pml; + bml_btl = mca_bml_base_btl_array_get_next(&endpoint->btl_eager); + descriptor = bml_btl->btl_alloc(bml_btl->btl, + bml_btl->btl_eager_limit); + if (NULL == descriptor) { + ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE; + goto cleanup; + } + + /* verify at least enough space for header */ + if (descriptor->des_src[0].seg_len < sizeof(ompi_osc_pt2pt_reply_header_t)) { + ret = OMPI_ERR_OUT_OF_RESOURCE; + goto cleanup; + } + + /* setup descriptor */ + descriptor->des_cbfunc = ompi_osc_pt2pt_replyreq_send_cb; + descriptor->des_cbdata = (void*) replyreq; + descriptor->des_flags = MCA_BTL_DES_FLAGS_PRIORITY; + + /* pack header */ + header = (ompi_osc_pt2pt_reply_header_t*) descriptor->des_src[0].seg_addr.pval; + written_data += sizeof(ompi_osc_pt2pt_reply_header_t); + header->hdr_type = OMPI_OSC_PT2PT_HDR_REPLY; + header->hdr_origin_sendreq = replyreq->rep_origin_sendreq; + header->hdr_target_tag = 0; + + /* if sending data fits, pack payload */ + if (descriptor->des_src[0].seg_len >= + written_data + replyreq->rep_target_bytes_packed) { + struct iovec iov; + uint32_t iov_count = 1; + int32_t free_after; + size_t max_data = replyreq->rep_target_bytes_packed; + + iov.iov_len = max_data; + iov.iov_base = (unsigned char*) descriptor->des_src[0].seg_addr.pval + written_data; + + ret = ompi_convertor_pack(&replyreq->rep_target_convertor, &iov, &iov_count, + &max_data, &free_after); + if (ret < 0) { + ret = OMPI_ERR_FATAL; + goto cleanup; + } + + assert(max_data == replyreq->rep_target_bytes_packed); + written_data += max_data; + descriptor->des_src[0].seg_len = written_data; + + header->hdr_msg_length = replyreq->rep_target_bytes_packed; + } else { + header->hdr_msg_length = 0; + header->hdr_target_tag = create_send_tag(module); + } + +#if 0 /* BWB - FIX ME */ + /* put in network byte order */ + OMPI_OSC_PT2PT_REPLYREQ_HDR_HTON(header); +#endif + + /* send fragment */ + opal_output(0, "sending replyreq to %d", + replyreq->rep_origin_rank); + ret = mca_bml_base_send(bml_btl, descriptor, MCA_BTL_TAG_OSC_PT2PT); + goto done; + + cleanup: + if (descriptor != NULL) { + mca_bml_base_free(bml_btl, descriptor); + } + + done: + return ret; +} + + +/********************************************************************** + * + * Receive a put on the target side + * + **********************************************************************/ +static void +ompi_osc_pt2pt_sendreq_recv_put_long_cb(ompi_osc_pt2pt_longreq_t *longreq) +{ + OPAL_THREAD_LOCK(&(longreq->req_module->p2p_lock)); + opal_list_remove_item(&(longreq->req_module->p2p_long_msgs), &(longreq->super)); + longreq->req_module->p2p_num_long_msgs--; + OPAL_THREAD_UNLOCK(&(longreq->req_module->p2p_lock)); + + OBJ_RELEASE(longreq->req_datatype); + ompi_osc_pt2pt_longreq_free(longreq); + + OPAL_THREAD_ADD32(&(longreq->req_module->p2p_num_pending_in), -1); +} + + +int +ompi_osc_pt2pt_sendreq_recv_put(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_send_header_t *header, + void *inbuf) +{ + int ret = OMPI_SUCCESS; + void *target = (unsigned char*) module->p2p_win->w_baseptr + + (header->hdr_target_disp * module->p2p_win->w_disp_unit); + struct ompi_datatype_t *datatype = ompi_osc_pt2pt_datatype_create(header->hdr_target_dt_id, &inbuf); + + if (header->hdr_msg_length > 0) { + ompi_convertor_t convertor; + struct iovec iov; + uint32_t iov_count = 1; + int32_t free_after = 0; + size_t max_data; + ompi_proc_t *proc; + + /* create convertor */ + OBJ_CONSTRUCT(&convertor, ompi_convertor_t); + + /* initialize convertor */ + proc = ompi_comm_peer_lookup(module->p2p_comm, header->hdr_origin); + ompi_convertor_copy_and_prepare_for_recv(proc->proc_convertor, + datatype, + header->hdr_target_count, + target, + &convertor); + iov.iov_len = header->hdr_msg_length; + iov.iov_base = inbuf; + max_data = iov.iov_len; + ompi_convertor_unpack(&convertor, + &iov, + &iov_count, + &max_data, + &free_after); + OBJ_DESTRUCT(&convertor); + OBJ_RELEASE(datatype); + OPAL_THREAD_ADD32(&(module->p2p_num_pending_in), -1); + + } else { + ompi_osc_pt2pt_longreq_t *longreq; + ompi_osc_pt2pt_longreq_alloc(&longreq); + + longreq->req_comp_cb = ompi_osc_pt2pt_sendreq_recv_put_long_cb; + longreq->req_comp_cbdata = NULL; + longreq->req_datatype = datatype; + longreq->req_module = module; + + ret = mca_pml.pml_irecv(target, + header->hdr_target_count, + datatype, + header->hdr_origin, + header->hdr_origin_tag, + module->p2p_comm, + &(longreq->req_pml_req)); + + /* put the send request in the waiting list */ + OPAL_THREAD_LOCK(&(module->p2p_lock)); + opal_list_append(&(module->p2p_long_msgs), &(longreq->super)); + module->p2p_num_long_msgs++; + OPAL_THREAD_UNLOCK(&(module->p2p_lock)); + } + + return ret; +} + + + + +/********************************************************************** + * + * Receive an accumulate on the target side + * + **********************************************************************/ +static void +ompi_osc_pt2pt_sendreq_recv_accum_long_cb(ompi_osc_pt2pt_longreq_t *longreq) +{ + ompi_osc_pt2pt_send_header_t *header = + (ompi_osc_pt2pt_send_header_t*) longreq->req_comp_cbdata; + void *payload = (void*) (header + 1); + int ret; + + /* lock the window for accumulates */ + OPAL_THREAD_LOCK(&longreq->req_module->p2p_acc_lock); + + /* copy the data from the temporary buffer into the user window */ + ret = ompi_osc_pt2pt_process_op(longreq->req_module, + header, + longreq->req_datatype, + longreq->req_op, + payload, + header->hdr_msg_length); + + /* unlock the window for accumulates */ + OPAL_THREAD_UNLOCK(&longreq->req_module->p2p_acc_lock); + + /* free the temp buffer */ + free(longreq->req_comp_cbdata); + + /* Release datatype & op */ + OBJ_RELEASE(longreq->req_datatype); + OBJ_RELEASE(longreq->req_op); + + OPAL_THREAD_ADD32(&(longreq->req_module->p2p_num_pending_in), -1); + + OPAL_THREAD_LOCK(&(longreq->req_module->p2p_lock)); + opal_list_remove_item(&(longreq->req_module->p2p_long_msgs), &(longreq->super)); + longreq->req_module->p2p_num_long_msgs--; + OPAL_THREAD_UNLOCK(&(longreq->req_module->p2p_lock)); + + OBJ_RELEASE(longreq->req_datatype); + OBJ_RELEASE(longreq->req_op); + ompi_osc_pt2pt_longreq_free(longreq); + + OPAL_THREAD_ADD32(&(longreq->req_module->p2p_num_pending_in), -1); +} + + +int +ompi_osc_pt2pt_sendreq_recv_accum(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_send_header_t *header, + void *payload) +{ + int ret = OMPI_SUCCESS; + struct ompi_datatype_t *datatype = ompi_osc_pt2pt_datatype_create(header->hdr_target_dt_id, &payload); + struct ompi_op_t *op = ompi_osc_pt2pt_op_create(header->hdr_target_op); + + if (header->hdr_msg_length > 0) { + /* lock the window for accumulates */ + OPAL_THREAD_LOCK(&module->p2p_acc_lock); + + /* copy the data from the temporary buffer into the user window */ + ret = ompi_osc_pt2pt_process_op(module, header, datatype, op, payload, + header->hdr_msg_length); + + /* unlock the window for accumulates */ + OPAL_THREAD_UNLOCK(&module->p2p_acc_lock); + + /* Release datatype & op */ + OBJ_RELEASE(datatype); + OBJ_RELEASE(op); + + OPAL_THREAD_ADD32(&(module->p2p_num_pending_in), -1); + + } else { + ompi_osc_pt2pt_longreq_t *longreq; + long lb, extent, true_lb, true_extent; + size_t buflen; + + /* figure out how big a buffer we need */ + ompi_ddt_get_extent(datatype, &lb, &extent); + ompi_ddt_get_true_extent(datatype, &true_lb, &true_extent); + buflen = true_extent + (header->hdr_target_count - 1) * extent; + + /* get a longreq and fill it in */ + ompi_osc_pt2pt_longreq_alloc(&longreq); + + longreq->req_comp_cb = ompi_osc_pt2pt_sendreq_recv_accum_long_cb; + longreq->req_datatype = datatype; + longreq->req_op = op; + longreq->req_module = module; + + /* allocate a buffer to receive into ... */ + longreq->req_comp_cbdata = malloc(buflen + sizeof(ompi_osc_pt2pt_send_header_t)); + + if (NULL == longreq->req_comp_cbdata) return OMPI_ERR_TEMP_OUT_OF_RESOURCE; + + ret = mca_pml.pml_irecv(((char*) longreq->req_comp_cbdata) + sizeof(ompi_osc_pt2pt_send_header_t), + header->hdr_target_count, + datatype, + header->hdr_origin, + header->hdr_origin_tag, + module->p2p_comm, + &(longreq->req_pml_req)); + } + + return ret; +} + + +/********************************************************************** + * + * Recveive a get on the origin side + * + **********************************************************************/ +static void +ompi_osc_pt2pt_replyreq_recv_long_cb(ompi_osc_pt2pt_longreq_t *longreq) +{ + ompi_osc_pt2pt_sendreq_t *sendreq = + (ompi_osc_pt2pt_sendreq_t*) longreq->req_comp_cbdata; + + OPAL_THREAD_LOCK(&(longreq->req_module->p2p_lock)); + opal_list_remove_item(&(longreq->req_module->p2p_long_msgs), &(longreq->super)); + longreq->req_module->p2p_num_long_msgs--; + OPAL_THREAD_UNLOCK(&(longreq->req_module->p2p_lock)); + + ompi_osc_pt2pt_longreq_free(longreq); + + OPAL_THREAD_ADD32(&(sendreq->req_module->p2p_num_pending_out), -1); + ompi_osc_pt2pt_sendreq_free(sendreq); +} + +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 ret = OMPI_SUCCESS; + + /* receive into user buffer */ + if (header->hdr_msg_length > 0) { + /* short message. woo! */ + + struct iovec iov; + uint32_t iov_count = 1; + int32_t free_after = 0; + size_t max_data; + + iov.iov_len = header->hdr_msg_length; + iov.iov_base = payload; + max_data = iov.iov_len; + ompi_convertor_unpack(&sendreq->req_origin_convertor, + &iov, + &iov_count, + &max_data, + &free_after); + + OPAL_THREAD_ADD32(&(sendreq->req_module->p2p_num_pending_out), -1); + ompi_osc_pt2pt_sendreq_free(sendreq); + } else { + ompi_osc_pt2pt_longreq_t *longreq; + ompi_osc_pt2pt_longreq_alloc(&longreq); + + longreq->req_comp_cb = ompi_osc_pt2pt_replyreq_recv_long_cb; + longreq->req_comp_cbdata = sendreq; + longreq->req_module = module; + + /* BWB - FIX ME - George is going to kill me for this */ + ret = mca_pml.pml_irecv(sendreq->req_origin_convertor.pBaseBuf, + sendreq->req_origin_convertor.count, + sendreq->req_origin_datatype, + sendreq->req_target_rank, + header->hdr_target_tag, + module->p2p_comm, + &(longreq->req_pml_req)); + + /* put the send request in the waiting list */ + OPAL_THREAD_LOCK(&(module->p2p_lock)); + opal_list_append(&(module->p2p_long_msgs), &(longreq->super)); + module->p2p_num_long_msgs++; + OPAL_THREAD_UNLOCK(&(module->p2p_lock)); + } + + return ret; +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.h b/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.h new file mode 100644 index 0000000000..4b4304daa5 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_data_move.h @@ -0,0 +1,51 @@ +/* + * 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); + +#endif diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_header.h b/ompi/mca/osc/pt2pt/osc_pt2pt_header.h new file mode 100644 index 0000000000..9d6fce8a24 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_header.h @@ -0,0 +1,135 @@ +/* + * 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_HDR_H +#define OMPI_MCA_OSC_PT2PT_HDR_H + +struct ompi_osc_pt2pt_type_header_t { + uint8_t hdr_type; +}; +typedef struct ompi_osc_pt2pt_type_header_t ompi_osc_pt2pt_type_header_t; + +struct ompi_osc_pt2pt_send_header_t { + uint8_t hdr_type; + uint32_t hdr_windx; + + int32_t hdr_origin; + ompi_ptr_t hdr_origin_sendreq; + int32_t hdr_origin_tag; + + int16_t hdr_target_dt_id; + int32_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; + +struct ompi_osc_pt2pt_reply_header_t { + uint8_t hdr_type; + ompi_ptr_t hdr_origin_sendreq; + + int32_t hdr_target_tag; + int32_t hdr_msg_length; +}; +typedef struct ompi_osc_pt2pt_reply_header_t ompi_osc_pt2pt_reply_header_t; + + +#define OMPI_OSC_PT2PT_HDR_PUT 0x0001 +#define OMPI_OSC_PT2PT_HDR_ACC 0x0002 +#define OMPI_OSC_PT2PT_HDR_GET 0x0004 +#define OMPI_OSC_PT2PT_HDR_REPLY 0x0008 + +/* + * Convert a 64 bit value to network byte order. + */ +static inline uint64_t hton64(uint64_t val) +{ + union { uint64_t ll; + uint32_t l[2]; + } w, r; + + /* platform already in network byte order? */ + if(htonl(1) == 1L) + return val; + w.ll = val; + r.l[0] = htonl(w.l[1]); + r.l[1] = htonl(w.l[0]); + return r.ll; +} + + +/* + * Convert a 64 bit value from network to host byte order. + */ +static inline uint64_t ntoh64(uint64_t val) +{ + union { uint64_t ll; + uint32_t l[2]; + } w, r; + + /* platform already in network byte order? */ + if(htonl(1) == 1L) + return val; + w.ll = val; + r.l[0] = ntohl(w.l[1]); + r.l[1] = ntohl(w.l[0]); + return r.ll; +} + + +#define OMPI_OSC_PT2PT_REQ_HDR_HTON(hdr) \ + do { \ + (hdr).hdr_windx = htonl((hdr).hdr_windx); \ + (hdr).hdr_origin = htonl((hdr).hdr_origin); \ + (hdr).hdr_origin_sendreq = hton64((hdr).hdr_origin_sendreq); \ + (hdr).hdr_origin_tag = htonl((hdr).hdr_origin_tag); \ + (hdr).hdr_target_dt_id = htons((hdr).hdr_target_dt_id); \ + (hdr).hdr_target_disp = htonl((hdr).hdr_target_disp); \ + (hdr).hdr_target_count = htonl((hdr).hdr_target_count); \ + (hdr).hdr_msg_length = htonl((hdr).hdr_msg_length); \ + (hdr).hdr_target_op = htonl((hdr).hdr_target_op); \ + } while (0) + +#define OMPI_OSC_PT2PT_REQ_HDR_NTOH(hdr) \ + do { \ + (hdr).hdr_windx = ntohl((hdr).hdr_windx); \ + (hdr).hdr_origin = ntohl((hdr).hdr_origin); \ + (hdr).hdr_origin_sendreq = ntoh64((hdr).hdr_origin_sendreq); \ + (hdr).hdr_origin_tag = ntohl((hdr).hdr_origin_tag); \ + (hdr).hdr_target_dt_id = ntohs((hdr).hdr_target_dt_id); \ + (hdr).hdr_target_disp = ntohl((hdr).hdr_target_disp); \ + (hdr).hdr_target_count = ntohl((hdr).hdr_target_count); \ + (hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \ + (hdr).hdr_target_op = ntohl((hdr).hdr_target_op); \ + } while (0) + +#define OMPI_OSC_PT2PT_REPLY_HDR_HTON(hdr) \ + do { \ + (hdr).hdr_origin_sendreq = hton64((hdr).hdr_origin_sendreq); \ + (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 { \ + (hdr).hdr_origin_sendreq = ntoh64((hdr).hdr_origin_sendreq); \ + (hdr).hdr_target_tag = ntohl((hdr).hdr_target_tag); \ + (hdr).hdr_msg_length = ntohl((hdr).hdr_msg_length); \ + } while (0) + +#endif /* OMPI_MCA_OSC_PT2PT_HDR_H */ diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.c b/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.c new file mode 100644 index 0000000000..735515a1cf --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.c @@ -0,0 +1,26 @@ +/* + * 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" + +#include "opal/class/opal_list.h" + + +OBJ_CLASS_INSTANCE(ompi_osc_pt2pt_longreq_t, opal_list_item_t, + NULL, NULL); + diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.h b/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.h new file mode 100644 index 0000000000..bbd8f5976c --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_longreq.h @@ -0,0 +1,75 @@ +/* + * 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 "osc_pt2pt.h" + +#include "opal/class/opal_list.h" +#include "opal/class/opal_free_list.h" +#include "ompi/request/request.h" + +struct ompi_osc_pt2pt_longreq_t; +typedef struct ompi_osc_pt2pt_longreq_t ompi_osc_pt2pt_longreq_t; + +typedef void (*ompi_osc_pt2pt_longreq_comp_cb_t)(ompi_osc_pt2pt_longreq_t *longreq); + +struct ompi_osc_pt2pt_longreq_t { + opal_list_item_t super; + + /* warning - this doesn't always have a sane value */ + ompi_osc_pt2pt_module_t *req_module; + + ompi_request_t *req_pml_req; + ompi_osc_pt2pt_longreq_comp_cb_t req_comp_cb; + + /* general storage place - usually holds a request of some type */ + void *req_comp_cbdata; + + /* for long receives, to avoid a longrecvreq type */ + /* BWB - I don't like this, but I don't want another free list. What to do? */ + struct ompi_op_t *req_op; + struct ompi_datatype_t *req_datatype; +}; +OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_longreq_t); + +static inline int +ompi_osc_pt2pt_longreq_alloc(ompi_osc_pt2pt_longreq_t **longreq) +{ + opal_list_item_t *item; + int ret; + + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_longreqs, + item, ret); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + + *longreq = (ompi_osc_pt2pt_longreq_t*) item; + return ret; +} + +static inline int +ompi_osc_pt2pt_longreq_free(ompi_osc_pt2pt_longreq_t *longreq) +{ + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_longreqs, + (opal_list_item_t*) longreq); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + return OMPI_SUCCESS; +} + +#endif diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.c b/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.c new file mode 100644 index 0000000000..285a1ff2bc --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.c @@ -0,0 +1,97 @@ +/* + * 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$ + */ + +/* + * utility functions for dealing with remote datatype and op structures + */ + +#include "ompi_config.h" + +#include "ompi/op/op.h" + +#include "osc_pt2pt.h" +#include "osc_pt2pt_sendreq.h" +#include "osc_pt2pt_header.h" +#include "osc_pt2pt_obj_convert.h" + +int +ompi_osc_pt2pt_process_op(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_send_header_t *header, + struct ompi_datatype_t *datatype, + ompi_op_t *op, + void *inbuf, + size_t inbuflen) +{ + unsigned char *target_buffer; + + /* compute target buffer location */ + target_buffer = (unsigned char*) module->p2p_win->w_baseptr + + (header->hdr_target_disp * module->p2p_win->w_disp_unit); + + /* BWB - fix me - change back to the pointer comparison when the + replace o_f_to_c_index is set properly */ + /* if (op == &ompi_mpi_op_replace) { */ + if (header->hdr_target_op == ompi_mpi_op_replace.o_f_to_c_index) { + ompi_convertor_t convertor; + struct iovec iov; + uint32_t iov_count = 1; + int32_t free_after = 0; + size_t max_data; + ompi_proc_t *proc; + + /* create convertor */ + OBJ_CONSTRUCT(&convertor, ompi_convertor_t); + + /* initialize convertor */ + proc = ompi_comm_peer_lookup(module->p2p_comm, header->hdr_origin); + ompi_convertor_copy_and_prepare_for_recv(proc->proc_convertor, + datatype, + header->hdr_target_count, + target_buffer, + &convertor); + + /* short circuit the reduction operation MPI_REPLACE - it just + replaces the data, so push it out into the user's buffer. + This lets us avoid both the overhead of using the op + invocation and dealing with non-contiguous reductions + (since there are never user-defined reductions in + MPI_ACCUMULATE) */ + iov.iov_len = inbuflen; + iov.iov_base = inbuf; + max_data = iov.iov_len; + ompi_convertor_unpack(&convertor, + &iov, + &iov_count, + &max_data, + &free_after); + OBJ_DESTRUCT(&convertor); + } else { + /* reductions other than MPI_REPLACE. Since user-defined + reductions aren't allowed, these all have to be over + contigous data. We make sure to only send complete + datatypes in these cases, so we can unpack directly from + the user buffer*/ + /* BWB - FIX ME - this won't work if endianness is different. + Talk to George about a ddt function that allows us to fix + endianness "in place' or what else we could do here to keep + performance from sucking... */ + + ompi_op_reduce(op, inbuf, target_buffer, header->hdr_target_count, + datatype); + } + + return OMPI_SUCCESS; +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.h b/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.h new file mode 100644 index 0000000000..25544a8da6 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_obj_convert.h @@ -0,0 +1,82 @@ +/* + * 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$ + */ + +/* + * utility functions for dealing with remote datatype and op structures + */ + +#include "mpi.h" + +static inline +struct ompi_datatype_t* +ompi_osc_pt2pt_datatype_create(int datatype_id, void **payload) +{ + struct ompi_datatype_t *datatype; + + if (datatype_id == -1) { + /* not predefined datatype - need to construct out of payload */ + /* BWB - FIX ME - implement dt sending */ + opal_output(0, "remote datatypes not supported. aborting."); + abort(); + + /* don't forget to move the payload pointer */ + } else { + /* retain datatype so that can be released at end */ + datatype = MPI_Type_f2c(datatype_id); + OBJ_RETAIN(datatype); + } + + return datatype; +} + +static inline +ompi_op_t * +ompi_osc_pt2pt_op_create(int op_id) +{ + ompi_op_t *op = MPI_Op_f2c(op_id); + OBJ_RETAIN(op); + return op; +} + + +int ompi_osc_pt2pt_process_op(ompi_osc_pt2pt_module_t *module, + ompi_osc_pt2pt_send_header_t *header, + struct ompi_datatype_t *datatype, + ompi_op_t *op, + void *inbuf, + size_t inbuflen); + +/** + * Convert a window index number into a module instance. + */ +static inline ompi_osc_pt2pt_module_t* +ompi_osc_pt2pt_windx_to_module(uint32_t windx) +{ + int ret; + ompi_osc_pt2pt_module_t *module; + + /* find the right module and dispatch */ + ret = opal_hash_table_get_value_uint32(&mca_osc_pt2pt_component.p2p_c_modules, + windx, + (void**) (&module)); + if (OMPI_SUCCESS != ret) { + opal_output(0, "Could not translate windx %d to a local MPI_Win instance", + windx); + return NULL; + } + + return module; +} diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.c b/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.c new file mode 100644 index 0000000000..62c747b4a9 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.c @@ -0,0 +1,80 @@ + +/* + * 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_replyreq.h" + +#include "opal/class/opal_list.h" +#include "ompi/datatype/convertor.h" + +int +ompi_osc_pt2pt_replyreq_alloc_init(ompi_osc_pt2pt_module_t *module, + int origin, + ompi_ptr_t origin_request, + int 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), ompi_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); diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.h b/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.h new file mode 100644 index 0000000000..4d81e6c6bd --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_replyreq.h @@ -0,0 +1,142 @@ +/* + * 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_OSC_PT2PT_REPLYREQ_H +#define OMPI_OSC_PT2PT_REPLYREQ_H + +#include "osc_pt2pt.h" +#include "osc_pt2pt_longreq.h" + +#include "opal/class/opal_list.h" +#include "opal/threads/mutex.h" +#include "ompi/datatype/datatype.h" +#include "ompi/datatype/convertor.h" +#include "ompi/communicator/communicator.h" +#include "ompi/proc/proc.h" +#include "ompi/op/op.h" +#include "ompi/mca/pml/pml.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. */ + ompi_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, + int 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_list_item_t *item; + ompi_proc_t *proc = module->p2p_comm->c_pml_procs[origin_rank]->proc_ompi; + + /* BWB - FIX ME - is this really the right return code? */ + if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE; + + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_replyreqs, + item, ret); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + 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; + + ompi_convertor_copy_and_prepare_for_send(replyreq->rep_origin_proc->proc_convertor, + target_dt, + target_count, + target_addr, + &(replyreq->rep_target_convertor)); + ompi_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) +{ + ompi_convertor_cleanup(&replyreq->rep_target_convertor); + + OBJ_RELEASE(replyreq->rep_target_datatype); + + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_replyreqs, + (opal_list_item_t*) replyreq); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + + return OMPI_SUCCESS; +} + +#endif /* OMPI_OSC_PT2PT_REPLYREQ_H */ diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.c b/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.c new file mode 100644 index 0000000000..f4bc7d3fb2 --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.c @@ -0,0 +1,89 @@ + +/* + * 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_sendreq.h" + +#include "ompi/datatype/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, int 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; + + /* shortcut 0 count case */ + if (0 == origin_count || 0 == target_count) { + return OMPI_SUCCESS; + } + + /* 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_fini = NULL; + req->super.req_free = NULL; + req->super.req_cancel = NULL; + OBJ_CONSTRUCT(&(req->req_origin_convertor), ompi_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); diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.h b/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.h new file mode 100644 index 0000000000..30cb3e9a6e --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_sendreq.h @@ -0,0 +1,177 @@ +/* + * 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_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 "opal/threads/mutex.h" +#include "ompi/datatype/datatype.h" +#include "ompi/datatype/convertor.h" +#include "ompi/communicator/communicator.h" +#include "ompi/proc/proc.h" +#include "ompi/op/op.h" +#include "ompi/mca/pml/pml.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) */ + ompi_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 */ + int 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, int 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_list_item_t *item; + ompi_proc_t *proc = module->p2p_comm->c_pml_procs[target_rank]->proc_ompi; + + /* BWB - FIX ME - is this really the right return code? */ + if (NULL == proc) return OMPI_ERR_OUT_OF_RESOURCE; + + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_GET(&mca_osc_pt2pt_component.p2p_c_sendreqs, + item, ret); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + 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) { + ompi_convertor_copy_and_prepare_for_send(sendreq->req_target_proc->proc_convertor, + origin_dt, + origin_count, + origin_addr, + &(sendreq->req_origin_convertor)); + ompi_convertor_get_packed_size(&sendreq->req_origin_convertor, + &sendreq->req_origin_bytes_packed); + } else { + ompi_convertor_copy_and_prepare_for_recv(sendreq->req_target_proc->proc_convertor, + origin_dt, + origin_count, + origin_addr, + &(sendreq->req_origin_convertor)); + ompi_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, + int 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) +{ + ompi_convertor_cleanup(&sendreq->req_origin_convertor); + + OBJ_RELEASE(sendreq->req_target_datatype); + OBJ_RELEASE(sendreq->req_origin_datatype); + + OPAL_THREAD_LOCK(&mca_osc_pt2pt_component.p2p_c_lock); + OPAL_FREE_LIST_RETURN(&mca_osc_pt2pt_component.p2p_c_sendreqs, + (opal_list_item_t*) sendreq); + OPAL_THREAD_UNLOCK(&mca_osc_pt2pt_component.p2p_c_lock); + + return OMPI_SUCCESS; +} + +#endif /* OMPI_OSC_PT2PT_SENDREQ_H */ diff --git a/ompi/mca/osc/pt2pt/osc_pt2pt_sync.c b/ompi/mca/osc/pt2pt/osc_pt2pt_sync.c new file mode 100644 index 0000000000..8b9921e39e --- /dev/null +++ b/ompi/mca/osc/pt2pt/osc_pt2pt_sync.c @@ -0,0 +1,233 @@ +/* + * 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.h" +#include "osc_pt2pt_sendreq.h" +#include "osc_pt2pt_longreq.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" + + +static inline void +ompi_osc_pt2pt_progress(ompi_osc_pt2pt_module_t *module) +{ + if (0 != module->p2p_num_long_msgs) { + opal_list_item_t *item, *next; + + OPAL_THREAD_LOCK(&(module->p2p_lock)); + /* Have to go the convoluted while() route instead of a for() + loop because the callback will likely remove the request + from the list and free it, and that would lead to much + badness. */ + next = opal_list_get_first(&(module->p2p_long_msgs)); + while (opal_list_get_end(&(module->p2p_long_msgs)) != (item = next)) { + ompi_osc_pt2pt_longreq_t *longreq = + (ompi_osc_pt2pt_longreq_t*) item; + int ret, completed; + next = opal_list_get_next(item); + + ret = ompi_request_test(&(longreq->req_pml_req), &completed, NULL); + /* BWB - FIX ME - error handling */ + if (completed > 0) { + longreq->req_comp_cb(longreq); + } + } + OPAL_THREAD_UNLOCK(&(module->p2p_lock)); + } + opal_progress(); +} + + +int +ompi_osc_pt2pt_module_fence(int assert, ompi_win_t *win) +{ + short *outgoing_reqs = NULL; + short incoming_reqs; + int *counts = NULL; + int ret = OMPI_SUCCESS; + int i; + + OPAL_THREAD_LOCK(&(OSC_PT2PT_DATA(win)->p2p_lock)); + + if (0 == (assert & MPI_MODE_NOPRECEDE)) { + /* user has not promised nothing has happened - need to make + sure we've done all our requests */ + P2P_MODULE(win)->p2p_num_pending_out = 0; + + outgoing_reqs = malloc(sizeof(short) * + ompi_comm_size(P2P_MODULE(win)->p2p_comm)); + if (NULL == outgoing_reqs) { + ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE; + goto cleanup; + } + + for (i = 0 ; i < ompi_comm_size(P2P_MODULE(win)->p2p_comm) ; ++i) { + outgoing_reqs[i] = + opal_list_get_size(&(P2P_MODULE(win)->p2p_pending_out_sendreqs[i])); + P2P_MODULE(win)->p2p_num_pending_out += outgoing_reqs[i]; + } + + counts = malloc(sizeof(int) * + ompi_comm_size(P2P_MODULE(win)->p2p_comm)); + if (NULL == counts) { + ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE; + goto cleanup; + } + for (i = 0 ; i < ompi_comm_size(P2P_MODULE(win)->p2p_comm) ; ++i) { + counts[i] = 1; + } + + /* find out how much data everyone is going to send us... */ + ret = P2P_MODULE(win)->p2p_comm->c_coll.coll_reduce_scatter(outgoing_reqs, + &incoming_reqs, + counts, + MPI_SHORT, + MPI_SUM, + P2P_MODULE(win)->p2p_comm); + if (OMPI_SUCCESS != ret) goto cleanup; + + P2P_MODULE(win)->p2p_num_pending_in += incoming_reqs; + + opal_output(0, "fence: waiting on %d operations", + P2P_MODULE(win)->p2p_num_pending_in); + + for (i = 0 ; i < ompi_comm_size(P2P_MODULE(win)->p2p_comm) ; ++i) { + opal_list_item_t *item; + opal_list_t *req_list = + &(P2P_MODULE(win)->p2p_pending_out_sendreqs[i]); + + while (NULL != (item = opal_list_remove_first(req_list))) { + ompi_osc_pt2pt_sendreq_t *req = + (ompi_osc_pt2pt_sendreq_t*) item; + + ret = ompi_osc_pt2pt_sendreq_send(P2P_MODULE(win), req); + + if (OMPI_SUCCESS != ret) { + opal_output(0, "fence: failure in starting sendreq"); + opal_list_prepend(req_list, item); + goto cleanup; + } + } + } + + } else { + /* Don't trust the user that nothing has happened in this + epoch and count through all the pending sendreqs to + verify */ + int tmp = 0; + + for (i = 0 ; i < ompi_comm_size(P2P_MODULE(win)->p2p_comm) ; ++i) { + tmp += + opal_list_get_size(&(P2P_MODULE(win)->p2p_pending_out_sendreqs[i])); + } + + if (0 != tmp) { + ret = MPI_ERR_ASSERT; + goto cleanup; + } + + incoming_reqs = 0; + } + + /* now we know how many things we're waiting for - wait for them... */ + while (0 != P2P_MODULE(win)->p2p_num_pending_in || + 0 != P2P_MODULE(win)->p2p_num_pending_out) { + ompi_osc_pt2pt_progress(P2P_MODULE(win)); + } + + /* all transfers are done - back to the real world we go */ + if (0 == (assert & MPI_MODE_NOSUCCEED)) { + win->w_flags = OMPI_WIN_ACCESS_EPOCH | OMPI_WIN_EXPOSE_EPOCH; + } else { + win->w_flags = 0; + } + + cleanup: + OPAL_THREAD_UNLOCK(&(P2P_MODULE(win)->p2p_lock)); + + if (NULL != outgoing_reqs) free(outgoing_reqs); + if (NULL != counts) free(counts); + + return ret; +} + + +int +ompi_osc_pt2pt_module_start(ompi_group_t *group, + int assert, + ompi_win_t *win) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} + + +int +ompi_osc_pt2pt_module_complete(ompi_win_t *win) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} + +int +ompi_osc_pt2pt_module_post(ompi_group_t *group, + int assert, + ompi_win_t *win) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} + + +int +ompi_osc_pt2pt_module_wait(ompi_win_t *win) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} + + +int +ompi_osc_pt2pt_module_test(ompi_win_t *win, + int flag) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} + + +int +ompi_osc_pt2pt_module_lock(int lock_type, + int target, + int assert, + ompi_win_t *win) +{ + if (!P2P_MODULE(win)->p2p_want_locks) { + return MPI_ERR_OTHER; + } + + return OMPI_ERR_NOT_IMPLEMENTED; +} + + +int +ompi_osc_pt2pt_module_unlock(int target, + ompi_win_t *win) +{ + return OMPI_ERR_NOT_IMPLEMENTED; +} diff --git a/ompi/mpi/c/Makefile.am b/ompi/mpi/c/Makefile.am index ec576f555a..7db4abd10b 100644 --- a/ompi/mpi/c/Makefile.am +++ b/ompi/mpi/c/Makefile.am @@ -338,10 +338,7 @@ libmpi_c_mpi_la_SOURCES = \ waitany.c \ waitsome.c \ wtime.c \ - wtick.c - -if WANT_MPI2_ONE_SIDED -libmpi_c_mpi_la_SOURCES += \ + wtick.c \ accumulate.c \ get.c \ put.c \ @@ -369,7 +366,6 @@ libmpi_c_mpi_la_SOURCES += \ win_test.c \ win_unlock.c \ win_wait.c -endif # Conditionally install the header files diff --git a/ompi/mpi/c/accumulate.c b/ompi/mpi/c/accumulate.c index 89582cd71b..cfbf8d1c03 100644 --- a/ompi/mpi/c/accumulate.c +++ b/ompi/mpi/c/accumulate.c @@ -19,6 +19,10 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" +#include "op/op.h" +#include "ompi/datatype/datatype.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Accumulate = PMPI_Accumulate @@ -35,11 +39,36 @@ int MPI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_data int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; + ompi_win_t *ompi_win = (ompi_win_t*) win; - /* This function is not yet implemented */ + if (target_rank == MPI_PROC_NULL) return MPI_SUCCESS; - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + 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)) { + rc = MPI_ERR_RANK; + } else if (MPI_OP_NULL == op) { + rc = MPI_ERR_OP; + } else if (!ompi_op_is_intrinsic(op) || + (target_datatype->id < DT_MAX_PREDEFINED && + -1 == ompi_op_ddt_map[target_datatype->id])) { + rc = MPI_ERR_OP; + } else { + OMPI_CHECK_DATATYPE_FOR_SEND(rc, origin_datatype, origin_count); + } + OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME); + } + + rc = ompi_win->w_osc_module->osc_accumulate(origin_addr, origin_count, origin_datatype, + target_rank, target_disp, target_count, + target_datatype, op, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/attr_fn.c b/ompi/mpi/c/attr_fn.c index 10eabbbac4..8d20392d52 100644 --- a/ompi/mpi/c/attr_fn.c +++ b/ompi/mpi/c/attr_fn.c @@ -80,7 +80,6 @@ int OMPI_C_MPI_TYPE_DUP_FN( MPI_Datatype datatype, int type_keyval, return MPI_SUCCESS; } -#if OMPI_WANT_MPI2_ONE_SIDED int OMPI_C_MPI_WIN_NULL_DELETE_FN( MPI_Win window, int win_keyval, void* attribute_val_out, void* extra_state ) @@ -105,7 +104,6 @@ int OMPI_C_MPI_WIN_DUP_FN( MPI_Win window, int win_keyval, void* extra_state, *(void**)attribute_val_out = attribute_val_in; return MPI_SUCCESS; } -#endif int OMPI_C_MPI_COMM_NULL_DELETE_FN( MPI_Comm comm, int comm_keyval, void* attribute_val_out, diff --git a/ompi/mpi/c/get.c b/ompi/mpi/c/get.c index c8e5e8f373..6cd94c7866 100644 --- a/ompi/mpi/c/get.c +++ b/ompi/mpi/c/get.c @@ -19,6 +19,9 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" +#include "ompi/datatype/datatype.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Get = PMPI_Get @@ -36,11 +39,28 @@ int MPI_Get(void *origin_addr, int origin_count, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; + if (target_rank == MPI_PROC_NULL) return MPI_SUCCESS; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + rc = OMPI_SUCCESS; - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + 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)) { + rc = MPI_ERR_RANK; + } else { + OMPI_CHECK_DATATYPE_FOR_SEND(rc, origin_datatype, origin_count); + } + OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME); + } + + rc = win->w_osc_module->osc_get(origin_addr, origin_count, origin_datatype, + target_rank, target_disp, target_count, + target_datatype, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/profile/Makefile.am b/ompi/mpi/c/profile/Makefile.am index 9f74e5d620..5010e34ea3 100644 --- a/ompi/mpi/c/profile/Makefile.am +++ b/ompi/mpi/c/profile/Makefile.am @@ -320,10 +320,7 @@ nodist_libmpi_c_pmpi_la_SOURCES = \ pwaitany.c \ pwaitsome.c \ pwtime.c \ - pwtick.c - -if WANT_MPI2_ONE_SIDED -nodist_libmpi_c_pmpi_la_SOURCES += \ + pwtick.c \ paccumulate.c \ pget.c \ pput.c \ @@ -351,7 +348,6 @@ nodist_libmpi_c_pmpi_la_SOURCES += \ pwin_test.c \ pwin_unlock.c \ pwin_wait.c -endif # # Sym link in the sources from the real MPI directory diff --git a/ompi/mpi/c/put.c b/ompi/mpi/c/put.c index b3675f871b..efc886a7da 100644 --- a/ompi/mpi/c/put.c +++ b/ompi/mpi/c/put.c @@ -19,6 +19,9 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" +#include "ompi/datatype/datatype.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Put = PMPI_Put @@ -35,11 +38,28 @@ int MPI_Put(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) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; + if (target_rank == MPI_PROC_NULL) return MPI_SUCCESS; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + rc = OMPI_SUCCESS; - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + 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)) { + rc = MPI_ERR_RANK; + } else { + OMPI_CHECK_DATATYPE_FOR_SEND(rc, origin_datatype, origin_count); + } + OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME); + } + + rc = win->w_osc_module->osc_put(origin_addr, origin_count, origin_datatype, + target_rank, target_disp, target_count, + target_datatype, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_complete.c b/ompi/mpi/c/win_complete.c index 33a3a72477..c998991f3a 100644 --- a/ompi/mpi/c/win_complete.c +++ b/ompi/mpi/c/win_complete.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_complete = PMPI_Win_complete @@ -33,11 +35,16 @@ static const char FUNC_NAME[] = "MPI_Win_complete"; int MPI_Win_complete(MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_wait(win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_create.c b/ompi/mpi/c/win_create.c index c56c0cd57f..4679770bc4 100644 --- a/ompi/mpi/c/win_create.c +++ b/ompi/mpi/c/win_create.c @@ -16,10 +16,13 @@ * $HEADER$ */ #include "ompi_config.h" + #include #include "mpi/c/bindings.h" #include "info/info.h" +#include "win/win.h" +#include "attribute/attribute.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_create = PMPI_Win_create @@ -35,15 +38,41 @@ static const char FUNC_NAME[] = "MPI_Win_create"; int MPI_Win_create(void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - if (NULL == info || ompi_info_is_freed(info)) { - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO, - FUNC_NAME); + ompi_communicator_t *ompi_comm; + ompi_win_t *ompi_win; + int ret = OMPI_SUCCESS; + + /* argument checking */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); + + if (MPI_COMM_NULL == comm || 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); + } } - } - /* This function is not yet implemented */ + ompi_comm = (ompi_communicator_t*) comm; + if (OMPI_COMM_IS_INTER(ompi_comm)) { + /* must be an intracommunicator */ + return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COMM, FUNC_NAME); + } - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + /* + * Create a shell of a window + */ + ret = ompi_win_create(base, size, disp_unit, ompi_comm, + info, &ompi_win); + if (OMPI_SUCCESS != ret) return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_WIN, FUNC_NAME); + + *win = (MPI_Win) ompi_win; + + return OMPI_SUCCESS; } diff --git a/ompi/mpi/c/win_fence.c b/ompi/mpi/c/win_fence.c index e8ab4aa081..90ab4715aa 100644 --- a/ompi/mpi/c/win_fence.c +++ b/ompi/mpi/c/win_fence.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_fence = PMPI_Win_fence @@ -33,11 +35,19 @@ static const char FUNC_NAME[] = "MPI_Win_fence"; int MPI_Win_fence(int assert, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } 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); + } + } + + rc = win->w_osc_module->osc_fence(assert, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_free.c b/ompi/mpi/c/win_free.c index feb8ab89b4..2a4c7e76e9 100644 --- a/ompi/mpi/c/win_free.c +++ b/ompi/mpi/c/win_free.c @@ -19,6 +19,7 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_free = PMPI_Win_free @@ -33,11 +34,19 @@ static const char FUNC_NAME[] = "MPI_Win_free"; int MPI_Win_free(MPI_Win *win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int ret; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (NULL == win) { + return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME); + } + } + + /* BWB - fix me - need to add module cleanup code */ + ret = ompi_win_free((ompi_win_t*) *win); + if (OMPI_SUCCESS == ret) *win = MPI_WIN_NULL; + + OMPI_ERRHANDLER_RETURN(ret, *win, ret, FUNC_NAME); } diff --git a/ompi/mpi/c/win_get_attr.c b/ompi/mpi/c/win_get_attr.c index 971443b79a..8f98fa6152 100644 --- a/ompi/mpi/c/win_get_attr.c +++ b/ompi/mpi/c/win_get_attr.c @@ -52,5 +52,17 @@ int MPI_Win_get_attr(MPI_Win win, int win_keyval, ret = ompi_attr_get_c(win->w_keyhash, win_keyval, attribute_val, flag); + + /* MPI-2 Section 6.2.2 says that for MPI_WIN_BASE, base will be a + pointer to the window in C/C++ and an integer representation of + the base address in Fortran. The only rational way to do this + is to store a pointer to the pointer in C (so that the + attribute code will do the right thing in Fortran) and + dereference the C attribute here so that it's right for C as + well. */ + if (win_keyval == MPI_WIN_BASE) { + *((void**) attribute_val) = *((void**) attribute_val); + } + OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME); } diff --git a/ompi/mpi/c/win_get_group.c b/ompi/mpi/c/win_get_group.c index 2ef069f2d0..3709c727bf 100644 --- a/ompi/mpi/c/win_get_group.c +++ b/ompi/mpi/c/win_get_group.c @@ -19,6 +19,7 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_get_group = PMPI_Win_get_group @@ -33,11 +34,20 @@ static const char FUNC_NAME[] = "MPI_Win_get_group"; int MPI_Win_get_group(MPI_Win win, MPI_Group *group) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int ret; + ompi_win_t *ompi_win = (ompi_win_t*) win; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (MPI_WIN_NULL == ompi_win) { + return OMPI_ERRHANDLER_INVOKE(ompi_win, MPI_ERR_WIN, FUNC_NAME); + } + if (NULL == group) { + return OMPI_ERRHANDLER_INVOKE(ompi_win, MPI_ERR_ARG, FUNC_NAME); + } + } + + ret = ompi_win_group(ompi_win, (ompi_group_t**) group); + OMPI_ERRHANDLER_RETURN(ret, ompi_win, ret, FUNC_NAME); } diff --git a/ompi/mpi/c/win_get_name.c b/ompi/mpi/c/win_get_name.c index b5791e82c5..d7bf1e7293 100644 --- a/ompi/mpi/c/win_get_name.c +++ b/ompi/mpi/c/win_get_name.c @@ -19,6 +19,7 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_get_name = PMPI_Win_get_name @@ -33,11 +34,20 @@ static const char FUNC_NAME[] = "MPI_Win_get_name"; int MPI_Win_get_name(MPI_Win win, char *win_name, int *resultlen) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + ompi_win_t *ompi_win = (ompi_win_t*) win; + int ret; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (MPI_WIN_NULL == win || ompi_win_invalid(ompi_win)) + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + + if (NULL == win_name || NULL == resultlen) + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ARG, FUNC_NAME); + } + + ret = ompi_win_get_name(ompi_win, win_name, resultlen); + + OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME); } diff --git a/ompi/mpi/c/win_lock.c b/ompi/mpi/c/win_lock.c index e0c73acc57..92976a97a9 100644 --- a/ompi/mpi/c/win_lock.c +++ b/ompi/mpi/c/win_lock.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_lock = PMPI_Win_lock @@ -33,11 +35,23 @@ static const char FUNC_NAME[] = "MPI_Win_lock"; int MPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } else if (lock_type != MPI_LOCK_EXCLUSIVE && + lock_type != MPI_LOCK_SHARED) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_LOCKTYPE, FUNC_NAME); + } else if (ompi_win_peer_invalid(win, rank)) { + 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); + } + } + + rc = win->w_osc_module->osc_lock(lock_type, rank, assert, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_post.c b/ompi/mpi/c/win_post.c index d9982c0d59..e0dc690f19 100644 --- a/ompi/mpi/c/win_post.c +++ b/ompi/mpi/c/win_post.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_post = PMPI_Win_post @@ -33,11 +35,19 @@ static const char FUNC_NAME[] = "MPI_Win_post"; int MPI_Win_post(MPI_Group group, int assert, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } else if (0 != (assert & ~(MPI_MODE_NOCHECK | MPI_MODE_NOSTORE | + MPI_MODE_NOPUT))) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_post(group, assert, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_set_attr.c b/ompi/mpi/c/win_set_attr.c index 9f9fda3e54..003a0b0a2e 100644 --- a/ompi/mpi/c/win_set_attr.c +++ b/ompi/mpi/c/win_set_attr.c @@ -46,6 +46,6 @@ int MPI_Win_set_attr(MPI_Win win, int win_keyval, void *attribute_val) } ret = ompi_attr_set_c(WIN_ATTR, win, &win->w_keyhash, - win_keyval, attribute_val, false, true); + win_keyval, attribute_val, false, true); OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME); } diff --git a/ompi/mpi/c/win_set_errhandler.c b/ompi/mpi/c/win_set_errhandler.c index 3471020758..9ec2c096eb 100644 --- a/ompi/mpi/c/win_set_errhandler.c +++ b/ompi/mpi/c/win_set_errhandler.c @@ -38,10 +38,6 @@ int MPI_Win_set_errhandler(MPI_Win win, MPI_Errhandler errhandler) OMPI_ERR_INIT_FINALIZE(FUNC_NAME); } - /* This function is not yet implemented */ - - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); - if (MPI_PARAM_CHECK) { if (NULL == win || MPI_WIN_NULL == win) { diff --git a/ompi/mpi/c/win_set_name.c b/ompi/mpi/c/win_set_name.c index 351ae00b90..ec69f4a4e1 100644 --- a/ompi/mpi/c/win_set_name.c +++ b/ompi/mpi/c/win_set_name.c @@ -19,6 +19,7 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_set_name = PMPI_Win_set_name @@ -33,11 +34,20 @@ static const char FUNC_NAME[] = "MPI_Win_set_name"; int MPI_Win_set_name(MPI_Win win, char *win_name) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + ompi_win_t *ompi_win = (ompi_win_t*) win; + int ret; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (MPI_WIN_NULL == win || ompi_win_invalid(ompi_win)) + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + + if (NULL == win_name) + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ARG, FUNC_NAME); + } + + ret = ompi_win_set_name(ompi_win, win_name); + + OMPI_ERRHANDLER_RETURN(ret, win, ret, FUNC_NAME); } diff --git a/ompi/mpi/c/win_start.c b/ompi/mpi/c/win_start.c index 9cde110501..d6a1fc95f2 100644 --- a/ompi/mpi/c/win_start.c +++ b/ompi/mpi/c/win_start.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_start = PMPI_Win_start @@ -33,11 +35,18 @@ static const char FUNC_NAME[] = "MPI_Win_start"; int MPI_Win_start(MPI_Group group, int assert, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } else if (0 != (assert & ~(MPI_MODE_NOCHECK))) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_ASSERT, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_start(group, assert, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_test.c b/ompi/mpi/c/win_test.c index 40b708c0b2..4025f45311 100644 --- a/ompi/mpi/c/win_test.c +++ b/ompi/mpi/c/win_test.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_test = PMPI_Win_test @@ -33,11 +35,16 @@ static const char FUNC_NAME[] = "MPI_Win_test"; int MPI_Win_test(MPI_Win win, int *flag) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_wait(win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_unlock.c b/ompi/mpi/c/win_unlock.c index b453d0b1ae..e1a165409f 100644 --- a/ompi/mpi/c/win_unlock.c +++ b/ompi/mpi/c/win_unlock.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_unlock = PMPI_Win_unlock @@ -33,11 +35,18 @@ static const char FUNC_NAME[] = "MPI_Win_unlock"; int MPI_Win_unlock(int rank, MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } else if (ompi_win_peer_invalid(win, rank)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_RANK, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_unlock(rank, win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/win_wait.c b/ompi/mpi/c/win_wait.c index 1ea49535c1..20759b45b6 100644 --- a/ompi/mpi/c/win_wait.c +++ b/ompi/mpi/c/win_wait.c @@ -19,6 +19,8 @@ #include #include "mpi/c/bindings.h" +#include "win/win.h" +#include "mca/osc/osc.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_Win_wait = PMPI_Win_wait @@ -33,11 +35,16 @@ static const char FUNC_NAME[] = "MPI_Win_wait"; int MPI_Win_wait(MPI_Win win) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME); + if (ompi_win_invalid(win)) { + return OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_WIN, FUNC_NAME); + } + } + + rc = win->w_osc_module->osc_wait(win); + OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME); } diff --git a/ompi/mpi/cxx/mpicxx.cc b/ompi/mpi/cxx/mpicxx.cc index e1c0604fdc..7a115cff15 100644 --- a/ompi/mpi/cxx/mpicxx.cc +++ b/ompi/mpi/cxx/mpicxx.cc @@ -208,9 +208,7 @@ const Op REPLACE(MPI_REPLACE); // null handles const Group GROUP_NULL = MPI_GROUP_NULL; -#if OMPI_WANT_MPI2_ONE_SIDED const Win WIN_NULL = MPI_WIN_NULL; -#endif const Info INFO_NULL = MPI_INFO_NULL; //const Comm COMM_NULL = MPI_COMM_NULL; //const MPI_Comm COMM_NULL = MPI_COMM_NULL; diff --git a/ompi/mpi/cxx/win.h b/ompi/mpi/cxx/win.h index 6fa9e25271..7f8828a2dd 100644 --- a/ompi/mpi/cxx/win.h +++ b/ompi/mpi/cxx/win.h @@ -18,7 +18,6 @@ // -#if OMPI_WANT_MPI2_ONE_SIDED class Win { #if 0 /* OMPI_ENABLE_MPI_PROFILING */ // friend class P; @@ -166,4 +165,3 @@ protected: MPI_Win mpi_win; #endif }; -#endif // OMPI_WANT_MPI2_ONE_SIDED diff --git a/ompi/mpi/cxx/win_inln.h b/ompi/mpi/cxx/win_inln.h index 1c6a228592..4d02cd0466 100644 --- a/ompi/mpi/cxx/win_inln.h +++ b/ompi/mpi/cxx/win_inln.h @@ -23,7 +23,6 @@ // Miscellany // -#if OMPI_WANT_MPI2_ONE_SIDED inline MPI::Errhandler MPI::Win::Create_errhandler(MPI::Win::Errhandler_fn* function) @@ -274,4 +273,3 @@ typedef void MPI::Win::Errhandler_fn(Win &, int *, ... ); #endif -#endif // OMPI_WANT_MPI2_ONE_SIDED diff --git a/ompi/mpi/f77/Makefile.am b/ompi/mpi/f77/Makefile.am index b3332fa96a..e88861cb23 100644 --- a/ompi/mpi/f77/Makefile.am +++ b/ompi/mpi/f77/Makefile.am @@ -332,10 +332,7 @@ libmpi_f77_mpi_la_SOURCES = \ wait_f.c \ waitsome_f.c \ wtick_f.c \ - wtime_f.c - -if WANT_MPI2_ONE_SIDED -libmpi_f77_mpi_la_SOURCES += \ + wtime_f.c \ accumulate_f.c \ get_f.c \ put_f.c \ @@ -361,7 +358,6 @@ libmpi_f77_mpi_la_SOURCES += \ win_test_f.c \ win_unlock_f.c \ win_wait_f.c -endif # # Conditionally install the header files diff --git a/ompi/mpi/f77/attr_fn_f.c b/ompi/mpi/f77/attr_fn_f.c index 3e63404ac6..2c38b49815 100644 --- a/ompi/mpi/f77/attr_fn_f.c +++ b/ompi/mpi/f77/attr_fn_f.c @@ -49,7 +49,6 @@ #pragma weak mpi_comm_null_copy_fn = mpi_comm_null_copy_fn_f #pragma weak mpi_comm_null_copy_fn_ = mpi_comm_null_copy_fn_f #pragma weak mpi_comm_null_copy_fn__ = mpi_comm_null_copy_fn_f -#if OMPI_WANT_MPI2_ONE_SIDED #pragma weak MPI_WIN_NULL_DELETE_FN = mpi_win_null_delete_fn_f #pragma weak mpi_win_null_delete_fn = mpi_win_null_delete_fn_f #pragma weak mpi_win_null_delete_fn_ = mpi_win_null_delete_fn_f @@ -62,7 +61,6 @@ #pragma weak mpi_win_dup_fn = mpi_win_dup_fn_f #pragma weak mpi_win_dup_fn_ = mpi_win_dup_fn_f #pragma weak mpi_win_dup_fn__ = mpi_win_dup_fn_f -#endif #pragma weak MPI_NULL_COPY_FN = mpi_null_copy_fn_f #pragma weak mpi_null_copy_fn = mpi_null_copy_fn_f #pragma weak mpi_null_copy_fn_ = mpi_null_copy_fn_f @@ -141,7 +139,6 @@ OMPI_GENERATE_F77_BINDINGS( MPI_DUP_FN, (MPI_Fint* comm, MPI_Fint* comm_keyval, MPI_Fint* extra_state, MPI_Fint* attribute_val_in, MPI_Fint* attribute_val_out, ompi_fortran_logical_t* flag, MPI_Fint* ierr), (comm, comm_keyval, extra_state, attribute_val_in, attribute_val_out, flag, ierr) ) -#if OMPI_WANT_MPI2_ONE_SIDED OMPI_GENERATE_F77_BINDINGS( MPI_WIN_NULL_DELETE_FN, mpi_win_null_delete_fn, mpi_win_null_delete_fn_, @@ -164,7 +161,6 @@ OMPI_GENERATE_F77_BINDINGS( MPI_WIN_DUP_FN, (MPI_Fint* window, MPI_Fint* win_keyval, MPI_Fint* extra_state, MPI_Fint* attribute_val_in, MPI_Fint* attribute_val_out, ompi_fortran_logical_t* flag, MPI_Fint* ierr), (window, win_keyval, extra_state, attribute_val_in, attribute_val_out, flag, ierr) ) #endif -#endif /* * Note that in this file, we invoke OMPI_C_ rather than @@ -273,7 +269,6 @@ void mpi_dup_fn_f( MPI_Fint* comm, MPI_Fint* comm_keyval, *ierr = OMPI_INT_2_FINT(MPI_SUCCESS); } -#if OMPI_WANT_MPI2_ONE_SIDED void mpi_win_null_delete_fn_f( MPI_Fint* window, MPI_Fint* win_keyval, MPI_Fint* attribute_val_out, MPI_Fint* extra_state, MPI_Fint* ierr ) @@ -301,4 +296,3 @@ void mpi_win_dup_fn_f( MPI_Fint* window, MPI_Fint* win_keyval, *attribute_val_out = *attribute_val_in; *ierr = OMPI_INT_2_FINT(MPI_SUCCESS); } -#endif diff --git a/ompi/mpi/f77/profile/Makefile.am b/ompi/mpi/f77/profile/Makefile.am index fe384b5b48..e53af582a1 100644 --- a/ompi/mpi/f77/profile/Makefile.am +++ b/ompi/mpi/f77/profile/Makefile.am @@ -301,10 +301,7 @@ nodist_libmpi_f77_pmpi_la_SOURCES = \ pwait_f.c \ pwaitsome_f.c \ pwtick_f.c \ - pwtime_f.c - -if WANT_MPI2_ONE_SIDED -nodist_libmpi_f77_pmpi_la_SOURCES += \ + pwtime_f.c \ paccumulate_f.c \ pget_f.c \ pput_f.c \ @@ -330,7 +327,6 @@ nodist_libmpi_f77_pmpi_la_SOURCES += \ pwin_test_f.c \ pwin_unlock_f.c \ pwin_wait_f.c -endif # # Sym link in the sources from the real MPI directory diff --git a/ompi/mpi/f77/win_create_keyval_f.c b/ompi/mpi/f77/win_create_keyval_f.c index 4cec301877..ac69a95902 100644 --- a/ompi/mpi/f77/win_create_keyval_f.c +++ b/ompi/mpi/f77/win_create_keyval_f.c @@ -32,7 +32,7 @@ OMPI_GENERATE_F77_BINDINGS (PMPI_WIN_CREATE_KEYVAL, pmpi_win_create_keyval_, pmpi_win_create_keyval__, pmpi_win_create_keyval_f, - (ompi_mpi2_fortran_copy_attr_function* win_copy_attr_fn, ompi_mpi2_fortran_delete_attr_function* win_delete_attr_fn, MPI_F_int *win_keyval, MPI_F_int *extra_state, MPI_F_int *ierr), + (ompi_mpi2_fortran_copy_attr_function* win_copy_attr_fn, ompi_mpi2_fortran_delete_attr_function* win_delete_attr_fn, MPI_Fint *win_keyval, MPI_Fint *extra_state, MPI_Fint *ierr), (win_copy_attr_fn, win_delete_attr_fn, win_keyval, extra_state, ierr) ) #endif @@ -49,7 +49,7 @@ OMPI_GENERATE_F77_BINDINGS (MPI_WIN_CREATE_KEYVAL, mpi_win_create_keyval_, mpi_win_create_keyval__, mpi_win_create_keyval_f, - (ompi_mpi2_fortran_copy_attr_function* win_copy_attr_fn, ompi_mpi2_fortran_delete_attr_function* win_delete_attr_fn, MPI_F_int *win_keyval, MPI_F_int *extra_state, MPI_F_int *ierr), + (ompi_mpi2_fortran_copy_attr_function* win_copy_attr_fn, ompi_mpi2_fortran_delete_attr_function* win_delete_attr_fn, MPI_Fint *win_keyval, MPI_Fint *extra_state, MPI_Fint *ierr), (win_copy_attr_fn, win_delete_attr_fn, win_keyval, extra_state, ierr) ) #endif diff --git a/ompi/mpi/f90/Makefile.am b/ompi/mpi/f90/Makefile.am index 70cfaadddc..edc75dad65 100644 --- a/ompi/mpi/f90/Makefile.am +++ b/ompi/mpi/f90/Makefile.am @@ -244,15 +244,12 @@ nodist_libmpi_f90_a_SOURCES = \ mpi_send_init_f90.f90 \ mpi_sendrecv_replace_f90.f90 \ mpi_ssend_f90.f90 \ - mpi_ssend_init_f90.f90 - -if WANT_MPI2_ONE_SIDED -nodist_libmpi_f90_a_SOURCES += \ + mpi_ssend_init_f90.f90 \ mpi_accumulate_f90.f90 \ mpi_get_f90.f90 \ mpi_put_f90.f90 \ mpi_win_create_f90.f90 -endif + # # Clean up all F90 module files and all generated files diff --git a/ompi/request/request.h b/ompi/request/request.h index 9f529c4018..6a83b89043 100644 --- a/ompi/request/request.h +++ b/ompi/request/request.h @@ -45,6 +45,7 @@ typedef enum { OMPI_REQUEST_PML, /**< MPI point-to-point request */ OMPI_REQUEST_IO, /**< MPI-2 IO request */ OMPI_REQUEST_GEN, /**< MPI-2 generalized request */ + OMPI_REQUEST_WIN, /**< MPI-2 one-sided request */ OMPI_REQUEST_NULL, /**< NULL request */ OMPI_REQUEST_MAX /**< Maximum request type */ } ompi_request_type_t; diff --git a/ompi/runtime/ompi_mpi_finalize.c b/ompi/runtime/ompi_mpi_finalize.c index cc16d19e15..9ffa0dc96f 100644 --- a/ompi/runtime/ompi_mpi_finalize.c +++ b/ompi/runtime/ompi_mpi_finalize.c @@ -50,6 +50,7 @@ #include "ompi/mca/pml/base/pml_base_module_exchange.h" #include "ompi/mca/pml/pml.h" #include "ompi/mca/pml/base/base.h" +#include "ompi/mca/osc/base/base.h" #include "ompi/mca/coll/coll.h" #include "ompi/mca/coll/base/base.h" #include "ompi/mca/topo/topo.h" @@ -114,6 +115,14 @@ int ompi_mpi_finalize(void) return ret; } + /* free window resources */ + if (OMPI_SUCCESS != (ret = ompi_win_finalize())) { + return ret; + } + if (OMPI_SUCCESS != (ret = ompi_osc_base_finalize())) { + return ret; + } + /* free communicator resources */ if (OMPI_SUCCESS != (ret = ompi_comm_finalize())) { return ret; @@ -204,6 +213,9 @@ int ompi_mpi_finalize(void) if (OMPI_SUCCESS != (ret = mca_topo_base_close())) { return ret; } + if (OMPI_SUCCESS != (ret = ompi_osc_base_close())) { + return ret; + } if (OMPI_SUCCESS != (ret = mca_coll_base_close())) { return ret; } diff --git a/ompi/runtime/ompi_mpi_init.c b/ompi/runtime/ompi_mpi_init.c index dc1c33ea6d..5d24b8ebd7 100644 --- a/ompi/runtime/ompi_mpi_init.c +++ b/ompi/runtime/ompi_mpi_init.c @@ -66,6 +66,7 @@ #include "ompi/mca/pml/pml.h" #include "ompi/mca/pml/base/pml_base_module_exchange.h" #include "ompi/mca/pml/base/base.h" +#include "ompi/mca/osc/base/base.h" #include "ompi/mca/coll/coll.h" #include "ompi/mca/coll/base/base.h" #include "ompi/mca/io/io.h" @@ -287,6 +288,11 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) goto error; } + if (OMPI_SUCCESS != (ret = ompi_osc_base_open())) { + error = "ompi_osc_base_open() failed"; + goto error; + } + /* In order to reduce the common case for MPI apps (where they don't use MPI-2 IO or MPI-1 topology functions), the io and topo frameworks are initialized lazily, at the first use of @@ -323,6 +329,13 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) goto error; } + if (OMPI_SUCCESS != + (ret = ompi_osc_base_find_available(OMPI_ENABLE_PROGRESS_THREADS, + OMPI_ENABLE_MPI_THREADS))) { + error = "ompi_osc_base_find_available() failed"; + goto error; + } + /* io and topo components are not selected here -- see comment above about the io and topo frameworks being loaded lazily */ @@ -381,6 +394,12 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) goto error; } + /* initialize windows */ + if (OMPI_SUCCESS != (ret = ompi_win_init())) { + error = "ompi_win_init() failed"; + goto error; + } + /* initialize attribute meta-data structure for comm/win/dtype */ if (OMPI_SUCCESS != (ret = ompi_attr_init())) { error = "ompi_attr_init() failed"; diff --git a/ompi/tools/ompi_info/components.cc b/ompi/tools/ompi_info/components.cc index 80b1910e65..b46c2f8203 100644 --- a/ompi/tools/ompi_info/components.cc +++ b/ompi/tools/ompi_info/components.cc @@ -58,6 +58,8 @@ #include "ompi/mca/btl/base/base.h" #include "ompi/mca/topo/topo.h" #include "ompi/mca/topo/base/base.h" +#include "ompi/mca/osc/osc.h" +#include "ompi/mca/osc/base/base.h" #include "orte/mca/errmgr/errmgr.h" #include "orte/mca/errmgr/base/base.h" @@ -232,6 +234,9 @@ void ompi_info::open_components() mca_pml_base_open(); component_map["pml"] = &mca_pml_base_components_available; + ompi_osc_base_open(); + component_map["osc"] = &ompi_osc_base_open_components; + /* mca_ptl_base_open() should not be called directly. This call is performed * in the PML base open. */ @@ -266,6 +271,7 @@ void ompi_info::close_components() mca_io_base_close(); mca_coll_base_close(); mca_allocator_base_close(); + ompi_osc_base_close(); orte_iof_base_close(); orte_sds_base_close(); diff --git a/ompi/tools/ompi_info/ompi_info.cc b/ompi/tools/ompi_info/ompi_info.cc index c1ea622bff..66f21bdf36 100644 --- a/ompi/tools/ompi_info/ompi_info.cc +++ b/ompi/tools/ompi_info/ompi_info.cc @@ -181,6 +181,7 @@ int main(int argc, char *argv[]) ompi_info::mca_types.push_back("ptl"); ompi_info::mca_types.push_back("btl"); ompi_info::mca_types.push_back("topo"); + ompi_info::mca_types.push_back("osc"); ompi_info::mca_types.push_back("errmgr"); ompi_info::mca_types.push_back("gpr"); diff --git a/ompi/win/win.c b/ompi/win/win.c index ad0d9163a3..003fc9ed03 100644 --- a/ompi/win/win.c +++ b/ompi/win/win.c @@ -17,4 +17,193 @@ */ #include "ompi_config.h" + +#include "mpi.h" #include "win/win.h" +#include "errhandler/errhandler.h" +#include "include/constants.h" +#include "attribute/attribute.h" +#include "group/group.h" +#include "info/info.h" +#include "mca/osc/base/base.h" +#include "mca/osc/osc.h" + +ompi_win_t ompi_mpi_win_null; + +static void ompi_win_construct(ompi_win_t *win); +static void ompi_win_destruct(ompi_win_t *win); + +OBJ_CLASS_INSTANCE(ompi_win_t, opal_object_t, + ompi_win_construct, ompi_win_destruct); + +int +ompi_win_init(void) +{ + OBJ_CONSTRUCT(&ompi_mpi_win_null, ompi_win_t); + ompi_mpi_win_null.w_flags = OMPI_WIN_INVALID; + ompi_mpi_win_null.w_group = &ompi_mpi_group_null; + ompi_win_set_name(&ompi_mpi_win_null, "MPI_WIN_NULL"); + + return OMPI_SUCCESS; +} + + +int +ompi_win_finalize(void) +{ + OBJ_DESTRUCT(&ompi_mpi_win_null); + + return OMPI_SUCCESS; +} + + +int +ompi_win_create(void *base, long size, + int disp_unit, ompi_communicator_t *comm, + ompi_info_t *info, + ompi_win_t** newwin) +{ + ompi_win_t *win; + ompi_group_t *group; + int ret; + + /* create the object */ + win = OBJ_NEW(ompi_win_t); + if (NULL == win) return OMPI_ERR_TEMP_OUT_OF_RESOURCE; + + /* setup data that is independent of osc component */ + group = comm->c_local_group; + OBJ_RETAIN(group); + ompi_group_increment_proc_count(group); + win->w_group = group; + + win->w_baseptr = base; + win->w_size = size; + win->w_disp_unit = disp_unit; + + /* Fill in required attributes */ + ret = ompi_attr_set_c(WIN_ATTR, win, &win->w_keyhash, + MPI_WIN_BASE, win->w_baseptr, true, true); + if (OMPI_SUCCESS != ret) { + OBJ_RELEASE(win); + return ret; + } + ret = ompi_attr_set_fortran_mpi2(WIN_ATTR, win, + &win->w_keyhash, + MPI_WIN_SIZE, win->w_size, true, true); + if (OMPI_SUCCESS != ret) { + OBJ_RELEASE(win); + return ret; + } + ret = ompi_attr_set_fortran_mpi2(WIN_ATTR, win, + &win->w_keyhash, + MPI_WIN_DISP_UNIT, win->w_disp_unit, + true, true); + if (OMPI_SUCCESS != ret) { + OBJ_RELEASE(win); + return ret; + } + + /* create backend onesided module for this window */ + ret = ompi_osc_base_select(win, (ompi_info_t*) info, comm); + if (OMPI_SUCCESS != ret) { + OBJ_RELEASE(win); + return ret; + } + + *newwin = win; + + return OMPI_SUCCESS; +} + + +int +ompi_win_free(ompi_win_t *win) +{ + int ret = win->w_osc_module->osc_free(win); + + if (OMPI_SUCCESS == ret) { + OBJ_RELEASE(win); + } + + return ret; +} + + +int +ompi_win_set_name(ompi_win_t *win, char *win_name) +{ + OPAL_THREAD_LOCK(&(win->w_lock)); + memset(win->w_name, 0, MPI_MAX_OBJECT_NAME); + strncpy(win->w_name, win_name, MPI_MAX_OBJECT_NAME); + win->w_name[MPI_MAX_OBJECT_NAME - 1] = 0; + OPAL_THREAD_UNLOCK(&(win->w_lock)); + + return OMPI_SUCCESS; +} + + +int +ompi_win_get_name(ompi_win_t *win, char *win_name, int *length) +{ + OPAL_THREAD_LOCK(&(win->w_lock)); + strncpy(win_name, win->w_name, MPI_MAX_OBJECT_NAME); + *length = strlen(win->w_name); + OPAL_THREAD_UNLOCK(&(win->w_lock)); + + return OMPI_SUCCESS; +} + + +int +ompi_win_group(ompi_win_t *win, ompi_group_t **group) { + OBJ_RETAIN(win->w_group); + ompi_group_increment_proc_count(win->w_group); + *group = win->w_group; + + return OMPI_SUCCESS; +} + + +static void +ompi_win_construct(ompi_win_t *win) +{ + OBJ_CONSTRUCT(&win->w_lock, opal_mutex_t); + win->w_name[0] = '\0'; + win->w_group = NULL; + win->w_keyhash = NULL; + win->w_f_to_c_index = 0; + + /* every new window defaults to MPI_ERRORS_ARE_FATAL (MPI-2 6.6.1, + pg. 137) */ + OBJ_RETAIN(&ompi_mpi_errors_are_fatal); + win->error_handler = &ompi_mpi_errors_are_fatal; + win->errhandler_type = OMPI_ERRHANDLER_TYPE_WIN; + + win->w_disp_unit = 0; + win->w_flags = 0; + win->w_baseptr = NULL; + win->w_size = 0; + win->w_osc_module = NULL; +} + + +static void +ompi_win_destruct(ompi_win_t *win) +{ + if (NULL != win->w_keyhash) { + ompi_attr_delete_all(WIN_ATTR, win, win->w_keyhash); + OBJ_RELEASE(win->w_keyhash); + } + + if (NULL != win->error_handler) { + OBJ_RELEASE(win->error_handler); + } + + if (NULL != win->w_group) { + ompi_group_decrement_proc_count(win->w_group); + OBJ_RELEASE(win->w_group); + } + + OBJ_DESTRUCT(&win->w_lock); +} diff --git a/ompi/win/win.h b/ompi/win/win.h index acc88ea6d5..4ace72bf49 100644 --- a/ompi/win/win.h +++ b/ompi/win/win.h @@ -19,40 +19,92 @@ #ifndef OMPI_WIN_H #define OMPI_WIN_H - +#include "ompi_config.h" #include "mpi.h" -#include "errhandler/errhandler.h" + #include "opal/class/opal_object.h" -#include "class/opal_hash_table.h" +#include "opal/class/opal_hash_table.h" +#include "ompi/errhandler/errhandler.h" +#include "ompi/info/info.h" +#include "ompi/communicator/communicator.h" +#include "ompi/group/group.h" +#include "ompi/mca/osc/osc.h" + #if defined(c_plusplus) || defined(__cplusplus) extern "C" { #endif +#define OMPI_WIN_FREED 0x00000001 +#define OMPI_WIN_INVALID 0x00000002 +#define OMPI_WIN_NO_LOCKS 0x00000004 +#define OMPI_WIN_ACCESS_EPOCH 0x00000008 +#define OMPI_WIN_EXPOSE_EPOCH 0x00000010 +#define OMPI_WIN_POSTED 0x00000020 +#define OMPI_WIN_STARTED 0x00000040 -#if OMPI_WANT_MPI2_ONE_SIDED struct ompi_win_t { - char w_name[MPI_MAX_OBJECT_NAME]; + opal_object_t w_base; - opal_object_t w_base; + opal_mutex_t w_lock; - /* Attributes */ + char w_name[MPI_MAX_OBJECT_NAME]; - opal_hash_table_t *w_keyhash; + ompi_group_t *w_group; - /* index in Fortran <-> C translation array */ + /* Attributes */ + opal_hash_table_t *w_keyhash; - int w_f_to_c_index; + /* index in Fortran <-> C translation array */ + int w_f_to_c_index; - /* Error handling. This field does not have the "w_" prefix so that - the OMPI_ERRHDL_* macros can find it, regardless of whether it's a - comm, window, or file. */ + /* Error handling. This field does not have the "w_" prefix so that + the OMPI_ERRHDL_* macros can find it, regardless of whether it's a + comm, window, or file. */ ompi_errhandler_t *error_handler; ompi_errhandler_type_t errhandler_type; + + /* displacement factor */ + int w_disp_unit; + + uint32_t w_flags; + + void *w_baseptr; + long w_size; + + /* one sided interface */ + ompi_osc_base_module_t *w_osc_module; }; typedef struct ompi_win_t ompi_win_t; OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_win_t); -#endif + + int ompi_win_init(void); + int ompi_win_finalize(void); + + int ompi_win_create(void *base, long size, int disp_unit, + ompi_communicator_t *comm, ompi_info_t *info, + ompi_win_t **newwin); + + int ompi_win_free(ompi_win_t *win); + + int ompi_win_set_name(ompi_win_t *win, char *win_name); + int ompi_win_get_name(ompi_win_t *win, char *win_name, int *length); + + int ompi_win_group(ompi_win_t *win, ompi_group_t **group); + + static inline int ompi_win_invalid(ompi_win_t *win) { + if (NULL == win || (OMPI_WIN_INVALID & win->w_flags)) return true; + return false; + } + + static inline int ompi_win_peer_invalid(ompi_win_t *win, int peer) { + if (win->w_group->grp_proc_count <= peer) return true; + return false; + } + + static inline int ompi_win_rank(ompi_win_t *win) { + return win->w_group->grp_my_rank; + } #if defined(c_plusplus) || defined(__cplusplus) }