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

Conversation

KFilipek
Copy link
Contributor

@KFilipek KFilipek commented Mar 21, 2025

[CTL] Add support for defaults

Description

This PR introduces initial support for setting up default values.

Checklist

  • Code compiles without errors locally
  • All tests pass locally
  • CI workflows execute properly

@KFilipek KFilipek added the enhancement New feature or request label Mar 21, 2025
@KFilipek KFilipek self-assigned this Mar 21, 2025
@KFilipek KFilipek linked an issue Mar 21, 2025 that may be closed by this pull request
@KFilipek KFilipek force-pushed the ctl-default branch 5 times, most recently from 2ec6659 to 408f2c4 Compare March 24, 2025 08:16
@KFilipek KFilipek marked this pull request as ready for review March 24, 2025 09:43
@KFilipek KFilipek requested a review from a team as a code owner March 24, 2025 09:43
umf_os_memory_provider_params_handle_t os_memory_provider_params = NULL;
umf_memory_provider_ops_t *os_provider_ops = umfOsMemoryProviderOps();
if (os_provider_ops == NULL) {
GTEST_SKIP() << "OS memory provider is not supported!";
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of adding such skip msg, I guess we should add this test in CMake only when OS prov and disjoint pool are enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's what for we've added a dummy function.

Copy link
Contributor

Choose a reason for hiding this comment

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

yy? not sure what you mean

@@ -35,7 +35,7 @@ TEST_F(test, ctl_by_handle_os_provider) {

int ipc_enabled = 0xBAD;
ret = umfCtlGet("umf.provider.by_handle.params.ipc_enabled", hProvider,
Copy link
Contributor

Choose a reason for hiding this comment

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

do we have any test for umfCtlGet that pass something else than 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I see it's not a part of this PR

Copy link
Contributor

Choose a reason for hiding this comment

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

You're adding a new paramter and without testing values other than 0 it's not properly tested. At least mark in tests a TODO for future.

Copy link
Contributor Author

@KFilipek KFilipek Mar 26, 2025

Choose a reason for hiding this comment

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

This callback discard completely size, so such test will cover completely nothing and will test nothing.

static int 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) {
    /* suppress unused-parameter errors */
    (void)source, (void)indexes, (void)ctx, (void)extra_name, (void)query_type,
        (void)size;

    int *arg_out = arg;
    os_memory_provider_t *os_provider = (os_memory_provider_t *)ctx;
    *arg_out = os_provider->IPC_enabled;
    return 0;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm reading your last comment as "size is useless" ;)

Let me re-phrase - whenever size is used, please add a test with various values (user may give some input we may not expect, e.g. on wrong assumptions on how this func works) or mark a TODO for adding tests in the future.

/// @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);
void *arg, size_t size, umf_ctl_query_type_t queryType);
Copy link
Contributor

Choose a reason for hiding this comment

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

hPool -> pool to be consistent across the file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

const char *extra_name,
umf_ctl_query_type_t queryType) {
(void)indexes, (void)source, (void)size, (void)ctx;
assert(queryType == CTL_QUERY_WRITE && "DO NOT SUPPORTED QUERY TYPE");
Copy link
Contributor

Choose a reason for hiding this comment

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

not supported query type (without "do" + small letters)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


#include "base_alloc_global.h"
#include "memory_pool_internal.h"
#include "memory_provider_internal.h"
#include "provider_tracking.h"

enum {
UMF_DEFAULT_SIZE = 100,
Copy link
Contributor

Choose a reason for hiding this comment

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

we use defines or static consts

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, I used #define

break;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what if we run out of default entries?
what if arg len > default len?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added error handling

disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
if (strstr(extra_name, pool->params.name) != NULL) {
strncpy(pool->params.name, (char *)arg,
sizeof(pool->params.name) / sizeof(pool->params.name[0]) - 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't get why we have a div here - could you comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Assuming that char is 1 byte, it's unnecessary

@@ -35,7 +35,7 @@ TEST_F(test, ctl_by_handle_os_provider) {

int ipc_enabled = 0xBAD;
ret = umfCtlGet("umf.provider.by_handle.params.ipc_enabled", hProvider,
&ipc_enabled);
&ipc_enabled, 0); // Some handlers omit size
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't get it - is size always required? is it a mandatory arg? when I should set it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added description that is an optional argument

@@ -12,6 +12,7 @@
#include "provider.hpp"
#include "provider_null.h"
#include "provider_trace.h"
#include "umf/memory_pool.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be #include <memory_pool.h>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it completely

#include <umf/memory_pool.h>
#include <umf/pools/pool_disjoint.h>

#include "base.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

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

cleanup includes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ASSERT_EQ(ret, UMF_RESULT_SUCCESS);

const char *val = "disjoint_new_name";
umfCtlSet("umf.pool.default.disjoint.name", NULL, (void *)val, strlen(val));
Copy link
Contributor

Choose a reason for hiding this comment

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

do this func return any result if succeeds? we should assert this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added macro to handle success


umf_memory_pool_handle_t hPool;
umf_disjoint_pool_params_handle_t params;
umfDisjointPoolParamsCreate(&params);
Copy link
Contributor

Choose a reason for hiding this comment

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

add asserts for results

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -135,12 +135,20 @@ typedef struct umf_memory_pool_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 size of the argument.
Copy link
Contributor

Choose a reason for hiding this comment

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

add: may be optional - please check spec for path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


///
/// @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 arg [in] pointer to the value that will be set
/// @param size [in] size of the value
Copy link
Contributor

@bratpiorka bratpiorka Mar 25, 2025

Choose a reason for hiding this comment

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

set + get: ctx - should be null for default + test

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

ASSERT_EQ(ret, UMF_RESULT_SUCCESS);

const char *val = "disjoint_new_name";
umfCtlSet("umf.pool.default.disjoint.name", NULL, (void *)val, strlen(val));
Copy link
Contributor

Choose a reason for hiding this comment

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

where do you test get?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@KFilipek KFilipek force-pushed the ctl-default branch 4 times, most recently from b7324ed to 8e3a2fc Compare March 25, 2025 13:00
Copy link
Contributor

@lplewa lplewa left a comment

Choose a reason for hiding this comment

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

umf_result_t umfCtlExec(const char *name, void *ctx, void *arg); should also have arg size imho.

src/ctl/ctl.c Outdated
@@ -416,11 +402,14 @@ int ctl_query(struct ctl *ctl, void *ctx, umf_ctl_query_source_t source,
errno = EINVAL;
goto out;
}
const char *extra_name = &name[0];
if (strstr(extra_name, "by_handle") != NULL) {
extra_name = &name[0] + name_offset;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not include UMF specyfic soultions in ctl* files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

const char *extra_name,
umf_ctl_query_type_t queryType) {
(void)indexes, (void)source, (void)size, (void)ctx;
assert(queryType == CTL_QUERY_WRITE && "not supported query type");
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not an assert. This sould return a correct error code to the user.

Copy link
Contributor

Choose a reason for hiding this comment

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

  • read should work

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

@@ -99,6 +135,15 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
goto err_pool_init;
}

// Set default property "name" to pool if exists
for (int i = 0; i < UMF_DEFAULT_SIZE; i++) {
if (CTL_DEFAULT_ENTRIES[i][0] != '\0') {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should only call it for entries with matching name, not all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now, should be fine

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2025 Intel Corporation
Copy link
Contributor

Choose a reason for hiding this comment

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

imho this should not be a .h files

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@KFilipek KFilipek force-pushed the ctl-default branch 2 times, most recently from 338947a to 29380ba Compare March 25, 2025 16:02
@@ -35,7 +35,7 @@ TEST_F(test, ctl_by_handle_os_provider) {

int ipc_enabled = 0xBAD;
ret = umfCtlGet("umf.provider.by_handle.params.ipc_enabled", hProvider,
Copy link
Contributor

Choose a reason for hiding this comment

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

You're adding a new paramter and without testing values other than 0 it's not properly tested. At least mark in tests a TODO for future.

umf_os_memory_provider_params_handle_t os_memory_provider_params = NULL;
umf_memory_provider_ops_t *os_provider_ops = umfOsMemoryProviderOps();
if (os_provider_ops == NULL) {
GTEST_SKIP() << "OS memory provider is not supported!";
Copy link
Contributor

Choose a reason for hiding this comment

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

yy? not sure what you mean

@KFilipek KFilipek force-pushed the ctl-default branch 2 times, most recently from 94ca030 to a8a7fe8 Compare March 26, 2025 11:45
@KFilipek KFilipek force-pushed the ctl-default branch 3 times, most recently from 864f888 to ac65d2f Compare March 26, 2025 13:43
src/ctl/ctl.c Outdated
if (name == NULL || arg == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
// using ctx is disallowed for default settings
Copy link
Contributor

Choose a reason for hiding this comment

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

There should not be any assumptions about ctl tree in ctl.c file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved UmfCtl* functions to libumf.c

umf_ctl_query_type_t queryType) {
(void)indexes, (void)source, (void)size, (void)ctx;

if (queryType == CTL_QUERY_WRITE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. Thread safety. you can add multithreaded tests too.
  2. What if user set default multipletimes, you should overide entry in table, not add another one.

// Set default property "name" to pool if exists
for (int i = 0; i < UMF_DEFAULT_SIZE; i++) {
if (CTL_DEFAULT_ENTRIES[i][0] != '\0' &&
strstr(CTL_DEFAULT_ENTRIES[i], umfPoolGetName(pool))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please cache umfPoolName, as you can change it latter on with ctl call, and all following default entries will not work

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now should work as designed, I've added test for that.

/// @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);
Copy link
Contributor

Choose a reason for hiding this comment

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

It should return pool type name if pool handle is null, and pool specific name if handle is not null.

This is wording we should update provider ops too - ATM all providers ignore provider handle in getName function, but we should document it too.

This allows us always check default provider/pool name even if it was changed.

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.

umf_ctl_index_utlist_t *indexes,
const char *extra_name,
umf_ctl_query_type_t queryType) {
(void)indexes, (void)source, (void)size, (void)ctx;
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait - you introduced size parameter exactly to be able precisely handle this function, so you can handle parameters with any size, and you are not using it here.

Please update this function to handle parameters any size. Please add test including arguments of different size and type.

Comment on lines +27 to +71
#include <ctl/ctl.h>

/* Disjoint pool CTL implementation */
struct ctl disjoint_ctl_root;
static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT;

static int 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)size, (void)extra_name;
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;

if (arg == NULL) {
return -1;
}

strncpy(pool->params.name, (char *)arg, sizeof(pool->params.name) - 1);
return 0;
}

static const umf_ctl_node_t CTL_NODE(disjoint)[] = {CTL_LEAF_RO(name),
CTL_NODE_END};

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) {
(void)operationType, (void)queryType;
utils_init_once(&ctl_initialized, initialize_disjoint_ctl);

const char *prefix = "disjoint.";
const char *name_wo_prefix = strstr(name, "disjoint.");

// Check if the name has the prefix
if ((name_wo_prefix = strstr(name, prefix)) == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
return ctl_query(&disjoint_ctl_root, hPool, CTL_QUERY_PROGRAMMATIC,
name_wo_prefix, CTL_QUERY_READ, arg, size);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add test if both strings works
umf.pool.byHandle.name
umf.pool.default. disjoint.name

imho it dont.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CTL - setting global namespace
4 participants