Skip to content

Commit 11affdc

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 ccecbac commit 11affdc

1 file changed

Lines changed: 65 additions & 23 deletions

File tree

src/schedule/zephyr_dp_schedule.c

Lines changed: 65 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 timestamp 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 */
@@ -555,31 +558,30 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data)
555558
* Now - pipeline is in stable state, CPU used almost in 100% (it would be 100% if DP3
556559
* needed 1.2ms for processing - but the example would be too complicated)
557560
*/
558-
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
561+
562+
/* Go through all DP tasks and recalculate their readness and dedlines
563+
* NOT REENTRANT, should be called with scheduler_dp_lock()
564+
*/
565+
static void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run)
559566
{
560-
(void)receiver_data;
561-
(void)event_type;
562-
(void)caller_data;
563567
struct list_item *tlist;
564568
struct task *curr_task;
565569
struct task_dp_pdata *pdata;
566-
unsigned int lock_key;
567-
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
568570

569-
lock_key = scheduler_dp_lock();
570571
list_for_item(tlist, &dp_sch->tasks) {
571572
curr_task = container_of(tlist, struct task, list);
572573
pdata = curr_task->priv_data;
573574
struct processing_module *mod = pdata->mod;
574575

575576
/* decrease number of LL ticks/cycles left till the module reaches its deadline */
576-
if (pdata->ll_cycles_to_start) {
577+
if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) {
577578
pdata->ll_cycles_to_start--;
578579
if (!pdata->ll_cycles_to_start)
579-
/* deadline reached, clear startup delay flag.
580+
/* delayed start complete, clear startup delay flag.
580581
* see dp_startup_delay comment for details
581582
*/
582583
mod->dp_startup_delay = false;
584+
583585
}
584586

585587
if (curr_task->state == SOF_TASK_STATE_QUEUED) {
@@ -590,16 +592,58 @@ void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *
590592
mod->sinks,
591593
mod->num_of_sinks);
592594
if (mod_ready) {
593-
/* set a deadline for given num of ticks, starting now */
594-
k_thread_deadline_set(pdata->thread_id,
595-
pdata->deadline_clock_ticks);
596-
597595
/* trigger the task */
598596
curr_task->state = SOF_TASK_STATE_RUNNING;
597+
if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) {
598+
/* first time run - use delayed start */
599+
pdata->ll_cycles_to_start =
600+
module_get_LPT(pdata->mod) / LL_TIMER_PERIOD_US;
601+
602+
/* in case LPT < LL cycle - delay at least cycle */
603+
if (!pdata->ll_cycles_to_start)
604+
pdata->ll_cycles_to_start = 1;
605+
}
606+
599607
k_sem_give(&pdata->sem);
600608
}
601609
}
610+
if (curr_task->state == SOF_TASK_STATE_RUNNING) {
611+
/* (re) calculate deadline for all running tasks */
612+
/* get module deadline in us*/
613+
uint32_t deadline = module_get_deadline(mod);
614+
615+
/* round down to 1ms */
616+
deadline = deadline / 1000;
617+
618+
/* calculate number of ticks */
619+
deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000);
620+
621+
/* add to "NOW", overflows are OK */
622+
deadline = dp_sch->last_ll_tick_timestamp + deadline;
623+
624+
/* set in Zephyr. Note that it may be in past, it does not matter,
625+
* Zephyr still will schedule the thread with earlier deadline
626+
* first
627+
*/
628+
k_thread_absolute_deadline_set(pdata->thread_id, deadline);
629+
}
602630
}
631+
}
632+
633+
void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data)
634+
{
635+
(void)receiver_data;
636+
(void)event_type;
637+
(void)caller_data;
638+
unsigned int lock_key;
639+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
640+
641+
if (event_type == NOTIFIER_ID_LL_PRE_RUN)
642+
/* remember current timestamp as "NOW" */
643+
dp_sch->last_ll_tick_timestamp = k_cycle_get_32();
644+
645+
lock_key = scheduler_dp_lock();
646+
scheduler_dp_recalculate(dp_sch, event_type == NOTIFIER_ID_LL_POST_RUN);
603647
scheduler_dp_unlock(lock_key);
604648
}
605649

@@ -663,6 +707,7 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
663707
unsigned int lock_key;
664708
enum task_state state;
665709
bool task_stop;
710+
struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP);
666711

667712
do {
668713
/*
@@ -704,6 +749,11 @@ static void dp_thread_fn(void *p1, void *p2, void *p3)
704749
/* if true exit the while loop, terminate the thread */
705750
task_stop = task->state == SOF_TASK_STATE_COMPLETED ||
706751
task->state == SOF_TASK_STATE_CANCEL;
752+
/* recalculate all DP tasks readiness and deadlines
753+
* TODO: it should be for all tasks, for all cores
754+
* currently its limited to current core only
755+
*/
756+
scheduler_dp_recalculate(dp_sch, false);
707757

708758
scheduler_dp_unlock(lock_key);
709759
} while (!task_stop);
@@ -719,7 +769,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
719769
struct scheduler_dp_data *dp_sch = (struct scheduler_dp_data *)data;
720770
struct task_dp_pdata *pdata = task->priv_data;
721771
unsigned int lock_key;
722-
uint64_t deadline_clock_ticks;
723772
int ret;
724773

725774
lock_key = scheduler_dp_lock();
@@ -755,14 +804,6 @@ static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t sta
755804
task->state = SOF_TASK_STATE_QUEUED;
756805
list_item_prepend(&task->list, &dp_sch->tasks);
757806

758-
deadline_clock_ticks = period * CONFIG_SYS_CLOCK_TICKS_PER_SEC;
759-
/* period/deadline is in us - convert to seconds in next step
760-
* or it always will be zero because of integer calculation
761-
*/
762-
deadline_clock_ticks /= 1000000;
763-
764-
pdata->deadline_clock_ticks = deadline_clock_ticks;
765-
pdata->ll_cycles_to_start = period / LL_TIMER_PERIOD_US;
766807
pdata->mod->dp_startup_delay = true;
767808
scheduler_dp_unlock(lock_key);
768809

@@ -804,6 +845,7 @@ int scheduler_dp_init(void)
804845
if (ret)
805846
return ret;
806847

848+
notifier_register(NULL, NULL, NOTIFIER_ID_LL_PRE_RUN, scheduler_dp_ll_tick, 0);
807849
notifier_register(NULL, NULL, NOTIFIER_ID_LL_POST_RUN, scheduler_dp_ll_tick, 0);
808850

809851
return 0;

0 commit comments

Comments
 (0)