Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CTL] Add support for defaults #1216

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions benchmark/benchmark_umf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct provider_interface {
return;
}
umfCtlExec("umf.provider.by_handle.stats.peak_memory.reset", provider,
NULL);
NULL, 0);
}

void postBench([[maybe_unused]] ::benchmark::State &state) {
Expand All @@ -54,7 +54,7 @@ struct provider_interface {
}
size_t arg;
umf_result_t ret = umfCtlGet(
"umf.provider.by_handle.stats.allocated_memory", provider, &arg);
"umf.provider.by_handle.stats.allocated_memory", provider, &arg, 0);
if (ret == UMF_RESULT_SUCCESS) {
state.counters["provider_memory_allocated"] =
static_cast<double>(arg);
Expand Down
11 changes: 7 additions & 4 deletions include/umf/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,30 @@ typedef enum umf_ctl_query_type {
/// @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
/// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure.
///
umf_result_t umfCtlGet(const char *name, void *ctx, void *arg);
umf_result_t umfCtlGet(const char *name, void *ctx, 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
/// @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
/// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure.
///
umf_result_t umfCtlSet(const char *name, void *ctx, void *arg);
umf_result_t umfCtlSet(const char *name, void *ctx, 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
/// @return UMF_RESULT_SUCCESS on success or UMF_RESULT_ERROR_UNKNOWN on failure.
///
umf_result_t umfCtlExec(const char *name, void *ctx, void *arg);
umf_result_t umfCtlExec(const char *name, void *ctx, void *arg, size_t size);

#ifdef __cplusplus
}
Expand Down
7 changes: 7 additions & 0 deletions include/umf/memory_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ umf_memory_pool_handle_t umfPoolByPtr(const void *ptr);
umf_result_t umfPoolGetMemoryProvider(umf_memory_pool_handle_t hPool,
umf_memory_provider_handle_t *hProvider);

///
/// @brief Retrieve name of a given memory \p pool.
/// @param pool handle to the memory pool
/// @return pointer to a string containing the name of the \p pool
///
const char *umfPoolGetName(umf_memory_pool_handle_t pool);

///
/// @brief Set a custom tag on the memory pool that can be later retrieved using umfPoolGetTag.
/// @param hPool specified memory pool
Expand Down
14 changes: 11 additions & 3 deletions include/umf/memory_pool_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,24 @@ typedef struct umf_memory_pool_ops_t {
/// The function is used to perform various control operations
/// on the memory pool.
///
/// @param hPool handle to the memory pool.
/// @param pool handle to the memory pool.
/// @param operationType type of the operation to be performed.
/// @param name name associated with the operation.
/// @param arg argument for the operation.
/// @param size size of the argument [optional - check path requirements]
/// @param queryType type of the query to be performed.
///
/// @return umf_result_t result of the control operation.
///
umf_result_t (*ctl)(void *hPool, int operationType, const char *name,
void *arg, umf_ctl_query_type_t queryType);
umf_result_t (*ctl)(void *pool, int operationType, const char *name,
void *arg, size_t size, umf_ctl_query_type_t queryType);

///
/// @brief Get the name of the memory pool.
/// @param pool pointer to the memory pool
/// @return name of the memory pool
///
const char *(*get_name)(void *pool);
} umf_memory_pool_ops_t;

#ifdef __cplusplus
Expand Down
3 changes: 2 additions & 1 deletion include/umf/memory_provider_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,13 @@ typedef struct umf_memory_provider_ops_t {
/// @param operationType type of the operation to be performed.
/// @param name name associated with the operation.
/// @param arg argument for the operation.
/// @param size TODO(kfilipek)
/// @param queryType type of the query to be performed.
///
/// @return umf_result_t result of the control operation.
///
umf_result_t (*ctl)(void *hProvider, int operationType, const char *name,
void *arg, umf_ctl_query_type_t queryType);
void *arg, size_t size, umf_ctl_query_type_t queryType);

} umf_memory_provider_ops_t;

Expand Down
80 changes: 17 additions & 63 deletions src/ctl/ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#include <stdio.h>
#endif

#define CTL_MAX_ENTRIES 100

#define MAX_CONFIG_FILE_LEN (1 << 20) /* 1 megabyte */

#define CTL_STRING_QUERY_SEPARATOR ";"
Expand All @@ -49,21 +47,6 @@
static int ctl_global_first_free = 0;
static umf_ctl_node_t CTL_NODE(global)[CTL_MAX_ENTRIES];

/*
* This is the top level node of the ctl tree structure. Each node can contain
* children and leaf nodes.
*
* Internal nodes simply create a new path in the tree whereas child nodes are
* the ones providing the read/write functionality by the means of callbacks.
*
* Each tree node must be NULL-terminated, CTL_NODE_END macro is provided for
* convenience.
*/
struct ctl {
umf_ctl_node_t root[CTL_MAX_ENTRIES];
int first_free;
};

void *Zalloc(size_t sz) {
void *ptr = umf_ba_global_alloc(sz);
if (ptr) {
Expand All @@ -81,36 +64,6 @@ char *Strdup(const char *s) {
return p;
}

umf_result_t umfCtlGet(const char *name, void *ctx, void *arg) {
if (name == NULL || arg == NULL || ctx == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_READ,
arg)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}

umf_result_t umfCtlSet(const char *name, void *ctx, void *arg) {
if (name == NULL || arg == NULL || ctx == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_WRITE,
arg)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}

umf_result_t umfCtlExec(const char *name, void *ctx, void *arg) {
if (name == NULL || ctx == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name,
CTL_QUERY_RUNNABLE, arg)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}

/*
* ctl_find_node -- (internal) searches for a matching entry point in the
* provided nodes
Expand Down Expand Up @@ -296,10 +249,10 @@ static void ctl_query_cleanup_real_args(const umf_ctl_node_t *n, void *real_arg,
*/
static int ctl_exec_query_read(void *ctx, const umf_ctl_node_t *n,
umf_ctl_query_source_t source, void *arg,
umf_ctl_index_utlist_t *indexes,
size_t size, umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t query_type) {
(void)extra_name, (void)query_type;
(void)query_type;
assert(n != NULL);
assert(n->cb[CTL_QUERY_READ] != NULL);
assert(MAX_CTL_QUERY_TYPE != query_type);
Expand All @@ -309,7 +262,7 @@ static int ctl_exec_query_read(void *ctx, const umf_ctl_node_t *n,
return -1;
}

return n->cb[CTL_QUERY_READ](ctx, source, arg, indexes, NULL,
return n->cb[CTL_QUERY_READ](ctx, source, arg, size, indexes, extra_name,
MAX_CTL_QUERY_TYPE);
}

Expand All @@ -318,10 +271,10 @@ static int ctl_exec_query_read(void *ctx, const umf_ctl_node_t *n,
*/
static int ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n,
umf_ctl_query_source_t source, void *arg,
umf_ctl_index_utlist_t *indexes,
size_t size, umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t query_type) {
(void)extra_name, (void)query_type;
(void)query_type;
assert(n != NULL);
assert(n->cb[CTL_QUERY_WRITE] != NULL);
assert(MAX_CTL_QUERY_TYPE != query_type);
Expand All @@ -336,8 +289,8 @@ static int ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n,
return -1;
}

int ret = n->cb[CTL_QUERY_WRITE](ctx, source, real_arg, indexes, NULL,
MAX_CTL_QUERY_TYPE);
int ret = n->cb[CTL_QUERY_WRITE](ctx, source, real_arg, size, indexes,
extra_name, MAX_CTL_QUERY_TYPE);
ctl_query_cleanup_real_args(n, real_arg, source);

return ret;
Expand All @@ -348,31 +301,32 @@ static int ctl_exec_query_write(void *ctx, const umf_ctl_node_t *n,
*/
static int ctl_exec_query_runnable(void *ctx, const umf_ctl_node_t *n,
umf_ctl_query_source_t source, void *arg,
umf_ctl_index_utlist_t *indexes,
size_t size, umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t query_type) {
(void)extra_name, (void)query_type;
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, indexes, NULL,
MAX_CTL_QUERY_TYPE);
return n->cb[CTL_QUERY_RUNNABLE](ctx, source, arg, size, indexes,
extra_name, MAX_CTL_QUERY_TYPE);
}

static int ctl_exec_query_subtree(void *ctx, const umf_ctl_node_t *n,
umf_ctl_query_source_t source, void *arg,
umf_ctl_index_utlist_t *indexes,
size_t size, umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t query_type) {
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, indexes, extra_name,
return n->cb[CTL_QUERY_SUBTREE](ctx, source, arg, size, indexes, extra_name,
query_type);
}

typedef int (*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);
Expand All @@ -389,7 +343,8 @@ static umf_ctl_exec_query_t ctl_exec_query[MAX_CTL_QUERY_TYPE] = {
* from the ctl tree
*/
int ctl_query(struct ctl *ctl, void *ctx, umf_ctl_query_source_t source,
const char *name, umf_ctl_query_type_t type, void *arg) {
const char *name, umf_ctl_query_type_t type, void *arg,
size_t size) {
if (name == NULL) {
errno = EINVAL;
return -1;
Expand Down Expand Up @@ -426,10 +381,9 @@ int ctl_query(struct ctl *ctl, void *ctx, umf_ctl_query_source_t source,
goto out;
}

const char *extra_name = &name[0] + name_offset;
ret =
ctl_exec_query[n->type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type](
ctx, n, source, arg, indexes, extra_name, type);
ctx, n, source, arg, size, indexes, name + name_offset, type);
out:
ctl_delete_indexes(indexes);

Expand Down Expand Up @@ -496,7 +450,7 @@ static int ctl_load_config(struct ctl *ctl, void *ctx, char *buf) {
}

r = ctl_query(ctl, ctx, CTL_QUERY_CONFIG_INPUT, name, CTL_QUERY_WRITE,
value);
value, 0);

if (r < 0 && ctx != NULL) {
return -1;
Expand Down
24 changes: 20 additions & 4 deletions src/ctl/ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
extern "C" {
#endif

struct ctl;
#define CTL_MAX_ENTRIES 100

typedef struct ctl_index_utlist {
const char *name;
Expand All @@ -46,7 +46,7 @@ typedef enum ctl_query_source {
} umf_ctl_query_source_t;

typedef int (*node_callback)(void *ctx, umf_ctl_query_source_t type, void *arg,
umf_ctl_index_utlist_t *indexes,
size_t size, umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t query_type);

Expand Down Expand Up @@ -98,8 +98,23 @@ typedef struct ctl_node {
const struct ctl_node *children;
} umf_ctl_node_t;

/*
* This is the top level node of the ctl tree structure. Each node can contain
* children and leaf nodes.
*
* Internal nodes simply create a new path in the tree whereas child nodes are
* the ones providing the read/write functionality by the means of callbacks.
*
* Each tree node must be NULL-terminated, CTL_NODE_END macro is provided for
* convenience.
*/
struct ctl {
umf_ctl_node_t root[CTL_MAX_ENTRIES];
int first_free;
};

struct ctl *ctl_new(void);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you move ctl struct to header you should remove this function, and update other places.

void ctl_delete(struct ctl *stats);
void ctl_delete(struct ctl *c);

void initialize_global_ctl(void);

Expand Down Expand Up @@ -138,7 +153,8 @@ int ctl_arg_string(const void *arg, void *dest, size_t dest_size);
#define CTL_NODE(name, ...) ctl_node_##__VA_ARGS__##_##name

int ctl_query(struct ctl *ctl, void *ctx, umf_ctl_query_source_t source,
const char *name, umf_ctl_query_type_t type, void *arg);
const char *name, umf_ctl_query_type_t type, void *arg,
size_t size);

/* Declaration of a new child node */
#define CTL_CHILD(name, ...) \
Expand Down
40 changes: 40 additions & 0 deletions src/libumf.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

#include <stddef.h>
#include <string.h>

#include "base_alloc_global.h"
#include "ipc_cache.h"
Expand Down Expand Up @@ -97,3 +98,42 @@ void umfTearDown(void) {
}

int umfGetCurrentVersion(void) { return UMF_VERSION_CURRENT; }

umf_result_t umfCtlGet(const char *name, void *ctx, void *arg, size_t size) {
if (name == NULL || arg == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
// using ctx is disallowed for default settings
if (ctx && strstr(name, ".default.")) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_READ,
arg, size)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}

umf_result_t umfCtlSet(const char *name, void *ctx, void *arg, size_t size) {
// Context can be NULL when setting defaults
if (name == NULL || arg == NULL || size == 0) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
// using ctx is disallowed for default settings
if (ctx && strstr(name, ".default.")) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name, CTL_QUERY_WRITE,
arg, size)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}

umf_result_t umfCtlExec(const char *name, void *ctx, void *arg, size_t size) {
if (name == NULL || arg == NULL || ctx == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name,
CTL_QUERY_RUNNABLE, arg, size)
? UMF_RESULT_ERROR_UNKNOWN
: UMF_RESULT_SUCCESS;
}
Loading
Loading