1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpiimpl.h"
7
8 /* -- Begin Profiling Symbol Block for routine MPI_T_pvar_read */
9 #if defined(HAVE_PRAGMA_WEAK)
10 #pragma weak MPI_T_pvar_read = PMPI_T_pvar_read
11 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
12 #pragma _HP_SECONDARY_DEF PMPI_T_pvar_read MPI_T_pvar_read
13 #elif defined(HAVE_PRAGMA_CRI_DUP)
14 #pragma _CRI duplicate MPI_T_pvar_read as PMPI_T_pvar_read
15 #elif defined(HAVE_WEAK_ATTRIBUTE)
16 int MPI_T_pvar_read(MPI_T_pvar_session session, MPI_T_pvar_handle handle, void *buf)
17 __attribute__ ((weak, alias("PMPI_T_pvar_read")));
18 #endif
19 /* -- End Profiling Symbol Block */
20
21 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
22 the MPI routines */
23 #ifndef MPICH_MPI_FROM_PMPI
24 #undef MPI_T_pvar_read
25 #define MPI_T_pvar_read PMPI_T_pvar_read
26
27 /* any non-MPI functions go here, especially non-static ones */
28
MPIR_T_pvar_read_impl(MPI_T_pvar_session session,MPI_T_pvar_handle handle,void * restrict buf)29 int MPIR_T_pvar_read_impl(MPI_T_pvar_session session, MPI_T_pvar_handle handle, void *restrict buf)
30 {
31 int i, mpi_errno = MPI_SUCCESS;
32
33 /* Reading a never started pvar, or a stopped and then reset wartermark,
34 * will run into this nasty situation. MPI-3.0 did not define what error
35 * code should be returned. We returned a generic MPI error code. With MPI-3.1
36 * approved, we changed it to MPI_T_ERR_INVALID.
37 */
38 if (!MPIR_T_pvar_is_oncestarted(handle)) {
39 mpi_errno = MPI_T_ERR_INVALID;
40 goto fn_fail;
41 }
42
43 /* For SUM pvars, return accum value + current value - offset value */
44 if (MPIR_T_pvar_is_sum(handle) && MPIR_T_pvar_is_started(handle)) {
45 if (handle->get_value == NULL) {
46 /* A running SUM without callback. Read its current value directly */
47 switch (handle->datatype) {
48 case MPI_UNSIGNED_LONG_LONG:
49 /* Put long long and double at front, since they are common */
50 for (i = 0; i < handle->count; i++) {
51 ((unsigned long long *) buf)[i] = ((unsigned long long *) handle->accum)[i]
52 + ((unsigned long long *) handle->addr)[i]
53 - ((unsigned long long *) handle->offset)[i];
54 }
55 break;
56 case MPI_DOUBLE:
57 for (i = 0; i < handle->count; i++) {
58 ((double *) buf)[i] = ((double *) handle->accum)[i]
59 + ((double *) handle->addr)[i]
60 - ((double *) handle->offset)[i];
61 }
62 break;
63 case MPI_UNSIGNED:
64 for (i = 0; i < handle->count; i++) {
65 ((unsigned *) buf)[i] = ((unsigned *) handle->accum)[i]
66 + ((unsigned *) handle->addr)[i]
67 - ((unsigned *) handle->offset)[i];
68 }
69 break;
70 case MPI_UNSIGNED_LONG:
71 for (i = 0; i < handle->count; i++) {
72 ((unsigned long *) buf)[i] = ((unsigned long *) handle->accum)[i]
73 + ((unsigned long *) handle->addr)[i]
74 - ((unsigned long *) handle->offset)[i];
75 }
76 break;
77 default:
78 /* Code should never come here */
79 mpi_errno = MPI_ERR_INTERN;
80 goto fn_fail;
81 break;
82 }
83 } else {
84 /* A running SUM with callback. Read its current value into handle */
85 handle->get_value(handle->addr, handle->obj_handle, handle->count, handle->current);
86
87 switch (handle->datatype) {
88 case MPI_UNSIGNED_LONG_LONG:
89 for (i = 0; i < handle->count; i++) {
90 ((unsigned long long *) buf)[i] = ((unsigned long long *) handle->accum)[i]
91 + ((unsigned long *) handle->current)[i]
92 - ((unsigned long long *) handle->offset)[i];
93 }
94 break;
95 case MPI_DOUBLE:
96 for (i = 0; i < handle->count; i++) {
97 ((double *) buf)[i] = ((double *) handle->accum)[i]
98 + ((double *) handle->current)[i]
99 - ((double *) handle->offset)[i];
100 }
101 break;
102 case MPI_UNSIGNED:
103 for (i = 0; i < handle->count; i++) {
104 ((unsigned *) buf)[i] = ((unsigned *) handle->accum)[i]
105 + ((unsigned *) handle->current)[i]
106 - ((unsigned *) handle->offset)[i];
107 }
108 break;
109 case MPI_UNSIGNED_LONG:
110 for (i = 0; i < handle->count; i++) {
111 ((unsigned long *) buf)[i] = ((unsigned long *) handle->accum)[i]
112 + ((unsigned long *) handle->current)[i]
113 - ((unsigned long *) handle->offset)[i];
114 }
115 break;
116 default:
117 /* Code should never come here */
118 mpi_errno = MPI_ERR_INTERN;
119 goto fn_fail;
120 break;
121 }
122 }
123 } else if (MPIR_T_pvar_is_sum(handle) && !MPIR_T_pvar_is_started(handle)) {
124 /* A SUM is stopped. Return accum directly */
125 MPIR_Memcpy(buf, handle->accum, handle->bytes * handle->count);
126 } else if (MPIR_T_pvar_is_watermark(handle)) {
127 /* Callback and array are not allowed for watermarks, since they
128 * can not gurantee correct semantics of watermarks.
129 */
130 MPIR_Assert(handle->get_value == NULL && handle->count == 1);
131
132 if (MPIR_T_pvar_is_first(handle)) {
133 /* Current value of the first handle of a watermark is stored at
134 * a special location nearby the watermark itself.
135 */
136 switch (handle->datatype) {
137 case MPI_UNSIGNED_LONG_LONG:
138 *(unsigned long long *) buf =
139 ((MPIR_T_pvar_watermark_t *) handle->addr)->watermark.ull;
140 break;
141 case MPI_DOUBLE:
142 *(double *) buf = ((MPIR_T_pvar_watermark_t *) handle->addr)->watermark.f;
143 break;
144 case MPI_UNSIGNED:
145 *(unsigned *) buf = ((MPIR_T_pvar_watermark_t *) handle->addr)->watermark.u;
146 break;
147 case MPI_UNSIGNED_LONG:
148 *(unsigned long *) buf =
149 ((MPIR_T_pvar_watermark_t *) handle->addr)->watermark.ul;
150 break;
151 default:
152 /* Code should never come here */
153 mpi_errno = MPI_ERR_INTERN;
154 goto fn_fail;
155 break;
156 }
157 } else {
158 /* For remaining handles, their current value are in the handle */
159 switch (handle->datatype) {
160 case MPI_UNSIGNED_LONG_LONG:
161 *(unsigned long long *) buf = handle->watermark.ull;
162 break;
163 case MPI_DOUBLE:
164 *(double *) buf = handle->watermark.f;
165 break;
166 case MPI_UNSIGNED:
167 *(unsigned *) buf = handle->watermark.u;
168 break;
169 case MPI_UNSIGNED_LONG:
170 *(unsigned long *) buf = handle->watermark.ul;
171 break;
172 default:
173 /* Code should never come here */
174 mpi_errno = MPI_ERR_INTERN;
175 goto fn_fail;
176 break;
177 }
178 }
179 } else {
180 /* For STATE, LEVEL, SIZE, PERCENTAGE, no caching is needed */
181 if (handle->get_value == NULL)
182 MPIR_Memcpy(buf, handle->addr, handle->bytes * handle->count);
183 else
184 handle->get_value(handle->addr, handle->obj_handle, handle->count, buf);
185 }
186
187 fn_exit:
188 return mpi_errno;
189 fn_fail:
190 goto fn_exit;
191 }
192
193 #endif /* MPICH_MPI_FROM_PMPI */
194
195 /*@
196 MPI_T_pvar_read - Read the value of a performance variable
197
198 Input Parameters:
199 + session - identifier of performance experiment session (handle)
200 - handle - handle of a performance variable (handle)
201
202 Output Parameters:
203 . buf - initial address of storage location for variable value (choice)
204
205 Notes:
206 The MPI_T_pvar_read() call queries the value of the performance variable with the
207 handle "handle" in the session identified by the parameter session and stores the result
208 in the buffer identified by the parameter buf. The user is responsible to ensure that the
209 buffer is of the appropriate size to hold the entire value of the performance variable
210 (based on the datatype and count returned by the corresponding previous calls to
211 MPI_T_pvar_get_info() and MPI_T_pvar_handle_alloc(), respectively).
212
213 The constant MPI_T_PVAR_ALL_HANDLES cannot be used as an argument for the function
214 MPI_T_pvar_read().
215
216 .N ThreadSafe
217
218 .N Errors
219 .N MPI_SUCCESS
220 .N MPI_T_ERR_NOT_INITIALIZED
221 .N MPI_T_ERR_INVALID_SESSION
222 .N MPI_T_ERR_INVALID_HANDLE
223 @*/
MPI_T_pvar_read(MPI_T_pvar_session session,MPI_T_pvar_handle handle,void * buf)224 int MPI_T_pvar_read(MPI_T_pvar_session session, MPI_T_pvar_handle handle, void *buf)
225 {
226 int mpi_errno = MPI_SUCCESS;
227
228 MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_T_PVAR_READ);
229 MPIR_ERRTEST_MPIT_INITIALIZED(mpi_errno);
230 MPIR_T_THREAD_CS_ENTER();
231 MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_T_PVAR_READ);
232
233 /* Validate parameters */
234 #ifdef HAVE_ERROR_CHECKING
235 {
236 MPID_BEGIN_ERROR_CHECKS;
237 {
238 MPIR_ERRTEST_PVAR_SESSION(session, mpi_errno);
239 MPIR_ERRTEST_PVAR_HANDLE(handle, mpi_errno);
240 MPIR_ERRTEST_ARGNULL(buf, "buf", mpi_errno);
241 if (handle == MPI_T_PVAR_ALL_HANDLES || session != handle->session
242 || !MPIR_T_pvar_is_oncestarted(handle)) {
243 mpi_errno = MPI_T_ERR_INVALID_HANDLE;
244 goto fn_fail;
245 }
246 }
247 MPID_END_ERROR_CHECKS;
248 }
249 #endif /* HAVE_ERROR_CHECKING */
250
251 /* ... body of routine ... */
252
253 mpi_errno = MPIR_T_pvar_read_impl(session, handle, buf);
254 if (mpi_errno)
255 goto fn_fail;
256
257 /* ... end of body of routine ... */
258
259 fn_exit:
260 MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_T_PVAR_READ);
261 MPIR_T_THREAD_CS_EXIT();
262 return mpi_errno;
263
264 fn_fail:
265 /* --BEGIN ERROR HANDLING-- */
266 #ifdef HAVE_ERROR_CHECKING
267 {
268 mpi_errno =
269 MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
270 "**mpi_t_pvar_read", "**mpi_t_pvar_read %p %p %p", session, handle,
271 buf);
272 }
273 #endif
274 mpi_errno = MPIR_Err_return_comm(NULL, __func__, mpi_errno);
275 goto fn_exit;
276 /* --END ERROR HANDLING-- */
277 }
278