@@ -30,12 +30,15 @@ DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO);
3030struct 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
3539struct 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