From 95fa167e453bf92ad5306a9aac430e6abab3af06 Mon Sep 17 00:00:00 2001 From: Laczen JMS Date: Tue, 15 Oct 2024 12:41:35 +0200 Subject: [PATCH] settings: introduce priority for commit A priority is introduced to allow scheduling of commit routines. Signed-off-by: Laczen JMS --- include/zephyr/settings/settings.h | 33 ++++++++++- subsys/settings/src/settings.c | 95 ++++++++++++++++++++++-------- 2 files changed, 102 insertions(+), 26 deletions(-) diff --git a/include/zephyr/settings/settings.h b/include/zephyr/settings/settings.h index 99b9fc21077..f22f1aba118 100644 --- a/include/zephyr/settings/settings.h +++ b/include/zephyr/settings/settings.h @@ -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. * diff --git a/subsys/settings/src/settings.c b/subsys/settings/src/settings.c index e2072234fa9..dde6135a411 100644 --- a/subsys/settings/src/settings.c +++ b/subsys/settings/src/settings.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -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; }