kernel: add new work queue implementation
This commit provides a complete reimplementation of the work queue infrastructure intended to eliminate the race conditions and feature gaps in the existing implementation. Both bare and delayable work structures are supported. Items can be submitted; delayable items can be scheduled for submission at a future time. Items can be delayed, queued, and running all at the same time. A running item can also be canceling. The new implementation: * replaces "pending" with "busy" which identifies the active states; * supports canceling delayed and submitted items; * prevents resubmission of a item being canceled until cancellation completes; * supports waiting for cancellation to complete; * supports flushing a work item (waiting for the last submission to complete without preventing resubmission); * supports waiting for a queue to drain (only allows resubmission from the work thread); * supports stopping a work queue in conjunction with draining it; * prevents handler-reentrancy during resubmission. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
44539ed645
commit
dc34e7c6f6
5 changed files with 2035 additions and 32 deletions
1001
include/kernel.h
1001
include/kernel.h
File diff suppressed because it is too large
Load diff
|
@ -45,6 +45,7 @@ set_target_properties(
|
|||
)
|
||||
|
||||
target_sources_ifdef(CONFIG_KERNEL_WORK1 kernel PRIVATE work_q.c)
|
||||
target_sources_ifdef(CONFIG_KERNEL_WORK2 kernel PRIVATE work.c)
|
||||
|
||||
target_sources_ifdef(CONFIG_STACK_CANARIES kernel PRIVATE compiler_stack_protect.c)
|
||||
target_sources_ifdef(CONFIG_SYS_CLOCK_EXISTS kernel PRIVATE timeout.c timer.c)
|
||||
|
|
|
@ -396,6 +396,15 @@ config SYSTEM_WORKQUEUE_PRIORITY
|
|||
priority. This means that any work handler, once started, won't
|
||||
be preempted by any other thread until finished.
|
||||
|
||||
config SYSTEM_WORKQUEUE_NO_YIELD
|
||||
bool "Select whether system work queue yields"
|
||||
help
|
||||
By default, the system work queue yields between each work item, to
|
||||
prevent other threads from being starved. Selecting this removes
|
||||
this yield, which may be useful if the work queue thread is
|
||||
cooperative and a sequence of work items is expected to complete
|
||||
without yielding.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Atomic Operations"
|
||||
|
|
|
@ -14,19 +14,31 @@
|
|||
#include <kernel.h>
|
||||
#include <init.h>
|
||||
|
||||
K_KERNEL_STACK_DEFINE(sys_work_q_stack, CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE);
|
||||
static K_KERNEL_STACK_DEFINE(sys_work_q_stack,
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE);
|
||||
|
||||
struct k_work_q k_sys_work_q;
|
||||
|
||||
static int k_sys_work_q_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
struct k_work_queue_config cfg = {
|
||||
.name = "sysworkq",
|
||||
.no_yield = IS_ENABLED(CONFIG_SYSTEM_WORKQUEUE_NO_YIELD),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KERNEL_WORK1
|
||||
k_work_q_start(&k_sys_work_q,
|
||||
sys_work_q_stack,
|
||||
K_KERNEL_STACK_SIZEOF(sys_work_q_stack),
|
||||
CONFIG_SYSTEM_WORKQUEUE_PRIORITY);
|
||||
k_thread_name_set(&k_sys_work_q.thread, "sysworkq");
|
||||
#else /* CONFIG_KERNEL_WORK1 */
|
||||
k_work_queue_start(&k_sys_work_q,
|
||||
sys_work_q_stack,
|
||||
K_KERNEL_STACK_SIZEOF(sys_work_q_stack),
|
||||
CONFIG_SYSTEM_WORKQUEUE_PRIORITY, &cfg);
|
||||
#endif /* CONFIG_KERNEL_WORK1 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
1042
kernel/work.c
Normal file
1042
kernel/work.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue