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