diff --git a/opal/class/opal_free_list.c b/opal/class/opal_free_list.c index 517d8ee0d3d..c2bdceb0817 100644 --- a/opal/class/opal_free_list.c +++ b/opal/class/opal_free_list.c @@ -15,6 +15,8 @@ * Copyright (c) 2011 NVIDIA Corporation. All rights reserved. * Copyright (c) 2012-2018 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,7 +34,17 @@ #include "opal/mca/rcache/rcache.h" #include "opal/util/sys_limits.h" -typedef struct opal_free_list_item_t opal_free_list_memory_t; +/* total memory in use for free-list buffers/headers */ +opal_atomic_int64_t opal_free_list_memory_allocated = 0; + +struct opal_free_list_memory_t { + opal_free_list_item_t super; + ssize_t memory_size; +}; +typedef struct opal_free_list_memory_t opal_free_list_memory_t; + +OBJ_CLASS_DECLARATION(opal_free_list_memory_t); +OBJ_CLASS_INSTANCE(opal_free_list_memory_t, opal_free_list_item_t, NULL, NULL); OBJ_CLASS_INSTANCE(opal_free_list_item_t, opal_list_item_t, @@ -54,8 +66,7 @@ static void opal_free_list_construct(opal_free_list_t* fl) fl->fl_mpool = NULL; fl->fl_rcache = NULL; /* default flags */ - fl->fl_rcache_reg_flags = MCA_RCACHE_FLAGS_CACHE_BYPASS | - MCA_RCACHE_FLAGS_CUDA_REGISTER_MEM; + fl->fl_rcache_reg_flags = MCA_RCACHE_FLAGS_CACHE_BYPASS; fl->ctx = NULL; OBJ_CONSTRUCT(&(fl->fl_allocations), opal_list_t); } @@ -63,18 +74,20 @@ static void opal_free_list_construct(opal_free_list_t* fl) static void opal_free_list_allocation_release (opal_free_list_t *fl, opal_free_list_memory_t *fl_mem) { if (NULL != fl->fl_rcache) { - fl->fl_rcache->rcache_deregister (fl->fl_rcache, fl_mem->registration); + fl->fl_rcache->rcache_deregister (fl->fl_rcache, fl_mem->super.registration); } if (NULL != fl->fl_mpool) { - fl->fl_mpool->mpool_free (fl->fl_mpool, fl_mem->ptr); - } else if (fl_mem->ptr) { - free (fl_mem->ptr); + fl->fl_mpool->mpool_free (fl->fl_mpool, fl_mem->super.ptr); + } else if (fl_mem->super.ptr) { + free (fl_mem->super.ptr); } + OPAL_THREAD_FETCH_ADD64(&opal_free_list_memory_allocated, -fl_mem->memory_size); + /* destruct the item (we constructed it), then free the memory chunk */ OBJ_DESTRUCT(fl_mem); - free(fl_mem); + mca_mpool_base_default_module->mpool_free (mca_mpool_base_default_module, fl_mem); } static void opal_free_list_destruct(opal_free_list_t *fl) @@ -204,10 +217,11 @@ int opal_free_list_grow_st (opal_free_list_t* flist, size_t num_elements, opal_f } /* calculate head allocation size */ - alloc_size = num_elements * head_size + sizeof(opal_free_list_memory_t) + + alloc_size = num_elements * head_size + sizeof (*alloc_ptr) + flist->fl_frag_alignment; - alloc_ptr = (opal_free_list_memory_t *) malloc(alloc_size); + alloc_ptr = mca_mpool_base_default_module->mpool_alloc (mca_mpool_base_default_module, alloc_size, + flist->fl_frag_alignment, 0); if (OPAL_UNLIKELY(NULL == alloc_ptr)) { return OPAL_ERR_TEMP_OUT_OF_RESOURCE; } @@ -216,7 +230,7 @@ int opal_free_list_grow_st (opal_free_list_t* flist, size_t num_elements, opal_f /* allocate the rest from the mpool (or use memalign/malloc) */ payload_ptr = (unsigned char *) flist->fl_mpool->mpool_alloc(flist->fl_mpool, buffer_size, align, 0); if (NULL == payload_ptr) { - free(alloc_ptr); + mca_mpool_base_default_module->mpool_free (mca_mpool_base_default_module, alloc_ptr); return OPAL_ERR_TEMP_OUT_OF_RESOURCE; } @@ -224,7 +238,7 @@ int opal_free_list_grow_st (opal_free_list_t* flist, size_t num_elements, opal_f rc = flist->fl_rcache->rcache_register (flist->fl_rcache, payload_ptr, num_elements * elem_size, flist->fl_rcache_reg_flags, MCA_RCACHE_ACCESS_ANY, ®); if (OPAL_UNLIKELY(OPAL_SUCCESS != rc)) { - free (alloc_ptr); + mca_mpool_base_default_module->mpool_free (mca_mpool_base_default_module, alloc_ptr); flist->fl_mpool->mpool_free (flist->fl_mpool, payload_ptr); return rc; @@ -234,11 +248,15 @@ int opal_free_list_grow_st (opal_free_list_t* flist, size_t num_elements, opal_f /* make the alloc_ptr a list item, save the chunk in the allocations list, * and have ptr point to memory right after the list item structure */ - OBJ_CONSTRUCT(alloc_ptr, opal_free_list_item_t); - opal_list_append(&(flist->fl_allocations), (opal_list_item_t*)alloc_ptr); + OBJ_CONSTRUCT(alloc_ptr, opal_free_list_memory_t); + opal_list_append(&(flist->fl_allocations), &alloc_ptr->super.super); + + OPAL_ATOMIC_FETCH_ADD64(&opal_free_list_memory_allocated, buffer_size); - alloc_ptr->registration = reg; - alloc_ptr->ptr = payload_ptr; + /* NTH: for not this tracks the total number of bytes allocated (header and buffer) */ + alloc_ptr->memory_size = buffer_size + alloc_size; + alloc_ptr->super.registration = reg; + alloc_ptr->super.ptr = payload_ptr; ptr = (unsigned char*)alloc_ptr + sizeof(opal_free_list_memory_t); ptr = OPAL_ALIGN_PTR(ptr, flist->fl_frag_alignment, unsigned char*); diff --git a/opal/class/opal_free_list.h b/opal/class/opal_free_list.h index b7fd1920219..42191c29d32 100644 --- a/opal/class/opal_free_list.h +++ b/opal/class/opal_free_list.h @@ -14,6 +14,8 @@ * Copyright (c) 2010-2015 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -370,6 +372,8 @@ static inline void opal_free_list_return (opal_free_list_t *flist, #define OPAL_FREE_LIST_RETURN(fl, item) \ opal_free_list_return (fl, item) +extern opal_atomic_int64_t opal_free_list_memory_allocated; + END_C_DECLS #endif diff --git a/opal/class/opal_object.c b/opal/class/opal_object.c index 64fef5712fc..803ef7bf484 100644 --- a/opal/class/opal_object.c +++ b/opal/class/opal_object.c @@ -12,6 +12,8 @@ * All rights reserved. * Copyright (c) 2015 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,6 +34,8 @@ #include "opal/sys/atomic.h" #include "opal/class/opal_object.h" #include "opal/constants.h" +#include "opal/mca/base/mca_base_pvar.h" +#include "opal/class/opal_free_list.h" /* * Instantiation of class descriptor for the base class. This is @@ -56,7 +60,7 @@ int opal_class_init_epoch = 1; * Local variables */ static opal_atomic_lock_t class_lock = OPAL_ATOMIC_LOCK_INIT; -static void** classes = NULL; +static opal_class_t **classes; static int num_classes = 0; static int max_classes = 0; static const int increment = 10; @@ -100,6 +104,12 @@ void opal_class_initialize(opal_class_t *cls) return; } +#if OPAL_ENABLE_DEBUG + /* set statistic counters to zero */ + cls->cls_alloc_count = 0; + cls->cls_alloc_count_high = 0; +#endif + /* * First calculate depth of class hierarchy * And the number of constructors and destructors @@ -179,11 +189,6 @@ int opal_class_finalize(void) } if (NULL != classes) { - for (i = 0; i < num_classes; ++i) { - if (NULL != classes[i]) { - free(classes[i]); - } - } free(classes); classes = NULL; num_classes = 0; @@ -200,8 +205,7 @@ static void save_class(opal_class_t *cls) expand_array(); } - classes[num_classes] = cls->cls_construct_array; - ++num_classes; + classes[num_classes++] = cls; } @@ -210,13 +214,204 @@ static void expand_array(void) int i; max_classes += increment; - classes = (void**)realloc(classes, sizeof(opal_class_t*) * max_classes); + classes = (opal_class_t **) realloc (classes, sizeof (opal_class_t *) * max_classes); if (NULL == classes) { perror("class malloc failed"); exit(-1); } - for (i = num_classes; i < max_classes; ++i) { - classes[i] = NULL; +} + +#if OPAL_ENABLE_DEBUG +static int class_enum_get_count (mca_base_var_enum_t *enumerator, int *count) +{ + *count = num_classes; + return OPAL_SUCCESS; +} + +static int class_enum_get_value (mca_base_var_enum_t *self, int index, int *value, const char **string_value) +{ + if (index >= num_classes) { + return OPAL_ERR_VALUE_OUT_OF_BOUNDS; + } + + *value = index; + *string_value = classes[index]->cls_name; + return OPAL_SUCCESS; +} + +static int class_enum_value_from_string (mca_base_var_enum_t *self, const char *string_value, int *value) +{ + const int class_count = num_classes; + + for (int i = 0 ; i < class_count ; ++i) { + if (0 == strcmp (string_value, classes[i]->cls_name)) { + *value = i; + return OPAL_SUCCESS; + } + } + + return OPAL_ERR_VALUE_OUT_OF_BOUNDS; +} + +static int class_enum_string_from_value (mca_base_var_enum_t *self, const int value, char **string_value) +{ + const int class_count = num_classes; + + if (value >= num_classes || value < 0) { + return OPAL_ERR_VALUE_OUT_OF_BOUNDS; + } + + *string_value = strdup (classes[value]->cls_name); + return (NULL != *string_value) ? OPAL_SUCCESS : OPAL_ERR_OUT_OF_RESOURCE; +} + +static int class_enum_dump (mca_base_var_enum_t *self, char **out) +{ + /* not really needed as this isn't a real enumerator */ + return OPAL_ERR_NOT_SUPPORTED; +} + +mca_base_var_enum_t opal_object_class_enum = { + .super = OPAL_OBJ_STATIC_INIT(opal_object_t), + .enum_is_static = true, + .enum_name = "opal_classes", + .get_count = class_enum_get_count, + .get_value = class_enum_get_value, + .value_from_string = class_enum_value_from_string, + .string_from_value = class_enum_string_from_value, + .dump = class_enum_dump, +}; + +static int opal_object_get_alloc_count (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj) +{ + const int class_count = pvar_handle->count; + size_t *values = (size_t *) value; + + for (int i = 0 ; i < class_count ; ++i) { + values[i] = classes[i]->cls_alloc_count; + } + + return OPAL_SUCCESS; +} + +static int opal_object_get_alloc_count_high (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj) +{ + const int class_count = pvar_handle->count; + size_t *values = (size_t *) value; + + for (int i = 0 ; i < class_count ; ++i) { + values[i] = classes[i]->cls_alloc_count_high; + } + + return OPAL_SUCCESS; +} + +static int opal_object_class_get_size (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj) +{ + const int class_count = pvar_handle->count; + size_t *values = (size_t *) value; + + for (int i = 0 ; i < class_count ; ++i) { + values[i] = classes[i]->cls_sizeof; } + + return OPAL_SUCCESS; } +static int opal_object_class_get_total_size (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj) +{ + const int class_count = num_classes; + size_t *total_size = (size_t *) value; + + *total_size = 0; + + for (int i = 0 ; i < class_count ; ++i) { + *total_size += classes[i]->cls_sizeof * classes[i]->cls_alloc_count; + } + + return OPAL_SUCCESS; +} + +static int opal_object_class_get_total_size_high (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj) +{ + const int class_count = pvar_handle->count; + size_t *total_size = (size_t *) value; + + *total_size = 0; + + for (int i = 0 ; i < class_count ; ++i) { + *total_size += classes[i]->cls_sizeof * classes[i]->cls_alloc_count_high; + } + + return OPAL_SUCCESS; +} + +static int opal_object_pvar_notify (struct mca_base_pvar_t *pvar, mca_base_pvar_event_t event, void *obj, int *count) +{ + if (count) { + *count = num_classes; + } + + return OPAL_SUCCESS; +} + +static int opal_object_pvar_enum_read (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *bound_obj) +{ + int *array = (int *) value; + + for (int i = 0 ; i < pvar_handle->count ; ++i) { + array[i] = i; + } + + return OPAL_SUCCESS; +} +#endif + +void opal_object_register_variables (void) +{ +#if OPAL_ENABLE_DEBUG + mca_base_pvar_register ("opal", "opal", "class", "names", "Enumerator providing the type names of each OPAL object " + "class. The ordering of classes will not change during a run but may change after " + "finalize and re-init if using MPI_T or MPI instances", OPAL_INFO_LVL_9, MCA_BASE_PVAR_CLASS_STATE, + MCA_BASE_VAR_TYPE_INT, &opal_object_class_enum, MCA_BASE_VAR_BIND_NO_OBJECT, + MCA_BASE_PVAR_FLAG_READONLY | MCA_BASE_PVAR_FLAG_CONTINUOUS, opal_object_pvar_enum_read, NULL, + opal_object_pvar_notify, NULL); + + /* pvars primarily intended for internal use */ + mca_base_pvar_register ("opal", "opal", "class", "counter", "Counters for each class instantiated by " + "the OPAL object system. The count returned when creating a handle is the current " + "number of OPAL object classes currently in use. This number may increase but will " + "not decrease.", OPAL_INFO_LVL_9, MCA_BASE_PVAR_CLASS_SIZE, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + opal_object_get_alloc_count, NULL, opal_object_pvar_notify, NULL); + + mca_base_pvar_register ("opal", "opal", "class", "counter_high", "High-watermark for counters for each class instantiated by " + "the OPAL object system. The count returned when creating a handle is the current " + "number of OPAL object classes currently in use. This number may increase but will " + "not decrease.", OPAL_INFO_LVL_9, MCA_BASE_PVAR_CLASS_HIGHWATERMARK, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + opal_object_get_alloc_count_high, NULL, opal_object_pvar_notify, NULL); + + mca_base_pvar_register ("opal", "opal", "class", "object_size", "Size of objects of this class. Can be used in " + "conjuction with the count to find the total number of bytes used by all objects of " + "this class", OPAL_INFO_LVL_9, MCA_BASE_PVAR_CLASS_SIZE, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + opal_object_class_get_size, NULL, opal_object_pvar_notify, NULL); + + /* more general pvars for users */ + mca_base_pvar_register ("opal", "opal", "class", "total_size", "Total memory allocated to OPAL objects of all classes.", + OPAL_INFO_LVL_5, MCA_BASE_PVAR_CLASS_SIZE, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + opal_object_class_get_total_size, NULL, NULL, NULL); + + mca_base_pvar_register ("opal", "opal", "class", "total_size_high", "High watermark of total memory allocated to OPAL objects of all classes.", + OPAL_INFO_LVL_5, MCA_BASE_PVAR_CLASS_HIGHWATERMARK, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + opal_object_class_get_total_size_high, NULL, NULL, NULL); + + mca_base_pvar_register ("opal", "opal", "free_list", "total_size", "Total memory allocated for OPAL buffers", + OPAL_INFO_LVL_5, MCA_BASE_PVAR_CLASS_SIZE, MCA_BASE_VAR_TYPE_SIZE_T, NULL, + MCA_BASE_VAR_BIND_NO_OBJECT, MCA_BASE_PVAR_FLAG_CONTINUOUS | MCA_BASE_PVAR_FLAG_READONLY, + NULL, NULL, NULL, (void *) &opal_free_list_memory_allocated); +#endif +} diff --git a/opal/class/opal_object.h b/opal/class/opal_object.h index 4d3380f0da0..c37ce56a491 100644 --- a/opal/class/opal_object.h +++ b/opal/class/opal_object.h @@ -15,6 +15,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2015 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * Additional copyrights may follow * $HEADER$ @@ -160,6 +162,10 @@ struct opal_class_t { opal_destruct_t *cls_destruct_array; /**< array of parent class destructors */ size_t cls_sizeof; /**< size of an object instance */ +#if OPAL_ENABLE_DEBUG + opal_atomic_size_t cls_alloc_count; /**< number of objects of this type allocated using OBJ_NEW() */ + opal_atomic_size_t cls_alloc_count_high; /**< highest number of objects of this type allocated at any time */ +#endif }; extern int opal_class_init_epoch; @@ -327,6 +333,7 @@ static inline opal_object_t *opal_obj_new_debug(opal_class_t* type, const char* assert(OPAL_OBJ_MAGIC_ID == ((opal_object_t *) (object))->obj_magic_id); \ assert(NULL != ((opal_object_t *) (object))->obj_class); \ if (0 == opal_obj_update((opal_object_t *) (object), -1)) { \ + OPAL_THREAD_ADD_FETCH_SIZE_T(&((opal_object_t *) (object))->obj_class->cls_alloc_count, -1); \ OBJ_SET_MAGIC_ID((object), 0); \ opal_obj_run_destructors((opal_object_t *) (object)); \ OBJ_REMEMBER_FILE_AND_LINENO( object, __FILE__, __LINE__ ); \ @@ -489,6 +496,12 @@ static inline opal_object_t *opal_obj_new(opal_class_t * cls) opal_class_initialize(cls); } if (NULL != object) { +#if OPAL_ENABLE_DEBUG + size_t count = OPAL_THREAD_ADD_FETCH_SIZE_T(&cls->cls_alloc_count, 1); + if (count > cls->cls_alloc_count_high) { + (void) opal_atomic_max_fetch_size_t (&cls->cls_alloc_count_high, count); + } +#endif object->obj_class = cls; object->obj_reference_count = 1; opal_obj_run_constructors(object); @@ -513,6 +526,11 @@ static inline int opal_obj_update(opal_object_t *object, int inc) return OPAL_THREAD_ADD_FETCH32(&object->obj_reference_count, inc); } +/** + * @brief Register performance variables exposed by the OPAL class system + */ +OPAL_DECLSPEC void opal_object_register_variables (void); + END_C_DECLS #endif diff --git a/opal/include/opal/sys/atomic.h b/opal/include/opal/sys/atomic.h index cf0115622ec..b33fd4051ee 100644 --- a/opal/include/opal/sys/atomic.h +++ b/opal/include/opal/sys/atomic.h @@ -513,17 +513,45 @@ opal_atomic_fetch_sub_size_t(opal_atomic_size_t *addr, size_t delta) #endif } +static inline size_t +opal_atomic_fetch_max_size_t(opal_atomic_size_t *addr, size_t value) +{ +#if SIZEOF_SIZE_T == 4 + return (size_t) opal_atomic_fetch_max_32((int32_t*) addr, value); +#elif SIZEOF_SIZE_T == 8 + return (size_t) opal_atomic_fetch_max_64((int64_t*) addr, value); +#else +#error "Unknown size_t size" +#endif +} + +static inline size_t +opal_atomic_max_fetch_size_t(opal_atomic_size_t *addr, size_t value) +{ +#if SIZEOF_SIZE_T == 4 + return (size_t) opal_atomic_max_fetch_32((int32_t*) addr, value); +#elif SIZEOF_SIZE_T == 8 + return (size_t) opal_atomic_max_fetch_64((int64_t*) addr, value); +#else +#error "Unknown size_t size" +#endif +} + #else #if SIZEOF_SIZE_T == 4 #define opal_atomic_add_fetch_size_t(addr, delta) ((size_t) opal_atomic_add_fetch_32((opal_atomic_int32_t *) addr, delta)) #define opal_atomic_fetch_add_size_t(addr, delta) ((size_t) opal_atomic_fetch_add_32((opal_atomic_int32_t *) addr, delta)) #define opal_atomic_sub_fetch_size_t(addr, delta) ((size_t) opal_atomic_sub_fetch_32((opal_atomic_int32_t *) addr, delta)) #define opal_atomic_fetch_sub_size_t(addr, delta) ((size_t) opal_atomic_fetch_sub_32((opal_atomic_int32_t *) addr, delta)) +#define opal_atomic_fetch_max_size_t(addr, value) ((size_t) opal_atomic_fetch_max_32((opal_atomic_int32_t *) addr, value)) +#define opal_atomic_max_fetch_size_t(addr, value) ((size_t) opal_atomic_max_fetch_32((opal_atomic_int32_t *) addr, value)) #elif SIZEOF_SIZE_T == 8 #define opal_atomic_add_fetch_size_t(addr, delta) ((size_t) opal_atomic_add_fetch_64((opal_atomic_int64_t *) addr, delta)) #define opal_atomic_fetch_add_size_t(addr, delta) ((size_t) opal_atomic_fetch_add_64((opal_atomic_int64_t *) addr, delta)) #define opal_atomic_sub_fetch_size_t(addr, delta) ((size_t) opal_atomic_sub_fetch_64((opal_atomic_int64_t *) addr, delta)) #define opal_atomic_fetch_sub_size_t(addr, delta) ((size_t) opal_atomic_fetch_sub_64((opal_atomic_int64_t *) addr, delta)) +#define opal_atomic_fetch_max_size_t(addr, value) ((size_t) opal_atomic_fetch_max_64((opal_atomic_int64_t *) addr, value)) +#define opal_atomic_max_fetch_size_t(addr, value) ((size_t) opal_atomic_max_fetch_64((opal_atomic_int64_t *) addr, value)) #else #error "Unknown size_t size" #endif diff --git a/opal/include/opal/sys/atomic_stdc.h b/opal/include/opal/sys/atomic_stdc.h index c5307bb9da6..5edbeb15609 100644 --- a/opal/include/opal/sys/atomic_stdc.h +++ b/opal/include/opal/sys/atomic_stdc.h @@ -173,6 +173,17 @@ static inline int64_t opal_atomic_fetch_max_64 (opal_atomic_int64_t *addr, int64 return old; } +static inline size_t opal_atomic_fetch_max_size_t (opal_atomic_size_t *addr, size_t value) +{ +#if SIZEOF_SIZE_T == 4 + return opal_atomic_fetch_max_32 ((opal_atomic_int32_t *)addr, value); +#elif SIZEOF_SIZE_T == 8 + return opal_atomic_fetch_max_64 ((opal_atomic_int64_t *) addr, value); +#else +#error "Unknown size_t size" +#endif +} + static inline int32_t opal_atomic_min_fetch_32 (opal_atomic_int32_t *addr, int32_t value) { int32_t old = opal_atomic_fetch_min_32 (addr, value); @@ -197,6 +208,12 @@ static inline int64_t opal_atomic_max_fetch_64 (opal_atomic_int64_t *addr, int64 return old >= value ? old : value; } +static inline size_t opal_atomic_max_fetch_size_t (opal_atomic_size_t *addr, size_t value) +{ + size_t old = opal_atomic_fetch_max_size_t (addr, value); + return old >= value ? old : value; +} + #define OPAL_ATOMIC_LOCK_UNLOCKED false #define OPAL_ATOMIC_LOCK_LOCKED true diff --git a/opal/mca/base/mca_base_pvar.c b/opal/mca/base/mca_base_pvar.c index 0efe919d130..c08aea4e961 100644 --- a/opal/mca/base/mca_base_pvar.c +++ b/opal/mca/base/mca_base_pvar.c @@ -9,6 +9,8 @@ * reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -146,8 +148,10 @@ int mca_base_pvar_get_count (int *count) return OPAL_SUCCESS; } -static int mca_base_pvar_default_get_value (const mca_base_pvar_t *pvar, void *value, void *obj_handle) +static int mca_base_pvar_default_get_value (const mca_base_pvar_handle_t *pvar_handle, void *value, void *obj_handle) { + const mca_base_pvar_t *pvar = pvar_handle->pvar; + /* not used */ (void) obj_handle; @@ -156,8 +160,10 @@ static int mca_base_pvar_default_get_value (const mca_base_pvar_t *pvar, void *v return OPAL_SUCCESS; } -static int mca_base_pvar_default_set_value (mca_base_pvar_t *pvar, const void *value, void *obj_handle) +static int mca_base_pvar_default_set_value (mca_base_pvar_handle_t *pvar_handle, const void *value, void *obj_handle) { + mca_base_pvar_t *pvar = pvar_handle->pvar; + /* not used */ (void) obj_handle; @@ -222,6 +228,7 @@ int mca_base_pvar_register (const char *project, const char *framework, const ch if (MCA_BASE_VAR_TYPE_UNSIGNED_INT != type && MCA_BASE_VAR_TYPE_UNSIGNED_LONG != type && MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG != type && + MCA_BASE_VAR_TYPE_SIZE_T != type && MCA_BASE_VAR_TYPE_DOUBLE != type) { return OPAL_ERR_BAD_PARAM; } @@ -516,10 +523,10 @@ int mca_base_pvar_handle_alloc (mca_base_pvar_session_t *session, int index, voi current value is not relevant. */ if (mca_base_pvar_is_continuous (pvar)) { if (mca_base_pvar_is_sum (pvar)) { - ret = pvar->get_value (pvar, pvar_handle->last_value, pvar_handle->obj_handle); + ret = pvar->get_value (pvar_handle, pvar_handle->last_value, pvar_handle->obj_handle); } else { /* the initial value of a watermark is the current value of the variable */ - ret = pvar->get_value (pvar, pvar_handle->current_value, pvar_handle->obj_handle); + ret = pvar->get_value (pvar_handle, pvar_handle->current_value, pvar_handle->obj_handle); } if (OPAL_SUCCESS != ret) { @@ -570,7 +577,7 @@ int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle) } if (mca_base_pvar_is_sum (handle->pvar) || mca_base_pvar_is_watermark (handle->pvar)) { - ret = handle->pvar->get_value (handle->pvar, handle->tmp_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->tmp_value, handle->obj_handle); if (OPAL_SUCCESS != ret) { return OPAL_ERROR; } @@ -596,6 +603,10 @@ int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle) ((double *) handle->current_value)[i] += ((double *) handle->tmp_value)[i] - ((double *) handle->last_value)[i]; break; + case MCA_BASE_VAR_TYPE_SIZE_T: + ((size_t *) handle->current_value)[i] += ((size_t *) handle->tmp_value)[i] - + ((size_t *) handle->last_value)[i]; + break; default: /* shouldn't happen */ break; @@ -625,6 +636,10 @@ int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle) ((double *) handle->current_value)[i] = min(((double *) handle->tmp_value)[i], ((double *) handle->current_value)[i]); break; + case MCA_BASE_VAR_TYPE_SIZE_T: + ((size_t *) handle->current_value)[i] = min(((size_t *) handle->tmp_value)[i], + ((size_t *) handle->current_value)[i]); + break; default: /* shouldn't happen */ break; @@ -647,6 +662,10 @@ int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle) ((double *) handle->current_value)[i] = max(((double *) handle->tmp_value)[i], ((double *) handle->current_value)[i]); break; + case MCA_BASE_VAR_TYPE_SIZE_T: + ((size_t *) handle->current_value)[i] = max(((size_t *) handle->tmp_value)[i], + ((size_t *) handle->current_value)[i]); + break; default: /* shouldn't happen */ break; @@ -656,7 +675,7 @@ int mca_base_pvar_handle_update (mca_base_pvar_handle_t *handle) } } else if (!mca_base_pvar_is_continuous (handle->pvar)) { /* cache the current value */ - ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->current_value, handle->obj_handle); if (OPAL_SUCCESS != ret) { return ret; } @@ -687,7 +706,7 @@ int mca_base_pvar_handle_read_value (mca_base_pvar_handle_t *handle, void *value memmove (value, handle->current_value, handle->count * ompi_var_type_sizes[handle->pvar->type]); } else { /* read the value directly from the variable. */ - ret = handle->pvar->get_value (handle->pvar, value, handle->obj_handle); + ret = handle->pvar->get_value (handle, value, handle->obj_handle); } return ret; @@ -706,7 +725,7 @@ int mca_base_pvar_handle_write_value (mca_base_pvar_handle_t *handle, const void } /* write the value directly from the variable. */ - ret = handle->pvar->set_value (handle->pvar, value, handle->obj_handle); + ret = handle->pvar->set_value (handle, value, handle->obj_handle); ret = mca_base_pvar_handle_update (handle); if (OPAL_SUCCESS != ret) { @@ -715,7 +734,7 @@ int mca_base_pvar_handle_write_value (mca_base_pvar_handle_t *handle, const void memmove (handle->current_value, value, handle->count * ompi_var_type_sizes[handle->pvar->type]); /* read the value directly from the variable. */ - ret = handle->pvar->set_value (handle->pvar, value, handle->obj_handle); + ret = handle->pvar->set_value (handle, value, handle->obj_handle); return OPAL_SUCCESS; } @@ -740,14 +759,14 @@ int mca_base_pvar_handle_start (mca_base_pvar_handle_t *handle) if (mca_base_pvar_is_sum (handle->pvar)) { /* Keep track of the counter value from when this counter started. */ - ret = handle->pvar->get_value (handle->pvar, handle->last_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->last_value, handle->obj_handle); if (OPAL_SUCCESS != ret) { return ret; } } else if (mca_base_pvar_is_watermark (handle->pvar)) { /* Find the current watermark. is this correct in the case where a watermark is started, stopped, then restarted? Probably will need to add a check. */ - ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->current_value, handle->obj_handle); if (OPAL_SUCCESS != ret) { return ret; } @@ -797,12 +816,12 @@ int mca_base_pvar_handle_reset (mca_base_pvar_handle_t *handle) memset (handle->current_value, 0, handle->count * ompi_var_type_sizes[handle->pvar->type]); if (mca_base_pvar_handle_is_running (handle)) { - ret = handle->pvar->get_value (handle->pvar, handle->last_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->last_value, handle->obj_handle); } } else if (mca_base_pvar_handle_is_running (handle) && mca_base_pvar_is_watermark (handle->pvar)) { /* watermarks should get set to the current value if runnning. */ - ret = handle->pvar->get_value (handle->pvar, handle->current_value, handle->obj_handle); + ret = handle->pvar->get_value (handle, handle->current_value, handle->obj_handle); } else if (mca_base_pvar_is_readonly (handle->pvar)) { return OPAL_ERR_PERM; } diff --git a/opal/mca/base/mca_base_pvar.h b/opal/mca/base/mca_base_pvar.h index 03ff53b98f8..f6f5a106d95 100644 --- a/opal/mca/base/mca_base_pvar.h +++ b/opal/mca/base/mca_base_pvar.h @@ -116,33 +116,38 @@ enum { }; struct mca_base_pvar_t; +struct mca_base_pvar_handle_t; /** * Function to retrieve the current value of a variable. * - * @param[in] pvar Performance variable to get the value of. + * @param[in] pvar Performance variable handle to get the value of. * @param[out] value Current value of the variable. * @param[in] obj Bound object * * This function will be called to get the current value of a variable. The value * pointer will be large enough to hold the datatype and count specified when this - * variable was created and bound. + * variable was created and bound. This function has been updated to take the pvar + * handle instead of the pvar. This allows the function to check the count returned + * when the handle was bound. */ -typedef int (*mca_base_get_value_fn_t) (const struct mca_base_pvar_t *pvar, void *value, void *obj); +typedef int (*mca_base_get_value_fn_t) (const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *obj); /** * Function to set the current value of a variable. * - * @param[in] pvar Performance variable to set the value of. + * @param[in] pvar Performance variable handle to set the value of. * @param[in] value Value to write. * @param[in] obj Bound object. * * This function will be called to set the current value of a variable. The value * pointer will be large enough to hold the datatype and count specified when this * variable was created and bound. Read-only variables are not expected to provide - * this function. + * this function. This function has been updated to take the pvar handle instead of + * the pvar. This allows the function to check the count returned when the handle was + * bound. */ -typedef int (*mca_base_set_value_fn_t) (struct mca_base_pvar_t *pvar, const void *value, void *obj); +typedef int (*mca_base_set_value_fn_t) (struct mca_base_pvar_handle_t *pvar_handle, const void *value, void *obj); /** * Function to notify of a pvar handle event. diff --git a/opal/mca/btl/usnic/btl_usnic_stats.c b/opal/mca/btl/usnic/btl_usnic_stats.c index ae2a816b5c4..5b63f82805f 100644 --- a/opal/mca/btl/usnic/btl_usnic_stats.c +++ b/opal/mca/btl/usnic/btl_usnic_stats.c @@ -279,10 +279,10 @@ static int usnic_pvar_notify(struct mca_base_pvar_t *pvar, * Function called by the pvar base when a user wants to read the * value of an MPI_T performance variable. */ -static int usnic_pvar_read(const struct mca_base_pvar_t *pvar, +static int usnic_pvar_read(const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *bound_obj) { - size_t offset = (size_t) pvar->ctx; + size_t offset = (size_t) pvar_handler->pvar->ctx; uint64_t *array = (uint64_t*) value; for (int i = 0; i < mca_btl_usnic_component.num_modules; ++i) { @@ -324,7 +324,7 @@ static void register_pvar_highwater(char *name, char *desc, size_t offset) * which will map to the strings in the devices_enum * setup_mpit_pvar_type(). */ -static int usnic_pvar_enum_read(const struct mca_base_pvar_t *pvar, +static int usnic_pvar_enum_read(const struct mca_base_pvar_handle_t *pvar_handle, void *value, void *bound_obj) { int *array = (int *) value; diff --git a/opal/runtime/opal_params.c b/opal/runtime/opal_params.c index 2897b64737f..cb1e68f9550 100644 --- a/opal/runtime/opal_params.c +++ b/opal/runtime/opal_params.c @@ -23,6 +23,8 @@ * All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. + * Copyright (c) 2019 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -387,6 +389,8 @@ int opal_register_params(void) return ret; } + opal_object_register_variables (); + opal_finalize_register_cleanup (opal_deregister_params); return OPAL_SUCCESS;