1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2005 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2009 Sun Microsystmes, Inc. All rights reserved.
14 * Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
15 * Copyright (c) 2014-2015 Los Alamos National Security, LLC. All right
16 * reserved.
17 * Copyright (c) 2015 Research Organization for Information Science
18 * and Technology (RIST). All rights reserved.
19 * $COPYRIGHT$
20 *
21 * Additional copyrights may follow
22 *
23 * $HEADER$
24 */
25 #include "ompi_config.h"
26 #include <stdio.h>
27 #include "ompi/mpi/c/bindings.h"
28 #include "ompi/runtime/params.h"
29 #include "ompi/communicator/communicator.h"
30 #include "ompi/request/request.h"
31 #include "ompi/errhandler/errhandler.h"
32 #include "ompi/win/win.h"
33 #include "ompi/mca/osc/osc.h"
34 #include "ompi/op/op.h"
35 #include "ompi/datatype/ompi_datatype.h"
36 #include "ompi/datatype/ompi_datatype_internal.h"
37 #include "ompi/memchecker.h"
38
39 #if OMPI_BUILD_MPI_PROFILING
40 #if OPAL_HAVE_WEAK_SYMBOLS
41 #pragma weak MPI_Rget_accumulate = PMPI_Rget_accumulate
42 #endif
43 #define MPI_Rget_accumulate PMPI_Rget_accumulate
44 #endif
45
46 static const char FUNC_NAME[] = "MPI_Rget_accumulate";
47
48 int MPI_Rget_accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
49 void *result_addr, int result_count, MPI_Datatype result_datatype,
50 int target_rank, MPI_Aint target_disp, int target_count,
51 MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request)
52 {
53 int rc;
54 ompi_win_t *ompi_win = (ompi_win_t*) win;
55
56 MEMCHECKER(
57 memchecker_datatype(origin_datatype);
58 memchecker_datatype(target_datatype);
59 memchecker_call(&opal_memchecker_base_isdefined, (void *) origin_addr, origin_count, origin_datatype);
60 );
61
62 if (MPI_PARAM_CHECK) {
63 rc = OMPI_SUCCESS;
64
65 OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
66
67 if (ompi_win_invalid(win)) {
68 return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
69 } else if (origin_count < 0 || target_count < 0) {
70 rc = MPI_ERR_COUNT;
71 } else if (ompi_win_peer_invalid(win, target_rank) &&
72 (MPI_PROC_NULL != target_rank)) {
73 rc = MPI_ERR_RANK;
74 } else if (MPI_OP_NULL == op) {
75 rc = MPI_ERR_OP;
76 } else if (!ompi_op_is_intrinsic(op)) {
77 rc = MPI_ERR_OP;
78 } else if ( MPI_WIN_FLAVOR_DYNAMIC != win->w_flavor && target_disp < 0 ) {
79 rc = MPI_ERR_DISP;
80 } else {
81 /* the origin datatype is meaningless when using MPI_OP_NO_OP */
82 if (&ompi_mpi_op_no_op.op != op) {
83 OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
84 } else {
85 rc = OMPI_SUCCESS;
86 }
87 if (OMPI_SUCCESS == rc) {
88 OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
89 }
90 if (OMPI_SUCCESS == rc) {
91 /* While technically the standard probably requires that the
92 datatypes used with MPI_REPLACE conform to all the rules
93 for other reduction operators, we don't require such
94 behavior, as checking for it is expensive here and we don't
95 care in implementation.. */
96 if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
97 ompi_datatype_t *op_check_dt, *origin_check_dt;
98 char *msg;
99
100 /* RGET_ACCUMULATE, unlike REDUCE, can use with derived
101 datatypes with predefinied operations, with some
102 restrictions outlined in MPI-3:11.3.4. The derived
103 datatype must be composed entierly from one predefined
104 datatype (so you can do all the construction you want,
105 but at the bottom, you can only use one datatype, say,
106 MPI_INT). If the datatype at the target isn't
107 predefined, then make sure it's composed of only one
108 datatype, and check that datatype against
109 ompi_op_is_valid(). */
110 origin_check_dt = ompi_datatype_get_single_predefined_type_from_args(origin_datatype);
111 op_check_dt = ompi_datatype_get_single_predefined_type_from_args(target_datatype);
112
113 if( !((origin_check_dt == op_check_dt) & (NULL != op_check_dt)) ) {
114 OMPI_ERRHANDLER_RETURN(MPI_ERR_ARG, win, MPI_ERR_ARG, FUNC_NAME);
115 }
116
117 /* check to make sure primitive type is valid for
118 reduction. Should do this on the target, but
119 then can't get the errcode back for this
120 call */
121 if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
122 int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
123 free(msg);
124 return ret;
125 }
126 }
127 }
128 }
129 OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
130 }
131
132 if (MPI_PROC_NULL == target_rank) {
133 *request = &ompi_request_empty;
134 return MPI_SUCCESS;
135 }
136
137 OPAL_CR_ENTER_LIBRARY();
138
139 rc = ompi_win->w_osc_module->osc_rget_accumulate(origin_addr,
140 origin_count,
141 origin_datatype,
142 result_addr,
143 result_count,
144 result_datatype,
145 target_rank,
146 target_disp,
147 target_count,
148 target_datatype,
149 op, win, request);
150 OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
151 }