1 /*
2  * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #ifndef ZEPHYR_INCLUDE_ZBUS_H_
7 #define ZEPHYR_INCLUDE_ZBUS_H_
8 
9 #include <string.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/iterable_sections.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Zbus API
20  * @defgroup zbus_apis Zbus APIs
21  * @ingroup os_services
22  * @{
23  */
24 
25 /**
26  * @brief Type used to represent a channel mutable data.
27  *
28  * Every channel has a zbus_channel_data structure associated.
29  */
30 struct zbus_channel_data {
31 	/** Static channel observer list start index. Considering the ITERABLE SECTIONS allocation
32 	 * order.
33 	 */
34 	int16_t observers_start_idx;
35 
36 	/** Static channel observer list end index. Considering the ITERABLE SECTIONS allocation
37 	 * order.
38 	 */
39 	int16_t observers_end_idx;
40 
41 	/** Access control semaphore. Points to the semaphore used to avoid race conditions
42 	 * for accessing the channel.
43 	 */
44 	struct k_sem sem;
45 
46 #if defined(CONFIG_ZBUS_PRIORITY_BOOST)
47 	/** Highest observer priority. Indicates the priority that the VDED will use to boost the
48 	 * notification process avoiding preemptions.
49 	 */
50 	int highest_observer_priority;
51 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
52 
53 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
54 	/** Channel observer list. Represents the channel's observers list, it can be empty
55 	 * or have listeners and subscribers mixed in any sequence. It can be changed in runtime.
56 	 */
57 	sys_slist_t observers;
58 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
59 
60 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
61 	/** Net buf pool for message subscribers. It can be either the global or a separated one.
62 	 */
63 	struct net_buf_pool *msg_subscriber_pool;
64 #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
65 
66 #if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
67 	/** Kernel timestamp of the last publish action on this channel */
68 	k_ticks_t publish_timestamp;
69 	/** Number of times data has been published to this channel */
70 	uint32_t publish_count;
71 #endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
72 };
73 
74 /**
75  * @brief Type used to represent a channel.
76  *
77  * Every channel has a zbus_channel structure associated used to control the channel
78  * access and usage.
79  */
80 struct zbus_channel {
81 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
82 	/** Channel name. */
83 	const char *name;
84 #endif
85 #if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
86 	/** Unique numeric channel identifier. */
87 	uint32_t id;
88 #endif
89 	/** Message reference. Represents the message's reference that points to the actual
90 	 * shared memory region.
91 	 */
92 	void *message;
93 
94 	/** Message size. Represents the channel's message size. */
95 	size_t message_size;
96 
97 	/** User data available to extend zbus features. The channel must be claimed before
98 	 * using this field.
99 	 */
100 	void *user_data;
101 
102 	/** Message validator. Stores the reference to the function to check the message
103 	 * validity before actually performing the publishing. No invalid messages can be
104 	 * published. Every message is valid when this field is empty.
105 	 */
106 	bool (*validator)(const void *msg, size_t msg_size);
107 
108 	/** Mutable channel data struct. */
109 	struct zbus_channel_data *data;
110 };
111 
112 /**
113  * @brief Type used to represent an observer type.
114  *
115  * A observer can be a listener or a subscriber.
116  */
117 enum __packed zbus_observer_type {
118 	ZBUS_OBSERVER_LISTENER_TYPE,
119 	ZBUS_OBSERVER_SUBSCRIBER_TYPE,
120 	ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE,
121 };
122 
123 struct zbus_observer_data {
124 	/** Enabled flag. Indicates if observer is receiving notification. */
125 	bool enabled;
126 
127 #if defined(CONFIG_ZBUS_PRIORITY_BOOST)
128 	/** Subscriber attached thread priority. */
129 	int priority;
130 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
131 };
132 
133 /**
134  * @brief Type used to represent an observer.
135  *
136  * Every observer has an representation structure containing the relevant information.
137  * An observer is a code portion interested in some channel. The observer can be notified
138  * synchronously or asynchronously and it is called listener and subscriber respectively.
139  * The observer can be enabled or disabled during runtime by change the enabled boolean
140  * field of the structure. The listeners have a callback function that is executed by the
141  * bus with the index of the changed channel as argument when the notification is sent.
142  * The subscribers have a message queue where the bus enqueues the index of the changed
143  * channel when a notification is sent.
144  *
145  * @see zbus_obs_set_enable function to properly change the observer's enabled field.
146  *
147  */
148 struct zbus_observer {
149 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
150 	/** Observer name. */
151 	const char *name;
152 #endif
153 	/** Type indication. */
154 	enum zbus_observer_type type;
155 
156 	/** Mutable observer data struct. */
157 	struct zbus_observer_data *data;
158 
159 	union {
160 		/** Observer message queue. It turns the observer into a subscriber. */
161 		struct k_msgq *queue;
162 
163 		/** Observer callback function. It turns the observer into a listener. */
164 		void (*callback)(const struct zbus_channel *chan);
165 
166 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
167 		/** Observer message FIFO. It turns the observer into a message subscriber. It only
168 		 * exists if the @kconfig{CONFIG_ZBUS_MSG_SUBSCRIBER} is enabled.
169 		 */
170 		struct k_fifo *message_fifo;
171 #endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
172 	};
173 };
174 
175 /** @cond INTERNAL_HIDDEN */
176 struct zbus_channel_observation_mask {
177 	bool enabled;
178 };
179 
180 struct zbus_channel_observation {
181 	const struct zbus_channel *chan;
182 	const struct zbus_observer *obs;
183 };
184 
185 #ifdef __cplusplus
186 #define _ZBUS_CPP_EXTERN extern
187 #else
188 #define _ZBUS_CPP_EXTERN
189 #endif /* __cplusplus */
190 
191 #define ZBUS_MIN_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1)
192 
193 #if defined(CONFIG_ZBUS_ASSERT_MOCK)
194 #define _ZBUS_ASSERT(_cond, _fmt, ...)                                                             \
195 	do {                                                                                       \
196 		if (!(_cond)) {                                                                    \
197 			printk("ZBUS ASSERT: ");                                                   \
198 			printk(_fmt, ##__VA_ARGS__);                                               \
199 			printk("\n");                                                              \
200 			return -EFAULT;                                                            \
201 		}                                                                                  \
202 	} while (0)
203 #else
204 #define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
205 #endif
206 
207 #if defined(CONFIG_ZBUS_CHANNEL_NAME)
208 #define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
209 #define _ZBUS_CHAN_NAME(_chan)        (_chan)->name
210 #else
211 #define ZBUS_CHANNEL_NAME_INIT(_name)
212 #define _ZBUS_CHAN_NAME(_chan) ""
213 #endif
214 
215 #if defined(CONFIG_ZBUS_OBSERVER_NAME)
216 #define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
217 #define _ZBUS_OBS_NAME(_obs)           (_obs)->name
218 #else
219 #define ZBUS_OBSERVER_NAME_INIT(_name)
220 #define _ZBUS_OBS_NAME(_obs) ""
221 #endif
222 
223 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS)
224 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
225 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
226 #else
227 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
228 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
229 #endif
230 
231 #define _ZBUS_OBS_EXTERN(_name) extern const struct zbus_observer _name
232 
233 #define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
234 
235 #define ZBUS_REF(_value) &(_value)
236 
237 #define FOR_EACH_FIXED_ARG_NONEMPTY_TERM(F, sep, fixed_arg, ...)                                   \
238 	COND_CODE_0(/* are there zero non-empty arguments ? */                                     \
239 		    NUM_VA_ARGS_LESS_1(                                                            \
240 			    LIST_DROP_EMPTY(__VA_ARGS__, _)), /* if so, expand to nothing */       \
241 		    (),                                       /* otherwise, expand to: */          \
242 		    (FOR_EACH_IDX_FIXED_ARG(                                                       \
243 			    F, sep, fixed_arg,                                                     \
244 			    LIST_DROP_EMPTY(__VA_ARGS__)) /* plus a final terminator */            \
245 		     __DEBRACKET sep))
246 
247 #define _ZBUS_OBSERVATION_PREFIX(_idx)                                                             \
248 	GET_ARG_N(_idx, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17,    \
249 		  18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,  \
250 		  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,  \
251 		  58, 59, 60, 61, 62, 63)
252 
253 #define _ZBUS_CHAN_OBSERVATION(_idx, _obs, _chan)                                                  \
254 	const STRUCT_SECTION_ITERABLE(                                                             \
255 		zbus_channel_observation,                                                          \
256 		_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx)))) = {.chan = &_chan,       \
257 									     .obs = &_obs};        \
258 	STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask,                                     \
259 				_CONCAT(_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx))),  \
260 					_mask)) = {.enabled = false};
261 
262 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
263 #define _ZBUS_RUNTIME_OBSERVERS(_name)      .observers = &(_CONCAT(_observers_, _name)),
264 #define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) static sys_slist_t _CONCAT(_observers_, _name);
265 #else
266 #define _ZBUS_RUNTIME_OBSERVERS(_name)
267 #define _ZBUS_RUNTIME_OBSERVERS_DECL(_name)
268 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
269 
270 #define _ZBUS_MESSAGE_NAME(_name) _CONCAT(_zbus_message_, _name)
271 
272 /* clang-format off */
273 #define _ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data)                               \
274 	static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = {                       \
275 		.observers_start_idx = -1,                                                         \
276 		.observers_end_idx = -1,                                                           \
277 		.sem = Z_SEM_INITIALIZER(_CONCAT(_zbus_chan_data_, _name).sem, 1, 1),              \
278 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST,                                             \
279 			   (.highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY,))               \
280 		 IF_ENABLED(CONFIG_ZBUS_RUNTIME_OBSERVERS,                                         \
281 			   (.observers = SYS_SLIST_STATIC_INIT(                                    \
282 				&_CONCAT(_zbus_chan_data_, _name).observers),))                    \
283 	};                                                                                         \
284 	static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name));                                       \
285 	_ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = {                    \
286 		ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */                                  \
287 		IF_ENABLED(CONFIG_ZBUS_CHANNEL_ID, (.id = _id,))                                   \
288 		.message = &_ZBUS_MESSAGE_NAME(_name),                                             \
289 		.message_size = sizeof(_type),                                                     \
290 		.user_data = _user_data,                                                           \
291 		.validator = _validator,                                                           \
292 		.data = &_CONCAT(_zbus_chan_data_, _name),                                         \
293 		IF_ENABLED(ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION,                             \
294 			   (.msg_subscriber_pool = &_zbus_msg_subscribers_pool,))                  \
295 	}
296 /* clang-format on */
297 
298 /** @endcond */
299 
300 /* clang-format off */
301 
302 /**
303  * @brief Add a static channel observation.
304  *
305  * This macro initializes a channel observation by receiving the
306  * channel and the observer.
307  *
308  * @param _chan Channel instance.
309  * @param _obs Observer instance.
310  * @param _masked Observation state.
311  * @param _prio Observer notification sequence priority.
312  */
313 #define ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, _masked, _prio)                                   \
314 	const STRUCT_SECTION_ITERABLE(zbus_channel_observation,                                    \
315 		_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs))) = {                             \
316 			.chan = &_chan,                                                            \
317 			.obs = &_obs,                                                              \
318 	};                                                                                         \
319 	STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask,                                     \
320 				_CONCAT(_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs)),         \
321 					_mask)) = {.enabled = _masked}
322 /* clang-format on */
323 
324 /**
325  * @brief Add a static channel observation.
326  *
327  * This macro initializes a channel observation by receiving the
328  * channel and the observer.
329  *
330  * @param _chan Channel instance.
331  * @param _obs Observer instance.
332  * @param _prio Observer notification sequence priority.
333  */
334 #define ZBUS_CHAN_ADD_OBS(_chan, _obs, _prio) ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, false, _prio)
335 
336 /**
337  * @def ZBUS_OBS_DECLARE
338  * This macro list the observers to be used in a file. Internally, it declares the observers with
339  * the extern statement. Note it is only necessary when the observers are declared outside the file.
340  */
341 #define ZBUS_OBS_DECLARE(...) FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
342 
343 /**
344  * @def ZBUS_CHAN_DECLARE
345  * This macro list the channels to be used in a file. Internally, it declares the channels with the
346  * extern statement. Note it is only necessary when the channels are declared outside the file.
347  */
348 #define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
349 
350 /**
351  * @def ZBUS_OBSERVERS_EMPTY
352  * This macro indicates the channel has no observers.
353  */
354 #define ZBUS_OBSERVERS_EMPTY
355 
356 /**
357  * @def ZBUS_OBSERVERS
358  * This macro indicates the channel has listed observers. Note the sequence of observer notification
359  * will follow the same as listed.
360  */
361 #define ZBUS_OBSERVERS(...) __VA_ARGS__
362 
363 /**
364  * @def ZBUS_CHAN_ID_INVALID
365  * This macro indicates the channel does not have a unique ID.
366  */
367 #define ZBUS_CHAN_ID_INVALID UINT32_MAX
368 
369 /**
370  * @brief Zbus channel definition.
371  *
372  * This macro defines a channel.
373  *
374  * @param _name The channel's name.
375  * @param _type The Message type. It must be a struct or union.
376  * @param _validator The validator function.
377  * @param _user_data A pointer to the user data.
378  *
379  * @see struct zbus_channel
380  * @param _observers The observers list. The sequence indicates the priority of the observer. The
381  * first the highest priority.
382  * @param _init_val The message initialization.
383  */
384 #define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val)              \
385 	static _type _ZBUS_MESSAGE_NAME(_name) = _init_val;                                        \
386 	_ZBUS_CHAN_DEFINE(_name, ZBUS_CHAN_ID_INVALID, _type, _validator, _user_data);             \
387 	/* Extern declaration of observers */                                                      \
388 	ZBUS_OBS_DECLARE(_observers);                                                              \
389 	/* Create all channel observations from observers list */                                  \
390 	FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
391 
392 /**
393  * @brief Zbus channel definition with numeric identifier.
394  *
395  * This macro defines a channel.
396  *
397  * @param _name The channel's name.
398  * @param _id The channel's unique numeric identifier.
399  * @param _type The Message type. It must be a struct or union.
400  * @param _validator The validator function.
401  * @param _user_data A pointer to the user data.
402  *
403  * @see struct zbus_channel
404  * @param _observers The observers list. The sequence indicates the priority of the observer. The
405  * first the highest priority.
406  * @param _init_val The message initialization.
407  */
408 #define ZBUS_CHAN_DEFINE_WITH_ID(_name, _id, _type, _validator, _user_data, _observers, _init_val) \
409 	static _type _ZBUS_MESSAGE_NAME(_name) = _init_val;                                        \
410 	_ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data);                              \
411 	/* Extern declaration of observers */                                                      \
412 	ZBUS_OBS_DECLARE(_observers);                                                              \
413 	/* Create all channel observations from observers list */                                  \
414 	FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
415 
416 /**
417  * @brief Initialize a message.
418  *
419  * This macro initializes a message by passing the values to initialize the message struct
420  * or union.
421  *
422  * @param[in] _val Variadic with the initial values. ``ZBUS_INIT(0)`` means ``{0}``, as
423  * ZBUS_INIT(.a=10, .b=30) means ``{.a=10, .b=30}``.
424  */
425 #define ZBUS_MSG_INIT(_val, ...) {_val, ##__VA_ARGS__}
426 
427 /* clang-format off */
428 
429 /**
430  * @brief Define and initialize a subscriber.
431  *
432  * This macro defines an observer of subscriber type. It defines a message queue where the
433  * subscriber will receive the notification asynchronously, and initialize the ``struct
434  * zbus_observer`` defining the subscriber.
435  *
436  * @param[in] _name The subscriber's name.
437  * @param[in] _queue_size The notification queue's size.
438  * @param[in] _enable The subscriber initial enable state.
439  */
440 #define ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, _enable)       \
441 	K_MSGQ_DEFINE(_zbus_observer_queue_##_name,                           \
442 		      sizeof(struct zbus_channel *),                          \
443 		      _queue_size, sizeof(struct zbus_channel *)              \
444 	);                                                                    \
445 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {  \
446 		.enabled = _enable,                                           \
447 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                      \
448 			.priority = ZBUS_MIN_THREAD_PRIORITY,                 \
449 		))                                                            \
450 	};                                                                    \
451 	_ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {  \
452 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */               \
453 		.type = ZBUS_OBSERVER_SUBSCRIBER_TYPE,                        \
454 		.data = &_CONCAT(_zbus_obs_data_, _name),                     \
455 		.queue = &_zbus_observer_queue_##_name,                       \
456 	}
457 /* clang-format on */
458 
459 /**
460  * @brief Define and initialize a subscriber.
461  *
462  * This macro defines an observer of subscriber type. It defines a message queue where the
463  * subscriber will receive the notification asynchronously, and initialize the ``struct
464  * zbus_observer`` defining the subscriber. The subscribers are defined in the enabled
465  * state with this macro.
466  *
467  * @param[in] _name The subscriber's name.
468  * @param[in] _queue_size The notification queue's size.
469  */
470 #define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size)                                                 \
471 	ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, true)
472 
473 /* clang-format off */
474 
475 /**
476  * @brief Define and initialize a listener.
477  *
478  * This macro defines an observer of listener type. This macro establishes the callback where the
479  * listener will be notified synchronously, and initialize the ``struct zbus_observer`` defining the
480  * listener.
481  *
482  * @param[in] _name The listener's name.
483  * @param[in] _cb The callback function.
484  * @param[in] _enable The listener initial enable state.
485  */
486 #define ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable)                                      \
487 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {                       \
488 		.enabled = _enable,                                                                \
489 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                                           \
490 			.priority = ZBUS_MIN_THREAD_PRIORITY,                                      \
491 		))                                                                                 \
492 	};                                                                                         \
493 	_ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {                   \
494 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */                                    \
495 		.type = ZBUS_OBSERVER_LISTENER_TYPE,                                               \
496 		.data = &_CONCAT(_zbus_obs_data_, _name),                                          \
497 		.callback = (_cb)                                                                  \
498 	}
499 /* clang-format on */
500 
501 /**
502  * @brief Define and initialize a listener.
503  *
504  * This macro defines an observer of listener type. This macro establishes the callback where the
505  * listener will be notified synchronously and initialize the ``struct zbus_observer`` defining the
506  * listener. The listeners are defined in the enabled state with this macro.
507  *
508  * @param[in] _name The listener's name.
509  * @param[in] _cb The callback function.
510  */
511 #define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
512 
513 /* clang-format off */
514 
515 /**
516  * @brief Define and initialize a message subscriber.
517  *
518  * This macro defines an observer of @ref ZBUS_OBSERVER_SUBSCRIBER_TYPE type. It defines a FIFO
519  * where the subscriber will receive the message asynchronously and initialize the @ref
520  * zbus_observer defining the subscriber.
521  *
522  * @param[in] _name The subscriber's name.
523  * @param[in] _enable The subscriber's initial state.
524  */
525 #define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable)                \
526 	static K_FIFO_DEFINE(_zbus_observer_fifo_##_name);                    \
527 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {  \
528 		.enabled = _enable,                                           \
529 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                      \
530 			.priority = ZBUS_MIN_THREAD_PRIORITY,                 \
531 		))                                                            \
532 	};                                                                    \
533 	_ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {  \
534 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */               \
535 		.type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE,                    \
536 		.data = &_CONCAT(_zbus_obs_data_, _name),                     \
537 		.message_fifo = &_zbus_observer_fifo_##_name,                 \
538 	}
539 /* clang-format on */
540 
541 /**
542  * @brief Define and initialize an enabled message subscriber.
543  *
544  * This macro defines an observer of message subscriber type. It defines a FIFO where the
545  * subscriber will receive the message asynchronously and initialize the @ref
546  * zbus_observer defining the subscriber. The message subscribers are defined in the enabled state
547  * with this macro.
548 
549  *
550  * @param[in] _name The subscriber's name.
551  */
552 #define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true)
553 /**
554  *
555  * @brief Publish to a channel
556  *
557  * This routine publishes a message to a channel.
558  *
559  * @param chan The channel's reference.
560  * @param msg Reference to the message where the publish function copies the channel's
561  * message data from.
562  * @param timeout Waiting period to publish the channel,
563  *                or one of the special values K_NO_WAIT and K_FOREVER.
564  *
565  * @retval 0 Channel published.
566  * @retval -ENOMSG The message is invalid based on the validator function or some of the
567  * observers could not receive the notification.
568  * @retval -EBUSY The channel is busy.
569  * @retval -EAGAIN Waiting period timed out.
570  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
571  * observer, or the function context is invalid (inside an ISR). The function only returns this
572  * value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
573  */
574 int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
575 
576 /**
577  * @brief Read a channel
578  *
579  * This routine reads a message from a channel.
580  *
581  * @param[in] chan The channel's reference.
582  * @param[out] msg Reference to the message where the read function copies the channel's
583  * message data to.
584  * @param[in] timeout Waiting period to read the channel,
585  *                or one of the special values K_NO_WAIT and K_FOREVER.
586  *
587  * @retval 0 Channel read.
588  * @retval -EBUSY The channel is busy.
589  * @retval -EAGAIN Waiting period timed out.
590  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
591  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
592  */
593 int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
594 
595 /**
596  * @brief Claim a channel
597  *
598  * This routine claims a channel. During the claiming period the channel is blocked for publishing,
599  * reading, notifying or claiming again. Finishing is the only available action.
600  *
601  * @warning After calling this routine, the channel cannot be used by other
602  * thread until the zbus_chan_finish routine is performed.
603  *
604  * @warning This routine should only be called once before a zbus_chan_finish.
605  *
606  * @param[in] chan The channel's reference.
607  * @param[in] timeout Waiting period to claim the channel,
608  *                or one of the special values K_NO_WAIT and K_FOREVER.
609  *
610  * @retval 0 Channel claimed.
611  * @retval -EBUSY The channel is busy.
612  * @retval -EAGAIN Waiting period timed out.
613  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
614  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
615  */
616 int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
617 
618 /**
619  * @brief Finish a channel claim.
620  *
621  * This routine finishes a channel claim. After calling this routine with success, the channel will
622  * be able to be used by other thread.
623  *
624  * @warning This routine must only be used after a zbus_chan_claim.
625  *
626  * @param chan The channel's reference.
627  *
628  * @retval 0 Channel finished.
629  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
630  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
631  */
632 int zbus_chan_finish(const struct zbus_channel *chan);
633 
634 /**
635  * @brief Force a channel notification.
636  *
637  * This routine forces the event dispatcher to notify the channel's observers even if the message
638  * has no changes. Note this function could be useful after claiming/finishing actions.
639  *
640  * @param chan The channel's reference.
641  * @param timeout Waiting period to notify the channel,
642  *                or one of the special values K_NO_WAIT and K_FOREVER.
643  *
644  * @retval 0 Channel notified.
645  * @retval -EBUSY The channel's semaphore returned without waiting.
646  * @retval -EAGAIN Timeout to take the channel's semaphore.
647  * @retval -ENOMEM There is not more buffer on the messgage buffers pool.
648  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
649  * observer, or the function context is invalid (inside an ISR). The function only returns this
650  * value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
651  */
652 int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
653 
654 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
655 
656 /**
657  * @brief Get the channel's name.
658  *
659  * This routine returns the channel's name reference.
660  *
661  * @param chan The channel's reference.
662  *
663  * @return Channel's name reference.
664  */
zbus_chan_name(const struct zbus_channel * chan)665 static inline const char *zbus_chan_name(const struct zbus_channel *chan)
666 {
667 	__ASSERT(chan != NULL, "chan is required");
668 
669 	return chan->name;
670 }
671 
672 #endif
673 
674 #if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
675 
676 /**
677  * @brief Retrieve a zbus channel from its numeric identifier
678  *
679  * @param channel_id Unique channel ID from @ref ZBUS_CHAN_DEFINE_WITH_ID
680  *
681  * @retval NULL If channel with ID @a channel_id does not exist.
682  * @retval chan Channel pointer with ID @a channel_id otherwise.
683  */
684 const struct zbus_channel *zbus_chan_from_id(uint32_t channel_id);
685 
686 #endif
687 
688 /**
689  * @brief Get the reference for a channel message directly.
690  *
691  * This routine returns the reference of a channel message.
692  *
693  * @warning This function must only be used directly for already locked channels. This
694  * can be done inside a listener for the receiving channel or after claim a channel.
695  *
696  * @param chan The channel's reference.
697  *
698  * @return Channel's message reference.
699  */
zbus_chan_msg(const struct zbus_channel * chan)700 static inline void *zbus_chan_msg(const struct zbus_channel *chan)
701 {
702 	__ASSERT(chan != NULL, "chan is required");
703 
704 	return chan->message;
705 }
706 
707 /**
708  * @brief Get a constant reference for a channel message directly.
709  *
710  * This routine returns a constant reference of a channel message. This should be used
711  * inside listeners to access the message directly. In this way zbus prevents the listener of
712  * changing the notifying channel's message during the notification process.
713  *
714  * @warning This function must only be used directly for already locked channels. This
715  * can be done inside a listener for the receiving channel or after claim a channel.
716  *
717  * @param chan The channel's constant reference.
718  *
719  * @return A constant channel's message reference.
720  */
zbus_chan_const_msg(const struct zbus_channel * chan)721 static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
722 {
723 	__ASSERT(chan != NULL, "chan is required");
724 
725 	return chan->message;
726 }
727 
728 /**
729  * @brief Get the channel's message size.
730  *
731  * This routine returns the channel's message size.
732  *
733  * @param chan The channel's reference.
734  *
735  * @return Channel's message size.
736  */
zbus_chan_msg_size(const struct zbus_channel * chan)737 static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
738 {
739 	__ASSERT(chan != NULL, "chan is required");
740 
741 	return chan->message_size;
742 }
743 
744 /**
745  * @brief Get the channel's user data.
746  *
747  * This routine returns the channel's user data.
748  *
749  * @param chan The channel's reference.
750  *
751  * @return Channel's user data.
752  */
zbus_chan_user_data(const struct zbus_channel * chan)753 static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
754 {
755 	__ASSERT(chan != NULL, "chan is required");
756 
757 	return chan->user_data;
758 }
759 
760 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
761 
762 /**
763  * @brief Set the channel's msg subscriber `net_buf` pool.
764  *
765  * @param chan The channel's reference.
766  * @param pool The reference to the `net_buf` memory pool.
767  */
zbus_chan_set_msg_sub_pool(const struct zbus_channel * chan,struct net_buf_pool * pool)768 static inline void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan,
769 					      struct net_buf_pool *pool)
770 {
771 	__ASSERT(chan != NULL, "chan is required");
772 	__ASSERT(pool != NULL, "pool is required");
773 
774 	chan->data->msg_subscriber_pool = pool;
775 }
776 
777 #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
778 
779 #if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
780 
781 /**
782  * @brief Update the publishing statistics for a channel
783  *
784  * This function updates the publishing statistics for the @ref zbus_chan_claim ->
785  * @ref zbus_chan_finish workflow, which cannot automatically determine whether
786  * new data has been published or not.
787  *
788  * @warning This function must only be used directly for already locked channels.
789  *
790  * @param chan The channel's reference.
791  */
zbus_chan_pub_stats_update(const struct zbus_channel * chan)792 static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
793 {
794 	__ASSERT(chan != NULL, "chan is required");
795 
796 	chan->data->publish_timestamp = k_uptime_ticks();
797 	chan->data->publish_count += 1;
798 }
799 
800 /**
801  * @brief Get the time a channel was last published to.
802  *
803  * @note Will return 0 if channel has not yet been published to.
804  *
805  * @param chan The channel's reference.
806  *
807  * @return The kernel timestamp of the last publishing action.
808  */
zbus_chan_pub_stats_last_time(const struct zbus_channel * chan)809 static inline k_ticks_t zbus_chan_pub_stats_last_time(const struct zbus_channel *chan)
810 {
811 	__ASSERT(chan != NULL, "chan is required");
812 
813 	return chan->data->publish_timestamp;
814 }
815 
816 /**
817  * @brief Get the number of times a channel has been published to.
818  *
819  * @note Will return 0 if channel has not yet been published to.
820  *
821  * @param chan The channel's reference.
822  *
823  * @return The number of times a channel has been published to.
824  */
zbus_chan_pub_stats_count(const struct zbus_channel * chan)825 static inline uint32_t zbus_chan_pub_stats_count(const struct zbus_channel *chan)
826 {
827 	__ASSERT(chan != NULL, "chan is required");
828 
829 	return chan->data->publish_count;
830 }
831 
832 /**
833  * @brief Get the average period between publishes to a channel.
834  *
835  * @note Will return 0 if channel has not yet been published to.
836  *
837  * @param chan The channel's reference.
838  *
839  * @return Average duration in milliseconds between publishes.
840  */
zbus_chan_pub_stats_avg_period(const struct zbus_channel * chan)841 static inline uint32_t zbus_chan_pub_stats_avg_period(const struct zbus_channel *chan)
842 {
843 	__ASSERT(chan != NULL, "chan is required");
844 
845 	/* Not yet published, period = 0ms */
846 	if (chan->data->publish_count == 0) {
847 		return 0;
848 	}
849 	/* Average period across application runtime */
850 	return k_uptime_get() / chan->data->publish_count;
851 }
852 
853 #else
854 
zbus_chan_pub_stats_update(const struct zbus_channel * chan)855 static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
856 {
857 	(void)chan;
858 }
859 
860 #endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
861 
862 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
863 
864 /**
865  * @brief Add an observer to a channel.
866  *
867  * This routine adds an observer to the channel.
868  *
869  * @param chan The channel's reference.
870  * @param obs The observer's reference to be added.
871  * @param timeout Waiting period to add an observer,
872  *                or one of the special values K_NO_WAIT and K_FOREVER.
873  *
874  * @retval 0 Observer added to the channel.
875  * @retval -EALREADY The observer is already present in the channel's runtime observers list.
876  * @retval -ENOMEM Returned without waiting.
877  * @retval -EAGAIN Waiting period timed out.
878  * @retval -EINVAL Some parameter is invalid.
879  */
880 int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
881 		      k_timeout_t timeout);
882 
883 /**
884  * @brief Remove an observer from a channel.
885  *
886  * This routine removes an observer to the channel.
887  *
888  * @param chan The channel's reference.
889  * @param obs The observer's reference to be removed.
890  * @param timeout Waiting period to remove an observer,
891  *                or one of the special values K_NO_WAIT and K_FOREVER.
892  *
893  * @retval 0 Observer removed to the channel.
894  * @retval -EINVAL Invalid data supplied.
895  * @retval -EBUSY Returned without waiting.
896  * @retval -EAGAIN Waiting period timed out.
897  * @retval -ENODATA no observer found in channel's runtime observer list.
898  * @retval -ENOMEM Returned without waiting.
899  */
900 int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
901 		     k_timeout_t timeout);
902 
903 /** @cond INTERNAL_HIDDEN */
904 
905 struct zbus_observer_node {
906 	sys_snode_t node;
907 	const struct zbus_observer *obs;
908 };
909 
910 /** @endcond */
911 
912 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
913 
914 /**
915  * @brief Change the observer state.
916  *
917  * This routine changes the observer state. A channel when disabled will not receive
918  * notifications from the event dispatcher.
919  *
920  * @param[in] obs The observer's reference.
921  * @param[in] enabled State to be. When false the observer stops to receive notifications.
922  *
923  * @retval 0 Observer set enable.
924  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
925  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
926  */
927 int zbus_obs_set_enable(const struct zbus_observer *obs, bool enabled);
928 
929 /**
930  * @brief Get the observer state.
931  *
932  * This routine retrieves the observer state.
933  *
934  * @param[in] obs The observer's reference.
935  * @param[out] enable The boolean output's reference.
936  *
937  * @return Observer state.
938  */
zbus_obs_is_enabled(const struct zbus_observer * obs,bool * enable)939 static inline int zbus_obs_is_enabled(const struct zbus_observer *obs, bool *enable)
940 {
941 	_ZBUS_ASSERT(obs != NULL, "obs is required");
942 	_ZBUS_ASSERT(enable != NULL, "enable is required");
943 
944 	*enable = obs->data->enabled;
945 
946 	return 0;
947 }
948 
949 /**
950  * @brief Mask notifications from a channel to an observer.
951  *
952  * The observer can mask notifications from a specific observing channel by calling this function.
953  *
954  * @param obs The observer's reference to be added.
955  * @param chan The channel's reference.
956  * @param masked The mask state. When the mask is true, the observer will not receive notifications
957  * from the channel.
958  *
959  * @retval 0 Channel notifications masked to the observer.
960  * @retval -ESRCH No observation found for the related pair chan/obs.
961  * @retval -EINVAL Some parameter is invalid.
962  */
963 int zbus_obs_set_chan_notification_mask(const struct zbus_observer *obs,
964 					const struct zbus_channel *chan, bool masked);
965 
966 /**
967  * @brief Get the notifications masking state from a channel to an observer.
968  *
969  * @param obs The observer's reference to be added.
970  * @param chan The channel's reference.
971  * @param[out] masked The mask state. When the mask is true, the observer will not receive
972  * notifications from the channel.
973  *
974  * @retval 0 Retrieved the masked state.
975  * @retval -ESRCH No observation found for the related pair chan/obs.
976  * @retval -EINVAL Some parameter is invalid.
977  */
978 int zbus_obs_is_chan_notification_masked(const struct zbus_observer *obs,
979 					 const struct zbus_channel *chan, bool *masked);
980 
981 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
982 
983 /**
984  * @brief Get the observer's name.
985  *
986  * This routine returns the observer's name reference.
987  *
988  * @param obs The observer's reference.
989  *
990  * @return The observer's name reference.
991  */
zbus_obs_name(const struct zbus_observer * obs)992 static inline const char *zbus_obs_name(const struct zbus_observer *obs)
993 {
994 	__ASSERT(obs != NULL, "obs is required");
995 
996 	return obs->name;
997 }
998 
999 #endif
1000 
1001 #if defined(CONFIG_ZBUS_PRIORITY_BOOST) || defined(__DOXYGEN__)
1002 
1003 /**
1004  * @brief Set the observer thread priority by attaching it to a thread.
1005  *
1006  * @param[in] obs The observer's reference.
1007  *
1008  * @retval 0 Observer detached from the thread.
1009  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
1010  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
1011  */
1012 int zbus_obs_attach_to_thread(const struct zbus_observer *obs);
1013 
1014 /**
1015  * @brief Clear the observer thread priority by detaching it from a thread.
1016  *
1017  * @param[in] obs The observer's reference.
1018  *
1019  * @retval 0 Observer detached from the thread.
1020  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
1021  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
1022  */
1023 int zbus_obs_detach_from_thread(const struct zbus_observer *obs);
1024 
1025 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
1026 
1027 /**
1028  * @brief Wait for a channel notification.
1029  *
1030  * This routine makes the subscriber to wait a notification. The notification comes as a channel
1031  * reference.
1032  *
1033  * @param[in] sub The subscriber's reference.
1034  * @param[out] chan The notification channel's reference.
1035  * @param[in] timeout Waiting period for a notification arrival,
1036  *                or one of the special values K_NO_WAIT and K_FOREVER.
1037  *
1038  * @retval 0 Notification received.
1039  * @retval -ENOMSG Returned without waiting.
1040  * @retval -EAGAIN Waiting period timed out.
1041  * @retval -EINVAL The observer is not a subscriber.
1042  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
1043  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
1044  */
1045 int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
1046 		  k_timeout_t timeout);
1047 
1048 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
1049 
1050 /**
1051  * @brief Wait for a channel message.
1052  *
1053  * This routine makes the subscriber wait for the new message in case of channel publication.
1054  *
1055  * @param[in] sub The subscriber's reference.
1056  * @param[out] chan The notification channel's reference.
1057  * @param[out] msg A reference to a copy of the published message.
1058  * @param[in] timeout Waiting period for a notification arrival,
1059  *                or one of the special values, K_NO_WAIT and K_FOREVER.
1060  *
1061  * @retval 0 Message received.
1062  * @retval -EINVAL The observer is not a subscriber.
1063  * @retval -ENOMSG Could not retrieve the net_buf from the subscriber FIFO.
1064  * @retval -EILSEQ Received an invalid channel reference.
1065  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
1066  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
1067  */
1068 int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg,
1069 		      k_timeout_t timeout);
1070 
1071 #endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
1072 
1073 /**
1074  *
1075  * @brief Iterate over channels.
1076  *
1077  * Enables the developer to iterate over the channels giving to this function an
1078  * iterator_func which is called for each channel. If the iterator_func returns false all
1079  * the iteration stops.
1080  *
1081  * @param[in] iterator_func The function that will be execute on each iteration.
1082  *
1083  * @retval true Iterator executed for all channels.
1084  * @retval false Iterator could not be executed. Some iterate returned false.
1085  */
1086 bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
1087 /**
1088  *
1089  * @brief Iterate over channels with user data.
1090  *
1091  * Enables the developer to iterate over the channels giving to this function an
1092  * iterator_func which is called for each channel. If the iterator_func returns false all
1093  * the iteration stops.
1094  *
1095  * @param[in] iterator_func The function that will be execute on each iteration.
1096  * @param[in] user_data The user data that can be passed in the function.
1097  *
1098  * @retval true Iterator executed for all channels.
1099  * @retval false Iterator could not be executed. Some iterate returned false.
1100  */
1101 bool zbus_iterate_over_channels_with_user_data(
1102 	bool (*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data);
1103 
1104 /**
1105  *
1106  * @brief Iterate over observers.
1107  *
1108  * Enables the developer to iterate over the observers giving to this function an
1109  * iterator_func which is called for each observer. If the iterator_func returns false all
1110  * the iteration stops.
1111  *
1112  * @param[in] iterator_func The function that will be execute on each iteration.
1113  *
1114  * @retval true Iterator executed for all channels.
1115  * @retval false Iterator could not be executed. Some iterate returned false.
1116  */
1117 bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
1118 /**
1119  *
1120  * @brief Iterate over observers with user data.
1121  *
1122  * Enables the developer to iterate over the observers giving to this function an
1123  * iterator_func which is called for each observer. If the iterator_func returns false all
1124  * the iteration stops.
1125  *
1126  * @param[in] iterator_func The function that will be execute on each iteration.
1127  * @param[in] user_data The user data that can be passed in the function.
1128  *
1129  * @retval true Iterator executed for all channels.
1130  * @retval false Iterator could not be executed. Some iterate returned false.
1131  */
1132 bool zbus_iterate_over_observers_with_user_data(
1133 	bool (*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data);
1134 
1135 /**
1136  * @}
1137  */
1138 
1139 #ifdef __cplusplus
1140 }
1141 #endif
1142 
1143 #endif /* ZEPHYR_INCLUDE_ZBUS_H_ */
1144