From 748c38fb3786f7285a0b136b6795f43886ec4d77 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Fri, 1 Nov 2024 13:34:04 +0800 Subject: [PATCH] DNM: Bluetooth: Host: Make bt rx thread never blocked Also look like sysworkq too. Signed-off-by: Lingao Meng --- include/zephyr/kernel.h | 5 +++++ include/zephyr/kernel/thread.h | 7 +++++++ kernel/sched.c | 4 ++++ kernel/work.c | 17 ++++++++++++++++- subsys/bluetooth/host/hci_core.c | 9 +++++++-- 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index e5f790abfe67a..248fb98cf2b42 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -3913,6 +3913,8 @@ enum { /* Static work queue flags */ K_WORK_QUEUE_NO_YIELD_BIT = 8, K_WORK_QUEUE_NO_YIELD = BIT(K_WORK_QUEUE_NO_YIELD_BIT), + K_WORK_QUEUE_NO_BLOCK_BIT = 9, + K_WORK_QUEUE_NO_BLOCK = BIT(K_WORK_QUEUE_NO_BLOCK_BIT), /** * INTERNAL_HIDDEN @endcond @@ -4103,6 +4105,9 @@ struct k_work_queue_config { * essential thread. */ bool essential; + + /** No Block by handler */ + bool no_block; }; /** @brief A structure used to hold work until it can be processed. */ diff --git a/include/zephyr/kernel/thread.h b/include/zephyr/kernel/thread.h index fd8e4c02f235e..fa229a3817c7d 100644 --- a/include/zephyr/kernel/thread.h +++ b/include/zephyr/kernel/thread.h @@ -252,6 +252,10 @@ struct z_poller { uint8_t mode; }; +enum { + Z_THREAD_NO_BLOCK = 0, +}; + /** * @ingroup thread_apis * Thread Structure @@ -269,6 +273,9 @@ struct k_thread { /** threads waiting in k_thread_join() */ _wait_q_t join_queue; + /** flags */ + atomic_t flags; + #if defined(CONFIG_POLL) struct z_poller poller; #endif /* CONFIG_POLL */ diff --git a/kernel/sched.c b/kernel/sched.c index 7db9c1b59fd06..d9e525efe6f45 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -661,6 +661,10 @@ int z_pend_curr(struct k_spinlock *lock, k_spinlock_key_t key, #endif /* CONFIG_TIMESLICING && CONFIG_SWAP_NONATOMIC */ __ASSERT_NO_MSG(sizeof(_sched_spinlock) == 0 || lock != &_sched_spinlock); + if (atomic_test_bit(&(_current->flags), Z_THREAD_NO_BLOCK)) { + return -ECANCELED; + } + /* We do a "lock swap" prior to calling z_swap(), such that * the caller's lock gets released as desired. But we ensure * that we hold the scheduler lock and leave local interrupts diff --git a/kernel/work.c b/kernel/work.c index 994d6d74e8041..cffc19a9c62c4 100644 --- a/kernel/work.c +++ b/kernel/work.c @@ -625,7 +625,7 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3) struct k_work *work = NULL; k_work_handler_t handler = NULL; k_spinlock_key_t key = k_spin_lock(&lock); - bool yield; + bool yield, block; /* Check for and prepare any new work. */ node = sys_slist_get(&queue->pending); @@ -684,9 +684,20 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3) k_spin_unlock(&lock, key); + block = !flag_test(&queue->flags, K_WORK_QUEUE_NO_BLOCK_BIT); + if (!block) { + atomic_set_bit(&(k_work_queue_thread_get(queue)->flags), + Z_THREAD_NO_BLOCK); + } + __ASSERT_NO_MSG(handler != NULL); handler(work); + if (!block) { + atomic_clear_bit(&(k_work_queue_thread_get(queue)->flags), + Z_THREAD_NO_BLOCK); + } + /* Mark the work item as no longer running and deal * with any cancellation and flushing issued while it * was running. Clear the BUSY flag and optionally @@ -747,6 +758,10 @@ void k_work_queue_start(struct k_work_q *queue, flags |= K_WORK_QUEUE_NO_YIELD; } + if ((cfg != NULL) && cfg->no_block) { + flags |= K_WORK_QUEUE_NO_BLOCK; + } + /* It hasn't actually been started yet, but all the state is in place * so we can submit things and once the thread gets control it's ready * to roll. diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 4606c8c9b1f1c..9471dc45d063e 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -4393,12 +4393,17 @@ int bt_enable(bt_ready_cb_t cb) k_fifo_init(&bt_dev.cmd_tx_queue); #if defined(CONFIG_BT_RECV_WORKQ_BT) + struct k_work_queue_config bt_workq_cfg = { + .name = "BT RX WQ", + .no_block = true, + }; + /* RX thread */ k_work_queue_init(&bt_workq); + k_work_queue_start(&bt_workq, rx_thread_stack, CONFIG_BT_RX_STACK_SIZE, - K_PRIO_COOP(CONFIG_BT_RX_PRIO), NULL); - k_thread_name_set(&bt_workq.thread, "BT RX WQ"); + K_PRIO_COOP(CONFIG_BT_RX_PRIO), &bt_workq_cfg); #endif #if DT_HAS_CHOSEN(zephyr_bt_hci)