/*@ MPI_Win_lock - Begin an RMA access epoch at the target process. Input Parameters: + lock_type - Indicates whether other processes may access the target window at the same time (if 'MPI_LOCK_SHARED') or not ('MPI_LOCK_EXCLUSIVE') . rank - rank of locked window (nonnegative integer) . assert - Used to optimize this call; zero may be used as a default. See notes. (integer) - win - window object (handle) Notes: The name of this routine is misleading. In particular, this routine need not block, except when the target process is the calling process. Implementations may restrict the use of RMA communication that is synchronized by lock calls to windows in memory allocated by 'MPI_Alloc_mem'. Locks can be used portably only in such memory. The 'assert' argument is used to indicate special conditions for the fence that an implementation may use to optimize the 'MPI_Win_lock' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions that are valid for 'MPI_Win_lock' are\: . MPI_MODE_NOCHECK - no other process holds, or will attempt to acquire a conflicting lock, while the caller holds the window lock. This is useful when mutual exclusion is achieved by other means, but the coherence operations that may be attached to the lock and unlock calls are still required. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_RANK .N MPI_ERR_WIN .N MPI_ERR_OTHER @*/ int MPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win) { static const char FCNAME[] = "MPI_Win_lock"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_LOCK); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_LOCK); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm *comm_ptr; /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not value, it will be reset to null */ if (mpi_errno) goto fn_fail; if (assert != 0 && assert != MPI_MODE_NOCHECK) { MPIU_ERR_SET1(mpi_errno,MPI_ERR_ARG, "**lockassertval", "**lockassertval %d", assert ); if (mpi_errno) goto fn_fail; } if (lock_type != MPI_LOCK_SHARED && lock_type != MPI_LOCK_EXCLUSIVE) { MPIU_ERR_SET(mpi_errno,MPI_ERR_OTHER, "**locktype" ); } if (win_ptr->lockRank != -1) { MPIU_ERR_SET1(mpi_errno,MPI_ERR_OTHER, "**lockwhilelocked", "**lockwhilelocked %d", win_ptr->lockRank ); } comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, rank, mpi_errno); if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr, Win_lock(lock_type, rank, assert, win_ptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* If the lock succeeded, remember which one with locked */ win_ptr->lockRank = rank; /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_LOCK); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_lock", "**mpi_win_lock %d %d %A %W", lock_type, rank, assert, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ 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 @*/ 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) { static const char FCNAME[] = "MPI_Accumulate"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_ACCUMULATE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_RMA_FUNC_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); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm * comm_ptr; /* Validate win_ptr */ MPID_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_COUNT(target_count, mpi_errno); MPIR_ERRTEST_DATATYPE(target_datatype, "target_datatype", mpi_errno); MPIR_ERRTEST_DISP(target_disp, mpi_errno); if (HANDLE_GET_KIND(origin_datatype) != HANDLE_KIND_BUILTIN) { MPID_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(origin_datatype, datatype_ptr); MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno); MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno); } if (HANDLE_GET_KIND(target_datatype) != HANDLE_KIND_BUILTIN) { MPID_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(target_datatype, datatype_ptr); MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno); MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno); } comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, target_rank, mpi_errno); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ if (target_rank == MPI_PROC_NULL) goto fn_exit; mpi_errno = MPIU_RMA_CALL(win_ptr,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: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_ACCUMULATE); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_Win_unlock_all - Completes an RMA access epoch at all processes on the given window. Completes a shared RMA access epoch started by a call to 'MPI_Win_lock_all'. RMA operations issued during this epoch will have completed both at the origin and at the target when the call returns. Input Parameters: . win - window object (handle) Notes: This call is not collective. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_RANK .N MPI_ERR_WIN .N MPI_ERR_OTHER .seealso: MPI_Win_lock_all @*/ int MPI_Win_unlock_all(MPI_Win win) { static const char FCNAME[] = "MPI_Win_unlock_all"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_UNLOCK_ALL); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_UNLOCK_ALL); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not valid, it will be reset to null */ if (mpi_errno) goto fn_fail; /* TODO: Test that the rank we are unlocking is the rank that we locked */ } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr,Win_unlock_all(win_ptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_UNLOCK_ALL); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_unlock_all", "**mpi_win_unlock_all %W", win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_flush - Complete all outstanding RMA operations at the given target. 'MPI_Win_flush' completes all outstanding RMA operations initiated by the calling process to the target rank on the specified window. The operations are completed both at the origin and at the target. Input Parameters: + rank - rank of window (nonnegative integer) - win - window object (handle) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_RANK .N MPI_ERR_WIN .N MPI_ERR_OTHER .seealso: MPI_Win_flush_all MPI_Win_flush_local MPI_Win_flush_local_all MPI_Win_lock MPI_Win_lock_all @*/ int MPI_Win_flush(int rank, MPI_Win win) { static const char FCNAME[] = "MPI_Win_flush"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_FLUSH); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_FLUSH); /* 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 */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm * comm_ptr; /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, rank, mpi_errno); /* TODO: Validate that the given window is in passive mode */ /* TODO: Validate that the given rank is locked */ } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr,Win_flush(rank, win_ptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_FLUSH); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_flush", "**mpi_win_flush %d %W", rank, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_call_errhandler - Call the error handler installed on a window object Input Parameters: + win - window with error handler (handle) - errorcode - error code (integer) Note: Assuming the input parameters are valid, when the error handler is set to MPI_ERRORS_RETURN, this routine will always return MPI_SUCCESS. .N ThreadSafeNoUpdate .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN @*/ int MPI_Win_call_errhandler(MPI_Win win, int errorcode) { int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; int in_cs = FALSE; MPID_THREADPRIV_DECL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_CALL_ERRHANDLER); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_CALL_ERRHANDLER); MPID_THREADPRIV_GET; /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not valid, it will be reset to null */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_WIN_MUTEX(win_ptr)); in_cs = TRUE; if (!win_ptr->errhandler || win_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) { mpi_errno = MPIR_Err_return_win( win_ptr, "MPI_Win_call_errhandler", errorcode ); goto fn_exit; } if (win_ptr->errhandler->handle == MPI_ERRORS_RETURN) { /* MPI_ERRORS_RETURN should always return MPI_SUCCESS */ goto fn_exit; } /* Check for the special case of errors-throw-exception. In this case return the error code; the C++ wrapper will cause an exception to be thrown. */ #ifdef HAVE_CXX_BINDING if (win_ptr->errhandler->handle == MPIR_ERRORS_THROW_EXCEPTIONS) { mpi_errno = errorcode; goto fn_exit; } #endif switch (win_ptr->errhandler->language) { case MPID_LANG_C: (*win_ptr->errhandler->errfn.C_Win_Handler_function)( &win_ptr->handle, &errorcode ); break; #ifdef HAVE_CXX_BINDING case MPID_LANG_CXX: MPIR_Process.cxx_call_errfn( 2, &win_ptr->handle, &errorcode, (void (*)(void))win_ptr->errhandler->errfn.C_Win_Handler_function ); break; #endif #ifdef HAVE_FORTRAN_BINDING case MPID_LANG_FORTRAN90: case MPID_LANG_FORTRAN: { /* If int and MPI_Fint aren't the same size, we need to convert. As this is not performance critical, we do this even if MPI_Fint and int are the same size. */ MPI_Fint ferr=errorcode; MPI_Fint winhandle=win_ptr->handle; (*win_ptr->errhandler->errfn.F77_Handler_function)( &winhandle, &ferr ); } break; #endif } /* ... end of body of routine ... */ fn_exit: if (in_cs) MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_WIN_MUTEX(win_ptr)); MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_CALL_ERRHANDLER); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING fn_fail: { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_call_errhandler", "**mpi_win_call_errhandler %W %d", win, errorcode); } mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; # endif /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_get_errhandler - Get the error handler for the MPI RMA window Input Parameters: . win - window (handle) Output Parameters: . errhandler - error handler currently associated with window (handle) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN .N MPI_ERR_OTHER @*/ int MPI_Win_get_errhandler(MPI_Win win, MPI_Errhandler *errhandler) { #ifdef HAVE_ERROR_CHECKING static const char FCNAME[] = "MPI_Win_get_errhandler"; #endif int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_GET_ERRHANDLER); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_GET_ERRHANDLER); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_ARGNULL(errhandler,"errhandler",mpi_errno); /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not valid, it will be reset to null */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ MPIU_THREAD_CS_ENTER(MPI_OBJ, win_ptr); if (win_ptr->errhandler) { *errhandler = win_ptr->errhandler->handle; MPIR_Errhandler_add_ref(win_ptr->errhandler); } else { /* Use the default */ *errhandler = MPI_ERRORS_ARE_FATAL; } MPIU_THREAD_CS_EXIT(MPI_OBJ, win_ptr); /* ... end of body of routine ... */ #ifdef HAVE_ERROR_CHECKING fn_exit: #endif MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_GET_ERRHANDLER); MPIU_THREAD_CS_EXIT(ALLFUNC,); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING fn_fail: { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_get_errhandler", "**mpi_win_get_errhandler %W %p", win, errhandler); } mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; # endif /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_free - Free an MPI RMA window Input Parameters: . win - window object (handle) Notes: If successfully freed, 'win' is set to 'MPI_WIN_NULL'. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN .N MPI_ERR_OTHER @*/ int MPI_Win_free(MPI_Win *win) { static const char FCNAME[] = "MPI_Win_free"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_FREE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_WIN_FREE); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( *win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; /* TODO: Check for unterminated passive target epoch */ /* TODO: check for unterminated active mode epoch */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ if (MPIR_Process.attr_free && win_ptr->attributes) { mpi_errno = MPIR_Process.attr_free( win_ptr->handle, &win_ptr->attributes ); } /* * If the user attribute free function returns an error, * then do not free the window */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* We need to release the error handler */ if (win_ptr->errhandler && ! (HANDLE_GET_KIND(win_ptr->errhandler->handle) == HANDLE_KIND_BUILTIN) ) { int in_use; MPIR_Errhandler_release_ref( win_ptr->errhandler,&in_use); if (!in_use) { MPIU_Handle_obj_free( &MPID_Errhandler_mem, win_ptr->errhandler ); } } mpi_errno = MPID_Win_free(&win_ptr); if (mpi_errno) goto fn_fail; *win = MPI_WIN_NULL; /* ... end of body of routine ... */ fn_exit: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_WIN_FREE); 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_free", "**mpi_win_free %p", win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
int MPIR_WinSetAttr( MPI_Win win, int win_keyval, void *attribute_val, MPIR_AttrType attrType ) { static const char FCNAME[] = "MPI_Win_set_attr"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_Keyval *keyval_ptr = NULL; MPID_Attribute *p, **old_p; MPID_MPI_STATE_DECL(MPID_STATE_MPIR_WIN_SET_ATTR); MPIR_ERRTEST_INITIALIZED_ORDIE(); /* The thread lock prevents a valid attr delete on the same window but in a different thread from causing problems */ MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_WIN_SET_ATTR); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); MPIR_ERRTEST_KEYVAL(win_keyval, MPID_WIN, "window", mpi_errno); MPIR_ERRTEST_KEYVAL_PERM(win_keyval, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); MPID_Keyval_get_ptr( win_keyval, keyval_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not valid, it will be reset to null */ /* Validate keyval */ MPID_Keyval_valid_ptr( keyval_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ /* Look for attribute. They are ordered by keyval handle. This uses a simple linear list algorithm because few applications use more than a handful of attributes */ old_p = &win_ptr->attributes; p = win_ptr->attributes; while (p) { if (p->keyval->handle == keyval_ptr->handle) { /* If found, call the delete function before replacing the attribute */ mpi_errno = MPIR_Call_attr_delete( win, p ); /* --BEGIN ERROR HANDLING-- */ if (mpi_errno) { /* FIXME : communicator of window? */ goto fn_fail; } /* --END ERROR HANDLING-- */ p->value = (MPID_AttrVal_t)(MPIR_Pint)attribute_val; p->attrType = attrType; /* Does not change the reference count on the keyval */ break; } else if (p->keyval->handle > keyval_ptr->handle) { MPID_Attribute *new_p = MPID_Attr_alloc(); MPIU_ERR_CHKANDJUMP1(!new_p,mpi_errno,MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Attribute" ); new_p->keyval = keyval_ptr; new_p->attrType = attrType; new_p->pre_sentinal = 0; new_p->value = (MPID_AttrVal_t)(MPIR_Pint)attribute_val; new_p->post_sentinal = 0; new_p->next = p->next; MPIR_Keyval_add_ref( keyval_ptr ); p->next = new_p; break; } old_p = &p->next; p = p->next; } if (!p) { MPID_Attribute *new_p = MPID_Attr_alloc(); MPIU_ERR_CHKANDJUMP1(!new_p,mpi_errno,MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Attribute" ); /* Did not find in list. Add at end */ new_p->attrType = attrType; new_p->keyval = keyval_ptr; new_p->pre_sentinal = 0; new_p->value = (MPID_AttrVal_t)(MPIR_Pint)attribute_val; new_p->post_sentinal = 0; new_p->next = 0; MPIR_Keyval_add_ref( keyval_ptr ); *old_p = new_p; } /* Here is where we could add a hook for the device to detect attribute value changes, using something like MPID_Dev_win_attr_hook( win_ptr, keyval, attribute_val ); */ /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_WIN_SET_ATTR); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_set_attr", "**mpi_win_set_attr %W %d %p", win, win_keyval, attribute_val); } # 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; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_FETCH_AND_OP); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_RMA_FUNC_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 */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm *comm_ptr; /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; if (op != MPI_NO_OP) { 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 (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) { MPIU_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) { MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OP, "**opnotpredefined"); } } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr,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: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_FETCH_AND_OP); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_Rput - Put data into a memory window on a remote process and return a request handle for the operation. 'MPI_Rput' is similar to 'MPI_Put', except that it allocates a communication request object and associates it with the request handle (the argument request). The completion of an 'MPI_Rput' operation (i.e., after the corresponding test or wait) indicates that the sender is now free to update the locations in the origin buffer. It does not indicate that the data is available at the target window. If remote completion is required, 'MPI_Win_flush', 'MPI_Win_flush_all', 'MPI_Win_unlock', or 'MPI_Win_unlock_all' can be used. Input Parameters: + origin_addr -initial address of origin buffer (choice) . origin_count -number of entries in origin buffer (nonnegative integer) . origin_datatype -datatype of each entry in origin buffer (handle) . target_rank -rank of target (nonnegative integer) . target_disp -displacement from start of window to target buffer (nonnegative integer) . target_count -number of entries in target buffer (nonnegative integer) . target_datatype -datatype of each entry in target buffer (handle) - win - window object used for communication (handle) Output Parameters: . request -RMA request (handle) .N ThreadSafe .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_Put @*/ int MPI_Rput(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win, MPI_Request *request) { static const char FCNAME[] = "MPI_Rput"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_Request *request_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_RPUT); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_RPUT); /* 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 */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm * comm_ptr; /* Validate win_ptr */ MPID_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) { MPID_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(origin_datatype, datatype_ptr); MPID_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) { MPID_Datatype *datatype_ptr = NULL; MPID_Datatype_get_ptr(target_datatype, datatype_ptr); MPID_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_ARGNULL(request,"request",mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Rput(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win_ptr, &request_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; *request = request_ptr->handle; /* ... end of body of routine ... */ fn_exit: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_RPUT); 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_rput", "**mpi_rput %p %d %D %d %d %d %D %W %p", origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win, request); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_set_name - Set the print name for an MPI RMA window Input Parameters: + win - window whose identifier is to be set (handle) - win_name - the character string which is remembered as the name (string) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN .N MPI_ERR_OTHER .N MPI_ERR_ARG @*/ int MPI_Win_set_name(MPI_Win win, const char *win_name) { static const char FCNAME[] = "MPI_Win_set_name"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_SET_NAME); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_SET_NAME); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; /* If win_ptr is not valid, it will be reset to null */ MPIR_ERRTEST_ARGNULL(win_name, "win_name", mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ MPL_strncpy( win_ptr->name, win_name, MPI_MAX_OBJECT_NAME ); /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_SET_NAME); 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_set_name", "**mpi_win_set_name %W %s", win, win_name); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_post - Start an RMA exposure epoch Input Parameters: + group - group of origin 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_post' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions that are valid for 'MPI_Win_post' are\: + MPI_MODE_NOCHECK - the matching calls to 'MPI_WIN_START' have not yet occurred on any origin processes when the call to 'MPI_WIN_POST' is made. The nocheck option can be specified by a post call if and only if it is specified by each matching start call. . MPI_MODE_NOSTORE - the local window was not updated by local stores (or local get or receive calls) since last synchronization. This may avoid the need for cache synchronization at the post call. - MPI_MODE_NOPUT - the local window will not be updated by put or accumulate calls after the post call, until the ensuing (wait) synchronization. This may avoid the need for cache synchronization at the wait call. .N Fortran .N Errors .N MPI_SUCCESS @*/ int MPI_Win_post(MPI_Group group, int assert, MPI_Win win) { static const char FCNAME[] = "MPI_Win_post"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_Group *group_ptr=NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_POST); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_WIN_POST); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); MPID_Group_get_ptr(group, group_ptr); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); MPID_Group_valid_ptr(group_ptr, mpi_errno); /* TODO: Validate assert argument */ /* TODO: Validate that window is not in passive mode */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr,Win_post(group_ptr, assert, win_ptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_WIN_POST); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_post", "**mpi_win_post %G %A %W", group, assert, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_set_errhandler - Set window error handler Input Parameters: + win - window (handle) - errhandler - new error handler for window (handle) .N ThreadSafeNoUpdate .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN @*/ int MPI_Win_set_errhandler(MPI_Win win, MPI_Errhandler errhandler) { #ifdef HAVE_ERROR_CHECKING static const char FCNAME[] = "MPI_Win_set_errhandler"; #endif int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; int in_use; MPID_Errhandler *errhan_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_SET_ERRHANDLER); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_SET_ERRHANDLER); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); MPIR_ERRTEST_ERRHANDLER(errhandler, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); MPID_Errhandler_get_ptr( errhandler, errhan_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); /* If win_ptr is not value, it will be reset to null */ if (HANDLE_GET_KIND(errhandler) != HANDLE_KIND_BUILTIN) { MPID_Errhandler_valid_ptr( errhan_ptr,mpi_errno ); /* Also check for a valid errhandler kind */ if (!mpi_errno) { if (errhan_ptr->kind != MPID_WIN) { mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**errhandnotwin", NULL ); } } } if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_WIN_MUTEX(win_ptr)); if (win_ptr->errhandler != NULL) { MPIR_Errhandler_release_ref(win_ptr->errhandler,&in_use); if (!in_use) { MPID_Errhandler_free( win_ptr->errhandler ); } } MPIR_Errhandler_add_ref(errhan_ptr); win_ptr->errhandler = errhan_ptr; MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_WIN_MUTEX(win_ptr)); /* ... end of body of routine ... */ #ifdef HAVE_ERROR_CHECKING fn_exit: #endif MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_SET_ERRHANDLER); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING fn_fail: { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_set_errhandler", "**mpi_win_set_errhandler %W %E", win, errhandler); } mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; # endif /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_attach - Attach memory to a dynamic window. Attaches a local memory region beginning at base for remote access within the given window. The memory region specified must not contain any part that is already attached to the window win, that is, attaching overlapping memory concurrently within the same window is erroneous. The argument win must be a window that was created with 'MPI_Win_create_dynamic'. Multiple (but non-overlapping) memory regions may be attached to the same window. Input Parameters: + size - size of memory to be attached in bytes . base - initial address of memory to be attached - win - window object used for communication (handle) .N ThreadSafe .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_Win_create_dynamic MPI_Win_detach @*/ int MPI_Win_attach(MPI_Win win, void *base, MPI_Aint size) { static const char FCNAME[] = "MPI_Win_attach"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_ATTACH); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_WIN_ATTACH); /* 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 */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) 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 (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) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ if (size == 0) goto fn_exit; mpi_errno = MPIU_RMA_CALL(win_ptr, Win_attach(win_ptr, base, size)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_WIN_ATTACH); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_attach", "**mpi_win_attach %W %p %d", size, base, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_lock_all - Begin an RMA access epoch at all processes on the given window. Starts an RMA access epoch to all processes in win, with a lock type of 'MPI_Lock_shared'. During the epoch, the calling process can access the window memory on all processes in win by using RMA operations. A window locked with 'MPI_Win_lock_all' must be unlocked with 'MPI_Win_unlock_all'. This routine is not collective -- the ALL refers to a lock on all members of the group of the window. Input Parameters: + assert - Used to optimize this call; zero may be used as a default. See notes. (integer) - win - window object (handle) Notes: This call is not collective. The 'assert' argument is used to indicate special conditions for the fence that an implementation may use to optimize the 'MPI_Win_lock_all' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions that are valid for 'MPI_Win_lock_all' are\: . 'MPI_MODE_NOCHECK' - No other process holds, or will attempt to acquire a conflicting lock, while the caller holds the window lock. This is useful when mutual exclusion is achieved by other means, but the coherence operations that may be attached to the lock and unlock calls are still required. There may be additional overheads associated with using 'MPI_Win_lock' and 'MPI_Win_lock_all' concurrently on the same window. These overheads could be avoided by specifying the assertion 'MPI_MODE_NOCHECK' when possible .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_RANK .N MPI_ERR_WIN .N MPI_ERR_OTHER .seealso: MPI_Win_unlock_all @*/ int MPI_Win_lock_all(int assert, MPI_Win win) { static const char FCNAME[] = "MPI_Win_lock_all"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_LOCK_ALL); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_LOCK_ALL); /* 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 /* Convert MPI object handles to object pointers */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; if (assert != 0 && assert != MPI_MODE_NOCHECK) { MPIU_ERR_SET1(mpi_errno,MPI_ERR_ARG, "**lockassertval", "**lockassertval %d", assert ); if (mpi_errno) goto fn_fail; } /* TODO: Validate that window is not already locked */ /* TODO: Validate that window is not already in active mode */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr, Win_lock_all(assert, win_ptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_LOCK_ALL); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_lock_all", "**mpi_win_lock_all %A %W", assert, win); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_shared_query - Query the size and base pointer for a patch of a shared memory window. This function queries the process-local address for remote memory segments created with 'MPI_Win_allocate_shared'. This function can return different process-local addresses for the same physical memory on different processes. The returned memory can be used for load/store accesses subject to the constraints defined in MPI 3.0, Section 11.7. This function can only be called with windows of type 'MPI_Win_flavor_shared'. If the passed window is not of flavor 'MPI_Win_flavor_shared', the error 'MPI_ERR_RMA_FLAVOR' is raised. When rank is 'MPI_PROC_NULL', the pointer, disp_unit, and size returned are the pointer, disp_unit, and size of the memory segment belonging the lowest rank that specified size > 0. If all processes in the group attached to the window specified size = 0, then the call returns size = 0 and a baseptr as if 'MPI_Alloc_mem' was called with size = 0. Input Parameters: + win - window object used for communication (handle) - rank - target rank Output Parameters: + size - size of the segment at the given rank . disp_unit - local unit size for displacements, in bytes (positive integer) - baseptr - base pointer in the calling process'' address space of the shared segment belonging to the target rank. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_ARG .N MPI_ERR_RANK .N MPI_ERR_WIN .seealso: MPI_Win_allocate_shared @*/ int MPI_Win_shared_query(MPI_Win win, int rank, MPI_Aint *size, int *disp_unit, void *baseptr) { static const char FCNAME[] = "MPI_Win_shared_query"; int mpi_errno = MPI_SUCCESS; MPID_Win *win_ptr = NULL; MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_SHARED_QUERY); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_WIN_SHARED_QUERY); /* 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 */ MPID_Win_get_ptr( win, win_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPID_Comm * comm_ptr; /* Validate win_ptr */ MPID_Win_valid_ptr( win_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; MPIR_ERRTEST_ARGNULL(size, "size", mpi_errno); MPIR_ERRTEST_ARGNULL(disp_unit, "disp_unit", mpi_errno); MPIR_ERRTEST_ARGNULL(baseptr, "baseptr", mpi_errno); comm_ptr = win_ptr->comm_ptr; MPIR_ERRTEST_SEND_RANK(comm_ptr, rank, mpi_errno); MPIR_ERRTEST_WIN_FLAVOR(win_ptr, MPI_WIN_FLAVOR_SHARED, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIU_RMA_CALL(win_ptr, Win_shared_query(win_ptr, rank, size, disp_unit, baseptr)); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_WIN_SHARED_QUERY); MPIU_THREAD_CS_EXIT(ALLFUNC,); 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_shared_query", "**mpi_win_shared_query %W %d %p %p", win, rank, size, baseptr); } # endif mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }