Skip to content

Commit 4225c27

Browse files
marcinszkudlinskitmleman
authored andcommitted
DP: use real module deadline calculation in DP
this commit enables (re) calculation of all DP modules deadlines at every DP scheduler run. It calculates all deadlines based on current buffers status and modules needs, as described Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
1 parent 4ec31f3 commit 4225c27

File tree

1 file changed

+74
-22
lines changed

1 file changed

+74
-22
lines changed

src/schedule/zephyr_dp_schedule.c

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO);
3333
struct scheduler_dp_data {
3434
struct list_item tasks; /* list of active dp tasks */
3535
struct task ll_tick_src; /* LL task - source of DP tick */
36+
uint32_t last_ll_tick_timestamp;/* a timestamp as k_cycle_get_32 of last LL tick,
37+
* "NOW" for DP deadline calculation
38+
*/
39+
3640
};
3741

3842
struct task_dp_pdata {
@@ -258,31 +262,31 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data)
258262
* Now - pipeline is in stable state, CPU used almost in 100% (it would be 100% if DP3
259263
* needed 1.2ms for processing - but the example would be too complicated)
260264
*/
261-
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
265+
266+
/* Go through all DP tasks and recalculate their readness and dedlines
267+
* NOT REENTRANT, should be called with scheduler_dp_lock()
268+
*/
269+
static void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run)
262270
{
263-
(void)receiver_data;
264-
(void)event_type;
265-
(void)caller_data;
266271
struct list_item *tlist;
267272
struct task *curr_task;
268273
struct task_dp_pdata *pdata;
269-
unsigned int lock_key;
270-
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
271274

272-
lock_key = scheduler_dp_lock(cpu_get_id());
273275
list_for_item(tlist, &dp_sch->tasks) {
274276
curr_task = container_of(tlist, struct task, list);
275277
pdata = curr_task->priv_data;
276278
struct processing_module *mod = pdata->mod;
279+
bool trigger_task = false;
277280

278281
/* decrease number of LL ticks/cycles left till the module reaches its deadline */
279-
if (pdata->ll_cycles_to_start) {
282+
if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) {
280283
pdata->ll_cycles_to_start--;
281284
if (!pdata->ll_cycles_to_start)
282-
/* deadline reached, clear startup delay flag.
285+
/* delayed start complete, clear startup delay flag.
283286
* see dp_startup_delay comment for details
284287
*/
285288
mod->dp_startup_delay = false;
289+
286290
}
287291

288292
if (curr_task->state == SOF_TASK_STATE_QUEUED) {
@@ -293,16 +297,66 @@ void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *
293297
mod->sinks,
294298
mod->num_of_sinks);
295299
if (mod_ready) {
296-
/* set a deadline for given num of ticks, starting now */
297-
k_thread_deadline_set(pdata->thread_id,
298-
pdata->deadline_clock_ticks);
299-
300300
/* trigger the task */
301301
curr_task->state = SOF_TASK_STATE_RUNNING;
302+
if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) {
303+
/* first time run - use delayed start */
304+
pdata->ll_cycles_to_start =
305+
module_get_lpt(pdata->mod) / LL_TIMER_PERIOD_US;
306+
307+
/* in case LPT < LL cycle - delay at least cycle */
308+
if (!pdata->ll_cycles_to_start)
309+
pdata->ll_cycles_to_start = 1;
310+
}
311+
trigger_task = true;
302312
k_sem_give(pdata->sem);
303313
}
304314
}
315+
if (curr_task->state == SOF_TASK_STATE_RUNNING) {
316+
/* (re) calculate deadline for all running tasks */
317+
/* get module deadline in us*/
318+
uint32_t deadline = module_get_deadline(mod);
319+
320+
/* if a deadline cannot be calculated, use a fixed value relative to its
321+
* first start
322+
*/
323+
if (deadline >= UINT32_MAX / 2 && trigger_task)
324+
deadline = module_get_lpt(mod);
325+
326+
if (deadline < UINT32_MAX) {
327+
/* round down to 1ms */
328+
deadline = deadline / 1000;
329+
330+
/* calculate number of ticks */
331+
deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000);
332+
333+
/* add to "NOW", overflows are OK */
334+
deadline = dp_sch->last_ll_tick_timestamp + deadline;
335+
336+
/* set in Zephyr. Note that it may be in past, it does not matter,
337+
* Zephyr still will schedule the thread with earlier deadline
338+
* first
339+
*/
340+
k_thread_absolute_deadline_set(pdata->thread_id, deadline);
341+
}
342+
}
305343
}
344+
}
345+
346+
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
347+
{
348+
(void)receiver_data;
349+
(void)event_type;
350+
(void)caller_data;
351+
unsigned int lock_key;
352+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
353+
354+
if (event_type == NOTIFIER_ID_LL_PRE_RUN)
355+
/* remember current timestamp as "NOW" */
356+
dp_sch->last_ll_tick_timestamp = k_cycle_get_32();
357+
358+
lock_key = scheduler_dp_lock(cpu_get_id());
359+
scheduler_dp_recalculate(dp_sch, event_type == NOTIFIER_ID_LL_POST_RUN);
306360
scheduler_dp_unlock(lock_key);
307361
}
308362

@@ -374,6 +428,7 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
374428
unsigned int lock_key;
375429
enum task_state state;
376430
bool task_stop;
431+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
377432

378433
do {
379434
/*
@@ -415,6 +470,11 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
415470
/* if true exit the while loop, terminate the thread */
416471
task_stop = task->state == SOF_TASK_STATE_COMPLETED ||
417472
task->state == SOF_TASK_STATE_CANCEL;
473+
/* recalculate all DP tasks readiness and deadlines
474+
* TODO: it should be for all tasks, for all cores
475+
* currently its limited to current core only
476+
*/
477+
scheduler_dp_recalculate(dp_sch, false);
418478

419479
scheduler_dp_unlock(lock_key);
420480
} while (!task_stop);
@@ -430,7 +490,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
430490
struct scheduler_dp_data *dp_sch = (struct scheduler_dp_data *)data;
431491
struct task_dp_pdata *pdata = task->priv_data;
432492
unsigned int lock_key;
433-
uint64_t deadline_clock_ticks;
434493
int ret;
435494

436495
lock_key = scheduler_dp_lock(cpu_get_id());
@@ -483,14 +542,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
483542
task->state = SOF_TASK_STATE_QUEUED;
484543
list_item_prepend(&task->list, &dp_sch->tasks);
485544

486-
deadline_clock_ticks = period * CONFIG_SYS_CLOCK_TICKS_PER_SEC;
487-
/* period/deadline is in us - convert to seconds in next step
488-
* or it always will be zero because of integer calculation
489-
*/
490-
deadline_clock_ticks /= 1000000;
491-
492-
pdata->deadline_clock_ticks = deadline_clock_ticks;
493-
pdata->ll_cycles_to_start = period / LL_TIMER_PERIOD_US;
494545
pdata->mod->dp_startup_delay = true;
495546
scheduler_dp_unlock(lock_key);
496547

@@ -532,6 +583,7 @@ int scheduler_dp_init(void)
532583
if (ret)
533584
return ret;
534585

586+
notifier_register(NULL, NULL, NOTIFIER_ID_LL_PRE_RUN, scheduler_dp_ll_tick, 0);
535587
notifier_register(NULL, NULL, NOTIFIER_ID_LL_POST_RUN, scheduler_dp_ll_tick, 0);
536588

537589
return 0;

0 commit comments

Comments
 (0)