@@ -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 timestap 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 */
@@ -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