/*@ MPI_Accumulate - Accumulate data into the target process using remote memory access Input Parameters: + origin_addr - initial address of buffer (choice) . origin_count - number of entries in buffer (nonnegative integer) . origin_datatype - datatype of each buffer entry (handle) . target_rank - rank of target (nonnegative integer) . target_disp - displacement from start of window to beginning of target buffer (nonnegative integer) . target_count - number of entries in target buffer (nonnegative integer) . target_datatype - datatype of each entry in target buffer (handle) . op - predefined reduce operation (handle) - win - window object (handle) Notes: The basic components of both the origin and target datatype must be the same predefined datatype (e.g., all 'MPI_INT' or all 'MPI_DOUBLE_PRECISION'). .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_ARG .N MPI_ERR_COUNT .N MPI_ERR_RANK .N MPI_ERR_TYPE .N MPI_ERR_WIN .seealso: MPI_Raccumulate @*/ int MPI_Accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win) { static const char FCNAME[] = "MPI_Accumulate"; int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_ACCUMULATE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_ACCUMULATE); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ MPIR_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_Comm * comm_ptr; /* Validate win_ptr */ MPIR_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; MPIR_ERRTEST_COUNT(origin_count, mpi_errno); MPIR_ERRTEST_DATATYPE(origin_datatype, "origin_datatype", mpi_errno); MPIR_ERRTEST_USERBUFFER(origin_addr, origin_count, origin_datatype, mpi_errno); MPIR_ERRTEST_COUNT(target_count, mpi_errno); MPIR_ERRTEST_DATATYPE(target_datatype, "target_datatype", mpi_errno); if (win_ptr->create_flavor != MPI_WIN_FLAVOR_DYNAMIC) MPIR_ERRTEST_DISP(target_disp, mpi_errno); if (HANDLE_GET_KIND(origin_datatype) != HANDLE_KIND_BUILTIN) { MPIR_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(origin_datatype, datatype_ptr); MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } if (HANDLE_GET_KIND(target_datatype) != HANDLE_KIND_BUILTIN) { MPIR_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(target_datatype, datatype_ptr); MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, target_rank, mpi_errno); MPIR_ERRTEST_OP_ACC(op, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Accumulate(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_ACCUMULATE); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_accumulate", "**mpi_accumulate %p %d %D %d %d %d %D %O %W", origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Fetch_and_op - Perform one-sided read-modify-write. Accumulate one element of type datatype from the origin buffer (origin_addr) to the buffer at offset target_disp, in the target window specified by target_rank and win, using the operation op and return in the result buffer result_addr the content of the target buffer before the accumulation. Input Parameters: + origin_addr - initial address of buffer (choice) . result_addr - initial address of result buffer (choice) . datatype - datatype of the entry in origin, result, and target buffers (handle) . target_rank - rank of target (nonnegative integer) . target_disp - displacement from start of window to beginning of target buffer (non-negative integer) . op - reduce operation (handle) - win - window object (handle) Notes: This operations is atomic with respect to other "accumulate" operations. The generic functionality of 'MPI_Get_accumulate' might limit the performance of fetch-and-increment or fetch-and-add calls that might be supported by special hardware operations. 'MPI_Fetch_and_op' thus allows for a fast implementation of a commonly used subset of the functionality of 'MPI_Get_accumulate'. The origin and result buffers (origin_addr and result_addr) must be disjoint. Any of the predefined operations for 'MPI_Reduce', as well as 'MPI_NO_OP' or 'MPI_REPLACE', can be specified as op; user-defined functions cannot be used. The datatype argument must be a predefined datatype. .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_ARG .N MPI_ERR_COUNT .N MPI_ERR_OP .N MPI_ERR_RANK .N MPI_ERR_TYPE .N MPI_ERR_WIN .seealso: MPI_Get_accumulate @*/ int MPI_Fetch_and_op(const void *origin_addr, void *result_addr, MPI_Datatype datatype, int target_rank, MPI_Aint target_disp, MPI_Op op, MPI_Win win) { static const char FCNAME[] = "MPI_Fetch_and_op"; int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_FETCH_AND_OP); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_FETCH_AND_OP); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ MPIR_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_Comm *comm_ptr; /* Validate win_ptr */ MPIR_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; if (op != MPI_NO_OP) { /* NOTE: when op is MPI_NO_OP, origin_addr is allowed to be NULL. * In such case, MPI_Fetch_and_op equals to an atomic GET. */ MPIR_ERRTEST_ARGNULL(origin_addr, "origin_addr", mpi_errno); } MPIR_ERRTEST_ARGNULL(result_addr, "result_addr", mpi_errno); MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno); if (!MPIR_DATATYPE_IS_PREDEFINED(datatype)) { MPIR_ERR_SETANDJUMP(mpi_errno, MPI_ERR_TYPE, "**typenotpredefined"); } if (win_ptr->create_flavor != MPI_WIN_FLAVOR_DYNAMIC) MPIR_ERRTEST_DISP(target_disp, mpi_errno); comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, target_rank, mpi_errno); MPIR_ERRTEST_OP_GACC(op, mpi_errno); if (HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) { MPIR_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OP, "**opnotpredefined"); } } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Fetch_and_op(origin_addr, result_addr, datatype, target_rank, target_disp, op, win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_FETCH_AND_OP); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_fetch_and_op", "**mpi_fetch_and_op %p %p %D %d %d %O %W", origin_addr, result_addr, datatype, target_rank, target_disp, op, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_create - Create an MPI Window object for one-sided communication This is a collective call executed by all processes in the group of comm. It returns a window object that can be used by these processes to perform RMA operations. Each process specifies a window of existing memory that it exposes to RMA accesses by the processes in the group of comm. The window consists of size bytes, starting at address base. In C, base is the starting address of a memory region. In Fortran, one can pass the first element of a memory region or a whole array, which must be ''simply contiguous'' (for ''simply contiguous'', see also MPI 3.0, Section 17.1.12 on page 626). A process may elect to expose no memory by specifying size = 0. Input Parameters: + base - initial address of window (choice) . size - size of window in bytes (nonnegative integer) . disp_unit - local unit size for displacements, in bytes (positive integer) . info - info argument (handle) - comm - communicator (handle) Output Parameters: . win - window object returned by the call (handle) Notes: The displacement unit argument is provided to facilitate address arithmetic in RMA operations: the target displacement argument of an RMA operation is scaled by the factor disp_unit specified by the target process, at window creation. The info argument provides optimization hints to the runtime about the expected usage pattern of the window. The following info keys are predefined. . no_locks - If set to true, then the implementation may assume that passive target synchronization (i.e., 'MPI_Win_lock', 'MPI_Win_lock_all') will not be used on the given window. This implies that this window is not used for 3-party communication, and RMA can be implemented with no (less) asynchronous agent activity at this process. . accumulate_ordering - Controls the ordering of accumulate operations at the target. The argument string should contain a comma-separated list of the following read/write ordering rules, where e.g. "raw" means read-after-write: "rar,raw,war,waw". . accumulate_ops - If set to same_op, the implementation will assume that all concurrent accumulate calls to the same target address will use the same operation. If set to same_op_no_op, then the implementation will assume that all concurrent accumulate calls to the same target address will use the same operation or 'MPI_NO_OP'. This can eliminate the need to protect access for certain operation types where the hardware can guarantee atomicity. The default is same_op_no_op. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_ARG .N MPI_ERR_COMM .N MPI_ERR_INFO .N MPI_ERR_OTHER .N MPI_ERR_SIZE .seealso: MPI_Win_allocate MPI_Win_allocate_shared MPI_Win_create_dynamic MPI_Win_free @*/ int MPI_Win_create(void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win) { static const char FCNAME[] = "MPI_Win_create"; int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_Comm *comm_ptr = NULL; MPIR_Info *info_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_WIN_CREATE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_WIN_CREATE); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_COMM(comm, mpi_errno); MPIR_ERRTEST_INFO_OR_NULL(info, mpi_errno); MPIR_ERRTEST_ARGNULL(win, "win", mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ MPIR_Comm_get_ptr( comm, comm_ptr ); MPIR_Info_get_ptr( info, info_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate pointers */ MPIR_Comm_valid_ptr( comm_ptr, mpi_errno, FALSE ); if (mpi_errno != MPI_SUCCESS) goto fn_fail; if (size < 0) mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_SIZE, "**rmasize", "**rmasize %d", size); if (disp_unit <= 0) mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**arg", "**arg %s", "disp_unit must be positive"); if (size > 0 && base == NULL) mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**nullptr", "**nullptr %s", "NULL base pointer is invalid when size is nonzero"); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Win_create(base, size, disp_unit, info_ptr, comm_ptr, &win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* Initialize a few fields that have specific defaults */ win_ptr->name[0] = 0; win_ptr->errhandler = 0; /* return the handle of the window object to the user */ MPIR_OBJ_PUBLISH_HANDLE(*win, win_ptr->handle); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_WIN_CREATE); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_create", "**mpi_win_create %p %d %d %I %C %p", base, size, disp_unit, info, comm, win); } # endif mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_get_info - Returns a new info object containing the hints of the window associated with win. The current setting of all hints actually used by the system related to this window is returned in info_used. If no such hints exist, a handle to a newly created info object is returned that contains no key/value pair. The user is responsible for freeing info_used via 'MPI_Info_free'. Input Parameters: . win - window object (handle) Output Parameters: . info_used - new info argument (handle) Notes: The info object returned in info_used will contain all hints currently active for this window. This set of hints may be greater or smaller than the set of hints specified when the window was created, as the system may not recognize some hints set by the user, and may recognize other hints that the user has not set. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_ARG .N MPI_ERR_WIN .N MPI_ERR_INFO .N MPI_ERR_OTHER .seealso: MPI_Win_set_info @*/ int MPI_Win_get_info(MPI_Win win, MPI_Info * info_used) { int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_Info *info_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_WIN_GET_INFO); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_WIN_GET_INFO); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_ARGNULL(info_used, "info", mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ MPIR_Win_get_ptr(win, win_ptr); /* Validate parameters and objects (post conversion) */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate pointers */ MPIR_Win_valid_ptr(win_ptr, mpi_errno); if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Win_get_info(win_ptr, &info_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; *info_used = info_ptr->handle; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_WIN_GET_INFO); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_get_info", "**mpi_win_get_info %W %p", win, info_used); } #endif mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_fence - Perform an MPI fence synchronization on a MPI window Input Parameters: + assert - program assertion (integer) - win - window object (handle) Notes: The 'assert' argument is used to indicate special conditions for the fence that an implementation may use to optimize the 'MPI_Win_fence' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions that are valid for 'MPI_Win_fence' are\: + MPI_MODE_NOSTORE - the local window was not updated by local stores (or local get or receive calls) since last synchronization. . MPI_MODE_NOPUT - the local window will not be updated by put or accumulate calls after the fence call, until the ensuing (fence) synchronization. . MPI_MODE_NOPRECEDE - the fence does not complete any sequence of locally issued RMA calls. If this assertion is given by any process in the window group, then it must be given by all processes in the group. - MPI_MODE_NOSUCCEED - the fence does not start any sequence of locally issued RMA calls. If the assertion is given by any process in the window group, then it must be given by all processes in the group. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_OTHER .N MPI_ERR_WIN @*/ int MPI_Win_fence(int assert, MPI_Win win) { static const char FCNAME[] = "MPI_Win_fence"; int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_WIN_FENCE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_WIN_FENCE); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* Convert MPI object handles to object pointers */ MPIR_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPIR_Win_valid_ptr( win_ptr, mpi_errno ); /* TODO: validate window is not in passive mode */ /* TODO: validate assert argument */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Win_fence(assert, win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_WIN_FENCE); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_fence", "**mpi_win_fence %A %W", assert, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_start - Start an RMA access epoch for MPI Input Parameters: + group - group of target processes (handle) . assert - Used to optimize this call; zero may be used as a default. See notes. (integer) - win - window object (handle) Notes: The 'assert' argument is used to indicate special conditions for the fence that an implementation may use to optimize the 'MPI_Win_start' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions tha are valid for 'MPI_Win_start' are\: . MPI_MODE_NOCHECK - the matching calls to 'MPI_WIN_POST' have already completed on all target processes when the call to 'MPI_WIN_START' is made. The nocheck option can be specified in a start call if and only if it is specified in each matching post call. This is similar to the optimization of ready-send that may save a handshake when the handshake is implicit in the code. (However, ready-send is matched by a regular receive, whereas both start and post must specify the nocheck option.) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN .N MPI_ERR_OTHER @*/ int MPI_Win_start(MPI_Group group, int assert, MPI_Win win) { int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_Group *group_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_WIN_START); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_WIN_START); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); MPIR_ERRTEST_GROUP(group, mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* Get handles to MPI objects. */ MPIR_Win_get_ptr(win, win_ptr); MPIR_Group_get_ptr(group, group_ptr); #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPIR_Win_valid_ptr(win_ptr, mpi_errno); if (mpi_errno) goto fn_fail; MPIR_Group_valid_ptr(group_ptr, mpi_errno); /* TODO: Validate assert argument */ /* TODO: Validate window state */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Win_start(group_ptr, assert, win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_WIN_START); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_start", "**mpi_win_start %G %A %W", group, assert, win); } #endif mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }