Skip to content

Commit a87f20c

Browse files
committed
core: introduce a system work queue, use it for EDF
Currently the EDF scheduler under Zephyr defines a delayed work queue to be run on the primary core. However such a work queue will be useful to multiple subsystems. Extract it from the EDF scheduler and make it globally available. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 7d11802 commit a87f20c

File tree

5 files changed

+51
-23
lines changed

5 files changed

+51
-23
lines changed

zephyr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ zephyr_library_sources(
528528
lib/alloc.c
529529
lib/cpu.c
530530
lib/pm_runtime.c
531+
lib/primary.c
531532

532533
# Common library functions - Will be moved to Zephyr over time
533534
lib.c

zephyr/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,10 @@ config VIRTUAL_HEAP
8989
help
9090
Enabling this option will use the virtual memory heap allocator to allocate buffers.
9191
It is based on a set of buffers whose size is predetermined.
92+
93+
config SOF_PRIMARY_WQ_STACK_SZ
94+
int "Primary work queue stack size"
95+
default 8192
96+
help
97+
Stack size for the primary core system work queue.
9298
endif

zephyr/edf_schedule.c

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
#include <zephyr/kernel.h>
1414
#include <zephyr/sys_clock.h>
1515

16-
static struct k_work_q edf_workq;
17-
static K_THREAD_STACK_DEFINE(edf_workq_stack, 8192);
18-
1916
/*
2017
* since only IPC is using the EDF scheduler - we schedule the work in the
2118
* next timer_domain time slice
@@ -39,9 +36,7 @@ static void edf_work_handler(struct k_work *work)
3936
if (deadline > now)
4037
timeout = K_TICKS(deadline - now);
4138

42-
k_work_reschedule_for_queue(&edf_workq,
43-
&task->z_delayed_work,
44-
timeout);
39+
sof_primary_wq_reschedule(&task->z_delayed_work, timeout);
4540
task->state = SOF_TASK_STATE_QUEUED;
4641
} else {
4742
task_complete(task);
@@ -56,9 +51,7 @@ static int schedule_edf_task(void *data, struct task *task, uint64_t start,
5651
/* start time is microseconds from now */
5752
k_timeout_t start_time = K_USEC(start + EDF_SCHEDULE_DELAY);
5853

59-
k_work_reschedule_for_queue(&edf_workq,
60-
&task->z_delayed_work,
61-
start_time);
54+
sof_primary_wq_reschedule(&task->z_delayed_work, start_time);
6255

6356
task->state = SOF_TASK_STATE_QUEUED;
6457
return 0;
@@ -100,22 +93,9 @@ static struct scheduler_ops schedule_edf_ops = {
10093

10194
int scheduler_init_edf(void)
10295
{
103-
struct k_thread *thread = &edf_workq.thread;
104-
10596
scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, NULL);
10697

107-
k_work_queue_start(&edf_workq,
108-
edf_workq_stack,
109-
K_THREAD_STACK_SIZEOF(edf_workq_stack),
110-
EDF_ZEPHYR_PRIORITY, NULL);
111-
112-
k_thread_suspend(thread);
113-
114-
k_thread_cpu_mask_clear(thread);
115-
k_thread_cpu_mask_enable(thread, PLATFORM_PRIMARY_CORE_ID);
116-
k_thread_name_set(thread, "edf_workq");
117-
118-
k_thread_resume(thread);
98+
sof_primary_wq_init();
11999

120100
return 0;
121101
}

zephyr/include/sof/lib/cpu.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ static inline int cpu_secondary_cores_prepare_d0ix(void) { return 0; };
9393

9494
#endif /* CONFIG_MULTICORE && CONFIG_SMP */
9595

96+
#include <rtos/kernel.h>
97+
struct k_work_delayable;
98+
void sof_primary_wq_init(void);
99+
void sof_primary_wq_reschedule(struct k_work_delayable *dwork, k_timeout_t delay);
100+
96101
#endif
97102

98103
#endif /* __SOF_LIB_CPU_H__ */

zephyr/lib/primary.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* Copyright(c) 2025 Intel Corporation.
4+
*/
5+
6+
#include <zephyr/arch/cpu.h>
7+
#include <zephyr/kernel.h>
8+
9+
#include <sof/lib/cpu.h>
10+
11+
static struct k_work_q sof_prime_wq;
12+
static K_THREAD_STACK_DEFINE(sof_prime_wq_stack, CONFIG_SOF_PRIMARY_WQ_STACK_SZ);
13+
static atomic_val_t sof_prime_wq_init;
14+
15+
void sof_primary_wq_reschedule(struct k_work_delayable *dwork, k_timeout_t delay)
16+
{
17+
k_work_schedule_for_queue(&sof_prime_wq, dwork, delay);
18+
}
19+
20+
void sof_primary_wq_init(void)
21+
{
22+
if (atomic_set(&sof_prime_wq_init, 1))
23+
return;
24+
25+
struct k_thread *thread = &sof_prime_wq.thread;
26+
27+
k_work_queue_start(&sof_prime_wq, sof_prime_wq_stack,
28+
K_THREAD_STACK_SIZEOF(sof_prime_wq_stack), 1, NULL);
29+
30+
k_thread_suspend(thread);
31+
32+
k_thread_cpu_pin(thread, PLATFORM_PRIMARY_CORE_ID);
33+
k_thread_name_set(thread, "sof_prime_wq");
34+
35+
k_thread_resume(thread);
36+
}

0 commit comments

Comments
 (0)