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