Skip to content

Commit 6ae9a98

Browse files
rodrigopexkartben
authored andcommitted
zbus: Improve consistency with runtime observers
A previous PR merged (to remove runtime observers' dependency with heap) added inconsistencies and compatibility breaks to the zbus. This commit improves that by removing the inconsistencies and still attending to the features requested by the community. Signed-off-by: Rodrigo Peixoto <rodrigopex@gmail.com>
1 parent e48c907 commit 6ae9a98

File tree

3 files changed

+205
-12
lines changed

3 files changed

+205
-12
lines changed

include/zephyr/zbus/zbus.h

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ struct zbus_channel_observation_mask {
177177
bool enabled;
178178
};
179179

180+
/**
181+
* @brief Structure for linking observers to chanels
182+
*/
180183
struct zbus_channel_observation {
181184
const struct zbus_channel *chan;
182185
const struct zbus_observer *obs;
@@ -862,17 +865,23 @@ static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
862865
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
863866

864867
/**
865-
* @brief Structure for linking observers to chanels
868+
* @brief Structure used to register runtime obeservers
869+
*
866870
*/
867871
struct zbus_observer_node {
868872
sys_snode_t node;
869873
const struct zbus_observer *obs;
874+
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE)
875+
const struct zbus_channel *chan;
876+
#endif
870877
};
871878

879+
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
872880
/**
873881
* @brief Add an observer to a channel.
874882
*
875-
* This routine adds an observer to the channel.
883+
* This routine adds an observer to the channel by providing an allocated node. This function is
884+
* only supported if the CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE is enabled.
876885
*
877886
* @param chan The channel's reference.
878887
* @param obs The observer's reference to be added.
@@ -881,13 +890,63 @@ struct zbus_observer_node {
881890
* or one of the special values K_NO_WAIT and K_FOREVER.
882891
*
883892
* @retval 0 Observer added to the channel.
893+
* @retval -EEXIST The observer is already present in the channel's observers list.
884894
* @retval -EALREADY The observer is already present in the channel's runtime observers list.
885895
* @retval -EAGAIN Waiting period timed out.
886896
* @retval -EINVAL Some parameter is invalid.
897+
* @retval -EBUSY The node is already in use.
898+
*/
899+
int zbus_chan_add_obs_with_node(const struct zbus_channel *chan, const struct zbus_observer *obs,
900+
struct zbus_observer_node *node, k_timeout_t timeout);
901+
#else
902+
static inline int zbus_chan_add_obs_with_node(const struct zbus_channel *chan,
903+
const struct zbus_observer *obs,
904+
struct zbus_observer_node *node, k_timeout_t timeout)
905+
{
906+
ARG_UNUSED(chan);
907+
ARG_UNUSED(obs);
908+
ARG_UNUSED(node);
909+
ARG_UNUSED(timeout);
910+
911+
return -ENOTSUP;
912+
}
913+
#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
914+
915+
#if !defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
916+
/**
917+
* @brief Add an observer to a channel.
918+
*
919+
* This routine adds an observer to the channel in runtime. This function is only supported if the
920+
* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC or
921+
* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC is enabled.
922+
*
923+
*
924+
* @param chan The channel's reference.
925+
* @param obs The observer's reference to be added.
926+
* @param timeout Waiting period to add an observer,
927+
* or one of the special values K_NO_WAIT and K_FOREVER.
928+
*
929+
* @retval 0 Observer added to the channel.
930+
* @retval -EBUSY Returned without waiting.
931+
* @retval -EAGAIN Waiting period timed out.
932+
* @retval -EEXIST The observer is already present in the channel's observers list.
933+
* @retval -EALREADY The observer is already present in the channel's runtime observers list.
934+
* @retval -ENOMEM No memory available for a new runtime observer node.
887935
*/
888936
int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
889-
struct zbus_observer_node *node, k_timeout_t timeout);
937+
k_timeout_t timeout);
938+
#else
939+
static inline int zbus_chan_add_obs(const struct zbus_channel *chan,
940+
const struct zbus_observer *obs, k_timeout_t timeout)
941+
{
942+
ARG_UNUSED(chan);
943+
ARG_UNUSED(obs);
944+
ARG_UNUSED(timeout);
945+
946+
return -ENOTSUP;
947+
}
890948

949+
#endif /* !CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
891950
/**
892951
* @brief Remove an observer from a channel.
893952
*
@@ -899,11 +958,9 @@ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observe
899958
* or one of the special values K_NO_WAIT and K_FOREVER.
900959
*
901960
* @retval 0 Observer removed to the channel.
902-
* @retval -EINVAL Invalid data supplied.
903961
* @retval -EBUSY Returned without waiting.
904962
* @retval -EAGAIN Waiting period timed out.
905963
* @retval -ENODATA no observer found in channel's runtime observer list.
906-
* @retval -ENOMEM Returned without waiting.
907964
*/
908965
int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
909966
k_timeout_t timeout);

subsys/zbus/Kconfig

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ menuconfig ZBUS
99

1010
if ZBUS
1111

12+
config ZBUS_PREFER_DYNAMIC_ALLOCATION
13+
bool "Set zbus to work with dynamic allocation using the system heap"
14+
default y
15+
1216
config ZBUS_CHANNELS_SYS_INIT_PRIORITY
1317
default 5
1418
int "The priority used during the SYS_INIT procedure."
@@ -33,7 +37,8 @@ if ZBUS_MSG_SUBSCRIBER
3337

3438
choice ZBUS_MSG_SUBSCRIBER_BUF_ALLOC
3539
prompt "ZBus msg_subscribers buffer allocation"
36-
default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC
40+
default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC if ZBUS_PREFER_DYNAMIC_ALLOCATION
41+
default ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_STATIC
3742

3843
config ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC
3944
bool "Use heap to allocate msg_subscriber buffers data"
@@ -63,6 +68,31 @@ endif # ZBUS_MSG_SUBSCRIBER
6368
config ZBUS_RUNTIME_OBSERVERS
6469
bool "Runtime observers support."
6570

71+
if ZBUS_RUNTIME_OBSERVERS
72+
73+
choice ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC
74+
prompt "ZBus runtime observers node allocation"
75+
default ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC if ZBUS_PREFER_DYNAMIC_ALLOCATION
76+
default ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC
77+
78+
config ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC
79+
bool "Use heap to allocate runtime observers node"
80+
81+
config ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC
82+
bool "Use a pool of runtime observers nodes"
83+
84+
config ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE
85+
bool "Use user-provided runtime observers nodes"
86+
87+
endchoice
88+
89+
config ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE
90+
int "Runtime observer pool size"
91+
depends on ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC
92+
default 8
93+
94+
endif # ZBUS_RUNTIME_OBSERVERS
95+
6696
config ZBUS_PRIORITY_BOOST
6797
bool "ZBus priority boost algorithm"
6898
default y
@@ -80,9 +110,9 @@ config ZBUS_ASSERT_MOCK
80110

81111
config HEAP_MEM_POOL_ADD_SIZE_ZBUS
82112
int
83-
default 2048 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && !ZBUS_RUNTIME_OBSERVERS
84-
default 1024 if !ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS
85-
default 3072 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS
113+
default 2048 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && !ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC
114+
default 1024 if !ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC
115+
default 3072 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC
86116

87117

88118
module = ZBUS

subsys/zbus/zbus_runtime_observers.c

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,63 @@
88

99
LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
1010

11-
int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
12-
struct zbus_observer_node *node, k_timeout_t timeout)
11+
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC)
12+
static inline int _zbus_runtime_observer_node_alloc(struct zbus_observer_node **node,
13+
k_timeout_t timeout)
14+
{
15+
ARG_UNUSED(timeout);
16+
17+
*node = k_malloc(sizeof(struct zbus_observer_node));
18+
19+
_ZBUS_ASSERT(*node != NULL, "could not allocate observer node the heap is full!");
20+
21+
if (*node == NULL) {
22+
return -ENOMEM;
23+
}
24+
25+
return 0;
26+
}
27+
28+
static inline void _zbus_runtime_observer_node_free(struct zbus_observer_node *node)
29+
{
30+
k_free(node);
31+
}
32+
33+
#elif defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_STATIC)
34+
35+
K_MEM_SLAB_DEFINE_STATIC(_zbus_runtime_observers_slab, sizeof(struct zbus_observer_node),
36+
CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE, 8);
37+
38+
static inline int _zbus_runtime_observer_node_alloc(struct zbus_observer_node **node,
39+
k_timeout_t timeout)
40+
{
41+
int err = k_mem_slab_alloc(&_zbus_runtime_observers_slab, (void **)node, timeout);
42+
43+
_ZBUS_ASSERT(*node != NULL, "not enough runtime observer nodes in the pool. Increase the "
44+
"ZBUS_RUNTIME_OBSERVERS_NODE_POOL_SIZE");
45+
46+
return err;
47+
}
48+
49+
static inline void _zbus_runtime_observer_node_free(struct zbus_observer_node *node)
50+
{
51+
k_mem_slab_free(&_zbus_runtime_observers_slab, (void *)node);
52+
}
53+
54+
#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC */
55+
56+
static inline int _zbus_runtime_take_chan_sem_and_obs_check(const struct zbus_channel *chan,
57+
const struct zbus_observer *obs,
58+
k_timeout_t timeout)
1359
{
1460
int err;
61+
1562
struct zbus_observer_node *obs_nd, *tmp;
1663
struct zbus_channel_observation *observation;
1764

1865
_ZBUS_ASSERT(!k_is_in_isr(), "ISR blocked");
1966
_ZBUS_ASSERT(chan != NULL, "chan is required");
2067
_ZBUS_ASSERT(obs != NULL, "obs is required");
21-
_ZBUS_ASSERT(node != NULL, "node is required");
2268

2369
err = k_sem_take(&chan->data->sem, timeout);
2470
if (err) {
@@ -47,7 +93,29 @@ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observe
4793
}
4894
}
4995

96+
return 0;
97+
}
98+
99+
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE)
100+
int zbus_chan_add_obs_with_node(const struct zbus_channel *chan, const struct zbus_observer *obs,
101+
struct zbus_observer_node *node, k_timeout_t timeout)
102+
{
103+
int err;
104+
105+
/* On success the channel semaphore has been taken */
106+
err = _zbus_runtime_take_chan_sem_and_obs_check(chan, obs, timeout);
107+
if (err) {
108+
return err;
109+
}
110+
111+
if (node->chan != NULL) {
112+
k_sem_give(&chan->data->sem);
113+
114+
return -EBUSY;
115+
}
116+
50117
node->obs = obs;
118+
node->chan = chan;
51119

52120
sys_slist_append(&chan->data->observers, &node->node);
53121

@@ -56,6 +124,39 @@ int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observe
56124
return 0;
57125
}
58126

127+
#else
128+
129+
int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
130+
k_timeout_t timeout)
131+
{
132+
int err;
133+
k_timepoint_t end_time = sys_timepoint_calc(timeout);
134+
135+
/* On success the channel semaphore has been taken */
136+
err = _zbus_runtime_take_chan_sem_and_obs_check(chan, obs, timeout);
137+
if (err) {
138+
return err;
139+
}
140+
141+
struct zbus_observer_node *new_obs_nd = NULL;
142+
143+
err = _zbus_runtime_observer_node_alloc(&new_obs_nd, sys_timepoint_timeout(end_time));
144+
if (err) {
145+
k_sem_give(&chan->data->sem);
146+
147+
return err;
148+
}
149+
150+
new_obs_nd->obs = obs;
151+
152+
sys_slist_append(&chan->data->observers, &new_obs_nd->node);
153+
154+
k_sem_give(&chan->data->sem);
155+
156+
return 0;
157+
}
158+
#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
159+
59160
int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
60161
k_timeout_t timeout)
61162
{
@@ -75,6 +176,11 @@ int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer
75176
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&chan->data->observers, obs_nd, tmp, node) {
76177
if (obs_nd->obs == obs) {
77178
sys_slist_remove(&chan->data->observers, &prev_obs_nd->node, &obs_nd->node);
179+
#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE)
180+
obs_nd->chan = NULL;
181+
#else
182+
_zbus_runtime_observer_node_free(obs_nd);
183+
#endif
78184

79185
k_sem_give(&chan->data->sem);
80186

0 commit comments

Comments
 (0)