Skip to content

Commit 6fcafbe

Browse files
committed
Bluetooth: Host: Add bt_taskq workqueue for quick non-blocking tasks
Add a new workqueue bt_taskq specifically designed for quick non-blocking work items in the Bluetooth subsystem. This workqueue is always available and does not depend on any Kconfig option. Signed-off-by: Aleksander Wasaznik <[email protected]>
1 parent 3635cd2 commit 6fcafbe

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed

subsys/bluetooth/host/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_LONG_WQ long_wq.c)
1414

1515
if(CONFIG_BT_HCI_HOST)
1616
zephyr_library_sources(
17+
bt_taskq.c
1718
uuid.c
1819
addr.c
1920
buf.c

subsys/bluetooth/host/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ menu "Bluetooth Host"
165165

166166
if BT_HCI_HOST
167167

168+
rsource "Kconfig.bt_taskq"
168169
rsource "../mesh/Kconfig"
169170
rsource "../audio/Kconfig"
170171

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# bt_taskq configuration options
2+
3+
# Copyright (c) 2025 Nordic Semiconductor
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
choice BT_TASKQ_CONTEXT
7+
prompt "bt_taskq thread selection"
8+
# nRF51 is too small to have a dedicated thread
9+
default BT_TASKQ_SYSTEM_WORKQUEUE if SOC_SERIES_NRF51X
10+
default BT_TASKQ_DEDICATED
11+
help
12+
Selects in which context the bt_taskq runs.
13+
14+
bt_taskq work is quick and non-blocking and must not be
15+
blocked by other work. It should be on a work queue that
16+
is exclusively for non-blocking work.
17+
18+
config BT_TASKQ_DEDICATED
19+
bool "Dedicated thread"
20+
help
21+
When this option is selected, the bt_taskq runs on a
22+
dedicated thread. This is the default and safe option.
23+
24+
config BT_TASKQ_SYSTEM_WORKQUEUE
25+
bool "System workqueue"
26+
help
27+
When this option is selected, the bt_taskq is the system
28+
workqueue.
29+
30+
WARNING: This is safe only if there is no blocking work on
31+
the system workqueue.
32+
33+
This is currently NEVER SAFE to use as the Host itself
34+
puts blocking work on the system workqueue. For now, this
35+
option exists for users that need to free up RAM by not
36+
having an extra thread and are willing to accept the risk
37+
of deadlocks. When using this option, it is advised to
38+
have a watchdog to recover from deadlocks. Risk of
39+
deadlocks can be mitigated by being mindful of buffers and
40+
whole-system analysis.
41+
42+
endchoice
43+
44+
config BT_TASKQ_STACK_SIZE_WITH_PROMPT
45+
bool "bt_taskq thread stack size override"
46+
depends on BT_TASKQ_DEDICATED
47+
48+
config BT_TASKQ_STACK_SIZE
49+
int
50+
default 1024
51+
prompt "bt_taskq thread stack size" if BT_TASKQ_STACK_SIZE_WITH_PROMPT
52+
53+
config BT_TASKQ_THREAD_PRIO
54+
# Hidden option
55+
int
56+
# -1 is the least urgent cooperative priority.
57+
# tx_processor() needs a cooperative thread for now.
58+
default -1

subsys/bluetooth/host/bt_taskq.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* bt_taskq.c - Workqueue for quick non-blocking Bluetooth tasks */
2+
3+
/*
4+
* Copyright (c) 2025 Nordic Semiconductor ASA
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <zephyr/autoconf.h>
10+
#include <zephyr/init.h>
11+
#include <zephyr/kernel.h>
12+
#include <zephyr/kernel/thread_stack.h>
13+
#include <zephyr/sys/util_macro.h>
14+
#include <zephyr/toolchain.h>
15+
16+
static K_THREAD_STACK_DEFINE(bt_taskq_stack, CONFIG_BT_TASKQ_STACK_SIZE);
17+
static struct k_work_q bt_taskq;
18+
19+
__maybe_unused static int bt_taskq_init(void)
20+
{
21+
struct k_work_queue_config cfg = {};
22+
23+
if (IS_ENABLED(CONFIG_THREAD_NAME)) {
24+
cfg.name = "bt_taskq";
25+
}
26+
27+
k_work_queue_start(&bt_taskq, bt_taskq_stack, K_THREAD_STACK_SIZEOF(bt_taskq_stack),
28+
CONFIG_BT_TASKQ_THREAD_PRIO, &cfg);
29+
30+
return 0;
31+
}
32+
33+
#if defined(CONFIG_BT_TASKQ_DEDICATED)
34+
/* The init priority is set to POST_KERNEL 999, the last level
35+
* before APPLICATION.
36+
*/
37+
SYS_INIT(bt_taskq_init, POST_KERNEL, 999);
38+
#endif /* CONFIG_BT_TASKQ_DEDICATED */
39+
40+
/* Exports */
41+
struct k_work_q *const bt_taskq_chosen =
42+
COND_CODE_1(CONFIG_BT_TASKQ_DEDICATED, (&bt_taskq), (&k_sys_work_q));

subsys/bluetooth/host/bt_taskq.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* bt_taskq.h - Workqueue for quick non-blocking Bluetooth tasks */
2+
3+
/*
4+
* Copyright (c) 2025 Nordic Semiconductor ASA
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <zephyr/kernel.h>
10+
11+
/**
12+
* @brief Bluetooth task workqueue
13+
*
14+
* bt_taskq is a workqueue intended for quick non-blocking work
15+
* items ("tasks") in the Bluetooth subsystem. This workqueue
16+
* must always exist and is not controlled by any Kconfig
17+
* option.
18+
*
19+
* Blocking means "waiting for something while running". A
20+
* task is NOT allowed to block. If a task need to "wait", it
21+
* should instead return immediately and schedule itself to run
22+
* later.
23+
*
24+
* Work items submitted to this queue should be:
25+
* - Quick to execute (non-blocking).
26+
* - Not perform long-running operations.
27+
* - Not block.
28+
*
29+
* @warning Non-blocking violation pitfalls:
30+
* - net_buf_unref() on a foreign buffer could have a blocking
31+
* destroy callback
32+
* - Any user-defined callback might be blocking
33+
* - Avoid any operations that could sleep or block the thread
34+
*
35+
* Use bt_long_wq for long-running or potentially blocking
36+
* operations instead.
37+
*
38+
* Available in APPLICATION initialization level and later.
39+
*/
40+
extern struct k_work_q *const bt_taskq_chosen;

0 commit comments

Comments
 (0)