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;
/**< 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);
/**< Get values handler of settings items identified by keyword names.
*
@ -136,6 +139,9 @@ struct settings_handler_static {
const char *name;
/**< 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);
/**< 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 _commit commit 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_.
*
*/
#define SETTINGS_STATIC_HANDLER_DEFINE(_hname, _tree, _get, _set, _commit, \
_export) \
#define SETTINGS_STATIC_HANDLER_DEFINE_WITH_CPRIO(_hname, _tree, _get, _set, \
_commit, _export, _cprio) \
const STRUCT_SECTION_ITERABLE(settings_handler_static, \
settings_handler_ ## _hname) = { \
.name = _tree, \
.cprio = _cprio, \
.h_get = _get, \
.h_set = _set, \
.h_commit = _commit, \
.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
*
@ -224,7 +238,20 @@ struct settings_handler_static {
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.
*

View File

@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <limits.h>
#include <zephyr/kernel.h>
#include <zephyr/settings/settings.h>
@ -36,7 +37,7 @@ void settings_init(void)
}
#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;
@ -55,12 +56,19 @@ int settings_register(struct settings_handler *handler)
goto end;
}
}
handler->cprio = cprio;
sys_slist_append(&settings_handlers, &handler->node);
end:
k_mutex_unlock(&settings_lock);
return rc;
}
int settings_register(struct settings_handler *handler)
{
return settings_register_with_cprio(handler, 0);
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
int settings_name_steq(const char *name, const char *key, const char **next)
@ -234,39 +242,80 @@ int settings_commit(void)
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 rc;
int rc2;
int cprio = INT_MIN;
rc = 0;
STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
}
if (ch->h_commit) {
rc2 = ch->h_commit();
if (!rc) {
rc = rc2;
}
}
}
while (true) {
int next_cprio = cprio;
#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
struct settings_handler *ch;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
}
if (ch->h_commit) {
rc2 = ch->h_commit();
if (!rc) {
rc = rc2;
STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
}
if (ch->h_commit) {
next_cprio = set_next_cprio(ch->cprio, cprio, next_cprio);
if (ch->cprio != cprio) {
continue;
}
rc2 = ch->h_commit();
if (!rc) {
rc = rc2;
}
}
}
if (IS_ENABLED(CONFIG_SETTINGS_DYNAMIC_HANDLERS)) {
struct settings_handler *ch;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
}
if (ch->h_commit) {
next_cprio = set_next_cprio(ch->cprio, cprio, next_cprio);
if (ch->cprio != cprio) {
continue;
}
rc2 = ch->h_commit();
if (!rc) {
rc = rc2;
}
}
}
}
if (cprio == next_cprio) {
break;
}
cprio = next_cprio;
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
return rc;
}