root/opal/mca/base/mca_base_pvar.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mca_base_pvar_init
  2. mca_base_pvar_find
  3. mca_base_pvar_find_by_name
  4. mca_base_pvar_finalize
  5. mca_base_pvar_get_count
  6. mca_base_pvar_default_get_value
  7. mca_base_pvar_default_set_value
  8. mca_base_pvar_notify_ignore
  9. mca_base_pvar_register
  10. mca_base_component_pvar_register
  11. mca_base_pvar_get_internal
  12. mca_base_pvar_get
  13. mca_base_pvar_mark_invalid
  14. mca_base_pvar_notify
  15. mca_base_pvar_update_all_handles
  16. mca_base_pvar_handle_alloc
  17. mca_base_pvar_handle_free
  18. mca_base_pvar_handle_update
  19. mca_base_pvar_handle_read_value
  20. mca_base_pvar_handle_write_value
  21. mca_base_pvar_handle_start
  22. mca_base_pvar_handle_stop
  23. mca_base_pvar_handle_reset
  24. mca_base_pvar_dump
  25. mca_base_pvar_contructor
  26. mca_base_pvar_destructor
  27. opal_mpi_pvar_session_constructor
  28. opal_mpi_pvar_session_destructor
  29. mca_base_pvar_handle_constructor
  30. mca_base_pvar_handle_destructor

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2013-2017 Los Alamos National Security, LLC. All rights
   4  *                         reserved.
   5  * Copyright (c) 2015      Cisco Systems, Inc.  All rights reserved.
   6  * Copyright (c) 2015      Bull SAS.  All rights reserved.
   7  * Copyright (c) 2015      The University of Tennessee and The University
   8  *                         of Tennessee Research Foundation.  All rights
   9  *                         reserved.
  10  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  11  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights reserved.
  12  * $COPYRIGHT$
  13  *
  14  * Additional copyrights may follow
  15  *
  16  * $HEADER$
  17  */
  18 
  19 #include "opal/mca/base/mca_base_pvar.h"
  20 #include "opal/mca/base/mca_base_vari.h"
  21 
  22 #include <stddef.h>
  23 #include <sys/time.h>
  24 #include <sys/resource.h>
  25 
  26 #include "opal/class/opal_pointer_array.h"
  27 #include "opal/class/opal_hash_table.h"
  28 #include "opal/util/printf.h"
  29 
  30 static opal_hash_table_t mca_base_pvar_index_hash;
  31 static opal_pointer_array_t registered_pvars;
  32 static bool mca_base_pvar_initialized = false;
  33 static int pvar_count = 0;
  34 
  35 #define min(a,b) ((a) < (b) ? (a) : (b))
  36 #define max(a,b) ((a) > (b) ? (a) : (b))
  37 
  38 static int mca_base_pvar_get_internal (int index, mca_base_pvar_t **pvar, bool invalidok);
  39 
  40 /* string representations of class names */
  41 static const char *pvar_class_names[] = {
  42     "state",
  43     "level",
  44     "size",
  45     "percentage",
  46     "high watermark",
  47     "low watermark",
  48     "counter",
  49     "aggregate",
  50     "timer",
  51     "generic"
  52 };
  53 
  54 int mca_base_pvar_init (void)
  55 {
  56     int ret = OPAL_SUCCESS;
  57 
  58     if (!mca_base_pvar_initialized) {
  59         mca_base_pvar_initialized = true;
  60 
  61         OBJ_CONSTRUCT(&registered_pvars, opal_pointer_array_t);
  62         opal_pointer_array_init(&registered_pvars, 128, 2048, 128);
  63 
  64         OBJ_CONSTRUCT(&mca_base_pvar_index_hash, opal_hash_table_t);
  65         ret = opal_hash_table_init (&mca_base_pvar_index_hash, 1024);
  66         if (OPAL_SUCCESS != ret) {
  67             mca_base_pvar_initialized = false;
  68             OBJ_DESTRUCT(&registered_pvars);
  69             OBJ_DESTRUCT(&mca_base_pvar_index_hash);
  70         }
  71     }
  72 
  73     return ret;
  74 }
  75 
  76 int mca_base_pvar_find (const char *project, const char *framework, const char *component, const char *name)
  77 {
  78     char *full_name;
  79     int ret, index;
  80 
  81     ret = mca_base_var_generate_full_name4 (NULL, framework, component, name, &full_name);
  82     if (OPAL_SUCCESS != ret) {
  83         return OPAL_ERROR;
  84     }
  85 
  86     ret = mca_base_pvar_find_by_name (full_name, MCA_BASE_PVAR_CLASS_ANY, &index);
  87     free (full_name);
  88 
  89     /* NTH: should we verify the name components match the returned variable? */
  90 
  91     return (OPAL_SUCCESS != ret) ? ret : index;
  92 }
  93 
  94 int mca_base_pvar_find_by_name (const char *full_name, int var_class, int *index)
  95 {
  96     mca_base_pvar_t *pvar;
  97     void *tmp;
  98     int rc;
  99 
 100     rc = opal_hash_table_get_value_ptr (&mca_base_pvar_index_hash, full_name, strlen (full_name),
 101                                         &tmp);
 102     if (OPAL_SUCCESS != rc) {
 103         return rc;
 104     }
 105 
 106     rc = mca_base_pvar_get_internal ((int)(uintptr_t) tmp, &pvar, false);
 107     if (OPAL_SUCCESS != rc) {
 108         return rc;
 109     }
 110 
 111     if (MCA_BASE_PVAR_CLASS_ANY != var_class && pvar->var_class != var_class) {
 112         return OPAL_ERR_NOT_FOUND;
 113     }
 114 
 115     *index = (int)(uintptr_t) tmp;
 116 
 117     return OPAL_SUCCESS;
 118 }
 119 
 120 int mca_base_pvar_finalize (void)
 121 {
 122     int i;
 123 
 124     if (mca_base_pvar_initialized)  {
 125         mca_base_pvar_initialized = false;
 126 
 127         for (i = 0 ; i < pvar_count ; ++i) {
 128             mca_base_pvar_t *pvar = opal_pointer_array_get_item (&registered_pvars, i);
 129             if (pvar) {
 130                 OBJ_RELEASE(pvar);
 131             }
 132         }
 133 
 134         pvar_count = 0;
 135 
 136         OBJ_DESTRUCT(&registered_pvars);
 137         OBJ_DESTRUCT(&mca_base_pvar_index_hash);
 138     }
 139 
 140     return OPAL_SUCCESS;
 141 }
 142 
 143 int mca_base_pvar_get_count (int *count)
 144 {
 145     *count = pvar_count;
 146     return OPAL_SUCCESS;
 147 }
 148 
 149 static int mca_base_pvar_default_get_value (const mca_base_pvar_t *pvar, void *value, void *obj_handle)
 150 {
 151     /* not used */
 152     (void) obj_handle;
 153 
 154     memmove (value, pvar->ctx, ompi_var_type_sizes[pvar->type]);
 155 
 156     return OPAL_SUCCESS;
 157 }
 158 
 159 static int mca_base_pvar_default_set_value (mca_base_pvar_t *pvar, const void *value, void *obj_handle)
 160 {
 161     /* not used */
 162     (void) obj_handle;
 163 
 164     memmove (pvar->ctx, value, ompi_var_type_sizes[pvar->type]);
 165 
 166     return OPAL_SUCCESS;
 167 }
 168 
 169 static int mca_base_pvar_notify_ignore (mca_base_pvar_t *pvar, mca_base_pvar_event_t event, void *obj_handle, int *count)
 170 {
 171     /* silence compiler warnings */
 172     (void) pvar;
 173     (void) obj_handle;
 174 
 175     /* default is only one value */
 176     if (MCA_BASE_PVAR_HANDLE_BIND == event) {
 177         *count = 1;
 178     }
 179 
 180     return OPAL_SUCCESS;
 181 }
 182 
 183 int mca_base_pvar_register (const char *project, const char *framework, const char *component, const char *name,
 184                             const char *description, mca_base_var_info_lvl_t verbosity,
 185                             int var_class, mca_base_var_type_t type, mca_base_var_enum_t *enumerator,
 186                             int bind, mca_base_pvar_flag_t flags, mca_base_get_value_fn_t get_value,
 187                             mca_base_set_value_fn_t set_value, mca_base_notify_fn_t notify, void *ctx)
 188 {
 189     int ret, group_index, pvar_index;
 190     mca_base_pvar_t *pvar;
 191 
 192     /* assert on usage errors */
 193     if (!get_value && !ctx) {
 194         return OPAL_ERR_BAD_PARAM;
 195     }
 196 
 197     /* ensure the caller did not set an invalid flag */
 198     assert (!(flags & 0x3f));
 199 
 200     flags &= ~MCA_BASE_PVAR_FLAG_INVALID;
 201 
 202     /* check that the datatype matches what is permitted for the variable class */
 203     switch (var_class) {
 204     case MCA_BASE_PVAR_CLASS_STATE:
 205         /* states MUST be integers */
 206         if (MCA_BASE_VAR_TYPE_INT != type) {
 207             return OPAL_ERR_BAD_PARAM;
 208         }
 209         break;
 210     case MCA_BASE_PVAR_CLASS_COUNTER:
 211         /* counters can have the any of types in the fall-through except double */
 212         if (MCA_BASE_VAR_TYPE_DOUBLE == type) {
 213             return OPAL_ERR_BAD_PARAM;
 214         }
 215         /* fall-through */
 216     case MCA_BASE_PVAR_CLASS_LEVEL:
 217     case MCA_BASE_PVAR_CLASS_SIZE:
 218     case MCA_BASE_PVAR_CLASS_HIGHWATERMARK:
 219     case MCA_BASE_PVAR_CLASS_LOWWATERMARK:
 220     case MCA_BASE_PVAR_CLASS_AGGREGATE:
 221     case MCA_BASE_PVAR_CLASS_TIMER:
 222         if (MCA_BASE_VAR_TYPE_UNSIGNED_INT != type &&
 223             MCA_BASE_VAR_TYPE_UNSIGNED_LONG != type &&
 224             MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG != type &&
 225             MCA_BASE_VAR_TYPE_DOUBLE != type) {
 226             return OPAL_ERR_BAD_PARAM;
 227         }
 228         break;
 229     case MCA_BASE_PVAR_CLASS_PERCENTAGE:
 230         /* percentages must be doubles */
 231         if (MCA_BASE_VAR_TYPE_DOUBLE != type) {
 232             return OPAL_ERR_BAD_PARAM;
 233         }
 234         break;
 235     case MCA_BASE_PVAR_CLASS_GENERIC:
 236         /* there are no additional restrictions on the type of generic
 237            variables */
 238         break;
 239     default:
 240         return OPAL_ERR_BAD_PARAM;
 241     }
 242 
 243     /* update this assert if more MPIT verbosity levels are added */
 244     assert (verbosity >= OPAL_INFO_LVL_1 && verbosity <= OPAL_INFO_LVL_9);
 245 
 246     /* check if this variable is already registered */
 247     ret = mca_base_pvar_find (project, framework, component, name);
 248     if (OPAL_SUCCESS <= ret) {
 249         ret = mca_base_pvar_get_internal (ret, &pvar, true);
 250         if (OPAL_SUCCESS != ret) {
 251             /* inconsistent internal state */
 252             return OPAL_ERROR;
 253         }
 254 
 255         if (pvar->enumerator) {
 256             OBJ_RELEASE(pvar->enumerator);
 257         }
 258     } else {
 259         /* find/register an MCA parameter group for this performance variable */
 260         group_index = mca_base_var_group_register (project, framework, component, NULL);
 261         if (-1 > group_index) {
 262             return group_index;
 263         }
 264 
 265         /* create a new parameter entry */
 266         pvar = OBJ_NEW(mca_base_pvar_t);
 267         if (NULL == pvar) {
 268             return OPAL_ERR_OUT_OF_RESOURCE;
 269         }
 270 
 271         do {
 272             /* generate the variable's full name */
 273             ret = mca_base_var_generate_full_name4 (NULL, framework, component, name, &pvar->name);
 274             if (OPAL_SUCCESS != ret) {
 275                 ret = OPAL_ERR_OUT_OF_RESOURCE;
 276                 break;
 277             }
 278 
 279             if (NULL != description) {
 280                 pvar->description = strdup(description);
 281                 if (NULL == pvar->description) {
 282                     ret = OPAL_ERR_OUT_OF_RESOURCE;
 283                     break;
 284                 }
 285             }
 286 
 287             pvar_index = opal_pointer_array_add (&registered_pvars, pvar);
 288             if (0 > pvar_index) {
 289                 break;
 290             }
 291             pvar->pvar_index = pvar_index;
 292 
 293             /* add this performance variable to the MCA variable group */
 294             if (0 <= group_index) {
 295                 ret = mca_base_var_group_add_pvar (group_index, pvar_index);
 296                 if (0 > ret) {
 297                     break;
 298                 }
 299             }
 300 
 301             pvar->pvar_index = pvar_count;
 302             opal_hash_table_set_value_ptr (&mca_base_pvar_index_hash, pvar->name, strlen (pvar->name),
 303                                            (void *)(uintptr_t) pvar->pvar_index);
 304 
 305             pvar_count++;
 306             ret = OPAL_SUCCESS;
 307         } while (0);
 308 
 309         if (OPAL_SUCCESS != ret) {
 310             OBJ_RELEASE(pvar);
 311             return ret;
 312         }
 313 
 314         pvar->group_index = group_index;
 315     }
 316 
 317     pvar->verbosity   = verbosity;
 318     pvar->var_class   = var_class;
 319     pvar->type        = type;
 320     pvar->enumerator  = enumerator;
 321     if (enumerator) {
 322         OBJ_RETAIN(enumerator);
 323     }
 324 
 325     pvar->bind = bind;
 326     pvar->flags = flags;
 327 
 328     pvar->get_value = get_value ? get_value : mca_base_pvar_default_get_value;
 329     pvar->notify = notify ? notify : mca_base_pvar_notify_ignore;
 330 
 331     if (!(flags & MCA_BASE_PVAR_FLAG_READONLY)) {
 332         pvar->set_value = set_value ? set_value : mca_base_pvar_default_set_value;
 333     }
 334 
 335     pvar->ctx        = ctx;
 336 
 337     return pvar->pvar_index;
 338 }
 339 
 340 int mca_base_component_pvar_register (const mca_base_component_t *component, const char *name,
 341                                       const char *description, mca_base_var_info_lvl_t verbosity,
 342                                       int var_class, mca_base_var_type_t type, mca_base_var_enum_t *enumerator,
 343                                       int bind, mca_base_pvar_flag_t flags, mca_base_get_value_fn_t get_value,
 344                                       mca_base_set_value_fn_t set_value, mca_base_notify_fn_t notify, void *ctx)
 345 {
 346     /* invalidate this variable if the component's group is deregistered */
 347     return mca_base_pvar_register(component->mca_project_name, component->mca_type_name, component->mca_component_name,
 348                                   name, description, verbosity, var_class, type, enumerator, bind,
 349                                   flags | MCA_BASE_PVAR_FLAG_IWG, get_value, set_value, notify, ctx);
 350 }
 351 
 352 static int mca_base_pvar_get_internal (int index, mca_base_pvar_t **pvar, bool invalidok)
 353 {
 354     if (index >= pvar_count) {
 355         return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
 356     }
 357 
 358     *pvar = opal_pointer_array_get_item (&registered_pvars, index);
 359 
 360     /* variables should never be removed per MPI 3.0 § 14.3.7 */
 361     assert (*pvar);
 362 
 363     if (((*pvar)->flags & MCA_BASE_PVAR_FLAG_INVALID) && !invalidok) {
 364         *pvar = NULL;
 365         return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
 366     }
 367 
 368     return OPAL_SUCCESS;
 369 }
 370 
 371 int mca_base_pvar_get (int index, const mca_base_pvar_t **pvar)
 372 {
 373     return mca_base_pvar_get_internal (index, (mca_base_pvar_t **) pvar, false);
 374 }
 375 
 376 int mca_base_pvar_mark_invalid (int index)
 377 {
 378     mca_base_pvar_t *pvar;
 379     int ret;
 380 
 381     ret = mca_base_pvar_get_internal (index, &pvar, false);
 382     if (OPAL_SUCCESS != ret) {
 383         return ret;
 384     }
 385 
 386     pvar->flags |= MCA_BASE_PVAR_FLAG_INVALID;
 387 
 388     return OPAL_SUCCESS;
 389 }
 390 
 391 int mca_base_pvar_notify (mca_base_pvar_handle_t *handle, mca_base_pvar_event_t event, int *count)
 392 {
 393     if (mca_base_pvar_is_invalid (handle->pvar)) {
 394         return OPAL_ERR_NOT_BOUND;
 395     }
 396 
 397     return handle->pvar->notify (handle->pvar, event, handle->obj_handle, count);
 398 }
 399 
 400 int mca_base_pvar_update_all_handles (int index, const void *obj)
 401 {
 402     mca_base_pvar_handle_t *handle, *next;
 403     mca_base_pvar_t *pvar;
 404     int ret;
 405 
 406     ret = mca_base_pvar_get_internal (index, &pvar, false);
 407     if (OPAL_SUCCESS != ret) {
 408         return ret;
 409     }
 410 
 411     if (0 == opal_list_get_size (&pvar->bound_handles)) {
 412         /* nothing to do */
 413         return OPAL_SUCCESS;
 414     }
 415 
 416     /* TODO -- probably need to add a handle/variable lock */
 417     OPAL_LIST_FOREACH_SAFE(handle, next, &pvar->bound_handles, mca_base_pvar_handle_t) {
 418         handle = (mca_base_pvar_handle_t *)((char *) handle - offsetof (mca_base_pvar_handle_t, list2));
 419 
 420         if (handle->obj_handle != obj) {
 421             continue;
 422         }
 423 
 424         (void) mca_base_pvar_handle_update (handle);
 425     }
 426 
 427     return OPAL_SUCCESS;
 428 }
 429 
 430 int mca_base_pvar_handle_alloc (mca_base_pvar_session_t *session, int index, void *obj_handle,
 431                                 mca_base_pvar_handle_t **handle, int *count)
 432 {
 433     mca_base_pvar_handle_t *pvar_handle = NULL;
 434     size_t datatype_size;
 435     mca_base_pvar_t *pvar;
 436     int ret;
 437 
 438     do {
 439         /* find the requested performance variable */
 440         ret = mca_base_pvar_get_internal (index, &pvar, false);
 441         if (OPAL_SUCCESS != ret) {
 442             break;
 443         }
 444 
 445         if (0 == pvar->bind) {
 446             /* ignore binding object */
 447             obj_handle = NULL;
 448         } else if (0 != pvar->bind && NULL == obj_handle) {
 449             /* this is an application error. what is the correct error code? */
 450             ret = OPAL_ERR_BAD_PARAM;
 451             break;
 452         }
 453 
 454         /* allocate and initialize the handle */
 455         pvar_handle = OBJ_NEW(mca_base_pvar_handle_t);
 456         if (NULL == pvar_handle) {
 457             ret = OPAL_ERR_OUT_OF_RESOURCE;
 458             break;
 459         }
 460 
 461         pvar_handle->obj_handle = (NULL == obj_handle ? NULL : *(void**)obj_handle);
 462         pvar_handle->pvar = pvar;
 463 
 464         *handle = pvar_handle;
 465 
 466         /* notify the variable that a handle has been bound and determine
 467            how many values this handle has. NTH: finding the count should
 468            probably be pushed into a separate function. */
 469         ret = mca_base_pvar_notify (pvar_handle, MCA_BASE_PVAR_HANDLE_BIND, count);
 470         if (0 > ret) {
 471             ret = OPAL_ERROR;
 472             break;
 473         }
 474 
 475         pvar_handle->count = *count;
 476 
 477         /* get the size of this datatype since read functions will expect an
 478            array of datatype not mca_base_pvar_value_t's. */
 479         datatype_size = ompi_var_type_sizes[pvar->type];
 480         if (0 == datatype_size) {
 481             ret = OPAL_ERROR;
 482             break;
 483         }
 484 
 485         if (!mca_base_pvar_is_continuous (pvar) || mca_base_pvar_is_sum (pvar) ||
 486             mca_base_pvar_is_watermark (pvar)) {
 487             /* if a variable is not continuous we will need to keep track of its last value
 488                to support start->stop->read correctly. use calloc to initialize the current
 489                value to 0. */
 490             pvar_handle->current_value = calloc (*count, datatype_size);
 491             if (NULL == pvar_handle->current_value) {
 492                 ret = OPAL_ERR_OUT_OF_RESOURCE;
 493                 break;
 494             }
 495         }
 496 
 497         if (mca_base_pvar_is_sum (pvar) || mca_base_pvar_is_watermark (pvar)) {
 498             /* for sums (counters, timers, etc) we need to keep track of
 499                what the last value of the underlying counter was. this allows
 500                us to push the computation of handle values from the event(s)
 501                (which could be in a critical path) to pvar read/stop/reset/etc */
 502             pvar_handle->tmp_value = calloc (*count, datatype_size);
 503             if (NULL == pvar_handle->tmp_value) {
 504                 ret = OPAL_ERR_OUT_OF_RESOURCE;
 505                 break;
 506             }
 507 
 508             pvar_handle->last_value = calloc (*count, datatype_size);
 509             if (NULL == pvar_handle->last_value) {
 510                 ret = OPAL_ERR_OUT_OF_RESOURCE;
 511                 break;
 512             }
 513 
 514             /* get the current value of the performance variable if this is a
 515                continuous sum or watermark. if this variable needs to be started first the
 516                current value is not relevant. */
 517             if (mca_base_pvar_is_continuous (pvar)) {
 518                 if (mca_base_pvar_is_sum (pvar)) {
 519                     ret = pvar->get_value (pvar, pvar_handle->last_value, pvar_handle->obj_handle);
 520                 } else {
 521                     /* the initial value of a watermark is the current value of the variable */
 522                     ret = pvar->get_value (pvar, pvar_handle->current_value, pvar_handle->obj_handle);
 523                 }
 524 
 525                 if (OPAL_SUCCESS != ret) {
 526                     return ret;
 527                 }
 528             }
 529         }
 530 
 531         pvar_handle->session = session;
 532 
 533         /* the handle is ready. add it to the appropriate lists */
 534         opal_list_append (&session->handles, &pvar_handle->super);
 535         opal_list_append (&pvar->bound_handles, &pvar_handle->list2);
 536 
 537         if (mca_base_pvar_is_continuous (pvar)) {
 538             /* mark this variable as started */
 539             pvar_handle->started = true;
 540         }
 541 
 542         ret = OPAL_SUCCESS;
 543     } while (0);
 544 
 545     if (OPAL_SUCCESS != ret && pvar_handle) {
 546         OBJ_RELEASE(pvar_handle);
 547     }
 548 
 549     return ret;
 550 }
 551 
 552 int mca_base_pvar_handle_free (mca_base_pvar_handle_t *handle)
 553 {
 554     OBJ_RELEASE(handle);
 555 
 556     return OPAL_SUCCESS;
 557 }
 558 
 559 int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle)
 560 {
 561     int i, ret;
 562     void *tmp;
 563 
 564     if (mca_base_pvar_is_invalid (handle->pvar)) {
 565         return OPAL_ERR_NOT_BOUND;
 566     }
 567 
 568     if (!mca_base_pvar_handle_is_running (handle)) {
 569         return OPAL_SUCCESS;
 570     }
 571 
 572     if (mca_base_pvar_is_sum (handle->pvar) || mca_base_pvar_is_watermark (handle->pvar)) {
 573         ret = handle->pvar->get_value (handle->pvar, handle->tmp_value, handle->obj_handle);
 574         if (OPAL_SUCCESS != ret) {
 575             return OPAL_ERROR;
 576         }
 577 
 578         if (mca_base_pvar_is_sum (handle->pvar)) {
 579             for (i = 0 ; i < handle->count ; ++i) {
 580                 /* the instance started at 0. need to subract the initial value off the
 581                    result. */
 582                 switch (handle->pvar->type) {
 583                 case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
 584                     ((unsigned *) handle->current_value)[i] += ((unsigned *) handle->tmp_value)[i] -
 585                         ((unsigned *) handle->last_value)[i];
 586                     break;
 587                 case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
 588                     ((unsigned long *) handle->current_value)[i] += ((unsigned long *) handle->tmp_value)[i] -
 589                         ((unsigned long *) handle->last_value)[i];
 590                     break;
 591                 case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
 592                     ((unsigned long long *) handle->current_value)[i] += ((unsigned long long *) handle->tmp_value)[i] -
 593                         ((unsigned long long *) handle->last_value)[i];
 594                     break;
 595                 case MCA_BASE_VAR_TYPE_DOUBLE:
 596                     ((double *) handle->current_value)[i] += ((double *) handle->tmp_value)[i] -
 597                         ((double *) handle->last_value)[i];
 598                     break;
 599                 default:
 600                     /* shouldn't happen */
 601                     break;
 602                 }
 603             }
 604 
 605             tmp = handle->tmp_value;
 606             handle->tmp_value = handle->last_value;
 607             handle->last_value = tmp;
 608         } else {
 609             for (i = 0 ; i < handle->count ; ++i) {
 610                 if (MCA_BASE_PVAR_CLASS_LOWWATERMARK == handle->pvar->var_class) {
 611                     switch (handle->pvar->type) {
 612                     case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
 613                         ((unsigned *) handle->current_value)[i] = min(((unsigned *) handle->tmp_value)[i],
 614                                                                       ((unsigned *) handle->current_value)[i]);
 615                         break;
 616                     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
 617                         ((unsigned long *) handle->current_value)[i] = min(((unsigned long *) handle->tmp_value)[i],
 618                                                                            ((unsigned long *) handle->current_value)[i]);
 619                         break;
 620                     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
 621                         ((unsigned long long *) handle->current_value)[i] = min(((unsigned long long *) handle->tmp_value)[i],
 622                                                                                 ((unsigned long long *) handle->current_value)[i]);
 623                         break;
 624                     case MCA_BASE_VAR_TYPE_DOUBLE:
 625                         ((double *) handle->current_value)[i] = min(((double *) handle->tmp_value)[i],
 626                                                                     ((double *) handle->current_value)[i]);
 627                         break;
 628                     default:
 629                         /* shouldn't happen */
 630                         break;
 631                     }
 632                 } else {
 633                     switch (handle->pvar->type) {
 634                     case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
 635                         ((unsigned *) handle->current_value)[i] = max(((unsigned *) handle->tmp_value)[i],
 636                                                                       ((unsigned *) handle->current_value)[i]);
 637                         break;
 638                     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
 639                         ((unsigned long *) handle->current_value)[i] = max(((unsigned long *) handle->tmp_value)[i],
 640                                                                            ((unsigned long *) handle->current_value)[i]);
 641                         break;
 642                     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
 643                         ((unsigned long long *) handle->current_value)[i] = max(((unsigned long long *) handle->tmp_value)[i],
 644                                                                                 ((unsigned long long *) handle->current_value)[i]);
 645                         break;
 646                     case MCA_BASE_VAR_TYPE_DOUBLE:
 647                         ((double *) handle->current_value)[i] = max(((double *) handle->tmp_value)[i],
 648                                                                     ((double *) handle->current_value)[i]);
 649                         break;
 650                     default:
 651                         /* shouldn't happen */
 652                         break;
 653                     }
 654                 }
 655             }
 656         }
 657     } else if (!mca_base_pvar_is_continuous (handle->pvar)) {
 658         /* cache the current value */
 659         ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle);
 660         if (OPAL_SUCCESS != ret) {
 661             return ret;
 662         }
 663     }
 664 
 665     /* XXX -- TODO -- For watermarks this function will have to be invoked for each handle whenever the underlying value is updated. */
 666 
 667     return OPAL_SUCCESS;
 668 }
 669 
 670 int mca_base_pvar_handle_read_value (mca_base_pvar_handle_t *handle, void *value)
 671 {
 672     int ret;
 673 
 674     if (mca_base_pvar_is_invalid (handle->pvar)) {
 675         return OPAL_ERR_NOT_BOUND;
 676     }
 677 
 678     /* ensure this handle's value is up to date. */
 679     ret = mca_base_pvar_handle_update (handle);
 680     if (OPAL_SUCCESS != ret) {
 681         return ret;
 682     }
 683 
 684     if (mca_base_pvar_is_sum (handle->pvar) || mca_base_pvar_is_watermark (handle->pvar) ||
 685         !mca_base_pvar_handle_is_running (handle)) {
 686         /* read the value cached in the handle. */
 687         memmove (value, handle->current_value, handle->count * ompi_var_type_sizes[handle->pvar->type]);
 688     } else {
 689         /* read the value directly from the variable. */
 690         ret = handle->pvar->get_value (handle->pvar, value, handle->obj_handle);
 691     }
 692 
 693     return ret;
 694 }
 695 
 696 int mca_base_pvar_handle_write_value (mca_base_pvar_handle_t *handle, const void *value)
 697 {
 698     int ret;
 699 
 700     if (mca_base_pvar_is_invalid (handle->pvar)) {
 701         return OPAL_ERR_NOT_BOUND;
 702     }
 703 
 704     if (mca_base_pvar_is_readonly (handle->pvar)) {
 705         return OPAL_ERR_PERM;
 706     }
 707 
 708     /* write the value directly from the variable. */
 709     ret = handle->pvar->set_value (handle->pvar, value, handle->obj_handle);
 710 
 711     ret = mca_base_pvar_handle_update (handle);
 712     if (OPAL_SUCCESS != ret) {
 713         return ret;
 714     }
 715 
 716     memmove (handle->current_value, value, handle->count * ompi_var_type_sizes[handle->pvar->type]);
 717     /* read the value directly from the variable. */
 718     ret = handle->pvar->set_value (handle->pvar, value, handle->obj_handle);
 719 
 720     return OPAL_SUCCESS;
 721 }
 722 
 723 int mca_base_pvar_handle_start (mca_base_pvar_handle_t *handle)
 724 {
 725     int ret;
 726 
 727     /* Can't start a continuous or an already started variable */
 728     if ((handle->pvar->flags & MCA_BASE_PVAR_FLAG_CONTINUOUS) ||
 729         handle->started) {
 730         return OPAL_ERR_NOT_SUPPORTED;
 731     }
 732 
 733     /* Notify the variable that a handle has started */
 734     ret = mca_base_pvar_notify (handle, MCA_BASE_PVAR_HANDLE_START, NULL);
 735     if (OPAL_SUCCESS != ret) {
 736         return ret;
 737     }
 738 
 739     handle->started = true;
 740 
 741     if (mca_base_pvar_is_sum (handle->pvar)) {
 742         /* Keep track of the counter value from when this counter started. */
 743         ret = handle->pvar->get_value (handle->pvar, handle->last_value, handle->obj_handle);
 744         if (OPAL_SUCCESS != ret) {
 745             return ret;
 746         }
 747     } else if (mca_base_pvar_is_watermark (handle->pvar)) {
 748         /* Find the current watermark. is this correct in the case where a watermark is started, stopped,
 749            then restarted? Probably will need to add a check. */
 750         ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle);
 751         if (OPAL_SUCCESS != ret) {
 752             return ret;
 753         }
 754     }
 755 
 756     return OPAL_SUCCESS;
 757 }
 758 
 759 int mca_base_pvar_handle_stop (mca_base_pvar_handle_t *handle)
 760 {
 761     int ret;
 762 
 763     if (mca_base_pvar_is_invalid (handle->pvar)) {
 764         return OPAL_ERR_NOT_BOUND;
 765     }
 766 
 767     /* Can't stop a continuous or an already stopped variable */
 768     if (!mca_base_pvar_handle_is_running (handle) || mca_base_pvar_is_continuous (handle->pvar)) {
 769         return OPAL_ERR_NOT_SUPPORTED;
 770     }
 771 
 772     ret = mca_base_pvar_handle_update (handle);
 773     if (OPAL_SUCCESS != ret) {
 774         return ret;
 775     }
 776 
 777     /* Notify the variable that a handle has stopped */
 778     (void) mca_base_pvar_notify (handle, MCA_BASE_PVAR_HANDLE_STOP, NULL);
 779 
 780     /* Handle is stopped */
 781     handle->started = false;
 782 
 783     return OPAL_SUCCESS;
 784 }
 785 
 786 int mca_base_pvar_handle_reset (mca_base_pvar_handle_t *handle)
 787 {
 788     int ret = OPAL_SUCCESS;
 789 
 790     if (mca_base_pvar_is_invalid (handle->pvar)) {
 791         return OPAL_ERR_NOT_BOUND;
 792     }
 793 
 794     /* reset this handle to a state analagous to when it was created */
 795     if (mca_base_pvar_is_sum (handle->pvar)) {
 796         /* reset the running sum to 0 */
 797         memset (handle->current_value, 0, handle->count * ompi_var_type_sizes[handle->pvar->type]);
 798 
 799         if (mca_base_pvar_handle_is_running (handle)) {
 800             ret = handle->pvar->get_value (handle->pvar, handle->last_value, handle->obj_handle);
 801         }
 802     } else if (mca_base_pvar_handle_is_running (handle) && mca_base_pvar_is_watermark (handle->pvar)) {
 803             /* watermarks should get set to the current value if runnning. */
 804 
 805         ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle);
 806     } else if (mca_base_pvar_is_readonly (handle->pvar)) {
 807         return OPAL_ERR_PERM;
 808     }
 809     /* NTH: TODO -- Actually write the value for variable of other types */
 810 
 811     return ret;
 812 }
 813 
 814 int mca_base_pvar_dump(int index, char ***out, mca_base_var_dump_type_t output_type)
 815 {
 816     const char *framework, *component, *full_name;
 817     mca_base_var_group_t *group;
 818     int line = 0, line_count, i;
 819     const mca_base_pvar_t *pvar;
 820     int ret, enum_count = 0;
 821     char *tmp;
 822 
 823     ret = mca_base_pvar_get (index, &pvar);
 824     if (OPAL_SUCCESS != ret) {
 825         return ret;
 826     }
 827 
 828     ret = mca_base_var_group_get_internal (pvar->group_index, &group, true);
 829     if (OPAL_SUCCESS != ret) {
 830         return ret;
 831     }
 832 
 833     framework = group->group_framework;
 834     component = group->group_component ? group->group_component : "base";
 835     full_name = pvar->name;
 836 
 837     if (NULL != pvar->enumerator) {
 838         (void) pvar->enumerator->get_count(pvar->enumerator, &enum_count);
 839     }
 840 
 841     if (MCA_BASE_VAR_DUMP_PARSABLE == output_type) {
 842         line_count = 5 + !!(pvar->description) + enum_count;
 843 
 844         *out = (char **) calloc (line_count + 1, sizeof (char *));
 845         if (NULL == *out) {
 846             return OPAL_ERR_OUT_OF_RESOURCE;
 847         }
 848 
 849         /* build the message*/
 850         (void)opal_asprintf(&tmp, "mca:%s:%s:pvar:%s:", framework, component, full_name);
 851 
 852         (void)opal_asprintf(out[0] + line++, "%sclass:%s", tmp, pvar_class_names[pvar->var_class]);
 853         (void)opal_asprintf(out[0] + line++, "%sread-only:%s", tmp, mca_base_pvar_is_readonly(pvar) ? "true" : "false");
 854         (void)opal_asprintf(out[0] + line++, "%scontinuous:%s", tmp, mca_base_pvar_is_continuous(pvar) ? "true" : "false");
 855         (void)opal_asprintf(out[0] + line++, "%satomic:%s", tmp, mca_base_pvar_is_atomic(pvar) ? "true" : "false");
 856 
 857         /* if it has a help message, output the help message */
 858         if (pvar->description) {
 859             (void)opal_asprintf(out[0] + line++, "%shelp:%s", tmp, pvar->description);
 860         }
 861 
 862         if (NULL != pvar->enumerator) {
 863             for (i = 0 ; i < enum_count ; ++i) {
 864                 const char *enum_string = NULL;
 865                 int enum_value;
 866 
 867                 ret = pvar->enumerator->get_value(pvar->enumerator, i, &enum_value,
 868                                                      &enum_string);
 869                 if (OPAL_SUCCESS != ret) {
 870                     continue;
 871                 }
 872 
 873                 (void)opal_asprintf(out[0] + line++, "%senumerator:value:%d:%s", tmp, enum_value, enum_string);
 874             }
 875         }
 876 
 877         (void)opal_asprintf(out[0] + line++, "%stype:%s", tmp, ompi_var_type_names[pvar->type]);
 878         free(tmp);  // release tmp storage
 879     } else {
 880         /* there will be at most three lines in the pretty print case */
 881         *out = (char **) calloc (3, sizeof (char *));
 882         if (NULL == *out) {
 883             return OPAL_ERR_OUT_OF_RESOURCE;
 884         }
 885 
 886         (void)opal_asprintf (out[0] + line++, "performance \"%s\" (type: %s, class: %s)", full_name,
 887                         ompi_var_type_names[pvar->type], pvar_class_names[pvar->var_class]);
 888 
 889         if (pvar->description) {
 890             (void)opal_asprintf(out[0] + line++, "%s", pvar->description);
 891         }
 892 
 893         if (NULL != pvar->enumerator) {
 894             char *values;
 895 
 896             ret = pvar->enumerator->dump(pvar->enumerator, &values);
 897             if (OPAL_SUCCESS == ret) {
 898                 (void)opal_asprintf (out[0] + line++, "Values: %s", values);
 899                 free (values);
 900             }
 901         }
 902     }
 903 
 904     return OPAL_SUCCESS;
 905 }
 906 
 907 /* mca_base_pvar_t class */
 908 static void mca_base_pvar_contructor (mca_base_pvar_t *pvar)
 909 {
 910     memset ((char *) pvar + sizeof (pvar->super), 0, sizeof (*pvar) - sizeof (pvar->super));
 911     OBJ_CONSTRUCT(&pvar->bound_handles, opal_list_t);
 912 }
 913 
 914 static void mca_base_pvar_destructor (mca_base_pvar_t *pvar)
 915 {
 916     if (pvar->name) {
 917         free (pvar->name);
 918     }
 919 
 920     if (pvar->description) {
 921         free (pvar->description);
 922     }
 923 
 924     if (NULL != pvar->enumerator) {
 925         OBJ_RELEASE(pvar->enumerator);
 926     }
 927 
 928     OBJ_DESTRUCT(&pvar->bound_handles);
 929 }
 930 
 931 OBJ_CLASS_INSTANCE(mca_base_pvar_t, opal_object_t, mca_base_pvar_contructor, mca_base_pvar_destructor);
 932 
 933 /* mca_base_pvar_session_t class */
 934 static void opal_mpi_pvar_session_constructor (mca_base_pvar_session_t *session)
 935 {
 936     OBJ_CONSTRUCT(&session->handles, opal_list_t);
 937 }
 938 
 939 static void opal_mpi_pvar_session_destructor (mca_base_pvar_session_t *session)
 940 {
 941     mca_base_pvar_handle_t *handle, *next;
 942 
 943     /* it is likely a user error if there are any allocated handles when the session
 944      * is freed. clean it up anyway. The handle destructor will remove the handle from
 945      * the session's handle list. */
 946     OPAL_LIST_FOREACH_SAFE(handle, next, &session->handles, mca_base_pvar_handle_t) {
 947         OBJ_DESTRUCT(handle);
 948     }
 949 
 950     OBJ_DESTRUCT(&session->handles);
 951 }
 952 
 953 OBJ_CLASS_INSTANCE(mca_base_pvar_session_t, opal_object_t, opal_mpi_pvar_session_constructor,
 954                    opal_mpi_pvar_session_destructor);
 955 
 956 /* mca_base_pvar_handle_t class */
 957 static void mca_base_pvar_handle_constructor (mca_base_pvar_handle_t *handle)
 958 {
 959     memset ((char *) handle + sizeof (handle->super), 0, sizeof (*handle) - sizeof (handle->super));
 960 
 961     OBJ_CONSTRUCT(&handle->list2, opal_list_item_t);
 962 }
 963 
 964 static void mca_base_pvar_handle_destructor (mca_base_pvar_handle_t *handle)
 965 {
 966     if (handle->pvar) {
 967         (void) mca_base_pvar_notify (handle, MCA_BASE_PVAR_HANDLE_UNBIND, NULL);
 968     }
 969 
 970     if (NULL != handle->last_value) {
 971         free (handle->last_value);
 972     }
 973 
 974     if (NULL != handle->current_value) {
 975         free (handle->current_value);
 976     }
 977 
 978     if (NULL != handle->tmp_value) {
 979         free (handle->tmp_value);
 980     }
 981 
 982     /* remove this handle from the pvar list */
 983     if (handle->pvar) {
 984         opal_list_remove_item (&handle->pvar->bound_handles, &handle->list2);
 985     }
 986 
 987     OBJ_DESTRUCT(&handle->list2);
 988 
 989     /* remove this handle from the session */
 990     if (handle->session) {
 991         opal_list_remove_item (&handle->session->handles, &handle->super);
 992     }
 993 }
 994 
 995 OBJ_CLASS_INSTANCE(mca_base_pvar_handle_t, opal_list_item_t, mca_base_pvar_handle_constructor,
 996                    mca_base_pvar_handle_destructor);

/* [<][>][^][v][top][bottom][index][help] */