forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathzephyr_dp_schedule_application.c
More file actions
161 lines (136 loc) · 4.57 KB
/
zephyr_dp_schedule_application.c
File metadata and controls
161 lines (136 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2025 Intel Corporation. All rights reserved.
*
* Author: Marcin Szkudlinski
*/
#include <rtos/task.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/common.h>
#include <sof/list.h>
#include <sof/schedule/ll_schedule_domain.h>
#include <sof/schedule/dp_schedule.h>
#include <zephyr/kernel.h>
#include <stdbool.h>
#include <stdint.h>
#include "zephyr_dp_schedule.h"
/* Go through all DP tasks and recalculate their readiness and deadlines
* NOT REENTRANT, should be called with scheduler_dp_lock()
*/
void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run)
{
struct list_item *tlist;
struct task *curr_task;
struct task_dp_pdata *pdata;
list_for_item(tlist, &dp_sch->tasks) {
curr_task = container_of(tlist, struct task, list);
pdata = curr_task->priv_data;
struct processing_module *mod = pdata->mod;
bool trigger_task = false;
/* decrease number of LL ticks/cycles left till the module reaches its deadline */
if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) {
pdata->ll_cycles_to_start--;
if (!pdata->ll_cycles_to_start)
/* delayed start complete, clear startup delay flag.
* see dp_startup_delay comment for details
*/
mod->dp_startup_delay = false;
}
if (curr_task->state == SOF_TASK_STATE_QUEUED) {
bool mod_ready;
mod_ready = module_is_ready_to_process(mod, mod->sources,
mod->num_of_sources,
mod->sinks,
mod->num_of_sinks);
if (mod_ready) {
/* trigger the task */
curr_task->state = SOF_TASK_STATE_RUNNING;
if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) {
/* first time run - use delayed start */
pdata->ll_cycles_to_start =
module_get_lpt(pdata->mod) / LL_TIMER_PERIOD_US;
/* in case LPT < LL cycle - delay at least cycle */
if (!pdata->ll_cycles_to_start)
pdata->ll_cycles_to_start = 1;
}
trigger_task = true;
k_event_post(pdata->event, DP_TASK_EVENT_PROCESS);
}
}
if (curr_task->state == SOF_TASK_STATE_RUNNING) {
/* (re) calculate deadline for all running tasks */
/* get module deadline in us*/
uint32_t deadline = module_get_deadline(mod);
/* if a deadline cannot be calculated, use a fixed value relative to its
* first start
*/
if (deadline >= UINT32_MAX / 2 && trigger_task)
deadline = module_get_lpt(mod);
if (deadline < UINT32_MAX) {
/* round down to 1ms */
deadline = deadline / 1000;
/* calculate number of ticks */
deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000);
/* add to "NOW", overflows are OK */
deadline = dp_sch->last_ll_tick_timestamp + deadline;
/* set in Zephyr. Note that it may be in past, it does not matter,
* Zephyr still will schedule the thread with earlier deadline
* first
*/
k_thread_absolute_deadline_set(pdata->thread_id, deadline);
}
}
}
}
/* Thread function called in component context, on target core */
void dp_thread_fn(void *p1, void *p2, void *p3)
{
struct task *task = p1;
(void)p2;
(void)p3;
struct task_dp_pdata *task_pdata = task->priv_data;
unsigned int lock_key;
enum task_state state;
bool task_stop;
do {
/*
* the thread is started immediately after creation, it will stop on event.
* Event will be signalled once the task is ready to process.
*/
k_event_wait_safe(task_pdata->event, DP_TASK_EVENT_PROCESS | DP_TASK_EVENT_CANCEL,
false, K_FOREVER);
if (task->state == SOF_TASK_STATE_RUNNING)
state = task_run(task);
else
state = task->state; /* to avoid undefined variable warning */
lock_key = scheduler_dp_lock(task->core);
/*
* check if task is still running, may have been canceled by external call
* if not, set the state returned by run procedure
*/
if (task->state == SOF_TASK_STATE_RUNNING) {
task->state = state;
switch (state) {
case SOF_TASK_STATE_RESCHEDULE:
/* mark to reschedule, schedule time is already calculated */
task->state = SOF_TASK_STATE_QUEUED;
break;
case SOF_TASK_STATE_CANCEL:
case SOF_TASK_STATE_COMPLETED:
/* remove from scheduling */
list_item_del(&task->list);
break;
default:
/* illegal state, serious defect, won't happen */
k_panic();
}
}
/* if true exit the while loop, terminate the thread */
task_stop = task->state == SOF_TASK_STATE_COMPLETED ||
task->state == SOF_TASK_STATE_CANCEL;
scheduler_dp_unlock(lock_key);
} while (!task_stop);
/* call task_complete */
if (task->state == SOF_TASK_STATE_COMPLETED)
task_complete(task);
}