1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 /* Types and interfaces in this file are internally used by MPIR_T itself.
7 * Other modules should call higher level interfaces in mpit.h instead.
8 */
9 #ifndef MPITIMPL_H_INCLUDED
10 #define MPITIMPL_H_INCLUDED
11
12 #include "mpi.h"
13 #include "mpir_strerror.h"
14 #include "mpir_type_defs.h"
15 #include "mpir_assert.h"
16 #include "mpir_pointers.h"
17 #include "utarray.h"
18 #include "uthash.h"
19 #include "mpir_objects.h"
20
21 #ifdef HAVE_ERROR_CHECKING
22 typedef enum {
23 MPIR_T_OBJECT_INVALID = 0,
24 MPIR_T_ENUM_HANDLE,
25 MPIR_T_CVAR_HANDLE,
26 MPIR_T_PVAR_HANDLE,
27 MPIR_T_PVAR_SESSION
28 } MPIR_T_object_kind;
29 #endif
30
31 /* MPI_T enum
32 */
33 typedef struct enum_item_s {
34 const char *name;
35 int value;
36 } enum_item_t;
37
38 typedef struct MPIR_T_enum_s {
39 #ifdef HAVE_ERROR_CHECKING
40 MPIR_T_object_kind kind;
41 #endif
42 const char *name;
43 UT_array *items;
44 } MPIR_T_enum_t;
45
46 /* MPI_T category (cat)
47 */
48 typedef struct {
49 const char *name;
50 UT_array *cvar_indices;
51 UT_array *pvar_indices;
52 UT_array *subcat_indices;
53 const char *desc;
54 } cat_table_entry_t;
55
56 /* Hash names to indices in a table */
57 typedef struct {
58 const char *name;
59 unsigned idx;
60 UT_hash_handle hh; /* Makes this structure hashable */
61 } name2index_hash_t;
62
63 /* MPI_T control variable (cvar)
64 */
65 typedef struct MPIR_T_cvar_range_value_s {
66 int low;
67 int high;
68 } MPIR_T_cvar_range_value_t;
69
70 /* Type used to represent cvar default values */
71 typedef union MPIR_T_cvar_value_s {
72 int d;
73 unsigned u;
74 unsigned ul;
75 unsigned ull;
76 MPI_Count c;
77 const char *str;
78 double f;
79 MPIR_T_cvar_range_value_t range;
80 } MPIR_T_cvar_value_t;
81
82 typedef int MPIR_T_cvar_get_addr_cb(void *obj_handle, void **addr);
83 typedef int MPIR_T_cvar_get_count_cb(void *obj_handle, int *count);
84
85 typedef struct cvar_table_entry_s {
86 /* Is the cvar currently in use? False if the cvar is unregistered */
87 int active;
88
89 /* cvar name */
90 const char *name;
91
92 /* Address of the cvar. May be NULL when get_addr != NULL */
93 void *addr;
94
95 /* cvar data type */
96 MPI_Datatype datatype;
97
98 /* Num. of elements of the cvar. May be ignored when get_count != NULL */
99 int count;
100
101 /* Properties of the cvar */
102 MPI_T_enum enumtype;
103 MPIR_T_verbosity_t verbosity;
104 MPIR_T_bind_t bind;
105 MPIR_T_scope_t scope;
106
107 /* Default value */
108 MPIR_T_cvar_value_t defaultval;
109
110 /* If not NULL, components provide this callback to get addr of the cvar */
111 MPIR_T_cvar_get_addr_cb *get_addr;
112
113 /* If not NULL, components provide this callback to get count */
114 MPIR_T_cvar_get_count_cb *get_count;
115
116 /* Description of the cvar */
117 const char *desc;
118 } cvar_table_entry_t;
119
120 typedef struct MPIR_T_cvar_handle_s {
121 #ifdef HAVE_ERROR_CHECKING
122 MPIR_T_object_kind kind;
123 #endif
124
125 /* Address and count of the cvar. Set at handle allocation time */
126 void *addr;
127 int count;
128
129 /* Cached value from cvar_table_entry_t to avoid indirection */
130 MPI_Datatype datatype;
131 MPIR_T_scope_t scope;
132 } MPIR_T_cvar_handle_t;
133
134 void MPIR_T_CVAR_REGISTER_impl(MPI_Datatype dtype, const char *name, const void *addr, int count,
135 MPIR_T_enum_t * etype, MPIR_T_verbosity_t verb, MPIR_T_bind_t bind,
136 MPIR_T_scope_t scope, MPIR_T_cvar_get_addr_cb get_addr,
137 MPIR_T_cvar_get_count_cb get_count, MPIR_T_cvar_value_t defaultval,
138 const char *cat, const char *desc);
139
140 /* MPI_T performance variable (pvar)
141 */
142
143 /* Forward declaration */
144 struct MPIR_T_pvar_handle_s;
145 struct MPIR_T_pvar_session_s;
146
147 typedef void MPIR_T_pvar_get_value_cb(void *addr, void *obj_handle, int count, void *buf);
148 typedef void MPIR_T_pvar_get_count_cb(void *addr, void *obj_handle, int *count);
149
150 /* Basic pvar flags defined by MPI_T standard */
151 #define MPIR_T_PVAR_FLAG_READONLY 0x01
152 #define MPIR_T_PVAR_FLAG_CONTINUOUS 0x02
153 #define MPIR_T_PVAR_FLAG_ATOMIC 0x04
154
155 /* Auxlilary flags used by MPIR_T */
156
157 /* pvar is MPI_T_PVAR_CLASS_{COUNTER, TIMER, AGGREGATE} */
158 #define MPIR_T_PVAR_FLAG_SUM 0x08
159
160 /* pvar is MPI_T_PVAR_CLASS_{HIGH, LOW}WATERMARK */
161 #define MPIR_T_PVAR_FLAG_WATERMARK 0x10
162
163 /* pvar is continuous. If not, it has been started at least once */
164 #define MPIR_T_PVAR_FLAG_ONCESTARTED 0x20
165
166 /* pvar is continuous. If not, it is started */
167 #define MPIR_T_PVAR_FLAG_STARTED 0x40
168
169 /* Used only for watermark handles. Set if a pvar handle is the
170 * first handle of an associated watermark.
171 */
172 #define MPIR_T_PVAR_FLAG_FIRST 0x80
173
174 /* MPI_T performance variable (pvar) stuff */
175 typedef struct {
176 /* Is the pvar in use (i.e., not unregistered)? */
177 int active;
178
179 /* pvar name */
180 const char *name;
181
182 /* If not NULL, it is address of the pvar */
183 void *addr;
184
185 /* pvar data type */
186 MPI_Datatype datatype;
187
188 /* Num. of elements of the pvar */
189 int count;
190
191 /* Properties of the pvar */
192 MPIR_T_pvar_class_t varclass;
193 MPIR_T_verbosity_t verbosity;
194 MPIR_T_enum_t *enumtype;
195 MPIR_T_bind_t bind;
196
197 /* Basic flags of the pvar */
198 int flags;
199
200 /* If not NULL, components provide this callback to read the pvar */
201 MPIR_T_pvar_get_value_cb *get_value;
202
203 /* If not NULL, components provide this callback to get count */
204 MPIR_T_pvar_get_count_cb *get_count;
205
206 /* Description of the pvar */
207 const char *desc;
208 } pvar_table_entry_t;
209
210 /*
211 The following two macros do not work since C preprocessor does not support
212 nested ifdefs. So we use another woarkable but a little ugly approach.
213
214 #define PVAR_GATED_ACTION(MODULE, action_) \
215 do { \
216 #ifdef ENABLE_PVAR_##MODULE \
217 action_; \
218 #endif \
219 } while (0)
220 */
221
222 /* ENABLE_PVAR_##MODULE must be defined by configure script either to 0 or 1 */
223 #define PVAR_GATED_ACTION(MODULE, action_) \
224 do { \
225 if (ENABLE_PVAR_##MODULE) { \
226 action_; \
227 } \
228 } while (0)
229
230 /* For some classes of pvars, internally we can not represent them
231 * in basic data types. So come the following typedefs.
232 */
233
234 /* Timer type */
235 typedef struct {
236 /* Accumulated time */
237 MPL_time_t total;
238
239 /* Time when the timer was started recently */
240 MPL_time_t curstart;
241
242 /* A counter recording how many times the timer is started */
243 unsigned long long count;
244 } MPIR_T_pvar_timer_t;
245
246 /* An union to represent a watermark value */
247 typedef union {
248 double f;
249 unsigned u;
250 unsigned long ul;
251 unsigned long long ull;
252 } watermark_value_t;
253
254 /* Watermark type */
255 typedef struct {
256 /* current -- current resource utilization level
257 * waterarmk -- cached value for the first pvar handle
258 */
259 watermark_value_t current, watermark;
260
261 /* Datatype of the watermark */
262 MPI_Datatype datatype;
263
264 /* Is the cached value (i.e, watermark) in use by a pvar handle? */
265 int first_used;
266
267 /* Is the first pvar handle started? */
268 int first_started;
269
270 /* A double-linked list of handles of the pvar */
271 struct MPIR_T_pvar_handle_s *hlist;
272 } MPIR_T_pvar_watermark_t;
273
274 typedef struct MPIR_T_pvar_handle_s {
275 #ifdef HAVE_ERROR_CHECKING
276 MPIR_T_object_kind kind;
277 #endif
278
279 /* These are cached fields from pvar table. Do so to avoid extra
280 * indirection when accessing them through pvar handles.
281 */
282 void *addr;
283 MPI_Datatype datatype;
284 int count;
285 MPIR_T_pvar_get_value_cb *get_value;
286 MPIR_T_pvar_class_t varclass;
287
288 /* Bytes of an element of datatype */
289 int bytes;
290
291 /* Basic flags copied from pvar info + auxilary flags in pvar handle */
292 int flags;
293
294 /* Store info here in case we need other fields */
295 const pvar_table_entry_t *info;
296
297 /* Owner session from which the handle is allocated */
298 struct MPIR_T_pvar_session_s *session;
299
300 /* Object which this pvar is bound to. NULL if no binding */
301 void *obj_handle;
302
303 /* This is how we support pvar sessions.
304 *
305 * For pvars of counter, timer or aggregate type, we cache their value at
306 * the last start time in offset, their current value in current, and
307 * their accumlated value in accum. Generally, when such a pvar is running,
308 * reading the pvar should return
309 * accum[i] + current[i] - offset[i], 0 <= i < count - 1.
310 * When the pvar is stopped, reading just returns accum.
311 *
312 * For pvars of high/lowwatermark type, above method does not work.
313 * We have a copy of such a pvar in every handle of the pvar.
314 * Handles are registered to the pvar. Whenever a watermark changes,
315 * its copies in non-stopped handles are updated. That sounds non-scalable.
316 * Considering single-session is common, we reserve room in watermark
317 * themselves for cache buffer for the first handle. So when such a pvar
318 * changes, it also updates the watermark close to it in memory.
319 *
320 * For pvars of other classes, since they are supposed to be readonly
321 * and continuous (FIXME: Is it true?), caching is not needed.
322 */
323 void *accum;
324 void *offset;
325 void *current;
326
327 watermark_value_t watermark;
328
329 /* To chain handles in a session */
330 struct MPIR_T_pvar_handle_s *prev, *next;
331
332 /* To chain handles of a watermark pvar */
333 struct MPIR_T_pvar_handle_s *prev2, *next2;
334 } MPIR_T_pvar_handle_t;
335
336 typedef struct MPIR_T_pvar_session_s {
337 #ifdef HAVE_ERROR_CHECKING
338 MPIR_T_object_kind kind;
339 #endif
340
341 /* A linked list of pvar handles */
342 MPIR_T_pvar_handle_t *hlist;
343 } MPIR_T_pvar_session_t;
344
345 extern void MPIR_T_PVAR_REGISTER_impl(MPIR_T_pvar_class_t varclass, MPI_Datatype dtype,
346 const char *name, void *addr, int count,
347 MPIR_T_enum_t * etype, MPIR_T_verbosity_t verb,
348 MPIR_T_bind_t bind, int flags,
349 MPIR_T_pvar_get_value_cb get_value,
350 MPIR_T_pvar_get_count_cb get_count, const char *cat,
351 const char *desc);
352
353 /* For static pvars (i.e., pvars with static storage), we embed their class name
354 * into their variable name, so that users can declare pvars with the same name
355 * for different classes, without worry of name conflict. "class + pvar name"
356 * should be unique as required by MPI_T.
357 */
358
359 /* MPI_T_PVAR_CLASS_STATE (continuous only)
360 */
361
362 /* Interfaces through pointer or name */
363 #define MPIR_T_PVAR_STATE_SET_VAR_impl(ptr_, val_) \
364 do { *(ptr_) = (val_); } while (0)
365 #define MPIR_T_PVAR_STATE_GET_VAR_impl(ptr_) \
366 (*(ptr_))
367
368 #define MPIR_T_PVAR_STATE_SET_impl(name_, val_) \
369 MPIR_T_PVAR_STATE_SET_VAR_impl(&PVAR_STATE_##name_, val_)
370 #define MPIR_T_PVAR_STATE_GET_impl(name_) \
371 MPIR_T_PVAR_STATE_GET_VAR_impl(&PVAR_STATE_##name_)
372
373 /* Registration AND initialization for static pvar */
374 #define MPIR_T_PVAR_STATE_REGISTER_STATIC_impl(dtype_, name_, \
375 initval_, etype_, verb_, bind_, flags_, cat_, desc_) \
376 do { \
377 void *addr_; \
378 /* Allowable datatypes only */ \
379 MPIR_Assert((dtype_) == MPI_INT); \
380 /* Double check if dtype_ and name_ match */ \
381 MPIR_Assert(sizeof(PVAR_STATE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
382 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
383 /* State pvars should be describled further by an enum */ \
384 MPIR_Assert((etype_) != MPI_T_ENUM_NULL); \
385 PVAR_STATE_##name_ = (initval_); \
386 addr_ = &PVAR_STATE_##name_; \
387 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_STATE, dtype_, #name_, \
388 addr_, 1, etype_, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
389 } while (0)
390
391 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
392 #define MPIR_T_PVAR_STATE_REGISTER_DYNAMIC_impl(dtype_, name_, addr_, count_, \
393 etype_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
394 do { \
395 /* Allowable datatypes */ \
396 MPIR_Assert((dtype_) == MPI_INT); \
397 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
398 MPIR_Assert((etype_) != MPI_T_ENUM_NULL); \
399 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
400 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_STATE, dtype_, #name_, \
401 addr_, count_, etype_, verb_, bind_, flags_, get_value_, cat_, desc_); \
402 } while (0)
403
404
405 /* MPI_T_PVAR_CLASS_LEVEL (continuous only)
406 */
407
408 /* Interfaces through pointer or name */
409 #define MPIR_T_PVAR_LEVEL_SET_VAR_impl(ptr_, val_) \
410 do { *(ptr_) = (val_); } while (0)
411 #define MPIR_T_PVAR_LEVEL_GET_VAR_impl(ptr_) \
412 (*(ptr_))
413 #define MPIR_T_PVAR_LEVEL_INC_VAR_impl(ptr_, val_) \
414 do { *(ptr_) += (val_); } while (0)
415 #define MPIR_T_PVAR_LEVEL_DEC_VAR_impl(ptr_, val_) \
416 do { *(ptr_) -= (val_); } while (0)
417
418 #define MPIR_T_PVAR_LEVEL_SET_impl(name_, val_) \
419 MPIR_T_PVAR_LEVEL_SET_VAR_impl(&PVAR_LEVEL_##name_, val_)
420 #define MPIR_T_PVAR_LEVEL_GET_impl(name_) \
421 MPIR_T_PVAR_LEVEL_GET_VAR_impl(&PVAR_LEVEL_##name_)
422 #define MPIR_T_PVAR_LEVEL_INC_impl(name_, val_) \
423 MPIR_T_PVAR_LEVEL_INC_VAR_impl(&PVAR_LEVEL_##name_, val_)
424 #define MPIR_T_PVAR_LEVEL_DEC_impl(name_, val_) \
425 MPIR_T_PVAR_LEVEL_DEC_VAR_impl(&PVAR_LEVEL_##name_, val_)
426
427 /* Registration AND initialization for static pvar */
428 #define MPIR_T_PVAR_LEVEL_REGISTER_STATIC_impl(dtype_, name_, \
429 initval_, verb_, bind_, flags_, cat_, desc_) \
430 do { \
431 void *addr_; \
432 /* Allowable datatypes only */ \
433 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
434 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
435 /* Double check if dtype_ and name_ match */ \
436 MPIR_Assert(sizeof(PVAR_LEVEL_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
437 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
438 PVAR_LEVEL_##name_ = (initval_); \
439 addr_ = &PVAR_LEVEL_##name_; \
440 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LEVEL, dtype_, #name_, \
441 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
442 } while (0)
443
444 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
445 #define MPIR_T_PVAR_LEVEL_REGISTER_DYNAMIC_impl(dtype_, name_, \
446 addr_, count_, verb_, bind_, flags_, get_value_, get_count, cat_, desc_) \
447 do { \
448 /* Allowable datatypes */ \
449 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
450 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
451 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
452 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
453 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LEVEL, dtype_, #name_, \
454 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
455 get_count, cat_, desc_); \
456 } while (0)
457
458
459 /* MPI_T_PVAR_CLASS_SIZE (continuous only)
460 */
461
462 /* Interfaces through pointer or name */
463 #define MPIR_T_PVAR_SIZE_SET_VAR_impl(ptr_, val_) \
464 do { *(ptr_) = (val_); } while (0)
465 #define MPIR_T_PVAR_SIZE_GET_VAR_impl(ptr_) \
466 (*(ptr_))
467
468 #define MPIR_T_PVAR_SIZE_SET_impl(name_, val_) \
469 MPIR_T_PVAR_SIZE_SET_VAR_impl(&PVAR_SIZE_##name_, val_)
470 #define MPIR_T_PVAR_SIZE_GET_impl(name_) \
471 MPIR_T_PVAR_SIZE_GET_VAR_impl(&PVAR_SIZE_##name_)
472
473 /* Registration AND initialization for static pvar */
474 #define MPIR_T_PVAR_SIZE_REGISTER_STATIC_impl(dtype_, name_, \
475 initval_, verb_, bind_, flags_, cat_, desc_) \
476 do { \
477 void *addr_; \
478 /* Allowable datatypes only */ \
479 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
480 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
481 /* Double check if dtype_ and name_ match */ \
482 MPIR_Assert(sizeof(PVAR_SIZE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
483 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
484 PVAR_SIZE_##name_ = (initval_); \
485 addr_ = &PVAR_SIZE_##name_; \
486 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_SIZE, dtype_, #name_, \
487 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
488 } while (0)
489
490 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
491 #define MPIR_T_PVAR_SIZE_REGISTER_DYNAMIC_impl(dtype_, name_, \
492 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
493 do { \
494 /* Allowable datatypes */ \
495 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
496 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
497 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
498 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
499 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_SIZE, dtype_, #name_, \
500 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
501 get_count_, cat_, desc_); \
502 } while (0)
503
504
505 /* MPI_T_PVAR_CLASS_PERCENTAGE (continuous only)
506 */
507
508 /* Interfaces through pointer or name */
509 #define MPIR_T_PVAR_PERCENTAGE_SET_VAR_impl(ptr_, val_) \
510 do { \
511 MPIR_Assert(0.0 <= (val_) && (val_) <= 1.0); \
512 *(ptr_) = (val_); \
513 } while (0)
514 #define MPIR_T_PVAR_PERCENTAGE_GET_VAR_impl(ptr_) \
515 (*(ptr_))
516
517 #define MPIR_T_PVAR_PERCENTAGE_SET_impl(name_, val_) \
518 MPIR_T_PVAR_PERCENTAGE_SET_VAR_impl(&PVAR_PERCENTAGE_##name_, val_)
519 #define MPIR_T_PVAR_PERCENTAGE_GET_impl(name_) \
520 MPIR_T_PVAR_PERCENTAGE_GET_VAR_impl(&PVAR_PERCENTAGE_##name_)
521
522 /* Registration AND initialization for static pvar */
523 #define MPIR_T_PVAR_PERCENTAGE_REGISTER_STATIC_impl(dtype_, name_, \
524 initval_, verb_, bind_, flags_, cat_, desc_) \
525 do { \
526 void *addr_; \
527 /* Allowable datatypes only */ \
528 MPIR_Assert((dtype_) == MPI_DOUBLE); \
529 /* Double check if dtype_ and name_ match */ \
530 MPIR_Assert(sizeof(PVAR_PERCENTAGE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
531 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
532 addr_ = &PVAR_PERCENTAGE_##name_; \
533 PVAR_PERCENTAGE_##name_ = (initval_); \
534 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_PERCENTAGE, dtype_, #name_, \
535 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
536 } while (0)
537
538 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
539 #define MPIR_T_PVAR_PERCENTAGE_REGISTER_DYNAMIC_impl(dtype_, name_, \
540 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
541 do { \
542 /* Allowable datatypes */ \
543 MPIR_Assert((dtype_) == MPI_DOUBLE); \
544 MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
545 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
546 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_PERCENTAGE, dtype_, #name_, \
547 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
548 get_count_, cat_, desc_); \
549 } while (0)
550
551
552 /* MPI_T_PVAR_CLASS_COUNTER (continuous or not)
553 */
554
555 /* Interfaces through pointer or name */
556 #define MPIR_T_PVAR_COUNTER_INIT_VAR_impl(ptr_) \
557 do { *(ptr_) = 0; } while (0)
558 /* _COUNTER_SET is intentionally not provided. Users should only INC counters */
559 #define MPIR_T_PVAR_COUNTER_GET_VAR_impl(ptr_) \
560 (*(ptr_))
561 #define MPIR_T_PVAR_COUNTER_INC_VAR_impl(ptr_, inc_) \
562 do { *(ptr_) += (inc_); } while (0)
563
564 #define MPIR_T_PVAR_COUNTER_INIT_impl(name_) \
565 MPIR_T_PVAR_COUNTER_INIT_VAR_impl(&PVAR_COUNTER_##name_)
566 #define MPIR_T_PVAR_COUNTER_GET_impl(name_) \
567 MPIR_T_PVAR_COUNTER_GET_VAR_impl(&PVAR_COUNTER_##name_)
568 #define MPIR_T_PVAR_COUNTER_INC_impl(name_, inc_) \
569 MPIR_T_PVAR_COUNTER_INC_VAR_impl(&PVAR_COUNTER_##name_, inc_)
570 #define MPIR_T_PVAR_COUNTER_ADDR_impl(name_) \
571 (&PVAR_COUNTER_##name_)
572
573 /* Registration AND initialization to zero for static pvar. */
574 #define MPIR_T_PVAR_COUNTER_REGISTER_STATIC_impl(dtype_, name_, \
575 verb_, bind_, flags_, cat_, desc_) \
576 do { \
577 void *addr_; \
578 /* Allowable datatypes only */ \
579 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
580 (dtype_) == MPI_UNSIGNED_LONG_LONG); \
581 /* Double check if dtype_ and name_ match*/ \
582 MPIR_Assert(sizeof(PVAR_COUNTER_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
583 PVAR_COUNTER_##name_ = 0; \
584 addr_ = &PVAR_COUNTER_##name_; \
585 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
586 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
587 } while (0)
588
589 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
590 #define MPIR_T_PVAR_COUNTER_REGISTER_DYNAMIC_impl(dtype_, name_, \
591 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
592 do { \
593 /* Allowable datatypes */ \
594 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
595 (dtype_) == MPI_UNSIGNED_LONG_LONG); \
596 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
597 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
598 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
599 get_count_, cat_, desc_); \
600 } while (0)
601
602 /* Interfaces through pointer or name */
603 #define MPIR_T_PVAR_COUNTER_ARRAY_INIT_VAR_impl(ptr_, count_) \
604 do { \
605 int idx_; \
606 idx_ = 0; \
607 for (; idx_ < (count_); idx_++) \
608 *((ptr_) + idx_) = 0; \
609 } while (0)
610 #define MPIR_T_PVAR_COUNTER_ARRAY_GET_VAR_impl(ptr_, idx_) \
611 *((ptr_) + (idx_))
612 #define MPIR_T_PVAR_COUNTER_ARRAY_INC_VAR_impl(ptr_, idx_, inc_) \
613 do { *((ptr_) + (idx_)) += (inc_); } while (0)
614
615 #define MPIR_T_PVAR_COUNTER_ARRAY_INIT_impl(name_) \
616 do { \
617 int count_; \
618 count_ = sizeof(PVAR_COUNTER_##name_)/sizeof(PVAR_COUNTER_##name_[0]); \
619 MPIR_T_PVAR_COUNTER_ARRAY_INIT_VAR_impl(PVAR_COUNTER_##name_, count_); \
620 } while (0)
621 #define MPIR_T_PVAR_COUNTER_ARRAY_GET_impl(name_, idx_) \
622 MPIR_T_PVAR_COUNTER_ARRAY_GET_VAR_impl(PVAR_COUNTER_##name_, idx_)
623 #define MPIR_T_PVAR_COUNTER_ARRAY_INC_impl(ptr_, idx_, inc_) \
624 MPIR_T_PVAR_COUNTER_ARRAY_INC_VAR_impl(PVAR_COUNTER_##name_, idx_, inc_)
625
626 /* Registration AND initialization to zero for static counter array */
627 #define MPIR_T_PVAR_COUNTER_ARRAY_REGISTER_STATIC_impl(dtype_, name_, \
628 verb_, bind_, flags_, cat_, desc_) \
629 do { \
630 void *addr_; \
631 int count_; \
632 /* Allowable datatypes only */ \
633 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
634 (dtype_) == MPI_UNSIGNED_LONG_LONG); \
635 /* Double check if dtype_ and name_ match */ \
636 MPIR_Assert(sizeof(PVAR_COUNTER_##name_[0]) == MPIR_Datatype_get_basic_size(dtype_)); \
637 addr_ = PVAR_COUNTER_##name_; \
638 MPIR_T_PVAR_COUNTER_ARRAY_INIT_impl(name_); \
639 count_ = sizeof(PVAR_COUNTER_##name_)/sizeof(PVAR_COUNTER_##name_[0]); \
640 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
641 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
642 } while (0)
643
644 /* Dynamic counter array is already provided by MPIR_T_PVAR_COUNTER_REGISTER_DYNAMIC */
645
646 /* MPI_T_PVAR_CLASS_AGGREGATE (continuous or not)
647 */
648
649 /* Interfaces through pointer or name */
650 #define MPIR_T_PVAR_AGGREGATE_INIT_VAR_impl(ptr_) \
651 do { *(ptr_) = 0; } while (0)
652 /* _AGGREGATE_SET is intentionally not provided as for counters */
653 #define MPIR_T_PVAR_AGGREGATE_GET_VAR_impl(ptr_) \
654 (*(ptr_))
655 #define MPIR_T_PVAR_AGGREGATE_INC_VAR_impl(ptr_, inc_) \
656 do { *(ptr_) += (inc_); } while (0)
657
658 #define MPIR_T_PVAR_AGGREGATE_INIT_impl(name_) \
659 MPIR_T_PVAR_AGGREGATE_INIT_VAR_impl(&PVAR_AGGREGATE_##name_)
660 #define MPIR_T_PVAR_AGGREGATE_GET_impl(name_) \
661 MPIR_T_PVAR_AGGREGATE_GET_VAR_impl(&PVAR_AGGREGATE_##name_)
662 #define MPIR_T_PVAR_AGGREGATE_INC_impl(name_, inc_) \
663 MPIR_T_PVAR_AGGREGATE_INC_VAR_impl(&PVAR_AGGREGATE_##name_, inc_)
664
665 /* Registration AND initialization to zero for static aggregate */
666 #define MPIR_T_PVAR_AGGREGATE_REGISTER_STATIC_impl(dtype_, name_, \
667 verb_, bind_, flags_, cat_, desc_) \
668 do { \
669 void *addr; \
670 /* Allowable datatypes only */ \
671 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
672 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
673 /* Double check if dtype_ and name_ match*/ \
674 MPIR_Assert(sizeof(PVAR_AGGREGATE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
675 PVAR_AGGREGATE_##name_ = 0; \
676 addr_ = &PVAR_AGGREGATE_##name_; \
677 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_AGGREGATE, dtype_, #name_, \
678 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
679 } while (0)
680
681 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
682 #define MPIR_T_PVAR_AGGREGATE_REGISTER_DYNAMIC_impl(dtype_, name_, \
683 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
684 do { \
685 /* Allowable datatypes */ \
686 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
687 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
688 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
689 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_AGGREGATE, dtype_, #name_, \
690 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
691 get_count_, cat_, desc_); \
692 } while (0)
693
694
695 /* MPI_T_PVAR_CLASS_TIMER (continuous or not)
696 */
697
698 /* Interfaces through pointer or name */
699 #define MPIR_T_PVAR_TIMER_INIT_VAR_impl(ptr_) \
700 do { \
701 /* FIXME: need a generic approach to init a timer */ \
702 memset(&((ptr_)->total), 0, sizeof(MPL_time_t)); \
703 } while (0)
704 #define MPIR_T_PVAR_TIMER_GET_VAR_impl(ptr_, buf) \
705 do { \
706 MPL_wtime_todouble(&((ptr_)->total), buf); \
707 } while (0)
708 #define MPIR_T_PVAR_TIMER_START_VAR_impl(ptr_) \
709 do { \
710 MPL_wtime(&((ptr_)->curstart)); \
711 (ptr_)->count++; \
712 } while (0)
713 #define MPIR_T_PVAR_TIMER_END_VAR_impl(ptr_) \
714 do { \
715 MPL_time_t tmp_; \
716 MPL_wtime(&tmp_); \
717 MPL_wtime_acc(&((ptr_)->curstart), &tmp_, &((ptr_)->total)); \
718 } while (0)
719
720 #define MPIR_T_PVAR_TIMER_INIT_impl(name_) \
721 MPIR_T_PVAR_TIMER_INIT_VAR_impl(&PVAR_TIMER_##name_)
722 #define MPIR_T_PVAR_TIMER_GET_impl(name_, buf_) \
723 MPIR_T_PVAR_TIMER_GET_VAR_impl(&PVAR_TIMER_##name_, buf_)
724 #define MPIR_T_PVAR_TIMER_START_impl(name_) \
725 MPIR_T_PVAR_TIMER_START_VAR_impl(&PVAR_TIMER_##name_)
726 #define MPIR_T_PVAR_TIMER_END_impl(name_) \
727 MPIR_T_PVAR_TIMER_END_VAR_impl(&PVAR_TIMER_##name_)
728 #define MPIR_T_PVAR_TIMER_ADDR_impl(name_) \
729 (&PVAR_TIMER_##name_)
730
731 /* Customized get_value() for MPIR_T_pvar_timer_t */
732 static inline
get_timer_time_in_double(MPIR_T_pvar_timer_t * timer,void * obj_handle,int count,double * buf)733 void get_timer_time_in_double(MPIR_T_pvar_timer_t * timer, void *obj_handle,
734 int count, double *buf)
735 {
736 int i;
737 for (i = 0; i < count; i++)
738 MPL_wtime_todouble(&(timer[i].total), &buf[i]);
739 }
740
741 /* Registration for static storage */
742 #define MPIR_T_PVAR_TIMER_REGISTER_STATIC_impl(dtype_, name_, \
743 verb_, bind_, flags_, cat_, desc_) \
744 do { \
745 void *addr_; \
746 void *count_addr_; \
747 /* Allowable datatypes only */ \
748 MPIR_Assert((dtype_) == MPI_DOUBLE); \
749 MPIR_T_PVAR_TIMER_INIT_impl(name_); \
750 addr_ = &PVAR_TIMER_##name_; \
751 count_addr_ = &(PVAR_TIMER_##name_.count); \
752 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_TIMER, dtype_, #name_, \
753 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, \
754 (MPIR_T_pvar_get_value_cb *)&get_timer_time_in_double, NULL, cat_, desc_); \
755 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, MPI_UNSIGNED_LONG_LONG, #name_, \
756 count_addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, \
757 NULL, NULL, cat_, desc_); \
758 } while (0)
759
760
761 /* MPI_T_PVAR_CLASS_HIGHWATERMARK (continuous or not)
762 */
763
764 /* Interfaces through pointer or name.
765 * In contrast to previous pvar classes, for each type we create a set
766 * of interfaces. That is because we have a pointer and a union in the
767 * struct. We need to know types to (de)reference them.
768 */
769 #define MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
770 do { \
771 (ptr_)->datatype = MPI_UNSIGNED; \
772 (ptr_)->current.u = (val_); \
773 (ptr_)->first_started = 0; \
774 (ptr_)->first_used = 0; \
775 (ptr_)->hlist = NULL; \
776 } while (0)
777
778 #define MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
779 do { \
780 (ptr_)->datatype = MPI_UNSIGNED_LONG; \
781 (ptr_)->current.ul = (val_); \
782 (ptr_)->first_started = 0; \
783 (ptr_)->first_used = 0; \
784 (ptr_)->hlist = NULL; \
785 } while (0)
786
787 #define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
788 do { \
789 (ptr_)->datatype = MPI_UNSIGNED_LONG_LONG; \
790 (ptr_)->current.ull = (val_); \
791 (ptr_)->first_started = 0; \
792 (ptr_)->first_used = 0; \
793 (ptr_)->hlist = NULL; \
794 } while (0)
795
796 #define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
797 do { \
798 (ptr_)->datatype = MPI_DOUBLE; \
799 (ptr_)->current.f = (val_); \
800 (ptr_)->first_started = 0; \
801 (ptr_)->first_used = 0; \
802 (ptr_)->hlist = NULL; \
803 } while (0)
804
805 #define MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
806 do { \
807 MPIR_T_pvar_handle_t *head; \
808 (ptr_)->current.u = (val_); \
809 if ((ptr_)->first_used && (ptr_)->first_started) { \
810 if ((val_) > (ptr_)->watermark.u) \
811 (ptr_)->watermark.u = (val_); \
812 } \
813 head = (ptr_)->hlist; \
814 while (head != NULL) { \
815 if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.u) { \
816 head->watermark.u = (val_); \
817 } \
818 head = head->next2; \
819 } \
820 } while (0)
821
822 #define MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
823 do { \
824 MPIR_T_pvar_handle_t *head; \
825 (ptr_)->current.ul = (val_); \
826 if ((ptr_)->first_used && (ptr_)->first_started) { \
827 if ((val_) > (ptr_)->watermark.ul) \
828 (ptr_)->watermark.ul = (val_); \
829 } \
830 head = (ptr_)->hlist; \
831 while (head != NULL) { \
832 if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.ul) { \
833 head->watermark.ul = (val_); \
834 } \
835 head = head->next2; \
836 } \
837 } while (0)
838
839 #define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
840 do { \
841 MPIR_T_pvar_handle_t *head; \
842 (ptr_)->current.ull = (val_); \
843 if ((ptr_)->first_used && (ptr_)->first_started) { \
844 if ((val_) > (ptr_)->watermark.ull) \
845 (ptr_)->watermark.ull = (val_); \
846 } \
847 head = (ptr_)->hlist; \
848 while (head != NULL) { \
849 if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.ull) { \
850 head->watermark.ull = (val_); \
851 } \
852 head = head->next2; \
853 } \
854 } while (0)
855
856 #define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
857 do { \
858 MPIR_T_pvar_handle_t *head; \
859 (ptr_)->current.f = (val_); \
860 if ((ptr_)->first_used && (ptr_)->first_started) { \
861 if ((val_) > (ptr_)->watermark.f) \
862 (ptr_)->watermark.f = (val_); \
863 } \
864 head = (ptr_)->hlist; \
865 while (head != NULL) { \
866 if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.f) { \
867 head->watermark.f = (val_); \
868 } \
869 head = head->next2; \
870 } \
871 } while (0)
872
873 #define MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_impl(name_, val_) \
874 MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
875 #define MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_impl(name_, val_) \
876 MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
877 #define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_impl(name_, val_) \
878 MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
879 #define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_impl(name_, val_) \
880 MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
881
882 #define MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_impl(name_, val_) \
883 MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
884 #define MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_impl(name_, val_) \
885 MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
886 #define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_impl(name_, val_) \
887 MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
888 #define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_impl(name_, val_) \
889 MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
890
891 /* Registration AND initialization for static pvar */
892 #define MPIR_T_PVAR_HIGHWATERMARK_REGISTER_STATIC_impl(dtype_, name_, \
893 initval_, verb_, bind_, flags_, cat_, desc_) \
894 do { \
895 void *addr_; \
896 /* Allowable datatypes only */ \
897 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
898 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
899 switch (dtype_) { \
900 case MPI_UNSIGNED: \
901 MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
902 case MPI_UNSIGNED_LONG: \
903 MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
904 case MPI_UNSIGNED_LONG_LONG: \
905 MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
906 case MPI_DOUBLE: \
907 MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
908 default: \
909 break; \
910 }; \
911 addr_ = &PVAR_HIGHWATERMARK_##name_; \
912 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_HIGHWATERMARK, dtype_, #name_, \
913 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
914 } while (0)
915
916 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
917 #define MPIR_T_PVAR_HIGHWATERMARK_REGISTER_DYNAMIC_impl(dtype_, name_, \
918 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
919 do { \
920 /* Allowable datatypes */ \
921 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
922 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
923 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
924 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_HIGHWATERMARK, dtype_, #name_, \
925 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
926 get_count_, cat_, desc_); \
927 } while (0)
928
929
930 /* MPI_T_PVAR_CLASS_LOWWATERMARK (continuous or not)
931 */
932
933 #define MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
934 do { \
935 (ptr_)->datatype = MPI_UNSIGNED; \
936 (ptr_)->current.u = (val_); \
937 (ptr_)->first_started = 0; \
938 (ptr_)->first_used = 0; \
939 (ptr_)->hlist = NULL; \
940 } while (0)
941
942 #define MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
943 do { \
944 (ptr_)->datatype = MPI_UNSIGNED_LONG; \
945 (ptr_)->current.ul = (val_); \
946 (ptr_)->first_started = 0; \
947 (ptr_)->first_used = 0; \
948 (ptr_)->hlist = NULL; \
949 } while (0)
950
951 #define MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
952 do { \
953 (ptr_)->datatype = MPI_UNSIGNED_LONG_LONG; \
954 (ptr_)->current.ull = (val_); \
955 (ptr_)->first_started = 0; \
956 (ptr_)->first_used = 0; \
957 (ptr_)->hlist = NULL; \
958 } while (0)
959
960 #define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
961 do { \
962 (ptr_)->datatype = MPI_DOUBLE; \
963 (ptr_)->current.f = (val_); \
964 (ptr_)->first_started = 0; \
965 (ptr_)->first_used = 0; \
966 (ptr_)->hlist = NULL; \
967 } while (0)
968
969 #define MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
970 do { \
971 MPIR_T_pvar_handle_t *head; \
972 (ptr_)->current.u = (val_); \
973 /* Update values in all handles */ \
974 if ((ptr_)->first_used && (ptr_)->first_started) { \
975 if ((val_) < (ptr_)->watermark.u) \
976 (ptr_)->watermark.u = (val_); \
977 } \
978 head = (ptr_)->hlist; \
979 while (head != NULL) { \
980 if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.u) { \
981 head->watermark.u = (val_); \
982 } \
983 head = head->next2; \
984 } \
985 } while (0)
986
987 #define MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
988 do { \
989 MPIR_T_pvar_handle_t *head; \
990 (ptr_)->current.ul = (val_); \
991 if ((ptr_)->first_used && (ptr_)->first_started) { \
992 if ((val_) < (ptr_)->watermark.ul) \
993 (ptr_)->watermark.ul = (val_); \
994 } \
995 head = (ptr_)->hlist; \
996 while (head != NULL) { \
997 if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.ul) { \
998 head->watermark.ul = (val_); \
999 } \
1000 head = head->next2; \
1001 } \
1002 } while (0)
1003
1004 #define MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
1005 do { \
1006 MPIR_T_pvar_handle_t *head; \
1007 (ptr_)->current.ull = (val_); \
1008 if ((ptr_)->first_used && (ptr_)->first_started) { \
1009 if ((val_) < (ptr_)->watermark.ull) \
1010 (ptr_)->watermark.ull = (val_); \
1011 } \
1012 head = (ptr_)->hlist; \
1013 while (head != NULL) { \
1014 if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.ull) { \
1015 head->watermark.ull = (val_); \
1016 } \
1017 head = head->next2; \
1018 } \
1019 } while (0)
1020
1021 #define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
1022 do { \
1023 MPIR_T_pvar_handle_t *head; \
1024 (ptr_)->current.f = (val_); \
1025 if ((ptr_)->first_used && (ptr_)->first_started) { \
1026 if ((val_) < (ptr_)->watermark.f) \
1027 (ptr_)->watermark.f = (val_); \
1028 } \
1029 head = (ptr_)->hlist; \
1030 while (head != NULL) { \
1031 if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.f) { \
1032 head->watermark.f = (val_); \
1033 } \
1034 head = head->next2; \
1035 } \
1036 } while (0)
1037
1038 #define MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_impl(name_, val_) \
1039 MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1040 #define MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_impl(name_, val_) \
1041 MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1042 #define MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_impl(name_, val_) \
1043 MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1044 #define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_impl(name_, val_) \
1045 MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1046
1047 #define MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_impl(name_, val_) \
1048 MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1049 #define MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_impl(name_, val_) \
1050 MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1051 #define MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_impl(name_, val_) \
1052 MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1053 #define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_impl(name_, val_) \
1054 MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
1055
1056 /* Registration AND initialization for static pvar */
1057 #define MPIR_T_PVAR_LOWWATERMARK_REGISTER_STATIC_impl(dtype_, name_, \
1058 initval_, verb_, bind_, flags_, cat_, desc_) \
1059 do { \
1060 void *addr_; \
1061 /* Allowable datatypes only */ \
1062 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
1063 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
1064 switch (dtype_) { \
1065 case MPI_UNSIGNED: \
1066 MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_impl(name_, initval_); break; \
1067 case MPI_UNSIGNED_LONG: \
1068 MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_impl(name_, initval_); break; \
1069 case MPI_UNSIGNED_LONG_LONG: \
1070 MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_impl(name_, initval_); break; \
1071 case MPI_DOUBLE: \
1072 MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_impl(name_, initval_); break; \
1073 default: \
1074 break; \
1075 }; \
1076 addr_ = &PVAR_LOWWATERMARK_##name_; \
1077 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LOWWATERMARK, dtype_, #name_, \
1078 addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
1079 } while (0)
1080
1081 /* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
1082 #define MPIR_T_PVAR_LOWWATERMARK_REGISTER_DYNAMIC_impl(dtype_, name_, \
1083 addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
1084 do { \
1085 /* Allowable datatypes */ \
1086 MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
1087 (dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
1088 MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
1089 MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LOWWATERMARK, dtype_, #name_, \
1090 addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
1091 get_count_, cat_, desc_); \
1092 } while (0)
1093
1094 /* Unregister a pvar by its index */
1095 #define MPIR_T_PVAR_UNREGISTER(idx_) \
1096 do { \
1097 if (pvar_table != NULL) { \
1098 pvar_table_entry_t *pvar = \
1099 (pvar_table_entry_t *)utarray_eltptr(pvar_table, idx_); \
1100 if (pvar != NULL) { \
1101 pvar->active = FALSE; \
1102 /* Do not do MPL_free(pvar->info), since it may be re-activated */ \
1103 } \
1104 } \
1105 } while (0)
1106
MPIR_T_pvar_is_readonly(MPIR_T_pvar_handle_t * handle)1107 static inline int MPIR_T_pvar_is_readonly(MPIR_T_pvar_handle_t * handle)
1108 {
1109 return handle->flags & MPIR_T_PVAR_FLAG_READONLY;
1110 }
1111
MPIR_T_pvar_is_continuous(MPIR_T_pvar_handle_t * handle)1112 static inline int MPIR_T_pvar_is_continuous(MPIR_T_pvar_handle_t * handle)
1113 {
1114 return handle->flags & MPIR_T_PVAR_FLAG_CONTINUOUS;
1115 }
1116
MPIR_T_pvar_is_atomic(MPIR_T_pvar_handle_t * handle)1117 static inline int MPIR_T_pvar_is_atomic(MPIR_T_pvar_handle_t * handle)
1118 {
1119 return handle->flags & MPIR_T_PVAR_FLAG_ATOMIC;
1120 }
1121
MPIR_T_pvar_is_sum(MPIR_T_pvar_handle_t * handle)1122 static inline int MPIR_T_pvar_is_sum(MPIR_T_pvar_handle_t * handle)
1123 {
1124 return handle->flags & MPIR_T_PVAR_FLAG_SUM;
1125 }
1126
MPIR_T_pvar_is_watermark(MPIR_T_pvar_handle_t * handle)1127 static inline int MPIR_T_pvar_is_watermark(MPIR_T_pvar_handle_t * handle)
1128 {
1129 return handle->flags & MPIR_T_PVAR_FLAG_WATERMARK;
1130 }
1131
MPIR_T_pvar_is_started(MPIR_T_pvar_handle_t * handle)1132 static inline int MPIR_T_pvar_is_started(MPIR_T_pvar_handle_t * handle)
1133 {
1134 return handle->flags & MPIR_T_PVAR_FLAG_STARTED;
1135 }
1136
MPIR_T_pvar_set_started(MPIR_T_pvar_handle_t * handle)1137 static inline void MPIR_T_pvar_set_started(MPIR_T_pvar_handle_t * handle)
1138 {
1139 handle->flags |= (MPIR_T_PVAR_FLAG_STARTED | MPIR_T_PVAR_FLAG_ONCESTARTED);
1140 }
1141
MPIR_T_pvar_unset_started(MPIR_T_pvar_handle_t * handle)1142 static inline void MPIR_T_pvar_unset_started(MPIR_T_pvar_handle_t * handle)
1143 {
1144 handle->flags &= ~MPIR_T_PVAR_FLAG_STARTED;
1145 }
1146
MPIR_T_pvar_is_oncestarted(MPIR_T_pvar_handle_t * handle)1147 static inline int MPIR_T_pvar_is_oncestarted(MPIR_T_pvar_handle_t * handle)
1148 {
1149 return handle->flags & MPIR_T_PVAR_FLAG_ONCESTARTED;
1150 }
1151
MPIR_T_pvar_unset_oncestarted(MPIR_T_pvar_handle_t * handle)1152 static inline void MPIR_T_pvar_unset_oncestarted(MPIR_T_pvar_handle_t * handle)
1153 {
1154 handle->flags &= ~MPIR_T_PVAR_FLAG_ONCESTARTED;
1155 }
1156
MPIR_T_pvar_is_first(MPIR_T_pvar_handle_t * handle)1157 static inline int MPIR_T_pvar_is_first(MPIR_T_pvar_handle_t * handle)
1158 {
1159 return handle->flags & MPIR_T_PVAR_FLAG_FIRST;
1160 }
1161
MPIR_T_pvar_set_first(MPIR_T_pvar_handle_t * handle)1162 static inline int MPIR_T_pvar_set_first(MPIR_T_pvar_handle_t * handle)
1163 {
1164 return handle->flags |= MPIR_T_PVAR_FLAG_FIRST;
1165 }
1166
MPIR_T_pvar_unset_first(MPIR_T_pvar_handle_t * handle)1167 static inline int MPIR_T_pvar_unset_first(MPIR_T_pvar_handle_t * handle)
1168 {
1169 return handle->flags &= ~MPIR_T_PVAR_FLAG_FIRST;
1170 }
1171
1172 /* A counter that keeps track of the relative balance of calls to
1173 * MPI_T_init_thread and MPI_T_finalize */
1174 extern int MPIR_T_init_balance;
MPIR_T_is_initialized(void)1175 static inline int MPIR_T_is_initialized(void)
1176 {
1177 return MPIR_T_init_balance > 0;
1178 }
1179
1180 /* A special strncpy to return strings in behavior defined by MPI_T */
1181 extern void MPIR_T_strncpy(char *dst, const char *src, int *len);
1182
1183 /* Stuffs to support multithreaded MPI_T */
1184 extern int MPIR_T_is_threaded;
1185 #define MPIR_T_THREAD_CHECK_BEGIN if (MPIR_T_is_threaded) {
1186 #define MPIR_T_THREAD_CHECK_END }
1187
1188 #ifdef MPICH_IS_THREADED
1189 extern MPID_Thread_mutex_t mpi_t_mutex;
1190 #define MPIR_T_THREAD_CS_INIT() \
1191 do { \
1192 int err_; \
1193 MPIR_T_THREAD_CHECK_BEGIN \
1194 MPID_Thread_init(&err_); \
1195 MPIR_Assert(err_ == 0); \
1196 MPID_Thread_mutex_create(&mpi_t_mutex, &err_); \
1197 MPIR_Assert(err_ == 0); \
1198 MPIR_T_THREAD_CHECK_END \
1199 } while (0)
1200
1201 #define MPIR_T_THREAD_CS_FINALIZE() \
1202 do { \
1203 int err_; \
1204 MPIR_T_THREAD_CHECK_BEGIN \
1205 MPID_Thread_mutex_destroy(&mpi_t_mutex, &err_); \
1206 MPIR_Assert(err_ == 0); \
1207 MPID_Thread_finalize(&err_); \
1208 MPIR_Assert(err_ == 0); \
1209 MPIR_T_THREAD_CHECK_END \
1210 } while (0)
1211
1212 #define MPIR_T_THREAD_CS_ENTER() \
1213 do { \
1214 int err; \
1215 MPIR_T_THREAD_CHECK_BEGIN \
1216 MPID_Thread_mutex_lock(&mpi_t_mutex,&err); \
1217 MPIR_T_THREAD_CHECK_END \
1218 } while (0)
1219
1220 #define MPIR_T_THREAD_CS_EXIT() \
1221 do { \
1222 int err; \
1223 MPIR_T_THREAD_CHECK_BEGIN \
1224 MPID_Thread_mutex_unlock(&mpi_t_mutex,&err); \
1225 MPIR_T_THREAD_CHECK_END \
1226 } while (0)
1227 #else /* !MPICH_IS_THREADED */
1228 #define MPIR_T_THREAD_CS_INIT() do { /* nothing */ } while (0)
1229 #define MPIR_T_THREAD_CS_FINALIZE() do { /* nothing */ } while (0)
1230 #define MPIR_T_THREAD_CS_ENTER() do { /* nothing */ } while (0)
1231 #define MPIR_T_THREAD_CS_EXIT() do { /* nothing */ } while (0)
1232 #endif
1233
1234 /* Init and finalize routines */
1235 extern int MPIR_T_env_init(void);
1236 extern void MPIR_T_env_finalize(void);
1237
1238 #endif /* MPITIMPL_H_INCLUDED */
1239