Skip to content

Commit d5d410b

Browse files
kernel: sys_workq: add option to allow blocking sys_workq
Add option which allows calling blocking APIs from the system workqueue. This option is inherently unsafe, but users may want to do it anyway. Signed-off-by: Bjarki Arge Andreasen <[email protected]>
1 parent ca019c9 commit d5d410b

File tree

7 files changed

+53
-1
lines changed

7 files changed

+53
-1
lines changed

doc/kernel/services/threads/workqueue.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ its queue until the handler function finishes executing.
110110
it do not depend on subsequent work items in the queue to unblock it.
111111

112112
Attempting to perform a blocking call will fail an assert if
113-
:kconfig:option:`CONFIG_ASSERT` is enabled.
113+
:kconfig:option:`CONFIG_ASSERT` is enabled, unless
114+
:kconfig:option:`CONFIG_SYS_WORKQUEUE_BLOCKING` is selected. Use at your
115+
own risk.
114116

115117
The single argument that is passed to a handler function can be ignored if it
116118
is not required. If the handler function requires additional information about

kernel/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,15 @@ config SYSTEM_WORKQUEUE_NO_YIELD
600600
cooperative and a sequence of work items is expected to complete
601601
without yielding.
602602

603+
config SYSTEM_WORKQUEUE_BLOCKING
604+
bool "Select whether system work queue allows blocking calls"
605+
help
606+
By default, the system work queue disallows blocking calls, to
607+
prevent deadlocking the system work queue. This is ensured by
608+
asserting that no work item handler unreadyes the system work
609+
queue thread. Selecting this removes the assert. Note that this
610+
option only has an effect if CONFIG_ASSERT=y.
611+
603612
endmenu
604613

605614
menu "Barrier Operations"

kernel/sched.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,9 @@ static inline void z_vrfy_k_thread_resume(k_tid_t thread)
523523

524524
static void unready_thread(struct k_thread *thread)
525525
{
526+
#ifndef CONFIG_SYSTEM_WORKQUEUE_BLOCKING
526527
__ASSERT_NO_MSG(!k_is_in_sys_work());
528+
#endif /* CONFIG_SYSTEM_WORKQUEUE_BLOCKING */
527529
if (z_is_thread_queued(thread)) {
528530
dequeue_thread(thread);
529531
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(sys_workq_blocking)
6+
7+
target_sources(app PRIVATE src/main.c)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_ASSERT=y
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
9+
void blocking_work_handler(struct k_work *work)
10+
{
11+
ARG_UNUSED(work);
12+
13+
k_msleep(1);
14+
}
15+
16+
K_WORK_DEFINE(blocking_work, blocking_work_handler);
17+
18+
int main(void)
19+
{
20+
k_work_submit(&blocking_work);
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests:
2+
common:
3+
tags:
4+
- kernel
5+
- workqueue
6+
min_flash: 34
7+
kernel.workq.sys_workq_blocking.disallow:
8+
kernel.workq.sys_workq_blocking.allow:
9+
extra_configs:
10+
- CONFIG_SYSTEM_WORKQUEUE_BLOCKING=y

0 commit comments

Comments
 (0)