2323#include <sof/lib/notifier.h>
2424#include <ipc4/base_fw.h>
2525
26+ #include "zephyr_dp_schedule.h"
27+
2628#include <zephyr/kernel/thread.h>
2729
2830LOG_MODULE_REGISTER (dp_schedule , CONFIG_SOF_LOG_LEVEL );
2931SOF_DEFINE_REG_UUID (dp_sched );
3032
3133DECLARE_TR_CTX (dp_tr , SOF_UUID (dp_sched_uuid ), LOG_LEVEL_INFO );
3234
33- struct scheduler_dp_data {
34- struct list_item tasks ; /* list of active dp tasks */
35- 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-
40- };
41-
42- struct task_dp_pdata {
43- k_tid_t thread_id ; /* zephyr thread ID */
44- struct k_thread * thread ; /* pointer to the kernels' thread object */
45- struct k_thread thread_struct ; /* thread object for kernel threads */
46- uint32_t deadline_clock_ticks ; /* dp module deadline in Zephyr ticks */
47- k_thread_stack_t __sparse_cache * p_stack ; /* pointer to thread stack */
48- size_t stack_size ; /* size of the stack in bytes */
49- struct k_sem * sem ; /* pointer to semaphore for task scheduling */
50- struct k_sem sem_struct ; /* semaphore for task scheduling for kernel threads */
51- struct processing_module * mod ; /* the module to be scheduled */
52- uint32_t ll_cycles_to_start ; /* current number of LL cycles till delayed start */
53- };
54-
5535#define DP_LOCK_INIT (i , _ ) Z_SEM_INITIALIZER(dp_lock[i], 1, 1)
5636#define DP_LOCK_INIT_LIST LISTIFY(CONFIG_MP_MAX_NUM_CPUS, DP_LOCK_INIT, (,))
5737
@@ -66,13 +46,13 @@ STRUCT_SECTION_ITERABLE_ARRAY(k_sem, dp_lock, CONFIG_MP_MAX_NUM_CPUS) = { DP_LOC
6646 *
6747 * TODO: consider using cpu_get_id() instead of supplying core as a parameter.
6848 */
69- static inline unsigned int scheduler_dp_lock (uint16_t core )
49+ unsigned int scheduler_dp_lock (uint16_t core )
7050{
7151 k_sem_take (& dp_lock [core ], K_FOREVER );
7252 return core ;
7353}
7454
75- static inline void scheduler_dp_unlock (unsigned int key )
55+ void scheduler_dp_unlock (unsigned int key )
7656{
7757 k_sem_give (& dp_lock [key ]);
7858}
@@ -243,86 +223,6 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data)
243223 * needed 1.2ms for processing - but the example would be too complicated)
244224 */
245225
246- /* Go through all DP tasks and recalculate their readness and dedlines
247- * NOT REENTRANT, should be called with scheduler_dp_lock()
248- */
249- static void scheduler_dp_recalculate (struct scheduler_dp_data * dp_sch , bool is_ll_post_run )
250- {
251- struct list_item * tlist ;
252- struct task * curr_task ;
253- struct task_dp_pdata * pdata ;
254-
255- list_for_item (tlist , & dp_sch -> tasks ) {
256- curr_task = container_of (tlist , struct task , list );
257- pdata = curr_task -> priv_data ;
258- struct processing_module * mod = pdata -> mod ;
259- bool trigger_task = false;
260-
261- /* decrease number of LL ticks/cycles left till the module reaches its deadline */
262- if (mod -> dp_startup_delay && is_ll_post_run && pdata -> ll_cycles_to_start ) {
263- pdata -> ll_cycles_to_start -- ;
264- if (!pdata -> ll_cycles_to_start )
265- /* delayed start complete, clear startup delay flag.
266- * see dp_startup_delay comment for details
267- */
268- mod -> dp_startup_delay = false;
269-
270- }
271-
272- if (curr_task -> state == SOF_TASK_STATE_QUEUED ) {
273- bool mod_ready ;
274-
275- mod_ready = module_is_ready_to_process (mod , mod -> sources ,
276- mod -> num_of_sources ,
277- mod -> sinks ,
278- mod -> num_of_sinks );
279- if (mod_ready ) {
280- /* trigger the task */
281- curr_task -> state = SOF_TASK_STATE_RUNNING ;
282- if (mod -> dp_startup_delay && !pdata -> ll_cycles_to_start ) {
283- /* first time run - use delayed start */
284- pdata -> ll_cycles_to_start =
285- module_get_lpt (pdata -> mod ) / LL_TIMER_PERIOD_US ;
286-
287- /* in case LPT < LL cycle - delay at least cycle */
288- if (!pdata -> ll_cycles_to_start )
289- pdata -> ll_cycles_to_start = 1 ;
290- }
291- trigger_task = true;
292- k_sem_give (pdata -> sem );
293- }
294- }
295- if (curr_task -> state == SOF_TASK_STATE_RUNNING ) {
296- /* (re) calculate deadline for all running tasks */
297- /* get module deadline in us*/
298- uint32_t deadline = module_get_deadline (mod );
299-
300- /* if a deadline cannot be calculated, use a fixed value relative to its
301- * first start
302- */
303- if (deadline >= UINT32_MAX / 2 && trigger_task )
304- deadline = module_get_lpt (mod );
305-
306- if (deadline < UINT32_MAX ) {
307- /* round down to 1ms */
308- deadline = deadline / 1000 ;
309-
310- /* calculate number of ticks */
311- deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000 );
312-
313- /* add to "NOW", overflows are OK */
314- deadline = dp_sch -> last_ll_tick_timestamp + deadline ;
315-
316- /* set in Zephyr. Note that it may be in past, it does not matter,
317- * Zephyr still will schedule the thread with earlier deadline
318- * first
319- */
320- k_thread_absolute_deadline_set (pdata -> thread_id , deadline );
321- }
322- }
323- }
324- }
325-
326226void scheduler_dp_ll_tick (void * receiver_data , enum notify_id event_type , void * caller_data )
327227{
328228 (void )receiver_data ;
@@ -398,76 +298,6 @@ static int scheduler_dp_task_free(void *data, struct task *task)
398298 return ret ;
399299}
400300
401- /* Thread function called in component context, on target core */
402- static void dp_thread_fn (void * p1 , void * p2 , void * p3 )
403- {
404- struct task * task = p1 ;
405- (void )p2 ;
406- (void )p3 ;
407- struct task_dp_pdata * task_pdata = task -> priv_data ;
408- struct scheduler_dp_data * dp_sch = NULL ;
409- unsigned int lock_key ;
410- enum task_state state ;
411- bool task_stop ;
412-
413- if (!(task -> flags & K_USER ))
414- dp_sch = scheduler_get_data (SOF_SCHEDULE_DP );
415-
416- do {
417- /*
418- * the thread is started immediately after creation, it will stop on semaphore
419- * Semaphore will be released once the task is ready to process
420- */
421- k_sem_take (task_pdata -> sem , K_FOREVER );
422-
423- if (task -> state == SOF_TASK_STATE_RUNNING )
424- state = task_run (task );
425- else
426- state = task -> state ; /* to avoid undefined variable warning */
427-
428- lock_key = scheduler_dp_lock (task -> core );
429- /*
430- * check if task is still running, may have been canceled by external call
431- * if not, set the state returned by run procedure
432- */
433- if (task -> state == SOF_TASK_STATE_RUNNING ) {
434- task -> state = state ;
435- switch (state ) {
436- case SOF_TASK_STATE_RESCHEDULE :
437- /* mark to reschedule, schedule time is already calculated */
438- task -> state = SOF_TASK_STATE_QUEUED ;
439- break ;
440-
441- case SOF_TASK_STATE_CANCEL :
442- case SOF_TASK_STATE_COMPLETED :
443- /* remove from scheduling */
444- list_item_del (& task -> list );
445- break ;
446-
447- default :
448- /* illegal state, serious defect, won't happen */
449- k_panic ();
450- }
451- }
452-
453- /* if true exit the while loop, terminate the thread */
454- task_stop = task -> state == SOF_TASK_STATE_COMPLETED ||
455- task -> state == SOF_TASK_STATE_CANCEL ;
456- /* recalculate all DP tasks readiness and deadlines
457- * TODO: it should be for all tasks, for all cores
458- * currently its limited to current core only
459- */
460- if (dp_sch )
461- scheduler_dp_recalculate (dp_sch , false);
462-
463- scheduler_dp_unlock (lock_key );
464- } while (!task_stop );
465-
466- /* call task_complete */
467- if (task -> state == SOF_TASK_STATE_COMPLETED )
468- task_complete (task );
469- }
470-
471301static int scheduler_dp_task_shedule (void * data , struct task * task , uint64_t start ,
472302 uint64_t period )
473303{
0 commit comments