1 /*
2 * Copyright (C) 2020-2021 Alibaba Group Holding Limited
3 */
4
5 #include <stdint.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <pthread.h>
9 #include <sched.h>
10 #include <aos/kernel.h>
11 #include <aos/rhino.h>
12
13 #include "internal/pthread.h"
14 #include "internal/sched.h"
15
16 /* Note: pid is directly converted into pthread handle. */
_pid_to_pthread(pid_t pid)17 static inline pthread_t _pid_to_pthread(pid_t pid)
18 {
19 if (pid == -1) {
20 return NULL;
21 }
22
23 /* todo, not surpport */
24 return (pthread_t)(uintptr_t)pid;
25 }
26
27 /* Convert pid to ptcb of the thread. */
sched_get_ptcb(pid_t pid)28 static inline pthread_tcb_t* sched_get_ptcb(pid_t pid)
29 {
30 pthread_t thread = 0;
31
32 thread = _pid_to_pthread(pid);
33 if (thread == 0) {
34 thread = pthread_self();
35 }
36
37 return __pthread_get_tcb(thread);
38 }
39
sched_yield(void)40 int sched_yield(void)
41 {
42 aos_task_yield();
43 return 0;
44 }
45
sched_setscheduler(pid_t pid,int policy,const struct sched_param * param)46 int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)
47 {
48 int ret = 0;
49 pthread_tcb_t *ptcb = NULL;
50 uint8_t priority = 0;
51 int kpolicy = 0;
52 uint8_t old_policy = 0;
53
54 ptcb = sched_get_ptcb(pid);
55 if (ptcb == NULL) {
56 errno = ESRCH;
57 return -1;
58 }
59
60 kpolicy = sched_policy_posix2rhino(policy);
61 if (kpolicy == -1) {
62 errno = EINVAL;
63 return -1;
64 }
65
66 if ((param == NULL) || (param->sched_priority < aos_sched_get_priority_min(kpolicy))
67 || (param->sched_priority > aos_sched_get_priority_max(kpolicy))) {
68 errno = EINVAL;
69 return -1;
70 }
71
72 priority = sched_priority_posix2rhino(kpolicy, param->sched_priority);
73
74 ret = aos_task_sched_policy_get(&(ptcb->task), &old_policy);
75 if (ret != 0) {
76 return -1;
77 }
78 old_policy = sched_policy_rhino2posix(old_policy);
79
80 /* Change the policy and priority of the thread */
81 ret = aos_task_sched_policy_set(&(ptcb->task), kpolicy, priority);
82 if ((ret == 0) && (kpolicy == KSCHED_RR)) {
83 ret = aos_task_time_slice_set(&(ptcb->task), param->slice);
84 }
85 if (ret != 0) {
86 return -1;
87 }
88
89 ptcb->attr.sched_priority = param->sched_priority;
90 ptcb->attr.sched_slice = param->slice;
91
92 return old_policy;
93 }
94
sched_getscheduler(pid_t pid)95 int sched_getscheduler(pid_t pid)
96 {
97 int ret = 0;
98 uint8_t policy = 0;
99 pthread_tcb_t *ptcb = NULL;
100
101 ptcb = sched_get_ptcb(pid);
102 if (ptcb == NULL) {
103 errno = ESRCH;
104 return -1;
105 }
106
107 ret = aos_task_sched_policy_get(&(ptcb->task), &policy);
108 if (ret != 0) {
109 errno = EINVAL;
110 return -1;
111 }
112
113 return sched_policy_rhino2posix(policy);
114 }
115
sched_setparam(pid_t pid,const struct sched_param * param)116 int sched_setparam(pid_t pid, const struct sched_param *param)
117 {
118 int ret = 0;
119 pthread_tcb_t *ptcb = NULL;
120 uint8_t old_priority = 0;
121 uint8_t priority = 0;
122 uint8_t kpolicy = 0;
123
124 ptcb = sched_get_ptcb(pid);
125 if (ptcb == NULL) {
126 errno = ESRCH;
127 return -1;
128 }
129
130 ret = aos_task_sched_policy_get(&(ptcb->task), &kpolicy);
131 if (ret != 0) {
132 return -1;
133 }
134
135 if ((param == NULL) || (param->sched_priority < aos_sched_get_priority_min(kpolicy))
136 || (param->sched_priority > aos_sched_get_priority_max(kpolicy))) {
137 errno = EINVAL;
138 return -1;
139 }
140
141 priority = sched_priority_posix2rhino(kpolicy, param->sched_priority);
142
143 /* Change the priority of the thread. */
144 ret = aos_task_pri_change(&(ptcb->task), priority, &old_priority);
145 if (ret != 0) {
146 return -1;
147 }
148 ptcb->attr.sched_priority = param->sched_priority;
149
150 if (kpolicy == KSCHED_RR) {
151 /* Change the time slice of the thread. */
152 ret = aos_task_time_slice_set(&(ptcb->task), param->slice);
153 if (ret != 0) {
154 return -1;
155 }
156 ptcb->attr.sched_slice = param->slice;
157 }
158
159 return 0;
160 }
161
sched_getparam(pid_t pid,struct sched_param * param)162 int sched_getparam(pid_t pid, struct sched_param *param)
163 {
164 int ret = 0;
165 pthread_tcb_t *ptcb = NULL;
166 int kpolicy = 0;
167
168 if (param == NULL) {
169 errno = EINVAL;
170 return -1;
171 }
172
173 ptcb = sched_get_ptcb(pid);
174 if (ptcb == NULL) {
175 errno = ESRCH;
176 return -1;
177 }
178
179 ret = aos_task_pri_get(&(ptcb->task), (uint8_t *)¶m->sched_priority);
180 if (ret != 0){
181 return -1;
182 }
183
184 ret = aos_task_sched_policy_get(&(ptcb->task), (uint8_t *)&kpolicy);
185 if (ret != 0) {
186 return -1;
187 }
188 param->sched_priority = sched_priority_rhino2posix(kpolicy, param->sched_priority);
189
190 /* Slice should be 0 if that is not RR policy. */
191 ret = aos_task_time_slice_get(&(ptcb->task), (uint32_t *)¶m->slice);
192 if (ret != 0) {
193 return -1;
194 }
195
196 return 0;
197 }
198
sched_get_priority_max(int policy)199 int sched_get_priority_max(int policy)
200 {
201 int ret = 0;
202
203 ret = sched_policy_posix2rhino(policy);
204 if (ret == -1) {
205 errno = EINVAL;
206 return -1;
207 }
208
209 ret = aos_sched_get_priority_max(ret);
210 if (ret < 0) {
211 errno = -ret;
212 return -1;
213 }
214
215 return ret;
216 }
217
sched_get_priority_min(int policy)218 int sched_get_priority_min(int policy)
219 {
220 int ret = 0;
221
222 ret = sched_policy_posix2rhino(policy);
223 if (ret == -1) {
224 errno = EINVAL;
225 return -1;
226 }
227
228 ret = aos_sched_get_priority_min(ret);
229 if (ret < 0) {
230 errno = -ret;
231 return -1;
232 }
233
234 return ret;
235 }
236
sched_rr_get_interval(pid_t pid,struct timespec * interval)237 int sched_rr_get_interval(pid_t pid, struct timespec *interval)
238 {
239 int ret = 0;
240 pthread_tcb_t *ptcb = NULL;
241 uint8_t policy = 0;
242 uint32_t slice_ms = 0;
243
244 if (interval == NULL) {
245 errno = EINVAL;
246 return -1;
247 }
248
249 ptcb = sched_get_ptcb(pid);
250 if (ptcb == NULL) {
251 errno = ESRCH;
252 return -1;
253 }
254
255 ret = aos_task_sched_policy_get(&(ptcb->task), &policy);
256 if ((ret != 0) || (policy != KSCHED_RR)) {
257 errno = EINVAL;
258 return -1;
259 }
260
261 ret = aos_task_time_slice_get(&(ptcb->task), &slice_ms);
262 if (ret != 0) {
263 return -1;
264 }
265
266 interval->tv_sec = slice_ms / 1000;
267 interval->tv_nsec = (slice_ms % 1000) * 1000000;
268
269 return 0;
270 }
271