settings: introduce priority for commit

A priority is introduced to allow scheduling of commit routines.

Signed-off-by: Laczen JMS <laczenjms@gmail.com>
This commit is contained in:
Laczen JMS 2024-10-15 12:41:35 +02:00 committed by David Leach
parent 54545254d9
commit 95fa167e45
2 changed files with 102 additions and 26 deletions

View file

@ -70,6 +70,9 @@ struct settings_handler {
const char *name; const char *name;
/**< Name of subtree. */ /**< Name of subtree. */
int cprio;
/**< Priority of commit, lower value is higher priority */
int (*h_get)(const char *key, char *val, int val_len_max); int (*h_get)(const char *key, char *val, int val_len_max);
/**< Get values handler of settings items identified by keyword names. /**< Get values handler of settings items identified by keyword names.
* *
@ -136,6 +139,9 @@ struct settings_handler_static {
const char *name; const char *name;
/**< Name of subtree. */ /**< Name of subtree. */
int cprio;
/**< Priority of commit, lower value is higher priority */
int (*h_get)(const char *key, char *val, int val_len_max); int (*h_get)(const char *key, char *val, int val_len_max);
/**< Get values handler of settings items identified by keyword names. /**< Get values handler of settings items identified by keyword names.
* *
@ -196,22 +202,30 @@ struct settings_handler_static {
* @param _set set routine (can be NULL) * @param _set set routine (can be NULL)
* @param _commit commit routine (can be NULL) * @param _commit commit routine (can be NULL)
* @param _export export routine (can be NULL) * @param _export export routine (can be NULL)
* @param _cprio commit priority (lower value is higher priority)
* *
* This creates a variable _hname prepended by settings_handler_. * This creates a variable _hname prepended by settings_handler_.
* *
*/ */
#define SETTINGS_STATIC_HANDLER_DEFINE(_hname, _tree, _get, _set, _commit, \ #define SETTINGS_STATIC_HANDLER_DEFINE_WITH_CPRIO(_hname, _tree, _get, _set, \
_export) \ _commit, _export, _cprio) \
const STRUCT_SECTION_ITERABLE(settings_handler_static, \ const STRUCT_SECTION_ITERABLE(settings_handler_static, \
settings_handler_ ## _hname) = { \ settings_handler_ ## _hname) = { \
.name = _tree, \ .name = _tree, \
.cprio = _cprio, \
.h_get = _get, \ .h_get = _get, \
.h_set = _set, \ .h_set = _set, \
.h_commit = _commit, \ .h_commit = _commit, \
.h_export = _export, \ .h_export = _export, \
} }
/* Handlers without commit priority are set to priority O */
#define SETTINGS_STATIC_HANDLER_DEFINE(_hname, _tree, _get, _set, _commit, \
_export) \
SETTINGS_STATIC_HANDLER_DEFINE_WITH_CPRIO(_hname, _tree, _get, _set, \
_commit, _export, 0)
/** /**
* Initialization of settings and backend * Initialization of settings and backend
* *
@ -224,7 +238,20 @@ struct settings_handler_static {
int settings_subsys_init(void); int settings_subsys_init(void);
/** /**
* Register a handler for settings items stored in RAM. * Register a handler for settings items stored in RAM with
* commit priority.
*
* @param cf Structure containing registration info.
* @param cprio Commit priority (lower value is higher priority).
*
* @return 0 on success, non-zero on failure.
*/
int settings_register_with_cprio(struct settings_handler *cf,
int cprio);
/**
* Register a handler for settings items stored in RAM with
* commit priority set to default.
* *
* @param cf Structure containing registration info. * @param cf Structure containing registration info.
* *

View file

@ -9,6 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/settings/settings.h> #include <zephyr/settings/settings.h>
@ -36,7 +37,7 @@ void settings_init(void)
} }
#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS) #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
int settings_register(struct settings_handler *handler) int settings_register_with_cprio(struct settings_handler *handler, int cprio)
{ {
int rc = 0; int rc = 0;
@ -55,12 +56,19 @@ int settings_register(struct settings_handler *handler)
goto end; goto end;
} }
} }
handler->cprio = cprio;
sys_slist_append(&settings_handlers, &handler->node); sys_slist_append(&settings_handlers, &handler->node);
end: end:
k_mutex_unlock(&settings_lock); k_mutex_unlock(&settings_lock);
return rc; return rc;
} }
int settings_register(struct settings_handler *handler)
{
return settings_register_with_cprio(handler, 0);
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */ #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
int settings_name_steq(const char *name, const char *key, const char **next) int settings_name_steq(const char *name, const char *key, const char **next)
@ -234,18 +242,45 @@ int settings_commit(void)
return settings_commit_subtree(NULL); return settings_commit_subtree(NULL);
} }
static int set_next_cprio(int handler_cprio, int cprio, int next_cprio)
{
if (handler_cprio <= cprio) {
return next_cprio;
}
/* If cprio and next_cprio are identical then next_cprio has not
* yet been set to any value and its initialized to the first
* handler_cprio above cprio.
*/
if (cprio == next_cprio) {
return handler_cprio;
}
return MIN(handler_cprio, next_cprio);
}
int settings_commit_subtree(const char *subtree) int settings_commit_subtree(const char *subtree)
{ {
int rc; int rc;
int rc2; int rc2;
int cprio = INT_MIN;
rc = 0; rc = 0;
while (true) {
int next_cprio = cprio;
STRUCT_SECTION_FOREACH(settings_handler_static, ch) { STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) { if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue; continue;
} }
if (ch->h_commit) { if (ch->h_commit) {
next_cprio = set_next_cprio(ch->cprio, cprio, next_cprio);
if (ch->cprio != cprio) {
continue;
}
rc2 = ch->h_commit(); rc2 = ch->h_commit();
if (!rc) { if (!rc) {
rc = rc2; rc = rc2;
@ -253,20 +288,34 @@ int settings_commit_subtree(const char *subtree)
} }
} }
#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS) if (IS_ENABLED(CONFIG_SETTINGS_DYNAMIC_HANDLERS)) {
struct settings_handler *ch; struct settings_handler *ch;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) { SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) { if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue; continue;
} }
if (ch->h_commit) { if (ch->h_commit) {
next_cprio = set_next_cprio(ch->cprio, cprio, next_cprio);
if (ch->cprio != cprio) {
continue;
}
rc2 = ch->h_commit(); rc2 = ch->h_commit();
if (!rc) { if (!rc) {
rc = rc2; rc = rc2;
} }
} }
} }
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */ }
if (cprio == next_cprio) {
break;
}
cprio = next_cprio;
}
return rc; return rc;
} }