Skip to content

Commit 3ee1d78

Browse files
marcinszkudlinskilgirdwood
authored andcommitted
scheduling: add Data Processing scheduler type
The DP scheduler is a scheduler based on Zephyr preemptible threads. It will start each SOF task as a separate Zephyr thread. At current implementation the scheduler can trigger each task/thread periodically or on demand. TODO: more sophisticated scheduling decisions, with deadline and task budgets calculations. Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
1 parent 62e3582 commit 3ee1d78

File tree

6 files changed

+484
-3
lines changed

6 files changed

+484
-3
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause */
2+
/*
3+
* Copyright(c) 2023 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Marcin Szkudlinski
6+
*/
7+
8+
#ifndef __SOF_SCHEDULE_DP_SCHEDULE_H__
9+
#define __SOF_SCHEDULE_DP_SCHEDULE_H__
10+
11+
#include <rtos/task.h>
12+
#include <sof/trace/trace.h>
13+
#include <user/trace.h>
14+
#include <stdint.h>
15+
16+
/**
17+
*
18+
* DP scheduler is a scheduler that creates a separate preemptible Zephyr thread for each SOF task
19+
* There's only one instance of DP in the system, however, threads can be assigned and pinned
20+
* to any core in the system for its execution, there's no SMP processing.
21+
*
22+
* The task execution may be delayed and task may be re-scheduled periodically
23+
* NOTE: delayed start and rescheduling takes place in sync with LL scheduler, meaning the
24+
* DP scheduler is triggered as the last task of LL running on a primary core.
25+
* That implies a limitation: LL scheduler MUST be running on primary core in order to have
26+
* this feature working.
27+
* It is fine, because rescheduling is a feature used for data processing when a pipeline is
28+
* running.
29+
*
30+
* Other possible usage of DP scheduler is to schedule task with DP_SCHEDULER_RUN_TASK_IMMEDIATELY
31+
* as start parameter. It will force the task to work without any delays and async to LL.
32+
* This kind of scheduling may be used for staring regular zephyr tasks using SOF api
33+
*
34+
* Task run() may return:
35+
* SOF_TASK_STATE_RESCHEDULE - the task will be rescheduled as specified in scheduler period
36+
* note that task won't ever be rescheduled if LL is not running
37+
* SOF_TASK_STATE_COMPLETED - the task will be removed from scheduling,
38+
* calling schedule_task will add the task to processing again
39+
* task_complete() will be called
40+
* SOF_TASK_STATE_CANCEL - the task will be removed from scheduling,
41+
* calling schedule_task will add the task to processing again
42+
* task_complete() won't be called
43+
* other statuses - assert will go off
44+
*
45+
* NOTE: task - means a SOF task
46+
* thread - means a Zephyr preemptible thread
47+
*
48+
* TODO - EDF:
49+
* Threads run on the same priority, lower than thread running LL tasks. Zephyr EDF mechanism
50+
* is used for decision which thread/task is to be scheduled next. The DP scheduler calculates
51+
* the task deadline and set it in Zephyr thread properties, the final scheduling decision is made
52+
* by Zephyr.
53+
*
54+
* Each time tick the scheduler iterates through the list of all active tasks and calculates
55+
* a deadline based on
56+
* - knowledge how the modules are bound
57+
* - declared time required by a task to complete processing
58+
* - the deadline of the last module
59+
*
60+
*/
61+
62+
/** \brief tell the scheduler to run the task immediately, even if LL tick is not yet running */
63+
#define SCHEDULER_DP_RUN_TASK_IMMEDIATELY ((uint64_t)-1)
64+
65+
/**
66+
* \brief Init the Data Processing scheduler
67+
*/
68+
int scheduler_dp_init(void);
69+
70+
/**
71+
* \brief Set the Data Processing scheduler to be accessible at secondary cores
72+
*/
73+
int scheduler_dp_init_secondary_core(void);
74+
75+
/**
76+
* \brief initialize a DP task and add it to scheduling
77+
*
78+
* \param[out] task pointer, pointer to allocated task structure will be return
79+
* \param[in] uid pointer to UUID of the task
80+
* \param[in] ops pointer to task functions
81+
* \param[in] data pointer to the thread private data
82+
* \param[in] core CPU the thread should run on
83+
* \param[in] stack_size size of stack for a zephyr task
84+
* \param[in] task_priority priority of the zephyr task
85+
*/
86+
int scheduler_dp_task_init(struct task **task,
87+
const struct sof_uuid_entry *uid,
88+
const struct task_ops *ops,
89+
void *data,
90+
uint16_t core,
91+
size_t stack_size,
92+
uint32_t task_priority);
93+
94+
#endif /* __SOF_SCHEDULE_DP_SCHEDULE_H__ */

src/include/sof/schedule/schedule.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ enum {
3131
SOF_SCHEDULE_LL_DMA, /**< Low latency DMA, schedules immediately
3232
* on scheduling component's DMA interrupt
3333
*/
34+
SOF_SCHEDULE_DP, /**< DataProcessing scheduler
35+
* Scheduler based on Zephyr peemptive threads
36+
* TODO: DP will become the Zephyr EDF scheduler type
37+
* and will be unified with SOF_SCHEDULE_EDF for Zephyr builds
38+
* current implementation of Zephyr based EDF is depreciated now
39+
*/
3440
SOF_SCHEDULE_COUNT /**< indicates number of scheduler types */
3541
};
3642

3743
/** \brief Scheduler free available flags */
3844
#define SOF_SCHEDULER_FREE_IRQ_ONLY BIT(0) /**< Free function disables only
3945
* interrupts
4046
*/
41-
4247
/**
4348
* Scheduler operations.
4449
*

src/init/init.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <rtos/idc.h>
2727
#include <sof/schedule/schedule.h>
2828
#include <sof/schedule/edf_schedule.h>
29+
#include <sof/schedule/dp_schedule.h>
2930
#include <sof/schedule/ll_schedule.h>
3031
#include <sof/schedule/ll_schedule_domain.h>
3132
#include <ipc/trace.h>
@@ -183,6 +184,12 @@ int secondary_core_init(struct sof *sof)
183184
if (dma_domain)
184185
scheduler_init_ll(dma_domain);
185186

187+
#if CONFIG_ZEPHYR_DP_SCHEDULER
188+
err = scheduler_dp_init_secondary_core();
189+
if (err < 0)
190+
return err;
191+
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
192+
186193
/* initialize IDC mechanism */
187194
trace_point(TRACE_BOOT_PLATFORM_IDC);
188195
err = idc_init();

src/platform/intel/ace/platform.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <sof/lib/mm_heap.h>
1616
#include <sof/lib/watchdog.h>
1717
#include <sof/schedule/edf_schedule.h>
18+
#include <sof/schedule/dp_schedule.h>
1819
#include <sof/schedule/ll_schedule.h>
1920
#include <sof/schedule/ll_schedule_domain.h>
2021
#include <sof/trace/trace.h>
@@ -84,9 +85,17 @@ int platform_init(struct sof *sof)
8485
trace_point(TRACE_BOOT_PLATFORM_SCHED);
8586
scheduler_init_edf();
8687

87-
/* init low latency timer domain and scheduler */
88+
/* init low latency timer domain and scheduler. Any failure is fatal */
8889
sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK);
89-
scheduler_init_ll(sof->platform_timer_domain);
90+
ret = scheduler_init_ll(sof->platform_timer_domain);
91+
if (ret < 0)
92+
return ret;
93+
94+
#if CONFIG_ZEPHYR_DP_SCHEDULER
95+
ret = scheduler_dp_init();
96+
if (ret < 0)
97+
return ret;
98+
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
9099

91100
/* init the system agent */
92101
trace_point(TRACE_BOOT_PLATFORM_AGENT);

0 commit comments

Comments
 (0)