1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ 2 /* 3 * Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights 4 * reserved. 5 * Copyright (c) 2018 The University of Tennessee and The University 6 * of Tennessee Research Foundation. All rights 7 * reserved. 8 * 9 * Additional copyrights may follow 10 * 11 * $HEADER$ 12 */ 13 14 #if !defined(OPAL_MPIT_PVAR_H) 15 #define OPAL_MPIT_PVAR_H 16 17 #include "opal/mca/base/mca_base_var.h" 18 19 /* 20 * These flags are used when registering a new pvar. 21 */ 22 typedef enum { 23 /** This variable should be marked as invalid when the containing 24 group is deregistered (IWG = "invalidate with group"). This 25 flag is set automatically when you register a variable with 26 mca_base_component_pvvar_register(), but can also be set 27 manually when you register a variable with 28 mca_base_pvar_register(). Analogous to the 29 MCA_BASE_VAR_FLAG_DWG flag. */ 30 MCA_BASE_PVAR_FLAG_IWG = 0x040, 31 /** This variable can not be written. Will be ignored for counter, 32 timer, and aggregate variables. These variable handles will be 33 updated relative to the value reported by the get_value() 34 function provided at registration time. */ 35 MCA_BASE_PVAR_FLAG_READONLY = 0x080, 36 /** This variable runs continuously after being bound to a handle. */ 37 MCA_BASE_PVAR_FLAG_CONTINUOUS = 0x100, 38 /** This variable can be updated atomically. This flag is ignored 39 by mca_base_pvar_register() at this time. */ 40 MCA_BASE_PVAR_FLAG_ATOMIC = 0x200, 41 /** This variable has been marked as invalid. This flag is ignored 42 by mca_base_pvar_register(). */ 43 MCA_BASE_PVAR_FLAG_INVALID = 0x400, 44 } mca_base_pvar_flag_t; 45 46 /* 47 * These flags are passed to the mca_base_notify_fn_t function. 48 */ 49 typedef enum { 50 /** A handle has been created an bound to this variable. The 51 return value must be the number of values associated with 52 the bound object or an OPAL error. For example, if the variable 53 is the number of messages sent to each peer in a communicator then the 54 return value should be the size of the bound communicator. */ 55 MCA_BASE_PVAR_HANDLE_BIND, 56 /** A handle associated with this variable has been started. It is 57 recommended that any computation that might affect perfomance 58 only be performed when a bound handle has been started. */ 59 MCA_BASE_PVAR_HANDLE_START, 60 /** A handle associated with this variable has been stopped */ 61 MCA_BASE_PVAR_HANDLE_STOP, 62 /** A handle associated with this variable has been freed */ 63 MCA_BASE_PVAR_HANDLE_UNBIND 64 } mca_base_pvar_event_t; 65 66 /* 67 * The class type is passed when registering a new pvar. 68 */ 69 enum { 70 /** Variable represents a state */ 71 MCA_BASE_PVAR_CLASS_STATE, 72 /** Variable represents a the utilization level of a resource */ 73 MCA_BASE_PVAR_CLASS_LEVEL, 74 /** Variable represents the fixed size of a resource */ 75 MCA_BASE_PVAR_CLASS_SIZE, 76 /** Variable represents the utilization level of a resource. 77 Valid type: double */ 78 MCA_BASE_PVAR_CLASS_PERCENTAGE, 79 /** Variable describes the high-watermark of the utilization 80 of a resource */ 81 MCA_BASE_PVAR_CLASS_HIGHWATERMARK, 82 /** Variable describes the low-watermark of the utilization 83 of a resource */ 84 MCA_BASE_PVAR_CLASS_LOWWATERMARK, 85 /** Variable counts the number of occurences of a specific event */ 86 MCA_BASE_PVAR_CLASS_COUNTER, 87 /** Variable represents a sum of arguments processed during a 88 specific event */ 89 MCA_BASE_PVAR_CLASS_AGGREGATE, 90 /** Variable represents the aggregated time that is spent 91 executing an specific event */ 92 MCA_BASE_PVAR_CLASS_TIMER, 93 /** Variable doesn't fit any other class */ 94 MCA_BASE_PVAR_CLASS_GENERIC 95 }; 96 97 #define MCA_BASE_PVAR_CLASS_ANY -1 98 99 /* 100 * Reserved bindings; passed when registering a new pvar. OPAL will 101 * ignore any other binding type. 102 */ 103 enum { 104 MCA_BASE_VAR_BIND_NO_OBJECT, 105 MCA_BASE_VAR_BIND_MPI_COMM, 106 MCA_BASE_VAR_BIND_MPI_DATATYPE, 107 MCA_BASE_VAR_BIND_MPI_ERRHANDLER, 108 MCA_BASE_VAR_BIND_MPI_FILE, 109 MCA_BASE_VAR_BIND_MPI_GROUP, 110 MCA_BASE_VAR_BIND_MPI_OP, 111 MCA_BASE_VAR_BIND_MPI_REQUEST, 112 MCA_BASE_VAR_BIND_MPI_WIN, 113 MCA_BASE_VAR_BIND_MPI_MESSAGE, 114 MCA_BASE_VAR_BIND_MPI_INFO, 115 MCA_BASE_VAR_BIND_FIRST_AVAILABLE, 116 }; 117 118 struct mca_base_pvar_t; 119 120 /** 121 * Function to retrieve the current value of a variable. 122 * 123 * @param[in] pvar Performance variable to get the value of. 124 * @param[out] value Current value of the variable. 125 * @param[in] obj Bound object 126 * 127 * This function will be called to get the current value of a variable. The value 128 * pointer will be large enough to hold the datatype and count specified when this 129 * variable was created and bound. 130 */ 131 typedef int (*mca_base_get_value_fn_t) (const struct mca_base_pvar_t *pvar, void *value, void *obj); 132 133 /** 134 * Function to set the current value of a variable. 135 * 136 * @param[in] pvar Performance variable to set the value of. 137 * @param[in] value Value to write. 138 * @param[in] obj Bound object. 139 * 140 * This function will be called to set the current value of a variable. The value 141 * pointer will be large enough to hold the datatype and count specified when this 142 * variable was created and bound. Read-only variables are not expected to provide 143 * this function. 144 */ 145 typedef int (*mca_base_set_value_fn_t) (struct mca_base_pvar_t *pvar, const void *value, void *obj); 146 147 /** 148 * Function to notify of a pvar handle event. 149 * 150 * @param[in] pvar Performance variable the handle is assocaited with 151 * @param[in] event Event that has occurred. See mca_base_pvar_event_t. 152 * @param[in] obj Bound object 153 * @param[out] count Value count for this object (on MCA_BASE_PVAR_HANDLE_BIND) 154 * 155 * Depending on the event this functions is expected to: 156 * On MCA_BASE_PVAR_HANDLE_BIND: depending on the bound object returns the number of values 157 * needed for get_value(). 158 * On MCA_BASE_PVAR_HANDLE_START: enable the performance variable. 159 * On MCA_BASE_PVAR_HANDLE_STOP: XXX -- TODO -- finish me 160 */ 161 typedef int (*mca_base_notify_fn_t) (struct mca_base_pvar_t *pvar, mca_base_pvar_event_t event, void *obj, int *count); 162 163 /** 164 * Structure representing an OPAL performance variable. 165 */ 166 typedef struct mca_base_pvar_t { 167 /** Make this an opal object */ 168 opal_object_t super; 169 170 /** Variable index */ 171 int pvar_index; 172 173 /** Full name of the variable: form is framework_component_name */ 174 char *name; 175 176 /** Description of this performance variable */ 177 char *description; 178 179 /** MCA variable group this variable is associated with */ 180 int group_index; 181 182 /** Verbosity level of this variable */ 183 mca_base_var_info_lvl_t verbosity; 184 185 /** Variable class. See mpi.h.in MPIT pvar classes */ 186 int var_class; 187 188 /** MPI datatype of the information stored in the performance variable */ 189 mca_base_var_type_t type; 190 191 /** Enumerator for integer values */ 192 mca_base_var_enum_t *enumerator; 193 194 /** Type of object to which this variable must be bound or MCA_BASE_VAR_BIND_NULL */ 195 int bind; 196 197 /** Flags for this variable */ 198 mca_base_pvar_flag_t flags; 199 200 /** Get the current value of this variable */ 201 mca_base_get_value_fn_t get_value; 202 203 /** Set the current value of this variable. Only valid for read-write variables. */ 204 mca_base_set_value_fn_t set_value; 205 206 /** Notify the creator of this variable of a change */ 207 mca_base_notify_fn_t notify; 208 209 /** Context of this variable */ 210 void *ctx; 211 212 /** List of bound pvar handles. NOTE: The items in this list are 213 offsetof(mca_base_pvar_handle_t, list2) into a pvar handle. */ 214 opal_list_t bound_handles; 215 } mca_base_pvar_t; 216 OBJ_CLASS_DECLARATION(mca_base_pvar_t); 217 218 /** 219 * Performance variable session 220 */ 221 typedef struct mca_base_pvar_session_t { 222 /** Make this an opal object */ 223 opal_object_t super; 224 225 /** List of all handles in the session */ 226 opal_list_t handles; 227 } mca_base_pvar_session_t; 228 OBJ_CLASS_DECLARATION(mca_base_pvar_session_t); 229 230 /** 231 * Performance variable handle 232 * 233 * Handles are used to bind performance variables to objects, read, write, and 234 * reset values. 235 */ 236 typedef struct mca_base_pvar_handle_t { 237 /** List item in pvar session */ 238 opal_list_item_t super; 239 240 /** XXX -- use me -- add this list item to the associated variable */ 241 opal_list_item_t list2; 242 243 /** session this handle is associated with */ 244 mca_base_pvar_session_t *session; 245 246 /** performance variable this handle is associated with */ 247 mca_base_pvar_t *pvar; 248 249 /** MPI object handle */ 250 void *obj_handle; 251 252 /** Number of values for this handle */ 253 int count; 254 255 /** Last value read from the variable */ 256 void *last_value; 257 258 /** Current sum for counters and timers */ 259 void *current_value; 260 261 /** Temporary buffer for counters. Used to calculate deltas between 262 the last value and the current value. */ 263 void *tmp_value; 264 265 /** Has this handle been started (or is continuous) */ 266 bool started; 267 } mca_base_pvar_handle_t; 268 OBJ_CLASS_DECLARATION(mca_base_pvar_handle_t); 269 270 /**************************************************************************** 271 * The following functions are public functions, and are intended to 272 * be used by components and frameworks to expose their performance 273 * variables. 274 ****************************************************************************/ 275 276 /** 277 * Register a performance variable 278 * 279 * @param[in] framework Name of registering framework 280 * @param[in] component Name of registering component 281 * @param[in] name Name of performance variable 282 * @param[in] description Description of the performance variable. Verbose 283 * is good! 284 * @param[in] verbosity Opal info verbosity of this variable. Equivalent to 285 * MPI_T verbosity. 286 * @param[in] var_class Class of performance variable. See mpi.h.in MPI_T_PVAR_CLASS_* 287 * @param[in] type Type of this performance variable 288 * @param[in] enumerator Enumerator for this variable. Will be 289 * OBJ_RETAIN'd (created by, for example, 290 * mca_base_var_enum_create()). 291 * @param[in] bind Object type this variable should be bound to. See mpi.h.in 292 * MPI_T_BIND_* 293 * @param[in] flags Flags for this variable. See mca_base_pvar_flag_t for acceptable 294 * flags. 295 * @param[in] get_value Function for reading the value of this variable. If this function 296 * is NULL a default function that reads 1 value from ctx will be used. 297 * See mca_base_get_value_fn_t. 298 * @param[in] set_value Function for writing the value of this variable. This pointer is 299 * ignored if the \flags includes \MCA_BASE_PVAR_FLAG_READONLY. If this 300 * function is NULL a default function that writes 1 value from ctx will 301 * be used. See mca_base_set_value_fn_t. 302 * @param[in] notify Function for notifying about variable handle events. If this function 303 * is NULL then a default function that ignores all events will be used. 304 * See mca_base_notify_fn_t. 305 * @param[in] ctx Context for this variable. Will be stored in the resulting variable 306 * for future use. 307 * 308 * @returns index On success returns the index of this variable. 309 * @returns OPAL_ERROR On error. 310 * 311 * Note: if used incorrectly this function may fail an assert(); see 312 * MPI 3.0 14.3 to see acceptable values for datatype given the class. 313 */ 314 OPAL_DECLSPEC int mca_base_pvar_register (const char *project, const char *framework, const char *component, const char *name, 315 const char *description, mca_base_var_info_lvl_t verbosity, 316 int var_class, mca_base_var_type_t type, mca_base_var_enum_t *enumerator, 317 int bind, mca_base_pvar_flag_t flags, mca_base_get_value_fn_t get_value, 318 mca_base_set_value_fn_t set_value, mca_base_notify_fn_t notify, void *ctx); 319 320 /** 321 * Convinience function for registering a performance variable 322 * associated with a component. 323 * 324 * While quite similar to mca_base_pvar_register(), there is one key 325 * difference: pvars registered with this function will automatically 326 * be unregistered / made unavailable when that component is closed by 327 * its framework. 328 */ 329 OPAL_DECLSPEC int mca_base_component_pvar_register (const mca_base_component_t *component, const char *name, 330 const char *description, mca_base_var_info_lvl_t verbosity, int var_class, 331 mca_base_var_type_t type, mca_base_var_enum_t *enumerator, int bind, 332 mca_base_pvar_flag_t flags, mca_base_get_value_fn_t get_value, 333 mca_base_set_value_fn_t set_value, mca_base_notify_fn_t notify, void *ctx); 334 335 336 /** 337 * Find the index for an MCA performance variable based on its names. 338 * 339 * @param project Name of the project 340 * @param type Name of the type containing the variable. 341 * @param component Name of the component containing the variable. 342 * @param param Name of the variable. 343 * 344 * @retval OPAL_ERROR If the variable was not found. 345 * @retval index If the variable was found. 346 * 347 * It is not always convenient to widely propagate a variable's index 348 * value, or it may be necessary to look up the variable from a 349 * different component. This function can be used to look up the index 350 * of any registered variable. The returned index can be used with 351 * mca_base_pvar_get(), mca_base_pvar_handle_alloc(), and 352 * mca_base_pvar_dump(). 353 */ 354 OPAL_DECLSPEC int mca_base_pvar_find (const char *project, const char *framework, const char *component, const char *name); 355 356 /** 357 * Find the index for a performance variable based on its full name 358 * 359 * @param full_name [in] Full name of the variable 360 * @param index [out] Index of the variable 361 * 362 * See mca_base_pvar_find(). 363 */ 364 OPAL_DECLSPEC int mca_base_pvar_find_by_name (const char *full_name, int var_class, int *index); 365 366 /**************************************************************************** 367 * The following functions are the back-end to the MPI_T API functions 368 * and/or the internals of the performance variable system itself. 369 ****************************************************************************/ 370 371 /** 372 * Return the number or registered performance variables. 373 * 374 * @param[out] count Number of registered performance variables. 375 * 376 * This function can be called before mca_base_pvar_init() and after 377 * mca_base_pvar_finalize(). 378 */ 379 OPAL_DECLSPEC int mca_base_pvar_get_count (int *count); 380 381 /** 382 * Update the handles associated with the specified performance variable and MPI object 383 * 384 * @param[in] index Index of the performance variable 385 * @param[in] value New value of the variable. 386 * @param[in] obj Object updated handles should be bound to. 387 * 388 * This function will obtain and hold the mpit big lock until all handles are updated. It 389 * is recommended this function not be called from within any critical code path. Calling 390 * this function should only be necessary to update watermarks. 391 */ 392 OPAL_DECLSPEC int mca_base_pvar_update_all_handles (int index, const void *obj); 393 394 /** 395 * Get the variable at an index 396 * 397 * @param[in] index Index of variable to get. 398 * @param[out] pvar Performance variable from index on success. 399 * 400 * @returns OPAL_SUCCESS on success 401 * @returns OPAL_ERR_VALUE_OUT_OF_BOUNDS on if index is out of range 402 */ 403 OPAL_DECLSPEC int mca_base_pvar_get (int index, const mca_base_pvar_t **pvar); 404 405 /** 406 * Dump strings describing the performance variable at an index 407 * 408 * @param[in] index Variable index 409 * @param[out] out Array of strings representing this variable 410 * @param[in] output_type Type of output desired 411 * 412 * This function returns an array of strings describing the variable. All strings 413 * and the array must be freed by the caller. The \output_type may be either 414 * MCA_BASE_VAR_DUMP_READABLE or MCA_BASE_VAR_DUMP_PARSABLE. 415 */ 416 OPAL_DECLSPEC int mca_base_pvar_dump(int index, char ***out, mca_base_var_dump_type_t output_type); 417 418 /** 419 * Mark a performance variable as invalid 420 * 421 * @param[in] index Variable index 422 * 423 * A performance variable that has been marked as invalid will not be available. To 424 * restore a performance variable it has to be re-registered using mca_base_pvar_register(). 425 */ 426 int mca_base_pvar_mark_invalid (int index); 427 428 /** 429 * Convienience functions for performance variables 430 */ 431 static inline bool mca_base_pvar_is_sum (const mca_base_pvar_t *pvar) 432 { 433 return (MCA_BASE_PVAR_CLASS_COUNTER == pvar->var_class || 434 MCA_BASE_PVAR_CLASS_TIMER == pvar->var_class || 435 MCA_BASE_PVAR_CLASS_AGGREGATE == pvar->var_class); 436 } 437 438 static inline bool mca_base_pvar_is_watermark (const mca_base_pvar_t *pvar) 439 { 440 return (MCA_BASE_PVAR_CLASS_HIGHWATERMARK == pvar->var_class || 441 MCA_BASE_PVAR_CLASS_LOWWATERMARK == pvar->var_class); 442 } 443 444 static inline bool mca_base_pvar_is_readonly (const mca_base_pvar_t *pvar) 445 { 446 return !!(pvar->flags & MCA_BASE_PVAR_FLAG_READONLY); 447 } 448 449 static inline bool mca_base_pvar_is_continuous (const mca_base_pvar_t *pvar) 450 { 451 return !!(pvar->flags & MCA_BASE_PVAR_FLAG_CONTINUOUS); 452 } 453 454 static inline bool mca_base_pvar_is_atomic (const mca_base_pvar_t *pvar) 455 { 456 return !!(pvar->flags & MCA_BASE_PVAR_FLAG_ATOMIC); 457 } 458 459 static inline bool mca_base_pvar_is_invalid (const mca_base_pvar_t *pvar) 460 { 461 return !!(pvar->flags & MCA_BASE_PVAR_FLAG_INVALID); 462 } 463 464 /* Handle functions */ 465 466 /** 467 * Bind a new handle and object to a performance variable 468 * 469 * @param[in] session Valid pvar session 470 * @param[in] index Variable index 471 * @param[in] obj_handle Object handle 472 * @param[out] handle New handle 473 * @param[out] count Number of values associated with this object 474 * 475 * This function allocates a new performance variable handle and binds it 476 * to \obj_handle (if the variable binding is 0 the object is ignored). On 477 * success a new handle is returned in \handle and the number of values i 478 * returned in \count. Calls to read/write must provide buffers that will 479 * hold \count values of the type of the performance variable specified by 480 * \index. 481 */ 482 OPAL_DECLSPEC int mca_base_pvar_handle_alloc (mca_base_pvar_session_t *session, int index, void *obj_handle, 483 mca_base_pvar_handle_t **handle, int *count); 484 485 /** 486 * Free an allocated performance variable handle 487 * 488 * @param[in] handle Handle to free 489 * 490 * After calling this function the performance variable will no longer be valid. 491 */ 492 OPAL_DECLSPEC int mca_base_pvar_handle_free (mca_base_pvar_handle_t *handle); 493 494 /** 495 * Update a performance variable handle. 496 * 497 * @param[in] handle Handle to update 498 * 499 * The new value of the handle will depend on the class of performance variable. 500 * For counters and timers the new value will be the current handle value plus the 501 * difference between the last and the current variable value. For high/low watermarks 502 * the new value will be the greater/lesser of the current handle value and the 503 * current variable value. This call does not update other types of handles. 504 */ 505 OPAL_DECLSPEC int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle); 506 507 /** 508 * Read the current value of a handle 509 * 510 * @param[in] handle Handle to read from 511 * @param[out] value Buffer to store the current value in 512 * 513 * Read the current value of the handle or variable (depending on the variable class) 514 * and return it in the buffer specified by value. The buffer must be large enough to 515 * hold the correct number and type of this handle's value (see mca_base_pvar_handle_update()). 516 */ 517 OPAL_DECLSPEC int mca_base_pvar_handle_read_value (mca_base_pvar_handle_t *handle, void *value); 518 519 /** 520 * Write a value to a read-write handle 521 * 522 * @param[in] handle Handle to update 523 * @param[in] value Value to write 524 * 525 * If the underlying variable is read-only this function will fail with OPAL_ERR_PERM. 526 */ 527 OPAL_DECLSPEC int mca_base_pvar_handle_write_value (mca_base_pvar_handle_t *handle, const void *value); 528 529 /** 530 * Convienience function for sending notification of a handle change 531 * 532 * @param[in] handle Handle event occurred on 533 * @param[in] event Event that occurred 534 * @param[out] count Value count returned when binding a handle 535 */ 536 OPAL_DECLSPEC int mca_base_pvar_notify (mca_base_pvar_handle_t *handle, mca_base_pvar_event_t event, int *count); 537 538 /** 539 * Start a performance variable handle 540 * 541 * @param[in] handle Handle to start 542 * 543 * @returns OPAL_SUCCESS on success 544 * @returns OPAL_ERR_NOT_SUPPORTED if the handle could not be started 545 */ 546 OPAL_DECLSPEC int mca_base_pvar_handle_start (mca_base_pvar_handle_t *handle); 547 548 /** 549 * Stop a performance variable handle 550 * 551 * @param[in] handle Handle to stop (must be started) 552 * 553 * @return OPAL_SUCCESS on success 554 * @returns OPAL_ERR_NOT_SUPPORTED if the handle could not be started 555 */ 556 OPAL_DECLSPEC int mca_base_pvar_handle_stop (mca_base_pvar_handle_t *handle); 557 558 /** 559 * Reset a performance variable handle 560 * 561 * @param[in] handle Handle to reset 562 * 563 * Reset the handle to a value equivalent to when the handle was first allocated. 564 */ 565 OPAL_DECLSPEC int mca_base_pvar_handle_reset (mca_base_pvar_handle_t *handle); 566 567 static inline bool mca_base_pvar_handle_is_running (mca_base_pvar_handle_t *handle) 568 { 569 return handle->started || !!(handle->pvar->flags & MCA_BASE_PVAR_FLAG_CONTINUOUS); 570 } 571 572 #endif