diff --git a/doc/releases/migration-guide-4.2.rst b/doc/releases/migration-guide-4.2.rst index 36cafac89819..d9efb14f68f9 100644 --- a/doc/releases/migration-guide-4.2.rst +++ b/doc/releases/migration-guide-4.2.rst @@ -305,13 +305,6 @@ SPI Other subsystems **************** -ZBus -==== - -* The function :c:func:`zbus_chan_add_obs` now requires a :c:struct:`zbus_observer_node` as an argument, - which was previously allocated through :c:func:`k_malloc` internally. The structure must remain valid - in memory until :c:func:`zbus_chan_rem_obs` is called. - Modules ******* diff --git a/doc/releases/release-notes-4.2.rst b/doc/releases/release-notes-4.2.rst index fa9666e72637..bd4e7be8c382 100644 --- a/doc/releases/release-notes-4.2.rst +++ b/doc/releases/release-notes-4.2.rst @@ -194,6 +194,16 @@ New APIs and options * :c:func:`video_query_ctrl` * :c:func:`video_print_ctrl` +* ZBus + + * Runtime observers can work without heap. Now it is possible to choose between static and dynamic + allocation for the runtime observers nodes. + + * :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC` + * :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC` + * :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE` + + New Boards ********** diff --git a/doc/services/zbus/index.rst b/doc/services/zbus/index.rst index a7d6b7c55c4b..cd42ee89b97d 100644 --- a/doc/services/zbus/index.rst +++ b/doc/services/zbus/index.rst @@ -848,28 +848,30 @@ The following code has the exact behavior of the code in :ref:`reading from a ch Runtime observer registration ----------------------------- -It is possible to add observers to channels at runtime if -:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` is enabled. In addition to the channel and observer -references, :c:func:`zbus_chan_add_obs` also requires a :c:struct:`zbus_observer_node` to link the two -together, which must remain valid in memory for the duration that the observer is attached to the -channel. The simplest way to achieve this is to make the structure ``static``. +It is possible to add observers to channels in runtime. Set the +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` to enable the feature. This feature uses the heap to +allocate the nodes dynamically or a memory slab to allocate the nodes statically. It depends on the +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC` which can be +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC` and +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC`. When the heap is enabled, the +dynamic one is automatically chosen. When +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC` is enabled, you need to set the +number of runtime observers you are going to use by setting the +:kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE` configuration. The following example +illustrates the runtime registration usage. + .. code-block:: c ZBUS_LISTENER_DEFINE(my_listener, callback); // ... void thread_entry(void) { - static struct zbus_observer_node obs_node; // ... /* Adding the observer to channel chan1 */ - zbus_chan_add_obs(&chan1, &my_listener, &obs_node, K_NO_WAIT); + zbus_chan_add_obs(&chan1, &my_listener, K_NO_WAIT); /* Removing the observer from channel chan1 */ zbus_chan_rm_obs(&chan1, &my_listener, K_NO_WAIT); -.. warning:: - - The :c:struct:`zbus_observer_node` can only be re-used in :c:func:`zbus_chan_add_obs` after removing - the channel observer it was first associated with through :c:func:`zbus_chan_rm_obs`. Samples ******* @@ -936,7 +938,13 @@ Related configuration options: a pool for the message subscriber for a set of channels; * :kconfig:option:`CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_STATIC_DATA_SIZE` the biggest message of zbus channels to be transported into a message buffer; -* :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` enables the runtime observer registration. +* :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS` enables the runtime observer registration; +* :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC` allocate the runtime observers + statically using a memory slab; +* :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC` allocate the runtime observers + dynamically using the heap; +* :kconfig:option:`CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE` the amount of enabled runtime + observers to statically allocate. API Reference ************* diff --git a/include/zephyr/zbus/zbus.h b/include/zephyr/zbus/zbus.h index c13e77082e73..d4c7b08921be 100644 --- a/include/zephyr/zbus/zbus.h +++ b/include/zephyr/zbus/zbus.h @@ -177,6 +177,9 @@ struct zbus_channel_observation_mask { bool enabled; }; +/** + * @brief Structure for linking observers to chanels + */ struct zbus_channel_observation { const struct zbus_channel *chan; const struct zbus_observer *obs; @@ -861,14 +864,6 @@ static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan) #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__) -/** - * @brief Structure for linking observers to chanels - */ -struct zbus_observer_node { - sys_snode_t node; - const struct zbus_observer *obs; -}; - /** * @brief Add an observer to a channel. * @@ -876,17 +871,18 @@ struct zbus_observer_node { * * @param chan The channel's reference. * @param obs The observer's reference to be added. - * @param node Persistent structure to link the channel to the observer * @param timeout Waiting period to add an observer, * or one of the special values K_NO_WAIT and K_FOREVER. * * @retval 0 Observer added to the channel. - * @retval -EALREADY The observer is already present in the channel's runtime observers list. + * @retval -EBUSY Returned without waiting. * @retval -EAGAIN Waiting period timed out. - * @retval -EINVAL Some parameter is invalid. + * @retval -EEXIST The observer is already present in the channel's observers list. + * @retval -EALREADY The observer is already present in the channel's runtime observers list. + * @retval -ENOMEM No memory available for a new runtime observer node. */ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs, - struct zbus_observer_node *node, k_timeout_t timeout); + k_timeout_t timeout); /** * @brief Remove an observer from a channel. @@ -899,15 +895,22 @@ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observe * or one of the special values K_NO_WAIT and K_FOREVER. * * @retval 0 Observer removed to the channel. - * @retval -EINVAL Invalid data supplied. * @retval -EBUSY Returned without waiting. * @retval -EAGAIN Waiting period timed out. * @retval -ENODATA no observer found in channel's runtime observer list. - * @retval -ENOMEM Returned without waiting. */ int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs, k_timeout_t timeout); +/** @cond INTERNAL_HIDDEN */ + +struct zbus_observer_node { + sys_snode_t node; + const struct zbus_observer *obs; +}; + +/** @endcond */ + #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */ /** diff --git a/samples/subsys/zbus/runtime_obs_registration/sample.yaml b/samples/subsys/zbus/runtime_obs_registration/sample.yaml index c2e87ce6a1fb..946c7a3ac11a 100644 --- a/samples/subsys/zbus/runtime_obs_registration/sample.yaml +++ b/samples/subsys/zbus/runtime_obs_registration/sample.yaml @@ -11,19 +11,49 @@ tests: type: multi_line ordered: false regex: - - "I: System started" - - "I: Activating filter" - - "I: Deactivating filter" - - "I: Bypass filter" - - "I: Disable bypass filter" - - "I: >-- Raw data fetched" - - "I: -|- Filtering data" - - "I: --> Consuming data: Acc x=0, y=0, z=0" - - "I: --> Consuming data: Acc x=2, y=2, z=2" - - "I: --> Consuming data: Acc x=4, y=4, z=4" - - "I: --> Consuming data: Acc x=6, y=6, z=6" - - "I: --> Consuming data: Acc x=7, y=7, z=7" - - "I: --> Consuming data: Acc x=8, y=8, z=8" - - "I: --> Consuming data: Acc x=9, y=9, z=9" - - "I: --> Consuming data: Acc x=10, y=10, z=10" + - ".*I: System started, runtime observers statically allocated" + - ".*I: Activating filter" + - ".*I: Deactivating filter" + - ".*I: Bypass filter" + - ".*I: Disable bypass filter" + - ".*I: >-- Raw data fetched" + - ".*I: -|- Filtering data" + - ".*I: --> Consuming data: Acc x=0, y=0, z=0" + - ".*I: --> Consuming data: Acc x=2, y=2, z=2" + - ".*I: --> Consuming data: Acc x=4, y=4, z=4" + - ".*I: --> Consuming data: Acc x=6, y=6, z=6" + - ".*I: --> Consuming data: Acc x=7, y=7, z=7" + - ".*I: --> Consuming data: Acc x=8, y=8, z=8" + - ".*I: --> Consuming data: Acc x=9, y=9, z=9" + - ".*I: --> Consuming data: Acc x=10, y=10, z=10" tags: zbus + extra_configs: + - CONFIG_ZBUS_PREFER_DYNAMIC_ALLOCATION=n + sample.zbus.runtime_os_registration_dynamic_alloc: + min_ram: 16 + integration_platforms: + - qemu_x86 + arch_exclude: nios2 + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - ".*I: System started, runtime observers dynamically allocated" + - ".*I: Activating filter" + - ".*I: Deactivating filter" + - ".*I: Bypass filter" + - ".*I: Disable bypass filter" + - ".*I: >-- Raw data fetched" + - ".*I: -|- Filtering data" + - ".*I: --> Consuming data: Acc x=0, y=0, z=0" + - ".*I: --> Consuming data: Acc x=2, y=2, z=2" + - ".*I: --> Consuming data: Acc x=4, y=4, z=4" + - ".*I: --> Consuming data: Acc x=6, y=6, z=6" + - ".*I: --> Consuming data: Acc x=7, y=7, z=7" + - ".*I: --> Consuming data: Acc x=8, y=8, z=8" + - ".*I: --> Consuming data: Acc x=9, y=9, z=9" + - ".*I: --> Consuming data: Acc x=10, y=10, z=10" + tags: zbus + extra_configs: + - CONFIG_HEAP_MEM_POOL_SIZE=1024 diff --git a/samples/subsys/zbus/runtime_obs_registration/src/main.c b/samples/subsys/zbus/runtime_obs_registration/src/main.c index 8f66f3644e11..4bf8692bb100 100644 --- a/samples/subsys/zbus/runtime_obs_registration/src/main.c +++ b/samples/subsys/zbus/runtime_obs_registration/src/main.c @@ -41,14 +41,15 @@ ZBUS_SUBSCRIBER_DEFINE(state_change_sub, 5); int main(void) { - LOG_INF("System started"); + LOG_INF("System started, runtime observers %s allocated", + IS_ENABLED(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC) ? "dynamically" + : "statically"); const struct zbus_channel *chan; - struct zbus_observer_node obs_node; while (1) { LOG_INF("Activating filter"); - zbus_chan_add_obs(&raw_data_chan, &filter_lis, &obs_node, K_MSEC(200)); + zbus_chan_add_obs(&raw_data_chan, &filter_lis, K_MSEC(200)); zbus_sub_wait(&state_change_sub, &chan, K_FOREVER); @@ -56,7 +57,7 @@ int main(void) zbus_chan_rm_obs(&raw_data_chan, &filter_lis, K_MSEC(200)); LOG_INF("Bypass filter"); - zbus_chan_add_obs(&raw_data_chan, &consumer_sub, &obs_node, K_MSEC(200)); + zbus_chan_add_obs(&raw_data_chan, &consumer_sub, K_MSEC(200)); zbus_sub_wait(&state_change_sub, &chan, K_FOREVER); diff --git a/subsys/zbus/Kconfig b/subsys/zbus/Kconfig index 9cd518c6215b..a752758d943c 100644 --- a/subsys/zbus/Kconfig +++ b/subsys/zbus/Kconfig @@ -9,6 +9,10 @@ menuconfig ZBUS if ZBUS +config ZBUS_PREFER_DYNAMIC_ALLOCATION + bool "Set zbus to work with dynamic allocation using the system heap" + default y + config ZBUS_CHANNELS_SYS_INIT_PRIORITY default 5 int "The priority used during the SYS_INIT procedure." @@ -33,7 +37,8 @@ if ZBUS_MSG_SUBSCRIBER choice ZBUS_MSG_SUBSCRIBER_BUF_ALLOC prompt "ZBus msg_subscribers buffer allocation" - default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC + default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC if ZBUS_PREFER_DYNAMIC_ALLOCATION + default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_STATIC config ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC bool "Use heap to allocate msg_subscriber buffers data" @@ -63,6 +68,28 @@ endif # ZBUS_MSG_SUBSCRIBER config ZBUS_RUNTIME_OBSERVERS bool "Runtime observers support." +if ZBUS_RUNTIME_OBSERVERS + +choice ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC + prompt "ZBus runtime observers node allocation" + default ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC if ZBUS_PREFER_DYNAMIC_ALLOCATION + default ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC + +config ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC + bool "Use heap to allocate runtime observers node" + +config ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC + bool "Use a pool of runtime observers nodes" + +endchoice + +config ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE + int "Runtime observer pool size" + depends on ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC + default 8 + +endif # ZBUS_RUNTIME_OBSERVERS + config ZBUS_PRIORITY_BOOST bool "ZBus priority boost algorithm" default y @@ -80,9 +107,9 @@ config ZBUS_ASSERT_MOCK config HEAP_MEM_POOL_ADD_SIZE_ZBUS int - default 2048 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && !ZBUS_RUNTIME_OBSERVERS - default 1024 if !ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS - default 3072 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS + default 2048 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && !ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC + default 1024 if !ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC + default 3072 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC module = ZBUS diff --git a/subsys/zbus/zbus_runtime_observers.c b/subsys/zbus/zbus_runtime_observers.c index 41c00c9aae7f..b1877a59c6be 100644 --- a/subsys/zbus/zbus_runtime_observers.c +++ b/subsys/zbus/zbus_runtime_observers.c @@ -8,17 +8,63 @@ LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL); +#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC) + +static inline int _zbus_runtime_observer_node_alloc(struct zbus_observer_node **node, + k_timeout_t timeout) +{ + ARG_UNUSED(timeout); + + *node = k_malloc(sizeof(struct zbus_observer_node)); + + _ZBUS_ASSERT(*node != NULL, "could not allocate observer node the heap is full!"); + + if (*node == NULL) { + return -ENOMEM; + } + + return 0; +} + +static inline void _zbus_runtime_observer_node_free(struct zbus_observer_node *node) +{ + k_free(node); +} +#else + +K_MEM_SLAB_DEFINE_STATIC(_zbus_runtime_observers_slab, sizeof(struct zbus_observer_node), + CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE, 8); + +static inline int _zbus_runtime_observer_node_alloc(struct zbus_observer_node **node, + k_timeout_t timeout) +{ + int err = k_mem_slab_alloc(&_zbus_runtime_observers_slab, (void **)node, timeout); + + _ZBUS_ASSERT(*node != NULL, "not enough runtime observer nodes in the pool. Increase the " + "ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE"); + + return err; +} + +static inline void _zbus_runtime_observer_node_free(struct zbus_observer_node *node) +{ + k_mem_slab_free(&_zbus_runtime_observers_slab, (void *)node); +} +#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC */ + int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs, - struct zbus_observer_node *node, k_timeout_t timeout) + k_timeout_t timeout) { int err; + struct zbus_observer_node *obs_nd, *tmp; struct zbus_channel_observation *observation; _ZBUS_ASSERT(!k_is_in_isr(), "ISR blocked"); _ZBUS_ASSERT(chan != NULL, "chan is required"); _ZBUS_ASSERT(obs != NULL, "obs is required"); - _ZBUS_ASSERT(node != NULL, "node is required"); + + k_timepoint_t end_time = sys_timepoint_calc(timeout); err = k_sem_take(&chan->data->sem, timeout); if (err) { @@ -47,9 +93,19 @@ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observe } } - node->obs = obs; + struct zbus_observer_node *new_obs_nd = NULL; - sys_slist_append(&chan->data->observers, &node->node); + err = _zbus_runtime_observer_node_alloc(&new_obs_nd, sys_timepoint_timeout(end_time)); + + if (err) { + k_sem_give(&chan->data->sem); + + return err; + } + + new_obs_nd->obs = obs; + + sys_slist_append(&chan->data->observers, &new_obs_nd->node); k_sem_give(&chan->data->sem); @@ -76,6 +132,8 @@ int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer if (obs_nd->obs == obs) { sys_slist_remove(&chan->data->observers, &prev_obs_nd->node, &obs_nd->node); + _zbus_runtime_observer_node_free(obs_nd); + k_sem_give(&chan->data->sem); return 0; diff --git a/tests/subsys/zbus/runtime_observers_registration/prj.conf b/tests/subsys/zbus/runtime_observers_registration/prj.conf index 741938a265c3..00ad9fa8ec82 100644 --- a/tests/subsys/zbus/runtime_observers_registration/prj.conf +++ b/tests/subsys/zbus/runtime_observers_registration/prj.conf @@ -4,5 +4,4 @@ CONFIG_ZBUS=y CONFIG_ZBUS_ASSERT_MOCK=y CONFIG_ZBUS_LOG_LEVEL_DBG=y CONFIG_ZBUS_RUNTIME_OBSERVERS=y -CONFIG_HEAP_MEM_POOL_SIZE=2048 CONFIG_ZBUS_OBSERVER_NAME=y diff --git a/tests/subsys/zbus/runtime_observers_registration/src/main.c b/tests/subsys/zbus/runtime_observers_registration/src/main.c index b72586aff27f..5a19a34952a8 100644 --- a/tests/subsys/zbus/runtime_observers_registration/src/main.c +++ b/tests/subsys/zbus/runtime_observers_registration/src/main.c @@ -14,29 +14,29 @@ struct sensor_data_msg { int b; }; -ZBUS_CHAN_DEFINE(chan1, /* Name */ +ZBUS_CHAN_DEFINE(chan1, /* Name */ struct sensor_data_msg, /* Message type */ - NULL, /* Validator */ - NULL, /* User data */ + NULL, /* Validator */ + NULL, /* User data */ ZBUS_OBSERVERS_EMPTY, /* observers */ ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ ); -ZBUS_CHAN_DEFINE(chan2, /* Name */ +ZBUS_CHAN_DEFINE(chan2, /* Name */ struct sensor_data_msg, /* Message type */ - NULL, /* Validator */ - NULL, /* User data */ + NULL, /* Validator */ + NULL, /* User data */ ZBUS_OBSERVERS(lis2), /* observers */ ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ ); -ZBUS_CHAN_DEFINE(chan3, /* Name */ +ZBUS_CHAN_DEFINE(chan3, /* Name */ struct sensor_data_msg, /* Message type */ - NULL, /* Validator */ - NULL, /* User data */ + NULL, /* Validator */ + NULL, /* User data */ ZBUS_OBSERVERS_EMPTY, /* observers */ ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ ); @@ -69,16 +69,15 @@ ZTEST(basic, test_specification_based__zbus_obs_add_rm_obs) { count_callback1 = 0; struct sensor_data_msg sd = {.a = 10, .b = 100}; - static struct zbus_observer_node n1, n2, n3, n4, n5, n6; /* Tyring to add same static observer as one dynamic */ - zassert_equal(-EEXIST, zbus_chan_add_obs(&chan2, &lis2, &n2, K_MSEC(200)), NULL); + zassert_equal(-EEXIST, zbus_chan_add_obs(&chan2, &lis2, K_MSEC(200)), NULL); zassert_equal(0, zbus_chan_pub(&chan1, &sd, K_MSEC(500)), NULL); zassert_equal(count_callback1, 0, "The counter could not be more than zero, no obs"); - zassert_equal(0, zbus_chan_add_obs(&chan1, &lis1, &n1, K_MSEC(200)), NULL); - zassert_equal(-EALREADY, zbus_chan_add_obs(&chan1, &lis1, &n1, K_MSEC(200)), + zassert_equal(0, zbus_chan_add_obs(&chan1, &lis1, K_MSEC(200)), NULL); + zassert_equal(-EALREADY, zbus_chan_add_obs(&chan1, &lis1, K_MSEC(200)), "It cannot be added twice"); zassert_equal(0, zbus_chan_pub(&chan1, &sd, K_MSEC(500)), NULL); @@ -99,21 +98,32 @@ ZTEST(basic, test_specification_based__zbus_obs_add_rm_obs) zassert_equal(0, zbus_chan_pub(&chan2, &sd, K_MSEC(500)), NULL); zassert_equal(count_callback2, 1, "The counter could not be more than zero, no obs"); - zassert_equal(0, zbus_chan_add_obs(&chan2, &lis3, &n3, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&chan2, &lis3, K_MSEC(200)), NULL); - zassert_equal(-EALREADY, zbus_chan_add_obs(&chan2, &lis3, &n3, K_MSEC(200)), + zassert_equal(-EALREADY, zbus_chan_add_obs(&chan2, &lis3, K_MSEC(200)), "It cannot be added twice"); zassert_equal(0, zbus_chan_pub(&chan2, &sd, K_MSEC(500)), NULL); zassert_equal(count_callback2, 3, "The counter could not be more than zero, no obs, %d", count_callback2); count_callback2 = 0; - zassert_equal(0, zbus_chan_add_obs(&chan2, &sub1, &n1, K_MSEC(200)), NULL); - zassert_equal(0, zbus_chan_add_obs(&chan2, &sub2, &n2, K_MSEC(200)), NULL); - zassert_equal(0, zbus_chan_add_obs(&chan2, &lis4, &n4, K_MSEC(200)), "It must add the obs"); - zassert_equal(0, zbus_chan_add_obs(&chan2, &lis5, &n5, K_MSEC(200)), "It must add the obs"); - zassert_equal(0, zbus_chan_add_obs(&chan2, &lis6, &n6, K_MSEC(200)), "It must add the obs"); - + zassert_equal(0, zbus_chan_add_obs(&chan2, &sub1, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&chan2, &sub2, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&chan2, &lis4, K_MSEC(200)), "It must add the obs"); + zassert_equal(0, zbus_chan_add_obs(&chan2, &lis5, K_MSEC(200)), "It must add the obs"); + zassert_equal(0, zbus_chan_add_obs(&chan2, &lis6, K_MSEC(200)), "It must add the obs"); + +#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC) + /* Make the heap full */ + void *mem; + + do { + mem = k_malloc(1); + } while (mem != NULL); + + /* With the heap full it will not be possible to add another obs */ +#endif + zassert_equal(-EFAULT, zbus_chan_add_obs(&chan2, &lis7, K_MSEC(200)), NULL); zassert_equal(0, zbus_chan_pub(&chan2, &sd, K_MSEC(500)), NULL); zassert_equal(count_callback2, 5, NULL); @@ -134,9 +144,7 @@ static struct aux2_wq_data wq_handler; static void wq_dh_cb(struct k_work *item) { - static struct zbus_observer_node node; - - zassert_equal(-EAGAIN, zbus_chan_add_obs(&chan2, &sub1, &node, K_MSEC(200)), NULL); + zassert_equal(-EAGAIN, zbus_chan_add_obs(&chan2, &sub1, K_MSEC(200)), NULL); zassert_equal(-EAGAIN, zbus_chan_rm_obs(&chan2, &sub2, K_MSEC(200)), NULL); } @@ -186,12 +194,11 @@ ZBUS_CHAN_ADD_OBS(chan4, prio_lis4, 2); ZTEST(basic, test_specification_based__zbus_obs_priority) { struct sensor_data_msg sd = {.a = 70, .b = 116}; - static struct zbus_observer_node n1, n2; execution_sequence_idx = 0; - zassert_equal(0, zbus_chan_add_obs(&chan4, &prio_lis2, &n1, K_MSEC(200)), NULL); - zassert_equal(0, zbus_chan_add_obs(&chan4, &prio_lis1, &n2, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&chan4, &prio_lis2, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&chan4, &prio_lis1, K_MSEC(200)), NULL); zassert_equal(0, zbus_chan_pub(&chan4, &sd, K_MSEC(500)), NULL); diff --git a/tests/subsys/zbus/runtime_observers_registration/testcase.yaml b/tests/subsys/zbus/runtime_observers_registration/testcase.yaml index bad6075a1435..4675e3b1bd68 100644 --- a/tests/subsys/zbus/runtime_observers_registration/testcase.yaml +++ b/tests/subsys/zbus/runtime_observers_registration/testcase.yaml @@ -1,5 +1,13 @@ tests: - message_bus.zbus.runtime_obs_reg.add_and_remove_observers: + message_bus.zbus.runtime_obs_reg.add_and_remove_observers_dynamic_memory: tags: zbus integration_platforms: - native_sim + extra_configs: + - CONFIG_HEAP_MEM_POOL_SIZE=2048 + message_bus.zbus.runtime_obs_reg.add_and_remove_observers_static_memory: + tags: zbus + integration_platforms: + - native_sim + extra_configs: + - CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE=6 diff --git a/tests/subsys/zbus/unittests/src/main.c b/tests/subsys/zbus/unittests/src/main.c index a40a70082f1f..c94d0c28b0e8 100644 --- a/tests/subsys/zbus/unittests/src/main.c +++ b/tests/subsys/zbus/unittests/src/main.c @@ -137,7 +137,6 @@ static struct action_msg ga; static void isr_handler(const void *operation) { - static struct zbus_observer_node fast_node, aux_node; enum operation *op = (enum operation *)operation; switch (*op) { @@ -157,7 +156,7 @@ static void isr_handler(const void *operation) isr_return = zbus_chan_finish(NULL); break; case ADD_OBS_ISR_INVAL: - isr_return = zbus_chan_add_obs(&aux2_chan, &fast_lis, &fast_node, K_MSEC(200)); + isr_return = zbus_chan_add_obs(&aux2_chan, &fast_lis, K_MSEC(200)); break; case RM_OBS_ISR_INVAL: isr_return = zbus_chan_rm_obs(&aux2_chan, &fast_lis, K_MSEC(200)); @@ -178,7 +177,7 @@ static void isr_handler(const void *operation) isr_return = zbus_chan_finish(&aux2_chan); break; case ADD_OBS_ISR: - isr_return = zbus_chan_add_obs(&aux2_chan, NULL, &aux_node, K_MSEC(200)); + isr_return = zbus_chan_add_obs(&aux2_chan, NULL, K_MSEC(200)); break; case RM_OBS_ISR: isr_return = zbus_chan_rm_obs(&aux2_chan, NULL, K_MSEC(200)); @@ -245,7 +244,6 @@ const STRUCT_SECTION_ITERABLE(zbus_observer, invalid_obs) = { ZTEST(basic, test_specification_based__zbus_chan) { - static struct zbus_observer_node node; struct action_msg a = {0}; /* Trying invalid parameters */ @@ -271,11 +269,9 @@ ZTEST(basic, test_specification_based__zbus_chan) zassert_equal(-EFAULT, zbus_chan_finish(NULL), "It must be -EFAULT"); - zassert_equal(-EFAULT, zbus_chan_add_obs(NULL, &sub1, &node, K_MSEC(200)), NULL); + zassert_equal(-EFAULT, zbus_chan_add_obs(NULL, &sub1, K_MSEC(200)), NULL); - zassert_equal(-EFAULT, zbus_chan_add_obs(&aux2_chan, NULL, &node, K_MSEC(200)), NULL); - - zassert_equal(-EFAULT, zbus_chan_add_obs(&aux2_chan, &sub1, NULL, K_MSEC(200)), NULL); + zassert_equal(-EFAULT, zbus_chan_add_obs(&aux2_chan, NULL, K_MSEC(200)), NULL); zassert_equal(-EFAULT, zbus_chan_rm_obs(NULL, &sub1, K_MSEC(200)), NULL); @@ -330,7 +326,7 @@ ZTEST(basic, test_specification_based__zbus_chan) k_msleep(100); - zassert_equal(0, zbus_chan_add_obs(&stuck_chan, &sub1, &node, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&stuck_chan, &sub1, K_MSEC(200)), NULL); zassert_equal(0, zbus_chan_notify(&stuck_chan, K_MSEC(200)), "It must finish correctly"); @@ -603,7 +599,6 @@ ZTEST(basic, test_hard_channel) ZTEST(basic, test_specification_based__zbus_obs_set_enable) { - struct zbus_observer_node node; bool enable; count_fast = 0; @@ -622,7 +617,7 @@ ZTEST(basic, test_specification_based__zbus_obs_set_enable) zbus_obs_is_enabled(&rt_fast_lis, &enable); zassert_equal(false, enable); - zassert_equal(0, zbus_chan_add_obs(&aux1_chan, &rt_fast_lis, &node, K_MSEC(200)), NULL); + zassert_equal(0, zbus_chan_add_obs(&aux1_chan, &rt_fast_lis, K_MSEC(200)), NULL); zassert_equal(0, zbus_obs_set_enable(&fast_lis, false), "Must be zero. The observer must be disabled");