@@ -26,6 +26,7 @@ DECLARE_TR_CTX(ll_tr, SOF_UUID(zll_sched_uuid), LOG_LEVEL_INFO);
2626
2727/* per-scheduler data */
2828struct zephyr_ll {
29+ struct list_item startup_tasks ;
2930 struct list_item tasks ; /* list of ll tasks */
3031 unsigned int n_tasks ; /* task counter */
3132 struct ll_schedule_domain * ll_domain ; /* scheduling domain */
@@ -109,6 +110,9 @@ static void zephyr_ll_task_insert_unlocked(struct zephyr_ll *sch, struct task *t
109110
110111 task -> state = SOF_TASK_STATE_QUEUED ;
111112
113+ list_item_append (& task -> list , & sch -> startup_tasks );
114+
115+ #if 0
112116 /*
113117 * Tasks are added into the list in priority order. List order
114118 * defines schedule order. Priority 0 indicates highest
@@ -129,6 +133,7 @@ static void zephyr_ll_task_insert_unlocked(struct zephyr_ll *sch, struct task *t
129133 */
130134 if (list == & sch -> tasks )
131135 list_item_append (& task -> list , & sch -> tasks );
136+ #endif // 0
132137}
133138
134139static void zephyr_ll_task_insert_before_unlocked (struct task * task , struct task * before )
@@ -187,12 +192,67 @@ static void zephyr_ll_run(void *data)
187192 struct zephyr_ll * sch = data ;
188193 struct task * task ;
189194 struct list_item * list , * tmp , task_head = LIST_INIT (task_head );
195+ struct list_item * list2 , removed_startup_task_head = LIST_INIT (removed_startup_task_head );
190196 uint32_t flags ;
191197
192198 tr_dbg (& ll_tr , "entry" );
193199
194200 zephyr_ll_lock (sch , & flags );
195201
202+ for (list = sch -> startup_tasks .next ; !list_is_empty (& sch -> startup_tasks ); list = sch -> startup_tasks .next ) {
203+ enum task_state state ;
204+ struct zephyr_ll_pdata * pdata ;
205+
206+ task = container_of (list , struct task , list );
207+ pdata = task -> priv_data ;
208+
209+ if (task -> state == SOF_TASK_STATE_CANCEL ) {
210+ list = list -> next ; ///!!! A BUG IS HEHE???!!!
211+ zephyr_ll_task_done (sch , task );
212+ continue ;
213+ }
214+
215+ pdata -> run = true;
216+ task -> state = SOF_TASK_STATE_RUNNING ;
217+
218+ /* Move the task to a temporary list */
219+ list_item_del (list );
220+ list_item_append (list , & removed_startup_task_head );
221+
222+ zephyr_ll_unlock (sch , & flags );
223+
224+ /*
225+ * task's .run() should only return either
226+ * SOF_TASK_STATE_COMPLETED or SOF_TASK_STATE_RESCHEDULE
227+ */
228+ state = do_task_run (task );
229+ if (state != SOF_TASK_STATE_COMPLETED &&
230+ state != SOF_TASK_STATE_RESCHEDULE ) {
231+ tr_err (& ll_tr ,
232+ "invalid return state %u" ,
233+ state );
234+ state = SOF_TASK_STATE_RESCHEDULE ;
235+ }
236+
237+ zephyr_ll_lock (sch , & flags );
238+
239+ if (pdata -> freeing || state == SOF_TASK_STATE_COMPLETED ) {
240+ zephyr_ll_task_done (sch , task );
241+ } else {
242+ /*
243+ * task->state could've been changed to
244+ * SOF_TASK_STATE_CANCEL
245+ */
246+ switch (task -> state ) {
247+ case SOF_TASK_STATE_CANCEL :
248+ zephyr_ll_task_done (sch , task );
249+ break ;
250+ default :
251+ break ;
252+ }
253+ }
254+ }
255+
196256 /*
197257 * We drop the lock while executing tasks, at that time tasks can be
198258 * removed from or added to the list, including the task that was
@@ -261,6 +321,28 @@ static void zephyr_ll_run(void *data)
261321 list_item_append (list , & sch -> tasks );
262322 }
263323
324+ /* Move startup tasks back but respecting priorities */
325+ list_for_item_safe (list , tmp , & removed_startup_task_head ) {
326+ list_item_del (list );
327+
328+ struct task * task_iter = container_of (list , struct task , list );
329+
330+ list_for_item (list2 , & sch -> tasks ) {
331+ struct task * task_iter2 = container_of (list2 , struct task , list );
332+ if (task_iter -> priority < task_iter2 -> priority ) {
333+ list_item_append (list , & task_iter2 -> list );
334+ break ;
335+ }
336+ }
337+
338+ /*
339+ * If the task has not been added, it means that it has the lowest
340+ * priority and should be added at the end of the list
341+ */
342+ if (list_is_empty (list ))
343+ list_item_append (list , & sch -> tasks );
344+ }
345+
264346 zephyr_ll_unlock (sch , & flags );
265347
266348#ifndef CONFIG_SOF_USERSPACE_LL
@@ -320,6 +402,26 @@ static int zephyr_ll_task_schedule_common(struct zephyr_ll *sch, struct task *ta
320402 return - EDEADLK ;
321403 }
322404
405+ /* check if the task is already scheduled */
406+ list_for_item (list , & sch -> startup_tasks ) {
407+ task_iter = container_of (list , struct task , list );
408+
409+ if (task_iter == task ) {
410+ /* if cancelled, reschedule the task */
411+ if (task -> state == SOF_TASK_STATE_CANCEL )
412+ break ;
413+
414+ /*
415+ * keep original start. TODO: this shouldn't be happening.
416+ * Remove after verification
417+ */
418+ zephyr_ll_unlock (sch , & flags );
419+ tr_warn (& ll_tr , "task %p (%pU) already scheduled" ,
420+ task , task -> uid );
421+ return 0 ;
422+ }
423+ }
424+
323425 /* check if the task is already scheduled */
324426 list_for_item (list , & sch -> tasks ) {
325427 task_iter = container_of (list , struct task , list );
@@ -593,6 +695,7 @@ int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain)
593695 memset (sch , 0 , sizeof (* sch ));
594696
595697 list_init (& sch -> tasks );
698+ list_init (& sch -> startup_tasks );
596699 sch -> ll_domain = domain ;
597700 sch -> core = core ;
598701 sch -> n_tasks = 0 ;
@@ -625,6 +728,7 @@ void scheduler_get_task_info_ll(struct scheduler_props *scheduler_props,
625728 struct zephyr_ll * ll_sch = (struct zephyr_ll * )scheduler_get_data (SOF_SCHEDULE_LL_TIMER );
626729
627730 zephyr_ll_lock (ll_sch , & flags );
731+ ///TODO: !!! CONCATENATE LISTS, MAYBE???!!!
628732 scheduler_get_task_info (scheduler_props , data_off_size , & ll_sch -> tasks );
629733 zephyr_ll_unlock (ll_sch , & flags );
630734}
0 commit comments