rget_accumulate.c 8 KB
Newer Older
1
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2
3
4
5
6
7
8
9
/*
 *
 *  (C) 2001 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "mpiimpl.h"

10
/* -- Begin Profiling Symbol Block for routine MPI_Rget_accumulate */
11
#if defined(HAVE_PRAGMA_WEAK)
12
#pragma weak MPI_Rget_accumulate = PMPI_Rget_accumulate
13
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
14
#pragma _HP_SECONDARY_DEF PMPI_Rget_accumulate  MPI_Rget_accumulate
15
#elif defined(HAVE_PRAGMA_CRI_DUP)
16
#pragma _CRI duplicate MPI_Rget_accumulate as PMPI_Rget_accumulate
17
18
19
20
21
22
#endif
/* -- End Profiling Symbol Block */

/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
   the MPI routines */
#ifndef MPICH_MPI_FROM_PMPI
23
24
#undef MPI_Rget_accumulate
#define MPI_Rget_accumulate PMPI_Rget_accumulate
25
26
27
28

#endif

#undef FUNCNAME
29
#define FUNCNAME MPI_Rget_accumulate
30
31

/*@
32
33
34
35
36
37
38
39
40
41
MPI_Rget_accumulate - Perform an atomic, one-sided read-and-accumulate
operation and return a request handle for the operation.


'MPI_Rget_accumulate' is similar to 'MPI_Get_accumulate', except that it allocates
a communication request object and associates it with the request handle (the
argument request) that can be used to wait or test for completion. The
completion of an 'MPI_Rget_accumulate' operation indicates that the data is
available in the result buffer and the origin buffer is free to be updated. It
does not indicate that the operation has been completed at the target window.
42

43
Input Parameters:
44
45
46
+ origin_addr - initial address of buffer (choice)
. origin_count - number of entries in buffer (nonnegative integer)
. origin_datatype - datatype of each buffer entry (handle)
47
48
49
. result_addr - initial address of result buffer (choice)
. result_count - number of entries in result buffer (non-negative integer)
. result_datatype - datatype of each entry in result buffer (handle)
50
51
52
53
54
55
56
. 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)
57

58
Output Parameters:
59
60
. request - RMA request (handle)

61
62
63
64
65
66
67
68
Notes:
This operations is atomic with respect to other "accumulate" operations.

The get and accumulate steps are executed atomically for each basic element in
the datatype (see MPI 3.0 Section 11.7 for details). The predefined operation
'MPI_REPLACE' provides fetch-and-set behavior.

The basic components of both the origin and target datatype must be the same
69
70
71
72
73
74
75
76
77
78
79
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
80
81

.seealso: MPI_Get_accumulate MPI_Fetch_and_op
82
@*/
83
int MPI_Rget_accumulate(const void *origin_addr, int origin_count,
84
85
86
87
88
        MPI_Datatype origin_datatype, void *result_addr, int result_count,
        MPI_Datatype result_datatype, int target_rank, MPI_Aint target_disp,
        int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win,
        MPI_Request *request)
{
89
    static const char FCNAME[] = "MPI_Rget_accumulate";
90
91
92
    int mpi_errno = MPI_SUCCESS;
    MPID_Win *win_ptr = NULL;
    MPID_Request *request_ptr = NULL;
93
    MPID_MPI_STATE_DECL(MPID_STATE_MPI_RGET_ACCUMULATE);
94
95
96
97

    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
    MPIU_THREAD_CS_ENTER(ALLFUNC,);
98
    MPID_MPI_RMA_FUNC_ENTER(MPID_STATE_MPI_RGET_ACCUMULATE);
99
100
101
102
103
104
105
106
107
108

    /* 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;
    }
109
#   endif /* HAVE_ERROR_CHECKING */
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    
    /* 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;

125
126
127
128
129
            if (op != MPI_NO_OP) {
                MPIR_ERRTEST_COUNT(origin_count, mpi_errno);
                MPIR_ERRTEST_DATATYPE(origin_datatype, "origin_datatype", mpi_errno);
                MPIR_ERRTEST_ARGNULL(origin_addr, "origin_addr", mpi_errno);
            }
130
            MPIR_ERRTEST_COUNT(result_count, mpi_errno);
131
            MPIR_ERRTEST_DATATYPE(result_datatype, "result_datatype", mpi_errno);
132
            MPIR_ERRTEST_ARGNULL(result_addr, "result_addr", mpi_errno);
133
            MPIR_ERRTEST_COUNT(target_count, mpi_errno);
134
            MPIR_ERRTEST_DATATYPE(target_datatype, "target_datatype", mpi_errno);
135
            if (win_ptr->create_flavor != MPI_WIN_FLAVOR_DYNAMIC)
136
                MPIR_ERRTEST_DISP(target_disp, mpi_errno);
137

138
139
            if (op != MPI_NO_OP &&
                HANDLE_GET_KIND(origin_datatype) != HANDLE_KIND_BUILTIN)
140
141
142
143
144
            {
                MPID_Datatype *datatype_ptr = NULL;
                
                MPID_Datatype_get_ptr(origin_datatype, datatype_ptr);
                MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno);
145
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
146
                MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno);
147
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
148
149
150
151
152
153
154
155
            }

            if (HANDLE_GET_KIND(result_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);
156
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
157
                MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno);
158
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
159
160
161
162
163
164
165
166
            }

            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);
167
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
168
                MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno);
169
                if (mpi_errno != MPI_SUCCESS) goto fn_fail;
170
171
172
173
            }

            comm_ptr = win_ptr->comm_ptr;
            MPIR_ERRTEST_SEND_RANK(comm_ptr, target_rank, mpi_errno);
174
            MPIR_ERRTEST_OP_GACC(op, mpi_errno);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ...  */
    
    mpi_errno = MPIU_RMA_CALL(win_ptr,Rget_accumulate(origin_addr, origin_count, 
                                         origin_datatype,
                                         result_addr, result_count,
                                         result_datatype,
                                         target_rank, target_disp, target_count,
                                         target_datatype, op, win_ptr,
                                         &request_ptr));
    if (mpi_errno != MPI_SUCCESS) goto fn_fail;

    *request = request_ptr->handle;

    /* ... end of body of routine ... */

  fn_exit:
196
    MPID_MPI_RMA_FUNC_EXIT(MPID_STATE_MPI_RGET_ACCUMULATE);
197
198
199
200
201
202
203
204
    MPIU_THREAD_CS_EXIT(ALLFUNC,);
    return mpi_errno;

  fn_fail:
    /* --BEGIN ERROR HANDLING-- */
#   ifdef HAVE_ERROR_CHECKING
    {
        mpi_errno = MPIR_Err_create_code(
205
206
            mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_rget_accumulate",
            "**mpi_rget_accumulate %p %d %D %p %d %D %d %d %d %D %O %W %p", origin_addr, origin_count, origin_datatype,
207
208
209
210
211
212
213
214
215
            result_addr, result_count, result_datatype,
            target_rank, target_disp, target_count, target_datatype, op, win, request);
    }
#   endif
    mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno );
    goto fn_exit;
    /* --END ERROR HANDLING-- */
}