1
1

Merge in present work on the MPI-2 onesided chapter. The current code is not

complete, but stable enough that it will have no impact on general development,
so into the trunk it goes.  Changes in this commit include:

 - Remove the --with option for disabling MPI-2 onesided support.  It
   complicated code, and has no real reason for existing
 - add a framework osc (OneSided Communication) for encapsulating
   all the MPI-2 onesided functionality
 - Modify the MPI interface functions for the MPI-2 onesided chapter
   to properly call the underlying framework and do the required
   error checking
 - Created an osc component pt2pt, which is layered over the BML/BTL
   for communication (although it also uses the PML for long message
   transfers).  Currently, all support functions, all communication
   functions (Put, Get, Accumulate), and the Fence synchronization
   function are implemented.  The PWSC active synchronization
   functions and Lock/Unlock passive synchronization functions are
   still not implemented

This commit was SVN r8836.
Этот коммит содержится в:
Brian Barrett 2006-01-28 15:38:37 +00:00
родитель dd13b098e1
Коммит b1d2424013
76 изменённых файлов: 4012 добавлений и 285 удалений

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

@ -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?
#

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

@ -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);

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

@ -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
!

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

@ -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);

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

@ -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 */

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

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

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

@ -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;

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

@ -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 */

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

@ -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;

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

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

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

@ -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 */

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

@ -18,6 +18,15 @@
#include "ompi_config.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <errno.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <limits.h>
#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;
}

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

@ -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

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

@ -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

39
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

23
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

56
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

59
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 <stdio.h>
#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;
}

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

98
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;
}

176
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 */

60
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_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.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

18
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"

79
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;
}

209
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 */

127
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;
}

385
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();
}
}

708
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;
}

51
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

135
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 */

26
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);

75
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

97
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;
}

82
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;
}

80
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);

142
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 */

89
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);

177
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 */

233
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;
}

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

@ -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

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

@ -19,6 +19,10 @@
#include <stdio.h>
#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);
}

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

@ -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,

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

@ -19,6 +19,9 @@
#include <stdio.h>
#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);
}

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

@ -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

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

@ -19,6 +19,9 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -16,10 +16,13 @@
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#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;
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,7 @@
#include <stdio.h>
#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);
}

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

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

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

@ -19,6 +19,7 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,7 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

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

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

@ -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) {

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

@ -19,6 +19,7 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -19,6 +19,8 @@
#include <stdio.h>
#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);
}

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

@ -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;

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

@ -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

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

@ -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

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

@ -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

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

@ -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_<function> 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

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

@ -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

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

@ -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

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

@ -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

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

@ -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;

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

@ -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;
}

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

@ -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";

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

@ -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();

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

@ -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");

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

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

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

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