diff --git a/benchmark/benchmark_umf.hpp b/benchmark/benchmark_umf.hpp index 4b88dabd0..d2d41b84b 100644 --- a/benchmark/benchmark_umf.hpp +++ b/benchmark/benchmark_umf.hpp @@ -45,8 +45,8 @@ struct provider_interface { if (state.thread_index() != 0) { return; } - umfCtlExec("umf.provider.by_handle.stats.peak_memory.reset", provider, - NULL, 0); + umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, 0, + provider); } void postBench([[maybe_unused]] ::benchmark::State &state) { @@ -55,8 +55,8 @@ struct provider_interface { } size_t arg; umf_result_t ret = - umfCtlGet("umf.provider.by_handle.stats.allocated_memory", provider, - &arg, sizeof(arg)); + umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", &arg, + sizeof(arg), provider); if (ret == UMF_RESULT_SUCCESS) { state.counters["provider_memory_allocated"] = static_cast(arg); diff --git a/include/umf/base.h b/include/umf/base.h index b5415c8aa..f7cd9de63 100644 --- a/include/umf/base.h +++ b/include/umf/base.h @@ -56,11 +56,16 @@ typedef enum umf_ctl_query_type { CTL_QUERY_READ, CTL_QUERY_WRITE, CTL_QUERY_RUNNABLE, - CTL_QUERY_SUBTREE, - - MAX_CTL_QUERY_TYPE } umf_ctl_query_type_t; +typedef enum ctl_query_source { + CTL_UNKNOWN_QUERY_SOURCE, + /* query executed directly from the program */ + CTL_QUERY_PROGRAMMATIC, + /* query executed from the config file */ + CTL_QUERY_CONFIG_INPUT +} umf_ctl_query_source_t; + #ifdef __cplusplus } #endif diff --git a/include/umf/experimental/ctl.h b/include/umf/experimental/ctl.h index 345446762..6af353234 100644 --- a/include/umf/experimental/ctl.h +++ b/include/umf/experimental/ctl.h @@ -19,32 +19,32 @@ extern "C" { /// /// @brief Get value of a specified attribute at the given name. /// @param name name of an attribute to be retrieved -/// @param ctx pointer to the pool or the provider /// @param arg [out] pointer to the variable where the value will be stored /// @param size size of the value, depends on the context +/// @param ... additional arguments that can be passed to the callback /// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure. /// -umf_result_t umfCtlGet(const char *name, void *ctx, void *arg, size_t size); +umf_result_t umfCtlGet(const char *name, void *arg, size_t size, ...); /// /// @brief Set value of a specified attribute at the given name. /// @param name name of an attribute to be set -/// @param ctx pointer to the pool or the provider, NULL for the 'default' path /// @param arg [in] pointer to the value that will be set /// @param size [in] size of the value, depends on the context +/// @param ... additional arguments that can be passed to the callback /// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure. /// -umf_result_t umfCtlSet(const char *name, void *ctx, void *arg, size_t size); +umf_result_t umfCtlSet(const char *name, void *arg, size_t size, ...); /// /// @brief Execute callback related with the specified attribute. /// @param name name of an attribute to be executed -/// @param ctx pointer to the pool or the provider /// @param arg [in/out] pointer to the value, can be used as an input or output /// @param size [in] size of the value, depends on the context +/// @param ... additional arguments that can be passed to the callback /// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure. /// -umf_result_t umfCtlExec(const char *name, void *ctx, void *arg, size_t size); +umf_result_t umfCtlExec(const char *name, void *arg, size_t size, ...); #ifdef __cplusplus } diff --git a/include/umf/memory_pool_ops.h b/include/umf/memory_pool_ops.h index e63b7aea1..e6d6736fe 100644 --- a/include/umf/memory_pool_ops.h +++ b/include/umf/memory_pool_ops.h @@ -10,6 +10,8 @@ #ifndef UMF_MEMORY_POOL_OPS_H #define UMF_MEMORY_POOL_OPS_H 1 +#include + #include #include @@ -153,17 +155,18 @@ typedef struct umf_memory_pool_ops_t { /// on the memory pool. /// /// @param pool handle to the memory pool. - /// @param operationType type of the operation to be performed. + /// @param source source of the ctl operation. /// @param name name associated with the operation. /// @param arg argument for the operation. /// @param size size of the argument [optional - check name requirements] /// @param queryType type of the query to be performed. + /// @param args variable arguments for the operation. /// /// @return umf_result_t result of the control operation. /// - umf_result_t (*ext_ctl)(void *hPool, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t queryType); + umf_result_t (*ext_ctl)(void *hPool, umf_ctl_query_source_t source, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t queryType, va_list args); } umf_memory_pool_ops_t; diff --git a/include/umf/memory_provider_ops.h b/include/umf/memory_provider_ops.h index 13793124d..16e1536fd 100644 --- a/include/umf/memory_provider_ops.h +++ b/include/umf/memory_provider_ops.h @@ -10,6 +10,8 @@ #ifndef UMF_MEMORY_PROVIDER_OPS_H #define UMF_MEMORY_PROVIDER_OPS_H 1 +#include + #include #ifdef __cplusplus @@ -263,17 +265,18 @@ typedef struct umf_memory_provider_ops_t { /// Backward compatibility is not guaranteed. /// /// @param provider handle to the memory provider. - /// @param operationType type of the operation to be performed. + /// @param source source of the ctl operation. /// @param name name associated with the operation. /// @param arg argument for the operation. /// @param size size of the argument [optional - check name requirements] /// @param queryType type of the query to be performed. + /// @param args variable arguments for the operation. /// /// @return umf_result_t result of the control operation. /// - umf_result_t (*ext_ctl)(void *provider, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t queryType); + umf_result_t (*ext_ctl)(void *provider, umf_ctl_query_source_t source, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t queryType, va_list args); } umf_memory_provider_ops_t; diff --git a/src/ctl/ctl.c b/src/ctl/ctl.c index d9682535c..b1e9de9d8 100644 --- a/src/ctl/ctl.c +++ b/src/ctl/ctl.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include "base_alloc/base_alloc_global.h" #include "ctl_internal.h" #include "utils/utils_common.h" +#include "utils_log.h" #include "utlist.h" #ifdef _WIN32 @@ -41,11 +43,17 @@ #define CTL_NAME_VALUE_SEPARATOR "=" #define CTL_QUERY_NODE_SEPARATOR "." #define CTL_VALUE_ARG_SEPARATOR "," +#define CTL_WILDCARD "{}" /* GLOBAL TREE */ static int ctl_global_first_free = 0; static umf_ctl_node_t CTL_NODE(global)[CTL_MAX_ENTRIES]; +typedef struct optional_umf_result_t { + bool is_valid; + umf_result_t value; +} optional_umf_result_t; + void *Zalloc(size_t sz) { void *ptr = umf_ba_global_alloc(sz); if (ptr) { @@ -63,95 +71,42 @@ char *Strdup(const char *s) { return p; } -/* - * ctl_find_node -- (internal) searches for a matching entry point in the - * provided nodes - * - * Name offset is used to return the offset of the name in the query string. - * The caller is responsible for freeing all of the allocated indexes, - * regardless of the return value. - */ -static const umf_ctl_node_t *ctl_find_node(const umf_ctl_node_t *nodes, - const char *name, - umf_ctl_index_utlist_t *indexes, - size_t *name_offset) { - assert(nodes != NULL); - assert(name != NULL); - assert(name_offset != NULL); - const umf_ctl_node_t *n = NULL; - char *sptr = NULL; - char *parse_str = Strdup(name); - if (parse_str == NULL) { - return NULL; - } - - char *node_name = strtok_r(parse_str, CTL_QUERY_NODE_SEPARATOR, &sptr); - - /* - * Go through the string and separate tokens that correspond to nodes - * in the main ctl tree. - */ - while (node_name != NULL) { - char *next_node = strtok_r(NULL, CTL_QUERY_NODE_SEPARATOR, &sptr); - *name_offset = node_name - parse_str; - if (n != NULL && n->type == CTL_NODE_SUBTREE) { - // if a subtree occurs, the subtree handler should be called - break; - } - char *endptr; - /* - * Ignore errno from strtol: FreeBSD returns EINVAL if no - * conversion is performed. Linux does not, but endptr - * check is valid in both cases. - */ - int tmp_errno = errno; - long index_value = strtol(node_name, &endptr, 0); - errno = tmp_errno; - umf_ctl_index_utlist_t *index_entry = NULL; - if (endptr != node_name) { /* a valid index */ - index_entry = umf_ba_global_alloc(sizeof(*index_entry)); - if (index_entry == NULL) { - goto error; - } - index_entry->value = index_value; - LL_PREPEND(indexes, index_entry); - } - - for (n = &nodes[0]; n->name != NULL; ++n) { - if (index_entry && n->type == CTL_NODE_INDEXED) { - break; - } else if (strcmp(n->name, node_name) == 0) { - if (n->type == CTL_NODE_LEAF && next_node != NULL) { - // this is not the last node in the query, so it couldn't be leaf - continue; - } - if (n->type != CTL_NODE_LEAF && next_node == NULL) { - // this is the last node in the query, so it must be a leaf - continue; - } - break; - } - } - - if (n->name == NULL) { - goto error; - } - - if (index_entry) { - index_entry->name = n->name; - } - - nodes = n->children; - node_name = next_node; - } - - umf_ba_global_free(parse_str); - return n; - -error: - umf_ba_global_free(parse_str); - return NULL; -} +// this must be a macro as passing a va_list to a function makes the va_list +// in the original function indeterminate if the function invokes the va_arg macro. +// Ref 7.15/3 of C99 standard +#define pop_va_list(va, ctl_argument, output) \ + do { \ + switch (ctl_argument->type) { \ + case CTL_ARG_TYPE_BOOLEAN: { \ + int b = va_arg(va, int); \ + *(bool *)output = b ? true : false; \ + break; \ + } \ + case CTL_ARG_TYPE_STRING: { \ + char *str = va_arg(va, char *); \ + memcpy(output, str, ctl_argument->dest_size); \ + break; \ + } \ + case CTL_ARG_TYPE_INT: { \ + int i = va_arg(va, int); \ + *(int *)output = i; \ + break; \ + } \ + case CTL_ARG_TYPE_LONG_LONG: { \ + long long ll = va_arg(va, long long); \ + *(long long *)output = ll; \ + break; \ + } \ + case CTL_ARG_TYPE_PTR: { \ + void *p = va_arg(va, void *); \ + *(uintptr_t *)output = (uintptr_t)p; \ + break; \ + } \ + default: \ + LOG_FATAL("Unknown ctl argument type %d", ctl_argument->type); \ + abort(); \ + } \ + } while (false) /* * ctl_delete_indexes -- @@ -165,11 +120,34 @@ static void ctl_delete_indexes(umf_ctl_index_utlist_t *indexes) { LL_FOREACH_SAFE(indexes, elem, tmp) { LL_DELETE(indexes, elem); if (elem) { + if (elem->arg) { + umf_ba_global_free(elem->arg); + } umf_ba_global_free(elem); } } } +/* + * ctl_query_cleanup_real_args -- (internal) cleanups relevant argument + * structures allocated as a result of the get_real_args call + */ +static void ctl_query_cleanup_real_args(const umf_ctl_node_t *n, void *real_arg, + umf_ctl_query_source_t source) { + /* suppress unused-parameter errors */ + (void)n; + + switch (source) { + case CTL_QUERY_CONFIG_INPUT: + umf_ba_global_free(real_arg); + break; + case CTL_QUERY_PROGRAMMATIC: + break; + default: + break; + } +} + /* * ctl_parse_args -- (internal) parses a string argument based on the node * structure @@ -223,45 +201,24 @@ static void *ctl_query_get_real_args(const umf_ctl_node_t *n, void *write_arg, return real_arg; } -/* - * ctl_query_cleanup_real_args -- (internal) cleanups relevant argument - * structures allocated as a result of the get_real_args call - */ -static void ctl_query_cleanup_real_args(const umf_ctl_node_t *n, void *real_arg, - umf_ctl_query_source_t source) { - /* suppress unused-parameter errors */ - (void)n; - - switch (source) { - case CTL_QUERY_CONFIG_INPUT: - umf_ba_global_free(real_arg); - break; - case CTL_QUERY_PROGRAMMATIC: - break; - default: - break; - } -} - /* * ctl_exec_query_read -- (internal) calls the read callback of a node */ static umf_result_t ctl_exec_query_read(void *ctx, const umf_ctl_node_t *n, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { - (void)query_type; + umf_ctl_index_utlist_t *indexes) { assert(n != NULL); - assert(n->cb[CTL_QUERY_READ] != NULL); - assert(MAX_CTL_QUERY_TYPE != query_type); + + if (n->read_cb == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } if (arg == NULL) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - return n->cb[CTL_QUERY_READ](ctx, source, arg, size, indexes, extra_name, - MAX_CTL_QUERY_TYPE); + + return n->read_cb(ctx, source, arg, size, indexes); } /* @@ -270,13 +227,12 @@ static umf_result_t ctl_exec_query_read(void *ctx, const umf_ctl_node_t *n, static umf_result_t ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { - (void)query_type; + umf_ctl_index_utlist_t *indexes) { assert(n != NULL); - assert(n->cb[CTL_QUERY_WRITE] != NULL); - assert(MAX_CTL_QUERY_TYPE != query_type); + + if (n->write_cb == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } if (arg == NULL) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; @@ -287,8 +243,7 @@ static umf_result_t ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - umf_result_t ret = n->cb[CTL_QUERY_WRITE]( - ctx, source, real_arg, size, indexes, extra_name, MAX_CTL_QUERY_TYPE); + umf_result_t ret = n->write_cb(ctx, source, real_arg, size, indexes); ctl_query_cleanup_real_args(n, real_arg, source); return ret; @@ -300,95 +255,252 @@ static umf_result_t ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n, static umf_result_t ctl_exec_query_runnable(void *ctx, const umf_ctl_node_t *n, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { - (void)query_type; + umf_ctl_index_utlist_t *indexes) { assert(n != NULL); - assert(n->cb[CTL_QUERY_RUNNABLE] != NULL); - assert(MAX_CTL_QUERY_TYPE != query_type); - return n->cb[CTL_QUERY_RUNNABLE](ctx, source, arg, size, indexes, - extra_name, MAX_CTL_QUERY_TYPE); + + if (n->runnable_cb == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + return n->runnable_cb(ctx, source, arg, size, indexes); } -static umf_result_t ctl_exec_query_subtree(void *ctx, const umf_ctl_node_t *n, - umf_ctl_query_source_t source, - void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +ctl_exec_query_subtree(void *ctx, const umf_ctl_node_t *n, + umf_ctl_query_source_t source, void *arg, size_t size, + umf_ctl_index_utlist_t *indexes, const char *extra_name, + umf_ctl_query_type_t query_type, va_list args) { assert(n != NULL); - assert(n->cb[CTL_QUERY_SUBTREE] != NULL); - assert(MAX_CTL_QUERY_TYPE != query_type); - return n->cb[CTL_QUERY_SUBTREE](ctx, source, arg, size, indexes, extra_name, - query_type); -} -typedef umf_result_t (*umf_ctl_exec_query_t)(void *ctx, const umf_ctl_node_t *n, - umf_ctl_query_source_t source, - void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type); + if (n->subtree_cb == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } -static umf_ctl_exec_query_t ctl_exec_query[MAX_CTL_QUERY_TYPE] = { - ctl_exec_query_read, - ctl_exec_query_write, - ctl_exec_query_runnable, - ctl_exec_query_subtree, -}; + return n->subtree_cb(ctx, source, arg, size, indexes, extra_name, + query_type, args); +} /* - * ctl_query -- (internal) parses the name and calls the appropriate methods - * from the ctl tree + * ctl_find_and_execulte_node -- (internal) searches for a matching entry point in the + * provided nodes + * + * Name offset is used to return the offset of the name in the query string. + * The caller is responsible for freeing all of the allocated indexes, + * regardless of the return value. */ -umf_result_t ctl_query(struct ctl *ctl, void *ctx, - umf_ctl_query_source_t source, const char *name, - umf_ctl_query_type_t type, void *arg, size_t size) { - if (name == NULL) { - return UMF_RESULT_ERROR_INVALID_ARGUMENT; + +static optional_umf_result_t +ctl_find_and_execute_node(const umf_ctl_node_t *nodes, void *ctx, + umf_ctl_query_source_t source, const char *name, + umf_ctl_query_type_t type, void *arg, size_t size, + va_list args) { + assert(nodes != NULL); + assert(name != NULL); + + const umf_ctl_node_t *n = NULL; + optional_umf_result_t ret; + size_t name_offset = 0; + ret.is_valid = true; + ret.value = UMF_RESULT_SUCCESS; + char *sptr = NULL; + char *parse_str = Strdup(name); + if (parse_str == NULL) { + ret.is_valid = false; + return ret; } - /* - * All of the indexes are put on this list so that the handlers can - * easily retrieve the index values. The list is cleared once the ctl - * query has been handled. - */ - umf_ctl_index_utlist_t *indexes = NULL; - indexes = Zalloc(sizeof(*indexes)); + umf_ctl_index_utlist_t *indexes = Zalloc(sizeof(*indexes)); if (!indexes) { - return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + ret.value = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + return ret; } + char *node_name = strtok_r(parse_str, CTL_QUERY_NODE_SEPARATOR, &sptr); - umf_result_t ret = UMF_RESULT_ERROR_UNKNOWN; - size_t name_offset = 0; + /* + * Go through the string and separate tokens that correspond to nodes + * in the main ctl tree. + */ + while (node_name != NULL) { + char *next_node = strtok_r(NULL, CTL_QUERY_NODE_SEPARATOR, &sptr); + name_offset = node_name - parse_str; + if (n != NULL && n->type == CTL_NODE_SUBTREE) { + // if a subtree occurs, the subtree handler should be called + break; + } - const umf_ctl_node_t *n = - ctl_find_node(CTL_NODE(global), name, indexes, &name_offset); + if (strcmp(node_name, CTL_WILDCARD) == 0) { + if (source == CTL_QUERY_CONFIG_INPUT) { + LOG_ERR("ctl {} wildcard is not supported for config input"); + goto error; + } + // node is wildcard - we are expecting standard node name here, so lets + // pop next node_name from the va_list + node_name = va_arg(args, char *); + } - if (n == NULL && ctl) { - ctl_delete_indexes(indexes); - indexes = NULL; - n = ctl_find_node(ctl->root, name, indexes, &name_offset); + if (!nodes) { + goto error; + } + + for (n = &nodes[0]; n->type != CTL_NODE_UNKNOWN; ++n) { + if (n->name && strcmp(n->name, node_name) == 0) { + if (n->type == CTL_NODE_LEAF && next_node != NULL) { + // this is not the last node in the query, so it couldn't be leaf + continue; + } + if (n->type != CTL_NODE_LEAF && next_node == NULL) { + // this is the last node in the query, so it must be a leaf + continue; + } + break; + } + } + + if (n->type == CTL_NODE_UNKNOWN) { + goto error; + } + + if (n->arg != NULL && n->type == CTL_NODE_NAMED) { + if (next_node == NULL) { + // if the node has an argument, but no next node, then it is an error + goto error; + } + void *node_arg; + if (strcmp(next_node, CTL_WILDCARD) == 0) { + if (source == CTL_QUERY_CONFIG_INPUT) { + LOG_ERR( + "ctl {} wildcard is not supported for config input"); + goto error; + } + // argument is a wildcard so we need to allocate it from va_list + node_arg = umf_ba_global_alloc(n->arg->dest_size); + if (node_arg == NULL) { + goto error; + } + pop_va_list(args, n->arg, node_arg); + } else { + node_arg = ctl_parse_args(n->arg, next_node); + + if (node_arg == NULL) { + goto error; + } + } + + umf_ctl_index_utlist_t *entry = NULL; + entry = umf_ba_global_alloc(sizeof(*entry)); + if (entry == NULL) { + umf_ba_global_free(arg); + goto error; + } + + entry->arg = node_arg; + entry->name = node_name; + entry->arg_size = n->arg->dest_size; + + LL_APPEND(indexes, entry); + // we parsed next_node as an argument so we next one + next_node = strtok_r(NULL, CTL_QUERY_NODE_SEPARATOR, &sptr); + if (next_node == NULL) { + // last node was a node with arg, but there is no next mode. + // check if there is nameless leaf on next level + for (n = n->children; n->type != CTL_NODE_UNKNOWN; ++n) { + if (n->type == CTL_NODE_LEAF && + strcmp(n->name, CTL_STR(CTL_NONAME)) == 0) { + // found a nameless leaf, so we can return it + break; + } + } + + if (n->type == CTL_NODE_UNKNOWN) { + goto error; + } + } else if (n->children) { + // if there is nameless subtree in the next node we should also stop here. + // This is the HACK which forbids mixing subtree and normal nodes as a child of the + // node with an argument. Probably no one will ever need to do so, so this is fine. + for (const umf_ctl_node_t *m = n->children; + m->type != CTL_NODE_UNKNOWN; ++m) { + if (m->type == CTL_NODE_SUBTREE && + strcmp(m->name, CTL_STR(CTL_NONAME)) == 0) { + // found a nameless subtree, so lets assign it as a current node + n = m; + break; + } + } + } + } + + nodes = n->children; + node_name = next_node; } // if the appropriate node (leaf or subtree) is not found, then return error if (n == NULL || - (n->type != CTL_NODE_LEAF && n->type != CTL_NODE_SUBTREE) || - n->cb[n->type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type] == NULL) { - ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; + (n->type != CTL_NODE_LEAF && n->type != CTL_NODE_SUBTREE)) { + ret.value = UMF_RESULT_ERROR_INVALID_ARGUMENT; goto out; } - ret = - ctl_exec_query[n->type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type]( - ctx, n, source, arg, size, indexes, name + name_offset, type); + if (n->type == CTL_NODE_SUBTREE) { + // if the node is a subtree, then we need to call the subtree handler + ret.value = + ctl_exec_query_subtree(ctx, n, source, arg, size, indexes->next, + name + name_offset, type, args); + } else { + switch (type) { + case CTL_QUERY_READ: + ret.value = + ctl_exec_query_read(ctx, n, source, arg, size, indexes->next); + break; + case CTL_QUERY_WRITE: + ret.value = + ctl_exec_query_write(ctx, n, source, arg, size, indexes->next); + break; + case CTL_QUERY_RUNNABLE: + ret.value = ctl_exec_query_runnable(ctx, n, source, arg, size, + indexes->next); + break; + } + } out: + umf_ba_global_free(parse_str); ctl_delete_indexes(indexes); + return ret; +error: + ctl_delete_indexes(indexes); + umf_ba_global_free(parse_str); + ret.is_valid = false; return ret; } +/* + * ctl_query -- (internal) parses the name and calls the appropriate methods + * from the ctl tree + */ +umf_result_t ctl_query(struct ctl *ctl, void *ctx, + umf_ctl_query_source_t source, const char *name, + umf_ctl_query_type_t type, void *arg, size_t size, + va_list args) { + if (name == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + va_list args_copy; + va_copy(args_copy, args); + + optional_umf_result_t ret = ctl_find_and_execute_node( + CTL_NODE(global), ctx, source, name, type, arg, size, args_copy); + + if (ret.is_valid == false && ctl) { + ret = ctl_find_and_execute_node(ctl->root, ctx, source, name, type, arg, + size, args); + } + + va_end(args_copy); + + return ret.is_valid ? ret.value : UMF_RESULT_ERROR_INVALID_ARGUMENT; +} + /* * ctl_register_module_node -- adds a new node to the CTL tree root. */ @@ -433,32 +545,46 @@ static int ctl_parse_query(char *qbuf, char **name, char **value) { } /* - * ctl_load_config -- executes the entire query collection from a provider + * ctl_load_config_helper -- windows do not allow to use uninitialized va_list, + * so this function allows us to initialize empty one */ -static umf_result_t ctl_load_config(struct ctl *ctl, void *ctx, char *buf) { +static umf_result_t ctl_load_config_helper(struct ctl *ctl, void *ctx, + char *buf, ...) { umf_result_t ret = UMF_RESULT_SUCCESS; char *sptr = NULL; /* for internal use of strtok */ char *name; char *value; char *qbuf = strtok_r(buf, CTL_STRING_QUERY_SEPARATOR, &sptr); - + va_list empty_args; + va_start(empty_args, buf); while (qbuf != NULL) { int parse_res = ctl_parse_query(qbuf, &name, &value); if (parse_res != 0) { - return UMF_RESULT_ERROR_INVALID_ARGUMENT; + ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; + goto end; } - + // we do not need to copy va_list before call as we know that for query_config_input + // ctl_query will not call va_arg on it. Ref 7.15/3 of C99 standard ret = ctl_query(ctl, ctx, CTL_QUERY_CONFIG_INPUT, name, CTL_QUERY_WRITE, - value, 0); + value, 0, empty_args); if (ret != UMF_RESULT_SUCCESS && ctx != NULL) { - return ret; + goto end; } qbuf = strtok_r(NULL, CTL_STRING_QUERY_SEPARATOR, &sptr); } - return 0; +end: + va_end(empty_args); + return ret; +} + +/* + * ctl_load_config -- executes the entire query collection from a provider + */ +static umf_result_t ctl_load_config(struct ctl *ctl, void *ctx, char *buf) { + return ctl_load_config_helper(ctl, ctx, buf); } /* diff --git a/src/ctl/ctl_internal.h b/src/ctl/ctl_internal.h index 06cfdb3e1..a45fa7732 100644 --- a/src/ctl/ctl_internal.h +++ b/src/ctl/ctl_internal.h @@ -19,6 +19,7 @@ #define UMF_CTL_INTERNAL_H 1 #include +#include #include #include @@ -31,33 +32,25 @@ extern "C" { typedef struct ctl_index_utlist { const char *name; - long value; + void *arg; + size_t arg_size; /* size of the argument */ struct ctl_index_utlist *next; } umf_ctl_index_utlist_t; -typedef enum ctl_query_source { - CTL_UNKNOWN_QUERY_SOURCE, - /* query executed directly from the program */ - CTL_QUERY_PROGRAMMATIC, - /* query executed from the config file */ - CTL_QUERY_CONFIG_INPUT, - - MAX_CTL_QUERY_SOURCE -} umf_ctl_query_source_t; - -typedef umf_result_t (*node_callback)(void *ctx, umf_ctl_query_source_t type, +typedef umf_result_t (*node_callback)(void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type); + umf_ctl_index_utlist_t *indexes); + +typedef umf_result_t (*node_callback_subtree)( + void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, + umf_ctl_index_utlist_t *indexes, const char *extra_name, + umf_ctl_query_type_t query_type, va_list args); enum ctl_node_type { CTL_NODE_UNKNOWN, CTL_NODE_NAMED, CTL_NODE_LEAF, - CTL_NODE_INDEXED, CTL_NODE_SUBTREE, - MAX_CTL_NODE }; @@ -68,9 +61,19 @@ struct ctl_argument_parser { size_t dest_size; /* size of the field inside of the argument */ ctl_arg_parser parser; }; +typedef enum ctl_arg_type { + CTL_ARG_TYPE_UNKNOWN = 0, + CTL_ARG_TYPE_BOOLEAN, + CTL_ARG_TYPE_STRING, + CTL_ARG_TYPE_INT, + CTL_ARG_TYPE_LONG_LONG, + CTL_ARG_TYPE_PTR, + MAX_CTL_ARG_TYPE +} ctl_arg_type_t; struct ctl_argument { size_t dest_size; /* size of the entire argument */ + ctl_arg_type_t type; /* type of the argument */ struct ctl_argument_parser parsers[]; /* array of 'fields' in arg */ }; @@ -93,7 +96,11 @@ typedef struct ctl_node { const char *name; enum ctl_node_type type; - node_callback cb[MAX_CTL_QUERY_TYPE]; + node_callback read_cb; + node_callback write_cb; + node_callback runnable_cb; + node_callback_subtree subtree_cb; + const struct ctl_argument *arg; const struct ctl_node *children; @@ -128,18 +135,22 @@ void ctl_register_module_node(struct ctl *c, const char *name, int ctl_arg_boolean(const void *arg, void *dest, size_t dest_size); #define CTL_ARG_BOOLEAN \ { \ - sizeof(int), { {0, sizeof(int), ctl_arg_boolean}, CTL_ARG_PARSER_END } \ + sizeof(int), CTL_ARG_TYPE_BOOLEAN, { \ + {0, sizeof(int), ctl_arg_boolean}, CTL_ARG_PARSER_END \ + } \ } int ctl_arg_integer(const void *arg, void *dest, size_t dest_size); #define CTL_ARG_INT \ { \ - sizeof(int), { {0, sizeof(int), ctl_arg_integer}, CTL_ARG_PARSER_END } \ + sizeof(int), CTL_ARG_TYPE_INT, { \ + {0, sizeof(int), ctl_arg_integer}, CTL_ARG_PARSER_END \ + } \ } #define CTL_ARG_LONG_LONG \ { \ - sizeof(long long), { \ + sizeof(long long), CTL_ARG_TYPE_LONG_LONG, { \ {0, sizeof(long long), ctl_arg_integer}, CTL_ARG_PARSER_END \ } \ } @@ -147,41 +158,68 @@ int ctl_arg_integer(const void *arg, void *dest, size_t dest_size); int ctl_arg_string(const void *arg, void *dest, size_t dest_size); #define CTL_ARG_STRING(len) \ { \ - len, { {0, len, ctl_arg_string}, CTL_ARG_PARSER_END } \ + len, CTL_ARG_TYPE_PTR, { \ + {0, len, ctl_arg_string}, CTL_ARG_PARSER_END \ + } \ + } + +#define CTL_ARG_PTR \ + { \ + sizeof(void *), CTL_ARG_TYPE_PTR, { {0, 0, NULL}, CTL_ARG_PARSER_END } \ } -#define CTL_STR(name) #name +#define _CTL_STR(name) #name +#define CTL_STR(name) _CTL_STR(name) + +// this macro is only needed because Microsoft cannot implement C99 standard +#define CTL_NONAME CTL_NAMELESS_NODE_ #define CTL_NODE_END \ - { NULL, CTL_NODE_UNKNOWN, {NULL, NULL, NULL}, NULL, NULL } + { NULL, CTL_NODE_UNKNOWN, NULL, NULL, NULL, NULL, NULL, NULL } #define CTL_NODE(name, ...) ctl_node_##__VA_ARGS__##_##name umf_result_t ctl_query(struct ctl *ctl, void *ctx, umf_ctl_query_source_t source, const char *name, - umf_ctl_query_type_t type, void *arg, size_t size); + umf_ctl_query_type_t type, void *arg, size_t size, + va_list args); /* Declaration of a new child node */ #define CTL_CHILD(name, ...) \ { \ - CTL_STR(name), CTL_NODE_NAMED, {NULL, NULL, NULL}, NULL, \ + CTL_STR(name), CTL_NODE_NAMED, NULL, NULL, NULL, NULL, NULL, \ + (struct ctl_node *)CTL_NODE(name, __VA_ARGS__) \ + } + +/* + * Declaration of a new child node with an argument + * This is used to declare that the following node is an argument node, which + * should be parsed and provided to the handler function in argument list. + */ +#define CTL_CHILD_WITH_ARG(name, ...) \ + { \ + CTL_STR(name), CTL_NODE_NAMED, NULL, NULL, NULL, NULL, &CTL_ARG(name), \ (struct ctl_node *)CTL_NODE(name, __VA_ARGS__) \ } /* Declaration of a new indexed node */ #define CTL_INDEXED(name, ...) \ { \ - CTL_STR(name), CTL_NODE_INDEXED, {NULL, NULL, NULL}, NULL, \ + CTL_STR(name), CTL_NODE_INDEXED, NULL, NULL, NULL, NULL, NULL, \ (struct ctl_node *)CTL_NODE(name, __VA_ARGS__) \ } -#define CTL_READ_HANDLER(name, ...) ctl_##__VA_ARGS__##_##name##_read +#define CTL_HANDLER_NAME(name, action, ...) \ + ctl_##__VA_ARGS__##_##name##_##action -#define CTL_WRITE_HANDLER(name, ...) ctl_##__VA_ARGS__##_##name##_write +#define CTL_READ_HANDLER(name, ...) CTL_HANDLER_NAME(name, read, __VA_ARGS__) +#define CTL_WRITE_HANDLER(name, ...) CTL_HANDLER_NAME(name, write, __VA_ARGS__) -#define CTL_RUNNABLE_HANDLER(name, ...) ctl_##__VA_ARGS__##_##name##_runnable +#define CTL_RUNNABLE_HANDLER(name, ...) \ + CTL_HANDLER_NAME(name, runnable, __VA_ARGS__) -#define CTL_SUBTREE_HANDLER(name, ...) ctl_##__VA_ARGS__##_##name##_subtree +#define CTL_SUBTREE_HANDLER(name, ...) \ + CTL_HANDLER_NAME(name, subtree, __VA_ARGS__) #define CTL_ARG(name) ctl_arg_##name @@ -191,9 +229,8 @@ umf_result_t ctl_query(struct ctl *ctl, void *ctx, */ #define CTL_LEAF_RO(name, ...) \ { \ - CTL_STR(name), CTL_NODE_LEAF, \ - {CTL_READ_HANDLER(name, __VA_ARGS__), NULL, NULL, NULL}, NULL, \ - NULL \ + CTL_STR(name), CTL_NODE_LEAF, CTL_READ_HANDLER(name, __VA_ARGS__), \ + NULL, NULL, NULL, NULL, NULL \ } /* @@ -202,9 +239,9 @@ umf_result_t ctl_query(struct ctl *ctl, void *ctx, */ #define CTL_LEAF_WO(name, ...) \ { \ - CTL_STR(name), CTL_NODE_LEAF, \ - {NULL, CTL_WRITE_HANDLER(name, __VA_ARGS__), NULL, NULL}, \ - &CTL_ARG(name), NULL \ + CTL_STR(name), CTL_NODE_LEAF, NULL, \ + CTL_WRITE_HANDLER(name, __VA_ARGS__), NULL, NULL, &CTL_ARG(name), \ + NULL \ } /* @@ -213,23 +250,14 @@ umf_result_t ctl_query(struct ctl *ctl, void *ctx, */ #define CTL_LEAF_RUNNABLE(name, ...) \ { \ - CTL_STR(name), CTL_NODE_LEAF, \ - {NULL, NULL, CTL_RUNNABLE_HANDLER(name, __VA_ARGS__), NULL}, NULL, \ - NULL \ + CTL_STR(name), CTL_NODE_LEAF, NULL, NULL, \ + CTL_RUNNABLE_HANDLER(name, __VA_ARGS__), NULL, NULL, NULL \ } #define CTL_LEAF_SUBTREE(name, ...) \ { \ - CTL_STR(name), CTL_NODE_SUBTREE, \ - {NULL, NULL, NULL, CTL_SUBTREE_HANDLER(name, __VA_ARGS__)}, NULL, \ - NULL \ - } - -#define CTL_LEAF_SUBTREE2(name, fun, ...) \ - { \ - CTL_STR(name), CTL_NODE_SUBTREE, \ - {NULL, NULL, NULL, CTL_SUBTREE_HANDLER(fun, __VA_ARGS__)}, NULL, \ - NULL \ + CTL_STR(name), CTL_NODE_SUBTREE, NULL, NULL, NULL, \ + CTL_SUBTREE_HANDLER(name, __VA_ARGS__), NULL, NULL \ } /* @@ -238,9 +266,8 @@ umf_result_t ctl_query(struct ctl *ctl, void *ctx, */ #define CTL_LEAF_RW(name) \ { \ - CTL_STR(name), CTL_NODE_LEAF, \ - {CTL_READ_HANDLER(name), CTL_WRITE_HANDLER(name), NULL, NULL}, \ - &CTL_ARG(name), NULL \ + CTL_STR(name), CTL_NODE_LEAF, CTL_READ_HANDLER(name), \ + CTL_WRITE_HANDLER(name), NULL, NULL, &CTL_ARG(name), NULL \ } #define CTL_REGISTER_MODULE(_ctl, name) \ diff --git a/src/libumf.c b/src/libumf.c index e9b78d489..fb01eae57 100644 --- a/src/libumf.c +++ b/src/libumf.c @@ -7,11 +7,13 @@ * */ +#include #include #include #include "base_alloc_global.h" #include "ipc_cache.h" +#include "memory_pool_internal.h" #include "memory_provider_internal.h" #include "memspace_internal.h" #include "pool/pool_scalable_internal.h" @@ -124,26 +126,34 @@ umf_result_t umfTearDown(void) { int umfGetCurrentVersion(void) { return UMF_VERSION_CURRENT; } -umf_result_t umfCtlGet(const char *name, void *ctx, void *arg, size_t size) { +umf_result_t umfCtlGet(const char *name, void *arg, size_t size, ...) { // ctx can be NULL when getting defaults if (name == NULL || arg == NULL || size == 0) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_READ, - arg, size); + va_list args; + va_start(args, size); + + umf_result_t ret = ctl_query(NULL, NULL, CTL_QUERY_PROGRAMMATIC, name, + CTL_QUERY_READ, arg, size, args); + va_end(args); + return ret; } -umf_result_t umfCtlSet(const char *name, void *ctx, void *arg, size_t size) { +umf_result_t umfCtlSet(const char *name, void *arg, size_t size, ...) { // ctx can be NULL when setting defaults if (name == NULL || arg == NULL || size == 0) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - - return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_WRITE, - arg, size); + va_list args; + va_start(args, size); + umf_result_t ret = ctl_query(NULL, NULL, CTL_QUERY_PROGRAMMATIC, name, + CTL_QUERY_WRITE, arg, size, args); + va_end(args); + return ret; } -umf_result_t umfCtlExec(const char *name, void *ctx, void *arg, size_t size) { +umf_result_t umfCtlExec(const char *name, void *arg, size_t size, ...) { // arg can be NULL when executing a command // ctx can be NULL when executing defaults // size can depends on the arg @@ -154,7 +164,11 @@ umf_result_t umfCtlExec(const char *name, void *ctx, void *arg, size_t size) { if ((arg == NULL && size != 0) || (arg != NULL && size == 0)) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } + va_list args; + va_start(args, size); - return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, - CTL_QUERY_RUNNABLE, arg, size); + umf_result_t ret = ctl_query(NULL, NULL, CTL_QUERY_PROGRAMMATIC, name, + CTL_QUERY_RUNNABLE, arg, size, args); + va_end(args); + return ret; } diff --git a/src/memory_pool.c b/src/memory_pool.c index 0af7b6b62..004f42d9e 100644 --- a/src/memory_pool.c +++ b/src/memory_pool.c @@ -7,13 +7,14 @@ * */ +#include +#include +#include + #include #include #include -#include -#include - #include "base_alloc_global.h" #include "ctl/ctl_internal.h" #include "libumf.h" @@ -37,18 +38,24 @@ static struct ctl umf_pool_ctl_root; static void ctl_init(void); -static umf_result_t CTL_SUBTREE_HANDLER(by_handle_pool)( +static umf_result_t CTL_SUBTREE_HANDLER(CTL_NONAME, by_handle)( void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t queryType) { - (void)indexes, (void)source; - umf_memory_pool_handle_t hPool = (umf_memory_pool_handle_t)ctx; + umf_ctl_query_type_t queryType, va_list args) { + (void)source, (void)ctx; + + umf_memory_pool_handle_t hPool = *(umf_memory_pool_handle_t *)indexes->arg; + va_list args2; + va_copy(args2, args); + umf_result_t ret = ctl_query(&umf_pool_ctl_root, hPool, source, extra_name, - queryType, arg, size); + queryType, arg, size, args2); + va_end(args2); + if (ret == UMF_RESULT_ERROR_INVALID_ARGUMENT) { // Node was not found in pool_ctl_root, try to query the specific pool ret = hPool->ops.ext_ctl(hPool->pool_priv, source, extra_name, arg, - size, queryType); + size, queryType, args); } return ret; @@ -57,9 +64,19 @@ static umf_result_t CTL_SUBTREE_HANDLER(by_handle_pool)( static umf_result_t CTL_SUBTREE_HANDLER(default)( void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t queryType) { - (void)indexes, (void)source, (void)ctx; + umf_ctl_query_type_t queryType, va_list args) { + (void)indexes, (void)source, (void)ctx, (void)args; utils_init_once(&mem_pool_ctl_initialized, ctl_init); + + if (strstr(extra_name, "{}") != NULL) { + // We might implement it in future - it requires store copy of va_list + // in defaults entries array, which according to C standard is possible, + // but quite insane. + LOG_ERR("%s, default setting do not support wildcard parameters {}", + extra_name); + return UMF_RESULT_ERROR_NOT_SUPPORTED; + } + utils_mutex_lock(&ctl_mtx); if (queryType == CTL_QUERY_WRITE) { @@ -99,12 +116,12 @@ static umf_result_t CTL_SUBTREE_HANDLER(default)( return UMF_RESULT_SUCCESS; } -static umf_result_t CTL_READ_HANDLER(alloc_count)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(alloc_count)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)size, (void)indexes, (void)extra_name, (void)query_type; + (void)source, (void)size, (void)indexes; size_t *arg_out = arg; if (ctx == NULL || arg_out == NULL) { @@ -121,7 +138,14 @@ static umf_result_t CTL_READ_HANDLER(alloc_count)( static const umf_ctl_node_t CTL_NODE(stats)[] = {CTL_LEAF_RO(alloc_count), CTL_NODE_END}; -umf_ctl_node_t CTL_NODE(pool)[] = {CTL_LEAF_SUBTREE2(by_handle, by_handle_pool), +static umf_ctl_node_t CTL_NODE(by_handle)[] = { + CTL_LEAF_SUBTREE(CTL_NONAME, by_handle), + CTL_NODE_END, +}; + +static const struct ctl_argument CTL_ARG(by_handle) = CTL_ARG_PTR; + +umf_ctl_node_t CTL_NODE(pool)[] = {CTL_CHILD_WITH_ARG(by_handle), CTL_LEAF_SUBTREE(default), CTL_NODE_END}; static void ctl_init(void) { @@ -129,16 +153,17 @@ static void ctl_init(void) { CTL_REGISTER_MODULE(&umf_pool_ctl_root, stats); } -static umf_result_t umfDefaultCtlPoolHandle(void *hPool, int operationType, - const char *name, void *arg, - size_t size, - umf_ctl_query_type_t queryType) { +static umf_result_t +umfDefaultCtlPoolHandle(void *hPool, umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t queryType, va_list args) { (void)hPool; (void)operationType; (void)name; (void)arg; (void)size; (void)queryType; + (void)args; return UMF_RESULT_ERROR_NOT_SUPPORTED; } @@ -146,6 +171,19 @@ static umf_result_t umfDefaultCtlPoolHandle(void *hPool, int operationType, static const umf_pool_create_flags_t UMF_POOL_CREATE_FLAG_ALL = UMF_POOL_CREATE_FLAG_OWN_PROVIDER | UMF_POOL_CREATE_FLAG_DISABLE_TRACKING; +// windows do not allow to use uninitialized va_list so this function help us to initialize it. +static umf_result_t default_ctl_helper(const umf_memory_pool_ops_t *ops, + void *ctl, const char *name, void *arg, + ...) { + va_list empty_args; + va_start(empty_args, arg); + umf_result_t ret = + ops->ext_ctl(ctl, CTL_QUERY_PROGRAMMATIC, name, arg, UMF_DEFAULT_LEN, + CTL_QUERY_WRITE, empty_args); + va_end(empty_args); + return ret; +} + static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, umf_memory_provider_handle_t provider, const void *params, @@ -217,9 +255,9 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, } if (CTL_DEFAULT_ENTRIES[i][0] != '\0' && pname && strstr(CTL_DEFAULT_ENTRIES[i], pname)) { - ops->ext_ctl(pool->pool_priv, CTL_QUERY_PROGRAMMATIC, - CTL_DEFAULT_ENTRIES[i], CTL_DEFAULT_VALUES[i], - UMF_DEFAULT_LEN, CTL_QUERY_WRITE); + + default_ctl_helper(ops, pool->pool_priv, CTL_DEFAULT_ENTRIES[i], + CTL_DEFAULT_VALUES[i]); } } diff --git a/src/memory_pool_internal.h b/src/memory_pool_internal.h index ad05464dd..00f9a2a05 100644 --- a/src/memory_pool_internal.h +++ b/src/memory_pool_internal.h @@ -22,6 +22,7 @@ extern "C" { #endif #include "base_alloc.h" +#include "ctl/ctl_internal.h" #include "utils_concurrency.h" typedef struct umf_pool_stats { @@ -44,6 +45,8 @@ typedef struct umf_memory_pool_t { umf_memory_pool_ops_t ops; } umf_memory_pool_t; +extern umf_ctl_node_t CTL_NODE(pool)[]; + #ifdef __cplusplus } #endif diff --git a/src/memory_provider.c b/src/memory_provider.c index 27f33f86f..b389bc57b 100644 --- a/src/memory_provider.c +++ b/src/memory_provider.c @@ -17,23 +17,32 @@ #include "base_alloc.h" #include "base_alloc_global.h" +#include "ctl/ctl_internal.h" #include "libumf.h" #include "memory_provider_internal.h" #include "utils_assert.h" -static umf_result_t CTL_SUBTREE_HANDLER(by_handle_provider)( +static umf_result_t CTL_SUBTREE_HANDLER(CTL_NONAME, by_handle)( void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t queryType) { - (void)indexes, (void)source; - umf_memory_provider_handle_t hProvider = (umf_memory_provider_handle_t)ctx; + umf_ctl_query_type_t queryType, va_list args) { + (void)indexes, (void)source, (void)ctx; + umf_memory_provider_handle_t hProvider = + *(umf_memory_provider_handle_t *)indexes->arg; hProvider->ops.ext_ctl(hProvider->provider_priv, /*unused*/ 0, extra_name, - arg, size, queryType); + arg, size, queryType, args); return UMF_RESULT_SUCCESS; } -umf_ctl_node_t CTL_NODE(provider)[] = { - CTL_LEAF_SUBTREE2(by_handle, by_handle_provider), CTL_NODE_END}; +static umf_ctl_node_t CTL_NODE(by_handle)[] = { + CTL_LEAF_SUBTREE(CTL_NONAME, by_handle), + CTL_NODE_END, +}; + +static const struct ctl_argument CTL_ARG(by_handle) = CTL_ARG_PTR; + +umf_ctl_node_t CTL_NODE(provider)[] = {CTL_CHILD_WITH_ARG(by_handle), + CTL_NODE_END}; static umf_result_t umfDefaultPurgeLazy(void *provider, void *ptr, size_t size) { @@ -108,16 +117,17 @@ static umf_result_t umfDefaultCloseIPCHandle(void *provider, void *ptr, return UMF_RESULT_ERROR_NOT_SUPPORTED; } -static umf_result_t umfDefaultCtlHandle(void *provider, int operationType, - const char *name, void *arg, - size_t size, - umf_ctl_query_type_t queryType) { +static umf_result_t +umfDefaultCtlHandle(void *provider, umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t queryType, va_list args) { (void)provider; (void)operationType; (void)name; (void)arg; (void)size; (void)queryType; + (void)args; return UMF_RESULT_ERROR_NOT_SUPPORTED; } diff --git a/src/memory_provider_internal.h b/src/memory_provider_internal.h index f620c2c79..65ba5d41c 100644 --- a/src/memory_provider_internal.h +++ b/src/memory_provider_internal.h @@ -30,7 +30,6 @@ void *umfMemoryProviderGetPriv(umf_memory_provider_handle_t hProvider); umf_memory_provider_handle_t *umfGetLastFailedMemoryProviderPtr(void); extern umf_ctl_node_t CTL_NODE(provider)[]; -extern umf_ctl_node_t CTL_NODE(pool)[]; #ifdef __cplusplus } diff --git a/src/pool/pool_disjoint.c b/src/pool/pool_disjoint.c index 51e0e85ac..b32d2b317 100644 --- a/src/pool/pool_disjoint.c +++ b/src/pool/pool_disjoint.c @@ -33,11 +33,12 @@ static char *DEFAULT_NAME = "disjoint"; struct ctl disjoint_ctl_root; static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT; -static umf_result_t -CTL_READ_HANDLER(name)(void *ctx, umf_ctl_query_source_t source, void *arg, - size_t size, umf_ctl_index_utlist_t *indexes, - const char *extra_name, umf_ctl_query_type_t queryType) { - (void)source, (void)indexes, (void)queryType, (void)extra_name; +static umf_result_t CTL_READ_HANDLER(name)(void *ctx, + umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + (void)source, (void)indexes; + disjoint_pool_t *pool = (disjoint_pool_t *)ctx; if (arg == NULL) { @@ -57,10 +58,8 @@ static const struct ctl_argument CTL_ARG(name) = CTL_ARG_STRING(255); static umf_result_t CTL_WRITE_HANDLER(name)(void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t queryType) { - (void)source, (void)indexes, (void)queryType, (void)size, (void)extra_name; + umf_ctl_index_utlist_t *indexes) { + (void)source, (void)indexes, (void)size; disjoint_pool_t *pool = (disjoint_pool_t *)ctx; if (arg == NULL) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; @@ -79,14 +78,15 @@ static void initialize_disjoint_ctl(void) { CTL_REGISTER_MODULE(&disjoint_ctl_root, disjoint); } -umf_result_t disjoint_pool_ctl(void *hPool, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t queryType) { +umf_result_t disjoint_pool_ctl(void *hPool, + umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t queryType, va_list args) { (void)operationType; utils_init_once(&ctl_initialized, initialize_disjoint_ctl); return ctl_query(&disjoint_ctl_root, hPool, CTL_QUERY_PROGRAMMATIC, name, - queryType, arg, size); + queryType, arg, size, args); } // Temporary solution for disabling memory poisoning. This is needed because diff --git a/src/pool/pool_scalable.c b/src/pool/pool_scalable.c index 3308d98aa..982a3408d 100644 --- a/src/pool/pool_scalable.c +++ b/src/pool/pool_scalable.c @@ -422,14 +422,14 @@ static umf_result_t tbb_get_last_allocation_error(void *pool) { return TLS_last_allocation_error; } -static umf_result_t pool_ctl(void *hPool, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t query_type) { +static umf_result_t pool_ctl(void *hPool, umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { (void)operationType; // unused umf_memory_pool_handle_t pool_provider = (umf_memory_pool_handle_t)hPool; utils_init_once(&ctl_initialized, NULL); return ctl_query(&pool_scallable_ctl_root, pool_provider->pool_priv, - CTL_QUERY_PROGRAMMATIC, name, query_type, arg, size); + CTL_QUERY_PROGRAMMATIC, name, query_type, arg, size, args); } static umf_result_t scalable_get_name(void *pool, const char **name) { diff --git a/src/provider/provider_ctl_stats_impl.h b/src/provider/provider_ctl_stats_impl.h index 59cc86168..6f1fdf910 100644 --- a/src/provider/provider_ctl_stats_impl.h +++ b/src/provider/provider_ctl_stats_impl.h @@ -21,12 +21,12 @@ extern "C" { #include "ctl/ctl_internal.h" #include "utils/utils_assert.h" -static umf_result_t CTL_READ_HANDLER(peak_memory)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(peak_memory)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)size, (void)indexes, (void)extra_name, (void)query_type; + (void)source, (void)size, (void)indexes; size_t *arg_out = arg; CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx; @@ -34,12 +34,12 @@ static umf_result_t CTL_READ_HANDLER(peak_memory)( return UMF_RESULT_SUCCESS; } -static umf_result_t CTL_READ_HANDLER(allocated_memory)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(allocated_memory)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)size, (void)indexes, (void)extra_name, (void)query_type; + (void)source, (void)size, (void)indexes; size_t *arg_out = arg; CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx; @@ -50,12 +50,9 @@ static umf_result_t CTL_READ_HANDLER(allocated_memory)( static umf_result_t CTL_RUNNABLE_HANDLER(reset)(void *ctx, umf_ctl_query_source_t source, void *arg, - size_t size, umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { + size_t size, umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)arg, (void)size, (void)extra_name, - (void)query_type; + (void)source, (void)indexes, (void)arg, (void)size; CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx; size_t allocated; diff --git a/src/provider/provider_fixed_memory.c b/src/provider/provider_fixed_memory.c index 5f047442a..08fd3e7f6 100644 --- a/src/provider/provider_fixed_memory.c +++ b/src/provider/provider_fixed_memory.c @@ -21,6 +21,7 @@ #include "coarse.h" #include "libumf.h" #include "provider_ctl_stats_type.h" +#include "umf/base.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -282,12 +283,13 @@ static umf_result_t fixed_free(void *provider, void *ptr, size_t size) { return ret; } -static umf_result_t fixed_ctl(void *provider, int operationType, +static umf_result_t fixed_ctl(void *provider, + umf_ctl_query_source_t operationType, const char *name, void *arg, size_t size, - umf_ctl_query_type_t query_type) { + umf_ctl_query_type_t query_type, va_list args) { utils_init_once(&ctl_initialized, initialize_fixed_ctl); return ctl_query(&fixed_memory_ctl_root, provider, operationType, name, - query_type, arg, size); + query_type, arg, size, args); } static umf_memory_provider_ops_t UMF_FIXED_MEMORY_PROVIDER_OPS = { diff --git a/src/provider/provider_level_zero.c b/src/provider/provider_level_zero.c index d24cef5af..509df52d3 100644 --- a/src/provider/provider_level_zero.c +++ b/src/provider/provider_level_zero.c @@ -810,12 +810,13 @@ ze_memory_provider_close_ipc_handle(void *provider, void *ptr, size_t size) { return UMF_RESULT_SUCCESS; } -static umf_result_t ze_ctl(void *provider, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t query_type) { +static umf_result_t ze_ctl(void *hProvider, + umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { utils_init_once(&ctl_initialized, initialize_ze_ctl); - return ctl_query(&ze_memory_ctl_root, provider, operationType, name, - query_type, arg, size); + return ctl_query(&ze_memory_ctl_root, hProvider, operationType, name, + query_type, arg, size, args); } static umf_memory_provider_ops_t UMF_LEVEL_ZERO_MEMORY_PROVIDER_OPS = { diff --git a/src/provider/provider_os_memory.c b/src/provider/provider_os_memory.c index bc6ba5241..5c79b0582 100644 --- a/src/provider/provider_os_memory.c +++ b/src/provider/provider_os_memory.c @@ -177,13 +177,12 @@ struct ctl os_memory_ctl_root; static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT; -static umf_result_t CTL_READ_HANDLER(ipc_enabled)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(ipc_enabled)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)size; int *arg_out = arg; os_memory_provider_t *os_provider = (os_memory_provider_t *)ctx; @@ -1443,12 +1442,13 @@ static umf_result_t os_close_ipc_handle(void *provider, void *ptr, return UMF_RESULT_SUCCESS; } -static umf_result_t os_ctl(void *hProvider, int operationType, const char *name, - void *arg, size_t size, - umf_ctl_query_type_t query_type) { +static umf_result_t os_ctl(void *hProvider, + umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { utils_init_once(&ctl_initialized, initialize_os_ctl); return ctl_query(&os_memory_ctl_root, hProvider, operationType, name, - query_type, arg, size); + query_type, arg, size, args); } static umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = { diff --git a/test/ctl/ctl_api.cpp b/test/ctl/ctl_api.cpp index dd0abbc5c..5137878c3 100644 --- a/test/ctl/ctl_api.cpp +++ b/test/ctl/ctl_api.cpp @@ -46,8 +46,8 @@ TEST_F(test, ctl_by_handle_os_provider) { ASSERT_EQ(ret, UMF_RESULT_SUCCESS); int ipc_enabled = 0xBAD; - ret = umfCtlGet("umf.provider.by_handle.params.ipc_enabled", hProvider, - &ipc_enabled, sizeof(ipc_enabled)); + ret = umfCtlGet("umf.provider.by_handle.{}.params.ipc_enabled", + &ipc_enabled, sizeof(ipc_enabled), hProvider); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(ipc_enabled, 0); @@ -86,28 +86,24 @@ class Pool { } template - void validateQuery(std::function - ctlApiFunction, - const char *name, T expectedValue, umf_result_t expected, - bool disableContext = 0) { + void validateQuery(umf_result_t (*ctlApiFunction)(const char *name, + void *arg, size_t, ...), + const char *name, T expectedValue, + umf_result_t expected) { T value = getReferenceValue(); umf_result_t ret; char ret_buf[256] = {0}; if constexpr (std::is_same_v) { strncpy(ret_buf, value.c_str(), sizeof(ret_buf) - 1); ret_buf[sizeof(ret_buf) - 1] = '\0'; // Ensure null-termination - ret = ctlApiFunction(name, disableContext ? nullptr : pool, - (void *)ret_buf, sizeof(ret_buf)); + ret = ctlApiFunction(name, (void *)ret_buf, sizeof(ret_buf), pool); } else if constexpr (std::is_arithmetic_v) { std::string value_str = std::to_string(value); strncpy(ret_buf, value_str.c_str(), sizeof(ret_buf) - 1); ret_buf[sizeof(ret_buf) - 1] = '\0'; // Ensure null-termination - ret = ctlApiFunction(name, disableContext ? nullptr : pool, - (void *)ret_buf, sizeof(ret_buf)); + ret = ctlApiFunction(name, (void *)ret_buf, sizeof(ret_buf), pool); } else { - ret = ctlApiFunction(name, disableContext ? nullptr : pool, &value, - sizeof(value)); + ret = ctlApiFunction(name, &value, sizeof(value), pool); } ASSERT_EQ(ret, expected); @@ -117,10 +113,9 @@ class Pool { } template - void executeQuery(std::function - ctlApiFunction, - const char *name, T value, bool disableContext = 0) { + void executeQuery(umf_result_t (*ctlApiFunction)(const char *name, + void *arg, size_t, ...), + const char *name, T value) { size_t value_len; if constexpr (std::is_arithmetic_v) { value_len = sizeof(value); @@ -131,8 +126,7 @@ class Pool { } else { throw std::runtime_error("Unsupported type for value"); } - umf_result_t ret = ctlApiFunction(name, disableContext ? nullptr : pool, - (void *)value, value_len); + umf_result_t ret = ctlApiFunction(name, (void *)value, value_len); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); } @@ -193,15 +187,14 @@ class CtlTest : public ::testing::Test { /* Case: default settings * This test sets a default value and then retrieves it */ TEST_F(CtlTest, ctlDefault) { - void *ctx = NULL; const char *arg = "default_name"; - auto res = umfCtlSet("umf.pool.default.some_pool.some_path", ctx, - (void *)arg, strlen(arg)); + auto res = umfCtlSet("umf.pool.default.some_pool.some_path", (void *)arg, + strlen(arg)); ASSERT_EQ(res, UMF_RESULT_SUCCESS); char output[64] = {1}; - res = umfCtlGet("umf.pool.default.some_pool.some_path", ctx, (void *)output, + res = umfCtlGet("umf.pool.default.some_pool.some_path", (void *)output, sizeof(output)); ASSERT_EQ(res, UMF_RESULT_SUCCESS); ASSERT_STREQ(output, arg); @@ -209,34 +202,32 @@ TEST_F(CtlTest, ctlDefault) { /* Case: umfCtlSet negative test */ TEST_F(CtlTest, ctlSetInvalid) { - void *valid_ctx = (void *)0xBABE; const char *valid_arg = "default_name"; const char *valid_path = "umf.pool.default.some_pool.some_path"; // umfCtlSet - invalid path - auto res = umfCtlSet(NULL, valid_ctx, (void *)valid_arg, strlen(valid_arg)); + auto res = umfCtlSet(NULL, (void *)valid_arg, strlen(valid_arg)); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); // umfCtlSet - invalid size - res = umfCtlSet(valid_path, NULL, (void *)valid_arg, 0); + res = umfCtlSet(valid_path, (void *)valid_arg, 0); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); // umfCtlSet - invalid arg - res = umfCtlSet(valid_path, valid_ctx, NULL, strlen(valid_arg)); + res = umfCtlSet(valid_path, NULL, strlen(valid_arg)); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); } /* Case: umfCtlGet negative test */ TEST_F(CtlTest, ctlGetInvalid) { - void *valid_ctx = (void *)0xBABE; const char *valid_arg = "default_name"; const char *valid_path = "umf.pool.default.some_pool.some_path"; // umfCtlGet - invalid path - auto res = umfCtlGet(NULL, valid_ctx, (void *)valid_arg, strlen(valid_arg)); + auto res = umfCtlGet(NULL, (void *)valid_arg, strlen(valid_arg)); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); // umfCtlGet - invalid arg - res = umfCtlGet(valid_path, valid_ctx, NULL, strlen(valid_arg)); + res = umfCtlGet(valid_path, NULL, strlen(valid_arg)); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); } @@ -254,7 +245,7 @@ TEST_F(CtlTest, ctlDefaultPoolMultithreaded) { max_size = max_size]() { for (size_t j = 0; j < max_size; j++) { std::string name = name_prefix + std::to_string(i * 10 + j); - umfCtlSet(name.c_str(), NULL, (void *)predefined_value, + umfCtlSet(name.c_str(), (void *)predefined_value, strlen(predefined_value)); std::atomic_fetch_add(&totalRecords, 1UL); } @@ -271,8 +262,7 @@ TEST_F(CtlTest, ctlDefaultPoolMultithreaded) { char output[100] = {0}; for (size_t i = 0; i < totalRecords.load(); i++) { std::string name = name_prefix + std::to_string(i); - auto status = - umfCtlGet(name.c_str(), nullptr, (void *)output, sizeof(output)); + auto status = umfCtlGet(name.c_str(), (void *)output, sizeof(output)); ASSERT_EQ(status, UMF_RESULT_SUCCESS); ASSERT_EQ(std::string(output), std::string(predefined_value)); } @@ -287,13 +277,13 @@ TEST_F(CtlTest, ctlDefaultPoolOverwrite) { for (int i = 0; i < max_size; i++) { values.push_back("value_" + std::to_string(i)); - umfCtlSet(name.c_str(), NULL, (void *)values.back().c_str(), + umfCtlSet(name.c_str(), (void *)values.back().c_str(), values.back().size()); } char output[100] = {0}; umf_result_t status = - umfCtlGet(name.c_str(), NULL, (void *)output, sizeof(output)); + umfCtlGet(name.c_str(), (void *)output, sizeof(output)); ASSERT_EQ(status, UMF_RESULT_SUCCESS); ASSERT_EQ(std::string(output), values.back()); } @@ -305,14 +295,14 @@ TEST_F(CtlTest, ctlNameValidation) { Pool p; try { - p.executeQuery(umfCtlSet, name.c_str(), value.c_str(), true); + p.executeQuery(umfCtlSet, name.c_str(), value.c_str()); umf_result_t res = umfDisjointPoolParamsCreate(¶ms); ASSERT_EQ(res, UMF_RESULT_SUCCESS); auto ret = p.instantiatePool(umfDisjointPoolOps(), params); ASSERT_EQ(ret, 0); - p.validateQuery(umfCtlGet, "umf.pool.by_handle.disjoint.name", + p.validateQuery(umfCtlGet, "umf.pool.by_handle.{}.disjoint.name", std::move(value), UMF_RESULT_SUCCESS); } catch (...) { GTEST_FAIL() << "Unknown exception!"; @@ -328,7 +318,7 @@ TEST_F(CtlTest, ctlSizeValidation) { Pool p; try { - p.executeQuery(umfCtlSet, name.c_str(), value.c_str(), true); + p.executeQuery(umfCtlSet, name.c_str(), value.c_str()); umf_result_t res = umfDisjointPoolParamsCreate(¶ms); ASSERT_EQ(res, UMF_RESULT_SUCCESS); @@ -336,13 +326,11 @@ TEST_F(CtlTest, ctlSizeValidation) { ASSERT_EQ(ret, 0); char output[100] = {0}; - umfCtlGet("umf.pool.default.disjoint.name", NULL, output, - sizeof(output)); + umfCtlGet("umf.pool.default.disjoint.name", output, sizeof(output)); ASSERT_EQ(std::string(output), value); memset(output, 0, sizeof(output)); - umfCtlGet("umf.pool.default.disjoint.name", NULL, output, - value.size() / 2); + umfCtlGet("umf.pool.default.disjoint.name", output, value.size() / 2); auto half_value = value.substr(0, value.size() / 2); ASSERT_EQ(half_value, std::string(output)); } catch (...) { @@ -354,9 +342,9 @@ TEST_F(CtlTest, ctlSizeValidation) { TEST_F(CtlTest, ctlExecInvalidSize) { std::string name = "umf.pool.default.disjoint.name"; - ASSERT_EQ(umfCtlSet(name.c_str(), NULL, (void *)"test_value", 0), + ASSERT_EQ(umfCtlSet(name.c_str(), (void *)"test_value", 0), UMF_RESULT_ERROR_INVALID_ARGUMENT); - ASSERT_EQ(umfCtlSet(name.c_str(), NULL, NULL, 10), + ASSERT_EQ(umfCtlSet(name.c_str(), NULL, 10), UMF_RESULT_ERROR_INVALID_ARGUMENT); } @@ -371,7 +359,7 @@ TEST_F(CtlTest, ctlDefaultMultithreadedProvider) { [i, &totalRecords, &predefined_value, &name_prefix]() { for (int j = 0; j < 10; j++) { std::string name = name_prefix + std::to_string(i * 10 + j); - umfCtlSet(name.c_str(), NULL, (void *)predefined_value, + umfCtlSet(name.c_str(), (void *)predefined_value, strlen(predefined_value)); std::atomic_fetch_add(&totalRecords, 1); } @@ -384,8 +372,7 @@ TEST_F(CtlTest, ctlDefaultMultithreadedProvider) { char output[100] = {0}; for (size_t i = 0; i < totalRecords.load(); i++) { std::string name = name_prefix + std::to_string(i); - auto status = - umfCtlGet(name.c_str(), nullptr, (void *)output, sizeof(output)); + auto status = umfCtlGet(name.c_str(), (void *)output, sizeof(output)); ASSERT_EQ(status, UMF_RESULT_SUCCESS); ASSERT_EQ(std::string(output), std::string(predefined_value)); } diff --git a/test/ctl/ctl_debug.c b/test/ctl/ctl_debug.c index ad6746eaa..e8730d896 100644 --- a/test/ctl/ctl_debug.c +++ b/test/ctl/ctl_debug.c @@ -11,6 +11,9 @@ * ctl_debug.c -- implementation of the debug CTL namespace */ +#include + +#include "ctl/ctl_internal.h" #include "ctl_debug.h" static struct ctl ctl_debug; @@ -24,13 +27,12 @@ struct ctl *get_debug_ctl(void) { return &ctl_debug; } /* * CTL_WRITE_HANDLER(alloc_pattern) -- sets the alloc_pattern field in heap */ -static umf_result_t CTL_WRITE_HANDLER(alloc_pattern)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_WRITE_HANDLER(alloc_pattern)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int arg_in = *(int *)arg; alloc_pattern = arg_in; @@ -40,52 +42,48 @@ static umf_result_t CTL_WRITE_HANDLER(alloc_pattern)( /* * CTL_READ_HANDLER(alloc_pattern) -- returns alloc_pattern heap field */ -static umf_result_t CTL_READ_HANDLER(alloc_pattern)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(alloc_pattern)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int *arg_out = arg; *arg_out = alloc_pattern; return UMF_RESULT_SUCCESS; } -static umf_result_t CTL_WRITE_HANDLER(enable_logging)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_WRITE_HANDLER(enable_logging)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int arg_in = *(int *)arg; enable_logging = arg_in; return UMF_RESULT_SUCCESS; } -static umf_result_t CTL_READ_HANDLER(enable_logging)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_READ_HANDLER(enable_logging)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int *arg_out = arg; *arg_out = enable_logging; return UMF_RESULT_SUCCESS; } -static umf_result_t CTL_WRITE_HANDLER(log_level)( - void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, - umf_ctl_index_utlist_t *indexes, const char *extra_name, - umf_ctl_query_type_t query_type) { +static umf_result_t +CTL_WRITE_HANDLER(log_level)(void *ctx, umf_ctl_query_source_t source, + void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int arg_in = *(int *)arg; log_level = arg_in; @@ -94,33 +92,91 @@ static umf_result_t CTL_WRITE_HANDLER(log_level)( static umf_result_t CTL_READ_HANDLER(log_level)(void *ctx, umf_ctl_query_source_t source, void *arg, - size_t size, umf_ctl_index_utlist_t *indexes, - const char *extra_name, - umf_ctl_query_type_t query_type) { + size_t size, umf_ctl_index_utlist_t *indexes) { /* suppress unused-parameter errors */ - (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type, - (void)size; + (void)source, (void)indexes, (void)ctx, (void)size; int *arg_out = arg; *arg_out = log_level; return UMF_RESULT_SUCCESS; } +static umf_result_t +CTL_READ_HANDLER(arg_value)(void *ctx, umf_ctl_query_source_t source, void *arg, + size_t size, umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)ctx, (void)size; + + if (indexes == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->next != NULL) { + // argument list should have exactly one argument + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (strcmp(indexes->name, "arg_test") != 0) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->arg_size != sizeof(int)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->arg == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + int *arg_out = arg; + *arg_out = *(int *)indexes->arg; + return UMF_RESULT_SUCCESS; +} + +static umf_result_t CTL_READ_HANDLER(CTL_NONAME, final_node)( + void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, + umf_ctl_index_utlist_t *indexes) { + /* suppress unused-parameter errors */ + (void)source, (void)ctx, (void)size; + + if (indexes == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->next != NULL) { + // argument list should have exactly one argument + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (strcmp(indexes->name, "arg_test_final") != 0) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->arg_size != sizeof(int)) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + if (indexes->arg == NULL) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + int *arg_out = arg; + *arg_out = *(int *)indexes->arg; + return UMF_RESULT_SUCCESS; +} + static const struct ctl_argument CTL_ARG(alloc_pattern) = CTL_ARG_LONG_LONG; static const struct ctl_argument CTL_ARG(enable_logging) = CTL_ARG_BOOLEAN; static const struct ctl_argument CTL_ARG(log_level) = CTL_ARG_INT; +static const struct ctl_argument CTL_ARG(arg_test) = CTL_ARG_INT; +static const struct ctl_argument CTL_ARG(arg_test_final) = CTL_ARG_INT; -static const umf_ctl_node_t CTL_NODE(heap)[] = {CTL_LEAF_RW(alloc_pattern), - CTL_LEAF_RW(enable_logging), - CTL_LEAF_RW(log_level), - - CTL_NODE_END}; +const umf_ctl_node_t CTL_NODE(arg_test)[] = {CTL_LEAF_RO(arg_value), + CTL_NODE_END}; +const umf_ctl_node_t CTL_NODE(arg_test_final)[] = { + CTL_LEAF_RO(CTL_NONAME, final_node), CTL_NODE_END}; -static const umf_ctl_node_t CTL_NODE(debug)[] = {CTL_CHILD(heap), +static const umf_ctl_node_t CTL_NODE(heap)[] = { + CTL_LEAF_RW(alloc_pattern), CTL_LEAF_RW(enable_logging), + CTL_LEAF_RW(log_level), CTL_NODE_END}; - CTL_NODE_END}; +static const umf_ctl_node_t CTL_NODE(debug)[] = { + CTL_CHILD(heap), CTL_CHILD_WITH_ARG(arg_test), + CTL_CHILD_WITH_ARG(arg_test_final), CTL_NODE_END}; /* * debug_ctl_register -- registers ctl nodes for "debug" module diff --git a/test/ctl/ctl_unittest.cpp b/test/ctl/ctl_unittest.cpp index a408dcb42..e6c04eaeb 100644 --- a/test/ctl/ctl_unittest.cpp +++ b/test/ctl/ctl_unittest.cpp @@ -13,17 +13,21 @@ using namespace umf_test; +void get_test_va_list(va_list *a, ...) { va_start(*a, a); } + TEST_F(test, ctl_debug_read_from_string) { initialize_debug_ctl(); auto ctl_handler = get_debug_ctl(); + va_list empty_args; + get_test_va_list(&empty_args); ASSERT_EQ(ctl_load_config_from_string(ctl_handler, NULL, "debug.heap.alloc_pattern=1"), UMF_RESULT_SUCCESS); int value = 0; ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, - "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, - sizeof(value)); + "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, sizeof(value), + empty_args); ASSERT_EQ(value, 1); // Test setting alloc_pattern to 2 @@ -31,8 +35,8 @@ TEST_F(test, ctl_debug_read_from_string) { "debug.heap.alloc_pattern=2"), UMF_RESULT_SUCCESS); ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, - "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, - sizeof(value)); + "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, sizeof(value), + empty_args); ASSERT_EQ(value, 2); // Test setting alloc_pattern to 0 @@ -40,23 +44,22 @@ TEST_F(test, ctl_debug_read_from_string) { "debug.heap.alloc_pattern=0"), UMF_RESULT_SUCCESS); ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, - "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, - sizeof(value)); + "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, sizeof(value), + empty_args); ASSERT_EQ(value, 0); // Negative test: non-existent configuration ASSERT_NE(ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, "debug.heap.non_existent", CTL_QUERY_READ, &value, - sizeof(value)), + sizeof(value), empty_args), UMF_RESULT_SUCCESS); // Negative test: invalid path ASSERT_NE(ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, "invalid.path.alloc_pattern", CTL_QUERY_READ, &value, - sizeof(value)), + sizeof(value), empty_args), UMF_RESULT_SUCCESS); - - debug_ctl_register(ctl_handler); + va_end(empty_args); } int ctl_config_write_to_file(const char *filename, const char *data) { @@ -70,6 +73,8 @@ int ctl_config_write_to_file(const char *filename, const char *data) { } TEST_F(test, ctl_debug_read_from_file) { + va_list empty_args; + get_test_va_list(&empty_args); #ifndef _WIN32 ASSERT_EQ(ctl_config_write_to_file( "config.txt", "debug.heap.alloc_pattern=321;\ndebug.heap." @@ -82,19 +87,110 @@ TEST_F(test, ctl_debug_read_from_file) { int value = 0; ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, - "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, 0); + "debug.heap.alloc_pattern", CTL_QUERY_READ, &value, 0, + empty_args); ASSERT_EQ(value, 321); value = 0; ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, "debug.heap.log_level", - CTL_QUERY_READ, &value, 0); + CTL_QUERY_READ, &value, 0, empty_args); ASSERT_EQ(value, 5); value = 0; ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, - "debug.heap.enable_logging", CTL_QUERY_READ, &value, 0); + "debug.heap.enable_logging", CTL_QUERY_READ, &value, 0, + empty_args); ASSERT_EQ(value, 1); - - debug_ctl_register(ctl_handler); #endif + va_end(empty_args); +} + +void ctl_helper(struct ctl *ctl_handler, const char *name, int *out, ...) { + va_list args; + va_start(args, out); + umf_result_t ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + name, CTL_QUERY_READ, out, sizeof(*out), args); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + va_end(args); +} + +TEST_F(test, ctl_debug_node_arg) { + initialize_debug_ctl(); + auto ctl_handler = get_debug_ctl(); + int arg; + va_list empty_args; + get_test_va_list(&empty_args); + + // Following ctl_query calls are expected to return a int value + // passed as a parameter inside of the name + umf_result_t ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test.972.arg_value", CTL_QUERY_READ, + &arg, sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(arg, 972); + + ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test.1410.arg_value", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(arg, 1410); + + ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test_final.1514", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(arg, 1514); + + ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test_final.1621", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(arg, 1621); + + ASSERT_NO_FATAL_FAILURE( + ctl_helper(ctl_handler, "debug.arg_test.{}.arg_value", &arg, 1651)); + + ASSERT_EQ(arg, 1651); + + ASSERT_NO_FATAL_FAILURE(ctl_helper(ctl_handler, "debug.{}.{}.arg_value", + &arg, "arg_test", 1655)); + + ASSERT_EQ(arg, 1655); + + ASSERT_NO_FATAL_FAILURE(ctl_helper(ctl_handler, "{}.{}.{}.{}", &arg, + "debug", "arg_test", 1920, "arg_value")); + + ASSERT_EQ(arg, 1920); + va_end(empty_args); +} + +TEST_F(test, ctl_debug_node_arg_invalid) { + initialize_debug_ctl(); + auto ctl_handler = get_debug_ctl(); + int arg; + va_list empty_args; + get_test_va_list(&empty_args); + + umf_result_t ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test.42", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test.arg_value", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + ret = ctl_query(ctl_handler, NULL, CTL_QUERY_PROGRAMMATIC, + "debug.arg_test.wrong_type.arg_value", CTL_QUERY_READ, &arg, + sizeof(arg), empty_args); + + ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + va_end(empty_args); } diff --git a/test/poolFixtures.hpp b/test/poolFixtures.hpp index 633ebba43..98778cd56 100644 --- a/test/poolFixtures.hpp +++ b/test/poolFixtures.hpp @@ -715,15 +715,15 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { const size_t max_allocs = 10; std::list ptrs; size_t alloc_count = 0; - auto ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + auto ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", + &alloc_count, sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, 0ull); for (size_t i = 1; i <= max_allocs; i++) { void *ptr = umfPoolMalloc(pool_get, size); ASSERT_NE(ptr, nullptr); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, i); ptrs.push_back(ptr); @@ -735,8 +735,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { } ptrs.clear(); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, 0ull); @@ -749,8 +749,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { ptr = umfPoolRealloc(pool_get, nullptr, size); } ASSERT_NE(ptr, nullptr); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", + &alloc_count, sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, i); ptrs.push_back(ptr); @@ -759,8 +759,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { ptr = umfPoolRealloc(pool_get, ptr, size * 2); ASSERT_NE(ptr, nullptr); } - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, max_allocs); size_t allocs = ptrs.size(); @@ -774,8 +774,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { } } ptrs.clear(); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, 0ull); } @@ -784,8 +784,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { for (size_t i = 1; i <= max_allocs; i++) { void *ptr = umfPoolCalloc(pool_get, 1, size); ASSERT_NE(ptr, nullptr); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", + &alloc_count, sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, i); ptrs.push_back(ptr); @@ -796,8 +796,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } ptrs.clear(); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, 0ull); } @@ -806,8 +806,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { for (size_t i = 1; i <= max_allocs; i++) { void *ptr = umfPoolAlignedMalloc(pool_get, size, 4096); ASSERT_NE(ptr, nullptr); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", + &alloc_count, sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, i); ptrs.push_back(ptr); @@ -819,8 +819,8 @@ TEST_P(umfPoolTest, ctl_stat_alloc_count) { } ptrs.clear(); - ret = umfCtlGet("umf.pool.by_handle.stats.alloc_count", pool_get, - &alloc_count, sizeof(alloc_count)); + ret = umfCtlGet("umf.pool.by_handle.{}.stats.alloc_count", &alloc_count, + sizeof(alloc_count), pool_get); ASSERT_EQ(ret, UMF_RESULT_SUCCESS); ASSERT_EQ(alloc_count, 0ull); } diff --git a/test/pools/disjoint_pool_ctl.cpp b/test/pools/disjoint_pool_ctl.cpp index cb2f870fa..a38af623d 100644 --- a/test/pools/disjoint_pool_ctl.cpp +++ b/test/pools/disjoint_pool_ctl.cpp @@ -101,8 +101,8 @@ TEST_F(test, disjointCtlName) { // Set default name const char *val = "disjoint_new_name"; - ASSERT_SUCCESS(umfCtlSet("umf.pool.default.disjoint.name", NULL, - (void *)val, strlen(val))); + ASSERT_SUCCESS( + umfCtlSet("umf.pool.default.disjoint.name", (void *)val, strlen(val))); umf_disjoint_pool_params_handle_t params = nullptr; ASSERT_SUCCESS(umfDisjointPoolParamsCreate(¶ms)); @@ -133,10 +133,10 @@ TEST_F(test, disjointCtlChangeNameTwice) { // Set default name const char *val = "disjoint_new_name"; const char *val2 = "another_name"; - ASSERT_SUCCESS(umfCtlSet("umf.pool.default.disjoint.name", NULL, - (void *)val, strlen(val))); - ASSERT_SUCCESS(umfCtlSet("umf.pool.default.disjoint.name", NULL, - (void *)val2, strlen(val2))); + ASSERT_SUCCESS( + umfCtlSet("umf.pool.default.disjoint.name", (void *)val, strlen(val))); + ASSERT_SUCCESS(umfCtlSet("umf.pool.default.disjoint.name", (void *)val2, + strlen(val2))); umf_disjoint_pool_params_handle_t params = nullptr; ASSERT_SUCCESS(umfDisjointPoolParamsCreate(¶ms));