Skip to content

Commit bf56dec

Browse files
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 aec3c0b commit bf56dec

File tree

1 file changed

+67
-23
lines changed

1 file changed

+67
-23
lines changed

src/schedule/zephyr_dp_schedule.c

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@ DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO);
3030
struct scheduler_dp_data {
3131
struct list_item tasks; /* list of active dp tasks */
3232
struct task ll_tick_src; /* LL task - source of DP tick */
33+
uint32_t last_ll_tick_timestamp;/* a timestap as k_cycle_get_32 of last LL tick,
34+
* "NOW" for DP deadline calculation
35+
*/
36+
3337
};
3438

3539
struct task_dp_pdata {
3640
k_tid_t thread_id; /* zephyr thread ID */
3741
struct k_thread thread; /* memory space for a thread */
38-
uint32_t deadline_clock_ticks; /* dp module deadline in Zephyr ticks */
3942
k_thread_stack_t __sparse_cache *p_stack; /* pointer to thread stack */
4043
size_t stack_size; /* size of the stack in bytes */
4144
struct k_sem sem; /* semaphore for task scheduling */
@@ -559,31 +562,30 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data)
559562
* Now - pipeline is in stable state, CPU used almost in 100% (it would be 100% if DP3
560563
* needed 1.2ms for processing - but the example would be too complicated)
561564
*/
562-
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
565+
566+
/* Go through all DP tasks and recalculate their readness and dedlines
567+
* NOT REENTRANT, should be called with scheduler_dp_lock()
568+
*/
569+
static void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run)
563570
{
564-
(void)receiver_data;
565-
(void)event_type;
566-
(void)caller_data;
567571
struct list_item *tlist;
568572
struct task *curr_task;
569573
struct task_dp_pdata *pdata;
570-
unsigned int lock_key;
571-
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
572574

573-
lock_key = scheduler_dp_lock();
574575
list_for_item(tlist, &dp_sch->tasks) {
575576
curr_task = container_of(tlist, struct task, list);
576577
pdata = curr_task->priv_data;
577578
struct processing_module *mod = pdata->mod;
578579

579580
/* decrease number of LL ticks/cycles left till the module reaches its deadline */
580-
if (pdata->ll_cycles_to_start) {
581+
if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) {
581582
pdata->ll_cycles_to_start--;
582583
if (!pdata->ll_cycles_to_start)
583-
/* deadline reached, clear startup delay flag.
584+
/* delayed start complete, clear startup delay flag.
584585
* see dp_startup_delay comment for details
585586
*/
586587
mod->dp_startup_delay = false;
588+
587589
}
588590

589591
if (curr_task->state == SOF_TASK_STATE_QUEUED) {
@@ -594,16 +596,60 @@ void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *
594596
mod->sinks,
595597
mod->num_of_sinks);
596598
if (mod_ready) {
597-
/* set a deadline for given num of ticks, starting now */
598-
k_thread_deadline_set(pdata->thread_id,
599-
pdata->deadline_clock_ticks);
600-
601599
/* trigger the task */
602600
curr_task->state = SOF_TASK_STATE_RUNNING;
601+
if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) {
602+
/* first time run - use delayed start */
603+
pdata->ll_cycles_to_start =
604+
module_get_LPT(pdata->mod) / LL_TIMER_PERIOD_US;
605+
606+
/* in case LPT < LL cycle - delay at least cycle */
607+
if (!pdata->ll_cycles_to_start)
608+
pdata->ll_cycles_to_start = 1;
609+
}
610+
603611
k_sem_give(&pdata->sem);
604612
}
605613
}
614+
if (curr_task->state == SOF_TASK_STATE_RUNNING) {
615+
/* (re) calculate deadline for all running tasks */
616+
/* get module deadline in us*/
617+
uint32_t deadline = module_get_deadline(mod);
618+
619+
/* round down to 1ms */
620+
deadline = deadline / 1000;
621+
622+
uint32_t out = sink_get_free_size(mod->sinks[0]);
623+
624+
/* calculate number of ticks */
625+
deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000);
626+
627+
/* add to "NOW", overflows are OK */
628+
deadline = dp_sch->last_ll_tick_timestamp + deadline;
629+
630+
/* set in Zephyr. Note that it may be in past, it does not matter,
631+
* Zephyr still will schedule the thread with earlier deadline
632+
* first
633+
*/
634+
k_thread_absolute_deadline_set(pdata->thread_id, deadline);
635+
}
606636
}
637+
}
638+
639+
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
640+
{
641+
(void)receiver_data;
642+
(void)event_type;
643+
(void)caller_data;
644+
unsigned int lock_key;
645+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
646+
647+
if (event_type == NOTIFIER_ID_LL_PRE_RUN)
648+
/* remember currect timestamp as "NOW" */
649+
dp_sch->last_ll_tick_timestamp = k_cycle_get_32();
650+
651+
lock_key = scheduler_dp_lock();
652+
scheduler_dp_recalculate(dp_sch, event_type == NOTIFIER_ID_LL_POST_RUN);
607653
scheduler_dp_unlock(lock_key);
608654
}
609655

@@ -667,6 +713,7 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
667713
unsigned int lock_key;
668714
enum task_state state;
669715
bool task_stop;
716+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
670717

671718
do {
672719
/*
@@ -708,6 +755,11 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
708755
/* if true exit the while loop, terminate the thread */
709756
task_stop = task->state == SOF_TASK_STATE_COMPLETED ||
710757
task->state == SOF_TASK_STATE_CANCEL;
758+
/* recalculate all DP tasks readiness and deadlines
759+
* TODO: it should be for all tasks, for all cores
760+
* currently its limited to current core only
761+
*/
762+
scheduler_dp_recalculate(dp_sch, false);
711763

712764
scheduler_dp_unlock(lock_key);
713765
} while (!task_stop);
@@ -723,7 +775,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
723775
struct scheduler_dp_data *dp_sch = (struct scheduler_dp_data *)data;
724776
struct task_dp_pdata *pdata = task->priv_data;
725777
unsigned int lock_key;
726-
uint64_t deadline_clock_ticks;
727778
int ret;
728779

729780
lock_key = scheduler_dp_lock();
@@ -759,14 +810,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
759810
task->state = SOF_TASK_STATE_QUEUED;
760811
list_item_prepend(&task->list, &dp_sch->tasks);
761812

762-
deadline_clock_ticks = period * CONFIG_SYS_CLOCK_TICKS_PER_SEC;
763-
/* period/deadline is in us - convert to seconds in next step
764-
* or it always will be zero because of integer calculation
765-
*/
766-
deadline_clock_ticks /= 1000000;
767-
768-
pdata->deadline_clock_ticks = deadline_clock_ticks;
769-
pdata->ll_cycles_to_start = period / LL_TIMER_PERIOD_US;
770813
pdata->mod->dp_startup_delay = true;
771814
scheduler_dp_unlock(lock_key);
772815

@@ -808,6 +851,7 @@ int scheduler_dp_init(void)
808851
if (ret)
809852
return ret;
810853

854+
notifier_register(NULL, NULL, NOTIFIER_ID_LL_PRE_RUN, scheduler_dp_ll_tick, 0);
811855
notifier_register(NULL, NULL, NOTIFIER_ID_LL_POST_RUN, scheduler_dp_ll_tick, 0);
812856

813857
return 0;

0 commit comments

Comments
 (0)