@@ -33,6 +33,10 @@ DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO);
3333struct 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
3842struct 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