|
24 | 24 | #include "utils_assert.h"
|
25 | 25 | #include "utils_concurrency.h"
|
26 | 26 | #include "utils_log.h"
|
| 27 | +#include "utlist.h" |
27 | 28 |
|
28 |
| -#define UMF_DEFAULT_SIZE 100 |
29 |
| -#define UMF_DEFAULT_LEN 100 |
| 29 | +typedef struct ctl_default_entry_t { |
| 30 | + char *name; |
| 31 | + void *value; |
| 32 | + size_t value_size; |
| 33 | + umf_ctl_query_source_t source; |
| 34 | + struct ctl_default_entry_t *next; |
| 35 | +} ctl_default_entry_t; |
| 36 | + |
| 37 | +static ctl_default_entry_t *ctl_default_list = NULL; |
30 | 38 |
|
31 | 39 | utils_mutex_t ctl_mtx;
|
32 | 40 | static UTIL_ONCE_FLAG mem_pool_ctl_initialized = UTIL_ONCE_FLAG_INIT;
|
33 | 41 |
|
34 |
| -char CTL_DEFAULT_ENTRIES[UMF_DEFAULT_SIZE][UMF_DEFAULT_LEN] = {0}; |
35 |
| -char CTL_DEFAULT_VALUES[UMF_DEFAULT_SIZE][UMF_DEFAULT_LEN] = {0}; |
36 |
| - |
37 | 42 | static struct ctl umf_pool_ctl_root;
|
38 | 43 |
|
39 | 44 | static void pool_ctl_init(void);
|
@@ -79,36 +84,76 @@ static umf_result_t CTL_SUBTREE_HANDLER(default)(
|
79 | 84 |
|
80 | 85 | utils_mutex_lock(&ctl_mtx);
|
81 | 86 |
|
| 87 | + ctl_default_entry_t *entry = NULL; |
| 88 | + LL_FOREACH(ctl_default_list, entry) { |
| 89 | + if (strcmp(entry->name, extra_name) == 0) { |
| 90 | + break; |
| 91 | + } |
| 92 | + } |
| 93 | + |
82 | 94 | if (queryType == CTL_QUERY_WRITE) {
|
83 |
| - int i = 0; |
84 |
| - for (; i < UMF_DEFAULT_SIZE; i++) { |
85 |
| - if (CTL_DEFAULT_ENTRIES[i][0] == '\0' || |
86 |
| - strcmp(CTL_DEFAULT_ENTRIES[i], extra_name) == 0) { |
87 |
| - strncpy(CTL_DEFAULT_ENTRIES[i], extra_name, UMF_DEFAULT_LEN); |
88 |
| - CTL_DEFAULT_ENTRIES[i][UMF_DEFAULT_LEN - 1] = '\0'; |
89 |
| - strncpy(CTL_DEFAULT_VALUES[i], arg, UMF_DEFAULT_LEN); |
90 |
| - CTL_DEFAULT_VALUES[i][UMF_DEFAULT_LEN - 1] = '\0'; |
91 |
| - break; |
| 95 | + bool is_new_entry = false; |
| 96 | + if (entry == NULL) { |
| 97 | + entry = umf_ba_global_alloc(sizeof(*entry)); |
| 98 | + if (entry == NULL) { |
| 99 | + utils_mutex_unlock(&ctl_mtx); |
| 100 | + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; |
92 | 101 | }
|
| 102 | + |
| 103 | + entry->name = NULL; |
| 104 | + entry->value = NULL; |
| 105 | + entry->next = NULL; |
| 106 | + is_new_entry = true; |
93 | 107 | }
|
94 |
| - if (UMF_DEFAULT_SIZE == i) { |
95 |
| - LOG_ERR("Default entries array is full"); |
| 108 | + |
| 109 | + size_t name_len = strlen(extra_name) + 1; |
| 110 | + char *new_name = umf_ba_global_alloc(name_len); |
| 111 | + if (new_name == NULL) { |
96 | 112 | utils_mutex_unlock(&ctl_mtx);
|
97 |
| - return UMF_RESULT_ERROR_OUT_OF_RESOURCES; |
| 113 | + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; |
98 | 114 | }
|
99 |
| - } else if (queryType == CTL_QUERY_READ) { |
100 |
| - int i = 0; |
101 |
| - for (; i < UMF_DEFAULT_SIZE; i++) { |
102 |
| - if (strcmp(CTL_DEFAULT_ENTRIES[i], extra_name) == 0) { |
103 |
| - strncpy(arg, CTL_DEFAULT_VALUES[i], size); |
104 |
| - break; |
| 115 | + |
| 116 | + memcpy(new_name, extra_name, name_len); |
| 117 | + if (entry->name) { |
| 118 | + umf_ba_global_free(entry->name); |
| 119 | + } |
| 120 | + entry->name = new_name; |
| 121 | + |
| 122 | + void *new_value = NULL; |
| 123 | + if (size > 0) { |
| 124 | + new_value = umf_ba_global_alloc(size); |
| 125 | + if (new_value == NULL) { |
| 126 | + utils_mutex_unlock(&ctl_mtx); |
| 127 | + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; |
105 | 128 | }
|
| 129 | + memcpy(new_value, arg, size); |
106 | 130 | }
|
107 |
| - if (UMF_DEFAULT_SIZE == i) { |
| 131 | + |
| 132 | + if (entry->value) { |
| 133 | + umf_ba_global_free(entry->value); |
| 134 | + } |
| 135 | + |
| 136 | + entry->value = new_value; |
| 137 | + entry->value_size = size; |
| 138 | + entry->source = source; |
| 139 | + |
| 140 | + if (is_new_entry) { |
| 141 | + LL_APPEND(ctl_default_list, entry); |
| 142 | + } |
| 143 | + } else if (queryType == CTL_QUERY_READ) { |
| 144 | + if (entry == NULL) { |
108 | 145 | LOG_WARN("Wrong path name: %s", extra_name);
|
109 | 146 | utils_mutex_unlock(&ctl_mtx);
|
110 | 147 | return UMF_RESULT_ERROR_INVALID_ARGUMENT;
|
111 | 148 | }
|
| 149 | + |
| 150 | + if (entry->value_size > size) { |
| 151 | + utils_mutex_unlock(&ctl_mtx); |
| 152 | + LOG_ERR("Provided buffer size %zu is smaller then field size %zu", |
| 153 | + size, entry->value_size); |
| 154 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 155 | + } |
| 156 | + memcpy(arg, entry->value, entry->value_size); |
112 | 157 | }
|
113 | 158 |
|
114 | 159 | utils_mutex_unlock(&ctl_mtx);
|
@@ -174,12 +219,11 @@ static const umf_pool_create_flags_t UMF_POOL_CREATE_FLAG_ALL =
|
174 | 219 | // windows do not allow to use uninitialized va_list so this function help us to initialize it.
|
175 | 220 | static umf_result_t default_ctl_helper(const umf_memory_pool_ops_t *ops,
|
176 | 221 | void *ctl, const char *name, void *arg,
|
177 |
| - ...) { |
| 222 | + size_t size, ...) { |
178 | 223 | va_list empty_args;
|
179 |
| - va_start(empty_args, arg); |
180 |
| - umf_result_t ret = |
181 |
| - ops->ext_ctl(ctl, CTL_QUERY_PROGRAMMATIC, name, arg, UMF_DEFAULT_LEN, |
182 |
| - CTL_QUERY_WRITE, empty_args); |
| 224 | + va_start(empty_args, size); |
| 225 | + umf_result_t ret = ops->ext_ctl(ctl, CTL_QUERY_PROGRAMMATIC, name, arg, |
| 226 | + size, CTL_QUERY_WRITE, empty_args); |
183 | 227 | va_end(empty_args);
|
184 | 228 | return ret;
|
185 | 229 | }
|
@@ -246,18 +290,23 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
|
246 | 290 | }
|
247 | 291 |
|
248 | 292 | // Set default property "name" to pool if exists
|
249 |
| - for (int i = 0; i < UMF_DEFAULT_SIZE; i++) { |
250 |
| - const char *pname = NULL; |
251 |
| - ret = ops->get_name(NULL, &pname); |
252 |
| - if (ret != UMF_RESULT_SUCCESS) { |
253 |
| - LOG_ERR("Failed to get pool name"); |
254 |
| - goto err_pool_init; |
255 |
| - } |
256 |
| - if (CTL_DEFAULT_ENTRIES[i][0] != '\0' && pname && |
257 |
| - strstr(CTL_DEFAULT_ENTRIES[i], pname)) { |
258 |
| - |
259 |
| - default_ctl_helper(ops, pool->pool_priv, CTL_DEFAULT_ENTRIES[i], |
260 |
| - CTL_DEFAULT_VALUES[i]); |
| 293 | + const char *pname = NULL; |
| 294 | + ret = ops->get_name(NULL, &pname); |
| 295 | + if (ret != UMF_RESULT_SUCCESS) { |
| 296 | + LOG_ERR("Failed to get pool name"); |
| 297 | + goto err_pool_init; |
| 298 | + } |
| 299 | + assert(pname != NULL); |
| 300 | + |
| 301 | + size_t pname_len = strlen(pname); |
| 302 | + ctl_default_entry_t *it = NULL; |
| 303 | + LL_FOREACH(ctl_default_list, it) { |
| 304 | + if (strlen(it->name) > pname_len + 1 && |
| 305 | + strncmp(it->name, pname, pname_len) == 0 && |
| 306 | + it->name[pname_len] == '.') { |
| 307 | + const char *ctl_name = it->name + pname_len + 1; |
| 308 | + default_ctl_helper(ops, pool->pool_priv, ctl_name, it->value, |
| 309 | + it->value_size); |
261 | 310 | }
|
262 | 311 | }
|
263 | 312 |
|
@@ -454,3 +503,23 @@ umf_result_t umfPoolGetTag(umf_memory_pool_handle_t hPool, void **tag) {
|
454 | 503 | utils_mutex_unlock(&hPool->lock);
|
455 | 504 | return UMF_RESULT_SUCCESS;
|
456 | 505 | }
|
| 506 | + |
| 507 | +void umfPoolCtlDefaultsDestroy(void) { |
| 508 | + utils_init_once(&mem_pool_ctl_initialized, pool_ctl_init); |
| 509 | + |
| 510 | + utils_mutex_lock(&ctl_mtx); |
| 511 | + |
| 512 | + ctl_default_entry_t *entry = NULL, *tmp = NULL; |
| 513 | + LL_FOREACH_SAFE(ctl_default_list, entry, tmp) { |
| 514 | + LL_DELETE(ctl_default_list, entry); |
| 515 | + if (entry->name) { |
| 516 | + umf_ba_global_free(entry->name); |
| 517 | + } |
| 518 | + if (entry->value) { |
| 519 | + umf_ba_global_free(entry->value); |
| 520 | + } |
| 521 | + umf_ba_global_free(entry); |
| 522 | + } |
| 523 | + |
| 524 | + utils_mutex_unlock(&ctl_mtx); |
| 525 | +} |
0 commit comments