1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2019 Intel Corporation. All rights reserved.
4 //
5 // Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
6 
7 #define _GNU_SOURCE
8 
9 #include <sof/audio/component.h>
10 #include <rtos/task.h>
11 #include <sof/schedule/schedule.h>
12 #include <platform/lib/ll_schedule.h>
13 #include <sof/schedule/ll_schedule_domain.h>
14 #include <rtos/wait.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <stdint.h>
20 
21  /* scheduler testbench definition */
22 
23 /* 77de2074-828c-4044-a40b-420b72749e8b */
24 DECLARE_SOF_UUID("ll-schedule", ll_sched_uuid, 0x77de2074, 0x828c, 0x4044,
25 		 0xa4, 0x0b, 0x42, 0x0b, 0x72, 0x74, 0x9e, 0x8b);
26 
27 DECLARE_TR_CTX(ll_tr, SOF_UUID(ll_sched_uuid), LOG_LEVEL_INFO);
28 
29 /* list of all tasks */
30 static struct list_item sched_list;
31 
schedule_ll_run_tasks(void)32 void schedule_ll_run_tasks(void)
33 {
34 	struct list_item *tlist, *tlist_;
35 	struct task *task;
36 
37 	/* list empty then return */
38 	if (list_is_empty(&sched_list))
39 		fprintf(stdout, "LL scheduler thread exit - list empty\n");
40 
41 	/* iterate through the task list */
42 	list_for_item_safe(tlist, tlist_, &sched_list) {
43 		task = container_of(tlist, struct task, list);
44 
45 		/* only run queued tasks */
46 		if (task->state == SOF_TASK_STATE_QUEUED) {
47 			task->state = SOF_TASK_STATE_RUNNING;
48 
49 			task->ops.run(task->data);
50 
51 			/* only re-queue if not cancelled */
52 			if (task->state == SOF_TASK_STATE_RUNNING)
53 				task->state = SOF_TASK_STATE_QUEUED;
54 
55 		}
56 	}
57 }
58 
59 /* schedule new LL task */
schedule_ll_task(void * data,struct task * task,uint64_t start,uint64_t period)60 static int schedule_ll_task(void *data, struct task *task, uint64_t start,
61 			    uint64_t period)
62 {
63 	/* add task to list */
64 	list_item_prepend(&task->list, &sched_list);
65 	task->state = SOF_TASK_STATE_QUEUED;
66 	task->start = 0;
67 
68 	return 0;
69 }
70 
ll_scheduler_free(void * data,uint32_t flags)71 static void ll_scheduler_free(void *data, uint32_t flags)
72 {
73 	free(data);
74 }
75 
76 /* TODO: scheduler free and cancel APIs can merge as part of Zephyr */
schedule_ll_task_cancel(void * data,struct task * task)77 static int schedule_ll_task_cancel(void *data, struct task *task)
78 {
79 	/* delete task */
80 	task->state = SOF_TASK_STATE_CANCEL;
81 	list_item_del(&task->list);
82 
83 	return 0;
84 }
85 
86 /* TODO: scheduler free and cancel APIs can merge as part of Zephyr */
schedule_ll_task_free(void * data,struct task * task)87 static int schedule_ll_task_free(void *data, struct task *task)
88 {
89 	task->state = SOF_TASK_STATE_FREE;
90 	list_item_del(&task->list);
91 
92 	return 0;
93 }
94 
95 static struct scheduler_ops schedule_ll_ops = {
96 	.schedule_task		= schedule_ll_task,
97 	.schedule_task_running	= NULL,
98 	.reschedule_task	= NULL,
99 	.schedule_task_cancel	= schedule_ll_task_cancel,
100 	.schedule_task_free	= schedule_ll_task_free,
101 	.scheduler_free		= ll_scheduler_free,
102 };
103 
schedule_task_init_ll(struct task * task,const struct sof_uuid_entry * uid,uint16_t type,uint16_t priority,enum task_state (* run)(void * data),void * data,uint16_t core,uint32_t flags)104 int schedule_task_init_ll(struct task *task,
105 			  const struct sof_uuid_entry *uid, uint16_t type,
106 			  uint16_t priority, enum task_state (*run)(void *data),
107 			  void *data, uint16_t core, uint32_t flags)
108 {
109 	return schedule_task_init(task, uid, SOF_SCHEDULE_LL_TIMER, 0, run,
110 				  data, core, flags);
111 }
112 
113 /* initialize scheduler */
scheduler_init_ll(struct ll_schedule_domain * domain)114 int scheduler_init_ll(struct ll_schedule_domain *domain)
115 {
116 	tr_info(&ll_tr, "ll_scheduler_init()");
117 
118 	list_init(&sched_list);
119 	scheduler_init(SOF_SCHEDULE_LL_TIMER, &schedule_ll_ops, NULL);
120 
121 	return 0;
122 }
123