Skip to content

Commit 1dc5f0f

Browse files
committed
lib: bm_queue: a dynamic queue implementation
A dynamic queue implementation based on Zephyr's k_queue. The library has a compatibility mode to export Zephyr's k_queue API, but it also exposes its own bm_queue API set so that bare metal libraries and application can avoid including zephyr/kernel.h and using a k_ prefixed (kernel's) API. Signed-off-by: Emanuele Di Santo <[email protected]>
1 parent 0bc6d3a commit 1dc5f0f

File tree

8 files changed

+637
-0
lines changed

8 files changed

+637
-0
lines changed

include/bm_queue.h

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
* Copyright (c) 2016, Wind River Systems, Inc.
3+
* Copyright (c) 2025, Nordic Semiconductor ASA
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <stdint.h>
9+
#include <stdbool.h>
10+
#include <zephyr/sys/slist.h>
11+
#include <zephyr/sys/sflist.h>
12+
13+
/**
14+
* @brief Queue.
15+
*/
16+
struct bm_queue {
17+
sys_sflist_t data_q;
18+
};
19+
20+
/**
21+
* @brief Initialize a queue.
22+
*
23+
* This routine initializes a queue, prior to its first use.
24+
*
25+
* @param queue Queue.
26+
*/
27+
void bm_queue_init(struct bm_queue *queue);
28+
29+
/**
30+
* @brief Append an element to the end of a queue.
31+
*
32+
* This routine appends a data item to @a queue. A queue data item must be
33+
* aligned on a word boundary, and the first word of the item is reserved
34+
* for internal use. The data is not copied.
35+
*
36+
* @funcprops \isr_ok
37+
*
38+
* @param queue Queue.
39+
* @param data Data item.
40+
*/
41+
void bm_queue_append(struct bm_queue *queue, void *data);
42+
43+
/**
44+
* @brief Allocate an element and append it to the queue.
45+
*
46+
* This routine appends a data item to @a queue. There is an implicit memory
47+
* allocation on the system heap to create an additional temporary bookkeeping data structure,
48+
* which is automatically freed when the item is removed. The data itself is not copied.
49+
*
50+
* @funcprops \isr_ok
51+
*
52+
* @param queue Queue.
53+
* @param data Data item.
54+
*
55+
* @retval 0 on success
56+
* @retval -ENOMEM if there isn't sufficient RAM in the system heap
57+
*/
58+
int32_t bm_queue_alloc_append(struct bm_queue *queue, void *data);
59+
60+
/**
61+
* @brief Prepend an element to the queue.
62+
*
63+
* This routine prepends a data item to @a queue. A queue data item must be
64+
* aligned on a word boundary, and the first word of the item is reserved
65+
* for internal use. The data is not copied.
66+
*
67+
* @funcprops \isr_ok
68+
*
69+
* @param queue Queue.
70+
* @param data Data item.
71+
*/
72+
void bm_queue_prepend(struct bm_queue *queue, void *data);
73+
74+
/**
75+
* @brief Prepend an element to a queue.
76+
*
77+
* This routine prepends a data item to @a queue. There is an implicit memory
78+
* allocation to create an additional temporary bookkeeping data structure from
79+
* the system heap, which is automatically freed when the item is removed.
80+
* The data itself is not copied.
81+
*
82+
* @funcprops \isr_ok
83+
*
84+
* @param queue Queue.
85+
* @param data Data item.
86+
*
87+
* @retval 0 on success
88+
* @retval -ENOMEM if there isn't sufficient RAM in the system heap.
89+
*/
90+
int32_t bm_queue_alloc_prepend(struct bm_queue *queue, void *data);
91+
92+
/**
93+
* @brief Insert an element at a given position in the queue.
94+
*
95+
* This routine inserts a data item to @a queue after previous item. A queue
96+
* data item must be aligned on a word boundary, and the first word of
97+
* the item is reserved for internal use.
98+
*
99+
* @funcprops \isr_ok
100+
*
101+
* @param queue Queue.
102+
* @param prev Previous element.
103+
* @param data Data item.
104+
*/
105+
void bm_queue_insert(struct bm_queue *queue, void *prev, void *data);
106+
107+
/**
108+
* @brief Atomically append a list of elements to a queue.
109+
*
110+
* This routine adds a list of data items to @a queue in one operation.
111+
* The data items must be in a singly-linked list, with the first word
112+
* in each data item pointing to the next data item; the list must be
113+
* NULL-terminated.
114+
*
115+
* @funcprops \isr_ok
116+
*
117+
* @param queue Queue.
118+
* @param head Pointer to first node in singly-linked list.
119+
* @param tail Pointer to last node in singly-linked list.
120+
*
121+
* @retval 0 on success
122+
* @retval -EINVAL on invalid supplied data
123+
*/
124+
int bm_queue_append_list(struct bm_queue *queue, void *head, void *tail);
125+
126+
/**
127+
* @brief Atomically add a list of elements to a queue.
128+
*
129+
* This routine adds a list of data items to @a queue in one operation.
130+
* The data items must be in a singly-linked list implemented using a
131+
* sys_slist_t object. Upon completion, the original list is empty.
132+
*
133+
* @funcprops \isr_ok
134+
*
135+
* @param queue Queue.
136+
* @param list Pointer to sys_slist_t object.
137+
*
138+
* @retval 0 on success
139+
* @retval -EINVAL on invalid data
140+
*/
141+
int bm_queue_merge_slist(struct bm_queue *queue, sys_slist_t *list);
142+
143+
/**
144+
* @brief Get an element from a queue.
145+
*
146+
* This routine removes first data item from @a queue. The first word of the
147+
* data item is reserved for internal use.
148+
*
149+
* @funcprops \isr_ok
150+
*
151+
* @param queue Queue.
152+
*
153+
* @return Address of the data item if successful; NULL otherwise.
154+
*/
155+
void *bm_queue_get(struct bm_queue *queue);
156+
157+
/**
158+
* @brief Remove an element from a queue.
159+
*
160+
* This routine removes data item from @a queue. The first word of the
161+
* data item is reserved for internal use. Removing elements from bm_queue
162+
* rely on sys_slist_find_and_remove which is not a constant time operation.
163+
*
164+
* @funcprops \isr_ok
165+
*
166+
* @param queue Queue.
167+
* @param data Data item.
168+
*
169+
* @return true if data item was removed
170+
*/
171+
bool bm_queue_remove(struct bm_queue *queue, void *data);
172+
173+
/**
174+
* @brief Append an element to a queue only if it's not present already.
175+
*
176+
* This routine appends data item to @a queue. The first word of the data
177+
* item is reserved for internal use. Appending elements to bm_queue
178+
* relies on sys_slist_is_node_in_list which is not a constant time operation.
179+
*
180+
* @funcprops \isr_ok
181+
*
182+
* @param queue Queue.
183+
* @param data Data item.
184+
*
185+
* @return true if data item was added, false if not
186+
*/
187+
bool bm_queue_unique_append(struct bm_queue *queue, void *data);
188+
189+
/**
190+
* @brief Query a queue to see if it has data available.
191+
*
192+
* @funcprops \isr_ok
193+
*
194+
* @param queue Queue.
195+
*
196+
* @return Non-zero if the queue is empty.
197+
* @return 0 if data is available.
198+
*/
199+
static inline bool bm_queue_is_empty(struct bm_queue *queue)
200+
{
201+
return sys_sflist_is_empty(&queue->data_q);
202+
}
203+
204+
/**
205+
* @brief Peek element at the head of queue.
206+
*
207+
* Return element from the head of queue without removing it.
208+
*
209+
* @param queue Queue.
210+
*
211+
* @return Head element, or NULL if queue is empty.
212+
*/
213+
void *bm_queue_peek_head(struct bm_queue *queue);
214+
215+
/**
216+
* @brief Peek element at the tail of queue.
217+
*
218+
* Return element from the tail of queue without removing it.
219+
*
220+
* @param queue Queue.
221+
*
222+
* @return Tail element, or NULL if queue is empty.
223+
*/
224+
void *bm_queue_peek_tail(struct bm_queue *queue);

lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_subdirectory_ifdef(CONFIG_BLE_RACP ble_racp)
1111
add_subdirectory_ifdef(CONFIG_EVENT_SCHEDULER event_scheduler)
1212
add_subdirectory_ifdef(CONFIG_BM_BUTTONS bm_buttons)
1313
add_subdirectory_ifdef(CONFIG_BM_TIMER bm_timer)
14+
add_subdirectory_ifdef(CONFIG_BM_QUEUE bm_queue)
1415
add_subdirectory_ifdef(CONFIG_BLE_QWR ble_qwr)
1516
add_subdirectory_ifdef(CONFIG_SENSORSIM sensorsim)
1617
add_subdirectory_ifdef(CONFIG_NCS_BARE_METAL_BOOT_BANNER boot_banner)

lib/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rsource "ble_racp/Kconfig"
1212
rsource "event_scheduler/Kconfig"
1313
rsource "bm_buttons/Kconfig"
1414
rsource "bm_timer/Kconfig"
15+
rsource "bm_queue/Kconfig"
1516
rsource "ble_qwr/Kconfig"
1617
rsource "sensorsim/Kconfig"
1718
rsource "boot_banner/Kconfig"

lib/bm_queue/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
zephyr_library()
7+
zephyr_library_sources(bm_queue.c)

lib/bm_queue/Kconfig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
menuconfig BM_QUEUE
7+
bool "Queue library"
8+
help
9+
A simple, dynamic queue using singly linked lists.
10+
11+
if BM_QUEUE
12+
13+
config BM_QUEUE_K_QUEUE_COMPAT
14+
bool "Export k_queue compatible API"
15+
depends on !MULTITHREADING
16+
help
17+
Export a k_queue compatible API for compatibility with Zephyr subsystems.
18+
19+
module=BM_QUEUE
20+
module-dep=LOG
21+
module-str=Queue library
22+
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"
23+
24+
endif

0 commit comments

Comments
 (0)