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) }