summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/cyclic.c17
-rw-r--r--doc/develop/cyclic.rst13
2 files changed, 30 insertions, 0 deletions
diff --git a/common/cyclic.c b/common/cyclic.c
index b695f092f52..ec952a01ee1 100644
--- a/common/cyclic.c
+++ b/common/cyclic.c
@@ -28,9 +28,23 @@ struct hlist_head *cyclic_get_list(void)
return (struct hlist_head *)&gd->cyclic_list;
}
+static bool cyclic_is_registered(const struct cyclic_info *cyclic)
+{
+ const struct cyclic_info *c;
+
+ hlist_for_each_entry(c, cyclic_get_list(), list) {
+ if (c == cyclic)
+ return true;
+ }
+
+ return false;
+}
+
void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
uint64_t delay_us, const char *name)
{
+ cyclic_unregister(cyclic);
+
memset(cyclic, 0, sizeof(*cyclic));
/* Store values in struct */
@@ -43,6 +57,9 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
void cyclic_unregister(struct cyclic_info *cyclic)
{
+ if (!cyclic_is_registered(cyclic))
+ return;
+
hlist_del(&cyclic->list);
}
diff --git a/doc/develop/cyclic.rst b/doc/develop/cyclic.rst
index 6f1da6f0d9b..a99b17052f5 100644
--- a/doc/develop/cyclic.rst
+++ b/doc/develop/cyclic.rst
@@ -54,3 +54,16 @@ responsible for calling all registered cyclic functions, into the
common schedule() function. This guarantees that cyclic_run() is
executed very often, which is necessary for the cyclic functions to
get scheduled and executed at their configured periods.
+
+Idempotence
+-----------
+
+Both the cyclic_register() and cyclic_unregister() functions are safe
+to call on any struct cyclic_info, regardless of whether that instance
+is already registered or not.
+
+More specifically, calling cyclic_unregister() with a cyclic_info
+which is not currently registered is a no-op, while calling
+cyclic_register() with a cyclic_info which is currently registered
+results in it being automatically unregistered, and then registered
+with the new callback function and timeout parameters.