/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2013 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/* Types and interfaces in this file are internally used by MPIR_T itself.
* Other modules should call higher level interfaces in mpit.h instead.
*/
#ifndef MPITIMPL_H_INCLUDED
#define MPITIMPL_H_INCLUDED
#include "mpi.h"
#include "mpir_strerror.h"
#include "mpir_type_defs.h"
#include "mpir_assert.h"
#include "mpir_pointers.h"
#include "utarray.h"
#include "uthash.h"
#include "mpir_objects.h"
#ifdef HAVE_ERROR_CHECKING
typedef enum {
MPIR_T_OBJECT_INVALID = 0,
MPIR_T_ENUM_HANDLE,
MPIR_T_CVAR_HANDLE,
MPIR_T_PVAR_HANDLE,
MPIR_T_PVAR_SESSION
} MPIR_T_object_kind;
#endif
/* MPI_T enum
*/
typedef struct enum_item_s {
const char *name;
int value;
} enum_item_t;
typedef struct MPIR_T_enum_s {
#ifdef HAVE_ERROR_CHECKING
MPIR_T_object_kind kind;
#endif
const char *name;
UT_array *items;
} MPIR_T_enum_t;
/* MPI_T category (cat)
*/
typedef struct {
const char *name;
UT_array *cvar_indices;
UT_array *pvar_indices;
UT_array *subcat_indices;
const char *desc;
} cat_table_entry_t;
/* Hash names to indices in a table */
typedef struct {
const char *name;
unsigned idx;
UT_hash_handle hh; /* Makes this structure hashable */
} name2index_hash_t;
/* MPI_T control variable (cvar)
*/
typedef struct MPIR_T_cvar_range_value_s {
int low;
int high;
} MPIR_T_cvar_range_value_t;
/* Type used to represent cvar default values */
typedef union MPIR_T_cvar_value_s {
int d;
unsigned u;
unsigned ul;
unsigned ull;
MPI_Count c;
const char *str;
double f;
MPIR_T_cvar_range_value_t range;
} MPIR_T_cvar_value_t;
typedef int MPIR_T_cvar_get_addr_cb(void *obj_handle, void **addr);
typedef int MPIR_T_cvar_get_count_cb(void *obj_handle, int *count);
typedef struct cvar_table_entry_s {
/* Is the cvar currently in use? False if the cvar is unregistered */
int active;
/* cvar name */
const char *name;
/* Address of the cvar. May be NULL when get_addr != NULL */
void *addr;
/* cvar data type */
MPI_Datatype datatype;
/* Num. of elements of the cvar. May be ignored when get_count != NULL */
int count;
/* Properties of the cvar */
MPI_T_enum enumtype;
MPIR_T_verbosity_t verbosity;
MPIR_T_bind_t bind;
MPIR_T_scope_t scope;
/* Default value */
MPIR_T_cvar_value_t defaultval;
/* If not NULL, components provide this callback to get addr of the cvar */
MPIR_T_cvar_get_addr_cb *get_addr;
/* If not NULL, components provide this callback to get count */
MPIR_T_cvar_get_count_cb *get_count;
/* Description of the cvar */
const char *desc;
} cvar_table_entry_t;
typedef struct MPIR_T_cvar_handle_s {
#ifdef HAVE_ERROR_CHECKING
MPIR_T_object_kind kind;
#endif
/* Address and count of the cvar. Set at handle allocation time */
void *addr;
int count;
/* Cached value from cvar_table_entry_t to avoid indirection */
MPI_Datatype datatype;
MPIR_T_scope_t scope;
} MPIR_T_cvar_handle_t;
void MPIR_T_CVAR_REGISTER_impl(MPI_Datatype dtype, const char *name, const void *addr, int count,
MPIR_T_enum_t * etype, MPIR_T_verbosity_t verb, MPIR_T_bind_t bind,
MPIR_T_scope_t scope, MPIR_T_cvar_get_addr_cb get_addr,
MPIR_T_cvar_get_count_cb get_count, MPIR_T_cvar_value_t defaultval,
const char *cat, const char *desc);
/* MPI_T performance variable (pvar)
*/
/* Forward declaration */
struct MPIR_T_pvar_handle_s;
struct MPIR_T_pvar_session_s;
typedef void MPIR_T_pvar_get_value_cb(void *addr, void *obj_handle, int count, void *buf);
typedef void MPIR_T_pvar_get_count_cb(void *addr, void *obj_handle, int *count);
/* Basic pvar flags defined by MPI_T standard */
#define MPIR_T_PVAR_FLAG_READONLY 0x01
#define MPIR_T_PVAR_FLAG_CONTINUOUS 0x02
#define MPIR_T_PVAR_FLAG_ATOMIC 0x04
/* Auxlilary flags used by MPIR_T */
/* pvar is MPI_T_PVAR_CLASS_{COUNTER, TIMER, AGGREGATE} */
#define MPIR_T_PVAR_FLAG_SUM 0x08
/* pvar is MPI_T_PVAR_CLASS_{HIGH, LOW}WATERMARK */
#define MPIR_T_PVAR_FLAG_WATERMARK 0x10
/* pvar is continuous. If not, it has been started at least once */
#define MPIR_T_PVAR_FLAG_ONCESTARTED 0x20
/* pvar is continuous. If not, it is started */
#define MPIR_T_PVAR_FLAG_STARTED 0x40
/* Used only for watermark handles. Set if a pvar handle is the
* first handle of an associated watermark.
*/
#define MPIR_T_PVAR_FLAG_FIRST 0x80
/* MPI_T performance variable (pvar) stuff */
typedef struct {
/* Is the pvar in use (i.e., not unregistered)? */
int active;
/* pvar name */
const char *name;
/* If not NULL, it is address of the pvar */
void *addr;
/* pvar data type */
MPI_Datatype datatype;
/* Num. of elements of the pvar */
int count;
/* Properties of the pvar */
MPIR_T_pvar_class_t varclass;
MPIR_T_verbosity_t verbosity;
MPIR_T_enum_t *enumtype;
MPIR_T_bind_t bind;
/* Basic flags of the pvar */
int flags;
/* If not NULL, components provide this callback to read the pvar */
MPIR_T_pvar_get_value_cb *get_value;
/* If not NULL, components provide this callback to get count */
MPIR_T_pvar_get_count_cb *get_count;
/* Description of the pvar */
const char *desc;
} pvar_table_entry_t;
/*
The following two macros do not work since C preprocessor does not support
nested ifdefs. So we use another woarkable but a little ugly approach.
#define PVAR_GATED_ACTION(MODULE, action_) \
do { \
#ifdef ENABLE_PVAR_##MODULE \
action_; \
#endif \
} while (0)
*/
/* ENABLE_PVAR_##MODULE must be defined by configure script either to 0 or 1 */
#define PVAR_GATED_ACTION(MODULE, action_) \
do { \
if (ENABLE_PVAR_##MODULE) { \
action_; \
} \
} while (0)
/* For some classes of pvars, internally we can not represent them
* in basic data types. So come the following typedefs.
*/
/* Timer type */
typedef struct {
/* Accumulated time */
MPID_Time_t total;
/* Time when the timer was started recently */
MPID_Time_t curstart;
/* A counter recording how many times the timer is started */
unsigned long long count;
} MPIR_T_pvar_timer_t;
/* An union to represent a watermark value */
typedef union {
double f;
unsigned u;
unsigned long ul;
unsigned long long ull;
} watermark_value_t;
/* Watermark type */
typedef struct {
/* current -- current resource utilization level
* waterarmk -- cached value for the first pvar handle
*/
watermark_value_t current, watermark;
/* Datatype of the watermark */
MPI_Datatype datatype;
/* Is the cached value (i.e, watermark) in use by a pvar handle? */
int first_used;
/* Is the first pvar handle started? */
int first_started;
/* A double-linked list of handles of the pvar */
struct MPIR_T_pvar_handle_s *hlist;
} MPIR_T_pvar_watermark_t;
typedef struct MPIR_T_pvar_handle_s {
#ifdef HAVE_ERROR_CHECKING
MPIR_T_object_kind kind;
#endif
/* These are cached fields from pvar table. Do so to avoid extra
* indirection when accessing them through pvar handles.
*/
void *addr;
MPI_Datatype datatype;
int count;
MPIR_T_pvar_get_value_cb *get_value;
MPIR_T_pvar_class_t varclass;
/* Bytes of an element of datatype */
int bytes;
/* Basic flags copied from pvar info + auxilary flags in pvar handle */
int flags;
/* Store info here in case we need other fields */
const pvar_table_entry_t *info;
/* Owner session from which the handle is allocated */
struct MPIR_T_pvar_session_s *session;
/* Object which this pvar is bound to. NULL if no binding */
void *obj_handle;
/* This is how we support pvar sessions.
*
* For pvars of counter, timer or aggregate type, we cache their value at
* the last start time in offset, their current value in current, and
* their accumlated value in accum. Generally, when such a pvar is running,
* reading the pvar should return
* accum[i] + current[i] - offset[i], 0 <= i < count - 1.
* When the pvar is stopped, reading just returns accum.
*
* For pvars of high/lowwatermark type, above method does not work.
* We have a copy of such a pvar in every handle of the pvar.
* Handles are registered to the pvar. Whenever a watermark changes,
* its copies in non-stopped handles are updated. That sounds non-scalable.
* Considering single-session is common, we reserve room in watermark
* themselves for cache buffer for the first handle. So when such a pvar
* changes, it also updates the watermark close to it in memory.
*
* For pvars of other classes, since they are supposed to be readonly
* and continuous (FIXME: Is it true?), caching is not needed.
*/
void *accum;
void *offset;
void *current;
watermark_value_t watermark;
/* To chain handles in a session */
struct MPIR_T_pvar_handle_s *prev, *next;
/* To chain handles of a watermark pvar */
struct MPIR_T_pvar_handle_s *prev2, *next2;
} MPIR_T_pvar_handle_t;
typedef struct MPIR_T_pvar_session_s {
#ifdef HAVE_ERROR_CHECKING
MPIR_T_object_kind kind;
#endif
/* A linked list of pvar handles */
MPIR_T_pvar_handle_t *hlist;
} MPIR_T_pvar_session_t;
extern void MPIR_T_PVAR_REGISTER_impl(MPIR_T_pvar_class_t varclass, MPI_Datatype dtype,
const char *name, void *addr, int count,
MPIR_T_enum_t * etype, MPIR_T_verbosity_t verb,
MPIR_T_bind_t bind, int flags,
MPIR_T_pvar_get_value_cb get_value,
MPIR_T_pvar_get_count_cb get_count, const char *cat,
const char *desc);
/* For static pvars (i.e., pvars with static storage), we embed their class name
* into their variable name, so that users can declare pvars with the same name
* for different classes, without worry of name conflict. "class + pvar name"
* should be unique as required by MPI_T.
*/
/* MPI_T_PVAR_CLASS_STATE (continuous only)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_STATE_SET_VAR_impl(ptr_, val_) \
do { *(ptr_) = (val_); } while (0)
#define MPIR_T_PVAR_STATE_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_STATE_SET_impl(name_, val_) \
MPIR_T_PVAR_STATE_SET_VAR_impl(&PVAR_STATE_##name_, val_)
#define MPIR_T_PVAR_STATE_GET_impl(name_) \
MPIR_T_PVAR_STATE_GET_VAR_impl(&PVAR_STATE_##name_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_STATE_REGISTER_STATIC_impl(dtype_, name_, \
initval_, etype_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_INT); \
/* Double check if dtype_ and name_ match */ \
MPIR_Assert(sizeof(PVAR_STATE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
/* State pvars should be describled further by an enum */ \
MPIR_Assert((etype_) != MPI_T_ENUM_NULL); \
PVAR_STATE_##name_ = (initval_); \
addr_ = &PVAR_STATE_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_STATE, dtype_, #name_, \
addr_, 1, etype_, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_STATE_REGISTER_DYNAMIC_impl(dtype_, name_, addr_, count_, \
etype_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_INT); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
MPIR_Assert((etype_) != MPI_T_ENUM_NULL); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_STATE, dtype_, #name_, \
addr_, count_, etype_, verb_, bind_, flags_, get_value_, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_LEVEL (continuous only)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_LEVEL_SET_VAR_impl(ptr_, val_) \
do { *(ptr_) = (val_); } while (0)
#define MPIR_T_PVAR_LEVEL_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_LEVEL_INC_VAR_impl(ptr_, val_) \
do { *(ptr_) += (val_); } while (0)
#define MPIR_T_PVAR_LEVEL_DEC_VAR_impl(ptr_, val_) \
do { *(ptr_) -= (val_); } while (0)
#define MPIR_T_PVAR_LEVEL_SET_impl(name_, val_) \
MPIR_T_PVAR_LEVEL_SET_VAR_impl(&PVAR_LEVEL_##name_, val_)
#define MPIR_T_PVAR_LEVEL_GET_impl(name_) \
MPIR_T_PVAR_LEVEL_GET_VAR_impl(&PVAR_LEVEL_##name_)
#define MPIR_T_PVAR_LEVEL_INC_impl(name_, val_) \
MPIR_T_PVAR_LEVEL_INC_VAR_impl(&PVAR_LEVEL_##name_, val_)
#define MPIR_T_PVAR_LEVEL_DEC_impl(name_, val_) \
MPIR_T_PVAR_LEVEL_DEC_VAR_impl(&PVAR_LEVEL_##name_, val_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_LEVEL_REGISTER_STATIC_impl(dtype_, name_, \
initval_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
/* Double check if dtype_ and name_ match */ \
MPIR_Assert(sizeof(PVAR_LEVEL_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
PVAR_LEVEL_##name_ = (initval_); \
addr_ = &PVAR_LEVEL_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LEVEL, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_LEVEL_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LEVEL, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_SIZE (continuous only)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_SIZE_SET_VAR_impl(ptr_, val_) \
do { *(ptr_) = (val_); } while (0)
#define MPIR_T_PVAR_SIZE_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_SIZE_SET_impl(name_, val_) \
MPIR_T_PVAR_SIZE_SET_VAR_impl(&PVAR_SIZE_##name_, val_)
#define MPIR_T_PVAR_SIZE_GET_impl(name_) \
MPIR_T_PVAR_SIZE_GET_VAR_impl(&PVAR_SIZE_##name_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_SIZE_REGISTER_STATIC_impl(dtype_, name_, \
initval_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
/* Double check if dtype_ and name_ match */ \
MPIR_Assert(sizeof(PVAR_SIZE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
PVAR_SIZE_##name_ = (initval_); \
addr_ = &PVAR_SIZE_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_SIZE, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_SIZE_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_SIZE, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_PERCENTAGE (continuous only)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_PERCENTAGE_SET_VAR_impl(ptr_, val_) \
do { \
MPIR_Assert(0.0 <= (val_) && (val_) <= 1.0); \
*(ptr_) = (val_); \
} while (0)
#define MPIR_T_PVAR_PERCENTAGE_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_PERCENTAGE_SET_impl(name_, val_) \
MPIR_T_PVAR_PERCENTAGE_SET_VAR_impl(&PVAR_PERCENTAGE_##name_, val_)
#define MPIR_T_PVAR_PERCENTAGE_GET_impl(name_) \
MPIR_T_PVAR_PERCENTAGE_GET_VAR_impl(&PVAR_PERCENTAGE_##name_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_PERCENTAGE_REGISTER_STATIC_impl(dtype_, name_, \
initval_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_DOUBLE); \
/* Double check if dtype_ and name_ match */ \
MPIR_Assert(sizeof(PVAR_PERCENTAGE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
addr_ = &PVAR_PERCENTAGE_##name_; \
PVAR_PERCENTAGE_##name_ = (initval_); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_PERCENTAGE, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_PERCENTAGE_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_DOUBLE); \
MPIR_Assert((flags_) & MPIR_T_PVAR_FLAG_CONTINUOUS); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_PERCENTAGE, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_COUNTER (continuous or not)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_COUNTER_INIT_VAR_impl(ptr_) \
do { *(ptr_) = 0; } while (0)
/* _COUNTER_SET is intentionally not provided. Users should only INC counters */
#define MPIR_T_PVAR_COUNTER_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_COUNTER_INC_VAR_impl(ptr_, inc_) \
do { *(ptr_) += (inc_); } while (0)
#define MPIR_T_PVAR_COUNTER_INIT_impl(name_) \
MPIR_T_PVAR_COUNTER_INIT_VAR_impl(&PVAR_COUNTER_##name_)
#define MPIR_T_PVAR_COUNTER_GET_impl(name_) \
MPIR_T_PVAR_COUNTER_GET_VAR_impl(&PVAR_COUNTER_##name_)
#define MPIR_T_PVAR_COUNTER_INC_impl(name_, inc_) \
MPIR_T_PVAR_COUNTER_INC_VAR_impl(&PVAR_COUNTER_##name_, inc_)
#define MPIR_T_PVAR_COUNTER_ADDR_impl(name_) \
(&PVAR_COUNTER_##name_)
/* Registration AND initialization to zero for static pvar. */
#define MPIR_T_PVAR_COUNTER_REGISTER_STATIC_impl(dtype_, name_, \
verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG); \
/* Double check if dtype_ and name_ match*/ \
MPIR_Assert(sizeof(PVAR_COUNTER_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
PVAR_COUNTER_##name_ = 0; \
addr_ = &PVAR_COUNTER_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_COUNTER_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_COUNTER_ARRAY_INIT_VAR_impl(ptr_, count_) \
do { \
int idx_; \
idx_ = 0; \
for (; idx_ < (count_); idx_++) \
*((ptr_) + idx_) = 0; \
} while (0)
#define MPIR_T_PVAR_COUNTER_ARRAY_GET_VAR_impl(ptr_, idx_) \
*((ptr_) + (idx_))
#define MPIR_T_PVAR_COUNTER_ARRAY_INC_VAR_impl(ptr_, idx_, inc_) \
do { *((ptr_) + (idx_)) += (inc_); } while (0)
#define MPIR_T_PVAR_COUNTER_ARRAY_INIT_impl(name_) \
do { \
int count_; \
count_ = sizeof(PVAR_COUNTER_##name_)/sizeof(PVAR_COUNTER_##name_[0]); \
MPIR_T_PVAR_COUNTER_ARRAY_INIT_VAR_impl(PVAR_COUNTER_##name_, count_); \
} while (0)
#define MPIR_T_PVAR_COUNTER_ARRAY_GET_impl(name_, idx_) \
MPIR_T_PVAR_COUNTER_ARRAY_GET_VAR_impl(PVAR_COUNTER_##name_, idx_)
#define MPIR_T_PVAR_COUNTER_ARRAY_INC_impl(ptr_, idx_, inc_) \
MPIR_T_PVAR_COUNTER_ARRAY_INC_VAR_impl(PVAR_COUNTER_##name_, idx_, inc_)
/* Registration AND initialization to zero for static counter array */
#define MPIR_T_PVAR_COUNTER_ARRAY_REGISTER_STATIC_impl(dtype_, name_, \
verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
int count_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG); \
/* Double check if dtype_ and name_ match */ \
MPIR_Assert(sizeof(PVAR_COUNTER_##name_[0]) == MPIR_Datatype_get_basic_size(dtype_)); \
addr_ = PVAR_COUNTER_##name_; \
MPIR_T_PVAR_COUNTER_ARRAY_INIT_impl(name_); \
count_ = sizeof(PVAR_COUNTER_##name_)/sizeof(mpit_pvar_##name_[0]); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Dynamic counter array is already provided by MPIR_T_PVAR_COUNTER_REGISTER_DYNAMIC */
/* MPI_T_PVAR_CLASS_AGGREGATE (continuous or not)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_AGGREGATE_INIT_VAR_impl(ptr_) \
do { *(ptr_) = 0; } while (0)
/* _AGGREGATE_SET is intentionally not provided as for counters */
#define MPIR_T_PVAR_AGGREGATE_GET_VAR_impl(ptr_) \
(*(ptr_))
#define MPIR_T_PVAR_AGGREGATE_INC_VAR_impl(ptr_, inc_) \
do { *(ptr_) += (inc_); } while (0)
#define MPIR_T_PVAR_AGGREGATE_INIT_impl(name_) \
MPIR_T_PVAR_AGGREGATE_INIT_VAR_impl(&PVAR_AGGREGATE_##name_)
#define MPIR_T_PVAR_AGGREGATE_GET_impl(name_) \
MPIR_T_PVAR_AGGREGATE_GET_VAR_impl(&PVAR_AGGREGATE_##name_)
#define MPIR_T_PVAR_AGGREGATE_INC_impl(name_, inc_) \
MPIR_T_PVAR_AGGREGATE_INC_VAR_impl(&PVAR_AGGREGATE_##name_, inc_)
/* Registration AND initialization to zero for static aggregate */
#define MPIR_T_PVAR_AGGREGATE_REGISTER_STATIC_impl(dtype_, name_, \
verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
/* Double check if dtype_ and name_ match*/ \
MPIR_Assert(sizeof(PVAR_AGGREGATE_##name_) == MPIR_Datatype_get_basic_size(dtype_)); \
PVAR_AGGREGATE_##name_ = 0; \
addr_ = &PVAR_AGGREGATE_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_AGGREGATE, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_AGGREGATE_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_AGGREGATE, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_TIMER (continuous or not)
*/
/* Interfaces through pointer or name */
#define MPIR_T_PVAR_TIMER_INIT_VAR_impl(ptr_) \
do { \
/* FIXME: need a generic approach to init a timer */ \
memset(&((ptr_)->total), 0, sizeof(MPID_Time_t)); \
} while (0)
#define MPIR_T_PVAR_TIMER_GET_VAR_impl(ptr_, buf) \
do { \
MPID_Wtime_todouble(&((ptr_)->total), buf); \
} while (0)
#define MPIR_T_PVAR_TIMER_START_VAR_impl(ptr_) \
do { \
MPID_Wtime(&((ptr_)->curstart)); \
(ptr_)->count++; \
} while (0)
#define MPIR_T_PVAR_TIMER_END_VAR_impl(ptr_) \
do { \
MPID_Time_t tmp_; \
MPID_Wtime(&tmp_); \
MPID_Wtime_acc(&((ptr_)->curstart), &tmp_, &((ptr_)->total)); \
} while (0)
#define MPIR_T_PVAR_TIMER_INIT_impl(name_) \
MPIR_T_PVAR_TIMER_INIT_VAR_impl(&PVAR_TIMER_##name_)
#define MPIR_T_PVAR_TIMER_GET_impl(name_, buf_) \
MPIR_T_PVAR_TIMER_GET_VAR_impl(&PVAR_TIMER_##name_, buf_)
#define MPIR_T_PVAR_TIMER_START_impl(name_) \
MPIR_T_PVAR_TIMER_START_VAR_impl(&PVAR_TIMER_##name_)
#define MPIR_T_PVAR_TIMER_END_impl(name_) \
MPIR_T_PVAR_TIMER_END_VAR_impl(&PVAR_TIMER_##name_)
#define MPIR_T_PVAR_TIMER_ADDR_impl(name_) \
(&PVAR_TIMER_##name_)
/* Customized get_value() for MPIR_T_pvar_timer_t */
static inline
void get_timer_time_in_double(MPIR_T_pvar_timer_t * timer, void *obj_handle,
int count, double *buf)
{
int i;
for (i = 0; i < count; i++)
MPID_Wtime_todouble(&(timer[i].total), &buf[i]);
}
/* Registration for static storage */
#define MPIR_T_PVAR_TIMER_REGISTER_STATIC_impl(dtype_, name_, \
verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
void *count_addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_DOUBLE); \
MPIR_T_PVAR_TIMER_INIT_impl(name_); \
addr_ = &PVAR_TIMER_##name_; \
count_addr_ = &(PVAR_TIMER_##name_.count); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_TIMER, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, \
(MPIR_T_pvar_get_value_cb *)&get_timer_time_in_double, NULL, cat_, desc_); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_COUNTER, MPI_UNSIGNED_LONG_LONG, #name_, \
count_addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, \
NULL, NULL, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_HIGHWATERMARK (continuous or not)
*/
/* Interfaces through pointer or name.
* In contrast to previous pvar classes, for each type we create a set
* of interfaces. That is because we have a pointer and a union in the
* struct. We need to know types to (de)reference them.
*/
#define MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED; \
(ptr_)->current.u = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED_LONG; \
(ptr_)->current.ul = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED_LONG_LONG; \
(ptr_)->current.ull = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_DOUBLE; \
(ptr_)->current.f = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.u = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) > (ptr_)->watermark.u) \
(ptr_)->watermark.u = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.u) { \
head->watermark.u = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.ul = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) > (ptr_)->watermark.ul) \
(ptr_)->watermark.ul = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.ul) { \
head->watermark.ul = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.ull = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) > (ptr_)->watermark.ull) \
(ptr_)->watermark.ull = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.ull) { \
head->watermark.ull = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.f = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) > (ptr_)->watermark.f) \
(ptr_)->watermark.f = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) > head->watermark.f) { \
head->watermark.f = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_UINT_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_ULONG_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_ULONG2_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
#define MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_UPDATE_VAR_impl(&PVAR_HIGHWATERMARK_##name_, val_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_HIGHWATERMARK_REGISTER_STATIC_impl(dtype_, name_, \
initval_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
switch (dtype_) { \
case MPI_UNSIGNED: \
MPIR_T_PVAR_UINT_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_UNSIGNED_LONG: \
MPIR_T_PVAR_ULONG_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_UNSIGNED_LONG_LONG: \
MPIR_T_PVAR_ULONG2_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_DOUBLE: \
MPIR_T_PVAR_DOUBLE_HIGHWATERMARK_INIT_impl(name_, initval_); break; \
default: \
break; \
}; \
addr_ = &PVAR_HIGHWATERMARK_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_HIGHWATERMARK, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_HIGHWATERMARK_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_HIGHWATERMARK, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* MPI_T_PVAR_CLASS_LOWWATERMARK (continuous or not)
*/
#define MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED; \
(ptr_)->current.u = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED_LONG; \
(ptr_)->current.ul = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_UNSIGNED_LONG_LONG; \
(ptr_)->current.ull = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_VAR_impl(ptr_, val_) \
do { \
(ptr_)->datatype = MPI_DOUBLE; \
(ptr_)->current.f = (val_); \
(ptr_)->first_started = 0; \
(ptr_)->first_used = 0; \
(ptr_)->hlist = NULL; \
} while (0)
#define MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.u = (val_); \
/* Update values in all handles */ \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) < (ptr_)->watermark.u) \
(ptr_)->watermark.u = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.u) { \
head->watermark.u = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.ul = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) < (ptr_)->watermark.ul) \
(ptr_)->watermark.ul = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.ul) { \
head->watermark.ul = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.ull = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) < (ptr_)->watermark.ull) \
(ptr_)->watermark.ull = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.ull) { \
head->watermark.ull = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_VAR_impl(ptr_, val_) \
do { \
MPIR_T_pvar_handle_t *head; \
(ptr_)->current.f = (val_); \
if ((ptr_)->first_used && (ptr_)->first_started) { \
if ((val_) < (ptr_)->watermark.f) \
(ptr_)->watermark.f = (val_); \
} \
head = (ptr_)->hlist; \
while (head != NULL) { \
if (MPIR_T_pvar_is_started(head) && (val_) < head->watermark.f) { \
head->watermark.f = (val_); \
} \
head = head->next2; \
} \
} while (0)
#define MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_impl(name_, val_) \
MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_UINT_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_ULONG_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_ULONG2_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
#define MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_impl(name_, val_) \
MPIR_T_PVAR_DOUBLE_LOWWATERMARK_UPDATE_VAR_impl(&PVAR_LOWWATERMARK_##name_, val_)
/* Registration AND initialization for static pvar */
#define MPIR_T_PVAR_LOWWATERMARK_REGISTER_STATIC_impl(dtype_, name_, \
initval_, verb_, bind_, flags_, cat_, desc_) \
do { \
void *addr_; \
/* Allowable datatypes only */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
switch (dtype_) { \
case MPI_UNSIGNED: \
MPIR_T_PVAR_UINT_LOWWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_UNSIGNED_LONG: \
MPIR_T_PVAR_ULONG_LOWWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_UNSIGNED_LONG_LONG: \
MPIR_T_PVAR_ULONG2_LOWWATERMARK_INIT_impl(name_, initval_); break; \
case MPI_DOUBLE: \
MPIR_T_PVAR_DOUBLE_LOWWATERMARK_INIT_impl(name_, initval_); break; \
default: \
break; \
}; \
addr_ = &PVAR_LOWWATERMARK_##name_; \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LOWWATERMARK, dtype_, #name_, \
addr_, 1, MPI_T_ENUM_NULL, verb_, bind_, flags_, NULL, NULL, cat_, desc_); \
} while (0)
/* Registration for dynamic pvar w/ or w/o callback. Init is left to users */
#define MPIR_T_PVAR_LOWWATERMARK_REGISTER_DYNAMIC_impl(dtype_, name_, \
addr_, count_, verb_, bind_, flags_, get_value_, get_count_, cat_, desc_) \
do { \
/* Allowable datatypes */ \
MPIR_Assert((dtype_) == MPI_UNSIGNED || (dtype_) == MPI_UNSIGNED_LONG || \
(dtype_) == MPI_UNSIGNED_LONG_LONG || (dtype_) == MPI_DOUBLE); \
MPIR_Assert((addr_) != NULL || (get_value_) != NULL); \
MPIR_T_PVAR_REGISTER_impl(MPI_T_PVAR_CLASS_LOWWATERMARK, dtype_, #name_, \
addr_, count_, MPI_T_ENUM_NULL, verb_, bind_, flags_, get_value_, \
get_count_, cat_, desc_); \
} while (0)
/* Unregister a pvar by its index */
#define MPIR_T_PVAR_UNREGISTER(idx_) \
do { \
if (pvar_table != NULL) { \
pvar_table_entry_t *pvar = \
(pvar_table_entry_t *)utarray_eltptr(pvar_table, idx_); \
if (pvar != NULL) { \
pvar->active = FALSE; \
/* Do not do MPL_free(pvar->info), since it may be re-activated */ \
} \
} \
} while (0)
static inline int MPIR_T_pvar_is_readonly(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_READONLY;
}
static inline int MPIR_T_pvar_is_continuous(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_CONTINUOUS;
}
static inline int MPIR_T_pvar_is_atomic(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_ATOMIC;
}
static inline int MPIR_T_pvar_is_sum(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_SUM;
}
static inline int MPIR_T_pvar_is_watermark(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_WATERMARK;
}
static inline int MPIR_T_pvar_is_started(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_STARTED;
}
static inline void MPIR_T_pvar_set_started(MPIR_T_pvar_handle_t * handle)
{
handle->flags |= (MPIR_T_PVAR_FLAG_STARTED | MPIR_T_PVAR_FLAG_ONCESTARTED);
}
static inline void MPIR_T_pvar_unset_started(MPIR_T_pvar_handle_t * handle)
{
handle->flags &= ~MPIR_T_PVAR_FLAG_STARTED;
}
static inline int MPIR_T_pvar_is_oncestarted(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_ONCESTARTED;
}
static inline void MPIR_T_pvar_unset_oncestarted(MPIR_T_pvar_handle_t * handle)
{
handle->flags &= ~MPIR_T_PVAR_FLAG_ONCESTARTED;
}
static inline int MPIR_T_pvar_is_first(MPIR_T_pvar_handle_t * handle)
{
return handle->flags & MPIR_T_PVAR_FLAG_FIRST;
}
static inline int MPIR_T_pvar_set_first(MPIR_T_pvar_handle_t * handle)
{
return handle->flags |= MPIR_T_PVAR_FLAG_FIRST;
}
static inline int MPIR_T_pvar_unset_first(MPIR_T_pvar_handle_t * handle)
{
return handle->flags &= ~MPIR_T_PVAR_FLAG_FIRST;
}
/* A counter that keeps track of the relative balance of calls to
* MPI_T_init_thread and MPI_T_finalize */
extern int MPIR_T_init_balance;
static inline int MPIR_T_is_initialized(void)
{
return MPIR_T_init_balance > 0;
}
/* A special strncpy to return strings in behavior defined by MPI_T */
extern void MPIR_T_strncpy(char *dst, const char *src, int *len);
/* Stuffs to support multithreaded MPI_T */
extern int MPIR_T_is_threaded;
#define MPIR_T_THREAD_CHECK_BEGIN if (MPIR_T_is_threaded) {
#define MPIR_T_THREAD_CHECK_END }
#ifdef MPICH_IS_THREADED
extern MPID_Thread_mutex_t mpi_t_mutex;
#define MPIR_T_THREAD_CS_INIT() \
do { \
int err_; \
MPIR_T_THREAD_CHECK_BEGIN \
MPID_Thread_mutex_create(&mpi_t_mutex, &err_); \
MPIR_Assert(err_ == 0); \
MPIR_T_THREAD_CHECK_END \
} while (0)
#define MPIR_T_THREAD_CS_FINALIZE() \
do { \
int err_; \
MPIR_T_THREAD_CHECK_BEGIN \
MPID_Thread_mutex_destroy(&mpi_t_mutex, &err_); \
MPIR_Assert(err_ == 0); \
MPIR_T_THREAD_CHECK_END \
} while (0)
#define MPIR_T_THREAD_CS_ENTER() \
do { \
int err; \
MPIR_T_THREAD_CHECK_BEGIN \
MPID_Thread_mutex_lock(&mpi_t_mutex,&err); \
MPIR_T_THREAD_CHECK_END \
} while (0)
#define MPIR_T_THREAD_CS_EXIT() \
do { \
int err; \
MPIR_T_THREAD_CHECK_BEGIN \
MPID_Thread_mutex_unlock(&mpi_t_mutex,&err); \
MPIR_T_THREAD_CHECK_END \
} while (0)
#else /* !MPICH_IS_THREADED */
#define MPIR_T_THREAD_CS_INIT() do { /* nothing */ } while (0)
#define MPIR_T_THREAD_CS_FINALIZE() do { /* nothing */ } while (0)
#define MPIR_T_THREAD_CS_ENTER() do { /* nothing */ } while (0)
#define MPIR_T_THREAD_CS_EXIT() do { /* nothing */ } while (0)
#endif
/* Init and finalize routines */
extern void MPIR_T_env_init(void);
extern void MPIR_T_env_finalize(void);
#endif /* MPITIMPL_H_INCLUDED */