1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: Task schedule implementation
14 */
15 #include "prt_exc_external.h"
16 #include "prt_task_internal.h"
17 #include "prt_amp_task_internal.h"
18
19 /* Unused TCBs and ECBs that can be allocated. */
20 OS_SEC_DATA struct TagListObject g_tskCbFreeList = LIST_OBJECT_INIT(g_tskCbFreeList);
21 OS_SEC_DATA struct TagListObject g_tskRecyleList = LIST_OBJECT_INIT(g_tskRecyleList);
22
23 /* tskmon队列 */
24 OS_SEC_BSS struct TagTskMonNode *g_tskMonList;
25
26 /*
27 * 描述:注册任务模块信息
28 */
OsTskRegister(struct TskModInfo * modInfo)29 OS_SEC_L4_TEXT U32 OsTskRegister(struct TskModInfo *modInfo)
30 {
31 if (((modInfo->maxNum) > (MAX_TASK_NUM)) || (modInfo->maxNum == 0)) {
32 return OS_ERRNO_TSK_MAX_NUM_NOT_SUITED;
33 }
34
35 g_tskModInfo.maxNum = modInfo->maxNum;
36 g_tskModInfo.defaultSize = modInfo->defaultSize;
37 g_tskModInfo.idleStackSize = modInfo->idleStackSize;
38 g_tskModInfo.magicWord = modInfo->magicWord;
39
40 /* task模块有动态加载的场景 */
41 if (g_tskIdleEntry == NULL) {
42 g_tskIdleEntry = (TskEntryFunc)OsTskIdleBgd;
43 }
44
45 g_tskMaxNum = g_tskModInfo.maxNum;
46
47 return OS_OK;
48 }
49
50 #if defined(OS_OPTION_TASK_INFO)
OsTskInfoGet(TskHandle * threadId,struct TskInfo * taskInfo)51 OS_SEC_L4_TEXT void OsTskInfoGet(TskHandle *threadId, struct TskInfo *taskInfo)
52 {
53 U32 ret;
54
55 if ((g_tskMaxNum > 0) && ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0)) { /* 任务存在时 */
56 ret = PRT_TaskSelf(threadId);
57 if (ret == OS_OK) {
58 /* 获取当前任务信息 */
59 OS_ERR_RECORD(PRT_TaskGetInfo((*threadId), taskInfo));
60 }
61 }
62 }
63
OsTaskNameAdd(U32 taskId,const char * name)64 OS_SEC_L4_TEXT U32 OsTaskNameAdd(U32 taskId, const char *name)
65 {
66 struct TagTskCb *taskCb = GET_TCB_HANDLE(taskId);
67 /* 不检测线程名同名 */
68 if (strncpy_s(taskCb->name, sizeof(taskCb->name), name, OS_TSK_NAME_LEN - 1) != EOK) {
69 OS_GOTO_SYS_ERROR1();
70 }
71
72 return OS_OK;
73 }
74
OsTaskNameGet(U32 taskId,char ** taskName)75 OS_SEC_L4_TEXT void OsTaskNameGet(U32 taskId, char **taskName)
76 {
77 struct TagTskCb *taskCb = GET_TCB_HANDLE(taskId);
78
79 *taskName = taskCb->name;
80 }
81 #endif
82
83 /*
84 * 描述:任务初始化
85 */
OsTskInit(void)86 OS_SEC_L4_TEXT U32 OsTskInit(void)
87 {
88 U32 ret;
89 ret = OsTskAMPInit();
90 if (ret != OS_OK) {
91 return ret;
92 }
93
94 g_taskScanHook = OsTaskScan;
95
96 #if defined(OS_OPTION_TASK_INFO)
97 // 异常时获取当前任务的信息
98 g_excTaskInfoGet = (ExcTaskInfoFunc)OsTskInfoGet;
99 g_taskNameAdd = OsTaskNameAdd;
100 g_taskNameGet = OsTaskNameGet;
101 #endif
102
103 /* 设置任务切换钩子标志位 */
104 UNI_FLAG |= OS_FLG_TSK_SWHK;
105
106 return OS_OK;
107 }
108
109 /*
110 * 描述:分配任务栈空间
111 */
OsTskMemAlloc(U32 size)112 OS_SEC_L4_TEXT void *OsTskMemAlloc(U32 size)
113 {
114 void *stackAddr = NULL;
115 stackAddr = OsMemAllocAlign((U32)OS_MID_TSK, (U8)OS_MEM_DEFAULT_FSC_PT, size,
116 /* 内存已按16字节大小对齐 */
117 OS_TSK_STACK_SIZE_ALLOC_ALIGN);
118 return stackAddr;
119 }
120
121 /*
122 * 描述:激活任务管理
123 */
OsActivate(void)124 OS_SEC_L4_TEXT U32 OsActivate(void)
125 {
126 U32 ret;
127 ret = OsIdleTskAMPCreate();
128 if (ret != OS_OK) {
129 return ret;
130 }
131
132 OsTskHighestSet();
133
134 /* Indicate that background task is running. */
135
136 UNI_FLAG |= OS_FLG_BGD_ACTIVE | OS_FLG_TSK_REQ;
137
138 OS_MHOOK_ACTIVATE_PARA0(OS_HOOK_FIRST_TIME_SWH);
139
140 /* Start Multitasking. */
141 OsFirstTimeSwitch();
142
143 return OS_ERRNO_TSK_ACTIVE_FAILED;
144 }
145
146 /*
147 * 描述:所有任务入口
148 */
OsTskEntry(TskHandle taskId)149 OS_SEC_L4_TEXT void OsTskEntry(TskHandle taskId)
150 {
151 struct TagTskCb *taskCb = NULL;
152 uintptr_t intSave;
153
154 (void)taskId;
155
156 taskCb = RUNNING_TASK;
157
158 taskCb->taskEntry(taskCb->args[OS_TSK_PARA_0], taskCb->args[OS_TSK_PARA_1], taskCb->args[OS_TSK_PARA_2],
159 taskCb->args[OS_TSK_PARA_3]);
160
161 // 调度结束后会开中断,所以不需要自己添加开中断
162 intSave = OsIntLock();
163
164 OS_TASK_LOCK_DATA = 0;
165
166 /* PRT_TaskDelete不能关中断操作,否则可能会导致它核发SGI等待本核响应时死等 */
167 OsIntRestore(intSave);
168
169 OsTaskExit(taskCb);
170 }
171
172 /*
173 * 描述:创建任务参数检查
174 */
OsTaskCreateParaCheck(const TskHandle * taskPid,struct TskInitParam * initParam)175 OS_SEC_L4_TEXT U32 OsTaskCreateParaCheck(const TskHandle *taskPid, struct TskInitParam *initParam)
176 {
177 U64 stackAddrLen;
178
179 if ((taskPid == NULL) || (initParam == NULL)) {
180 return OS_ERRNO_TSK_PTR_NULL;
181 }
182
183 if (initParam->taskEntry == NULL) {
184 return OS_ERRNO_TSK_ENTRY_NULL;
185 }
186
187 if (initParam->stackSize == 0) {
188 initParam->stackSize = g_tskModInfo.defaultSize;
189 }
190
191 if (((OS_TSK_STACK_SIZE_ALIGN - 1) & initParam->stackSize) != 0) {
192 return OS_ERRNO_TSK_STKSZ_NOT_ALIGN;
193 }
194
195 if (((OS_TSK_STACK_SIZE_ALIGN - 1) & (uintptr_t)initParam->stackAddr) != 0) {
196 return OS_ERRNO_TSK_STACKADDR_NOT_ALIGN;
197 }
198
199 if (initParam->stackSize < OS_TSK_MIN_STACK_SIZE) {
200 return OS_ERRNO_TSK_STKSZ_TOO_SMALL;
201 }
202 /* 使用用户内存,则需要包含OS使用的资源,size最小值要包含OS的消耗 */
203 if (initParam->stackAddr != 0) {
204 /* 保证栈空间在4G范围内不溢出 */
205 stackAddrLen = (U64)(initParam->stackAddr) + (U64)(initParam->stackSize);
206 if (stackAddrLen > OS_MAX_U32) {
207 return OS_ERRNO_TSK_STACKADDR_TOO_BIG;
208 }
209 }
210
211 if (initParam->taskPrio > OS_TSK_PRIORITY_LOWEST) {
212 return OS_ERRNO_TSK_PRIOR_ERROR;
213 }
214
215 /* 创建任务线程时做校验 */
216 if (initParam->name == NULL || initParam->name[0] == '\0') {
217 return OS_ERRNO_TSK_NAME_EMPTY;
218 }
219
220 return OS_OK;
221 }
222
OsTskRecycle(void)223 OS_SEC_L4_TEXT void OsTskRecycle(void)
224 {
225 struct TagTskCb *taskCb = NULL;
226
227 /* 释放掉之前自删除任务的资源,自删除时,由于任务还处于运行态,不会及时释放资源 */
228 /* 调用处已加recycle list锁 */
229 while (!ListEmpty(&g_tskRecyleList)) {
230 taskCb = GET_TCB_PEND(OS_LIST_FIRST(&g_tskRecyleList));
231 ListDelete(OS_LIST_FIRST(&g_tskRecyleList));
232 ListTailAdd(&taskCb->pendList, &g_tskCbFreeList);
233 OsTskResRecycle(taskCb);
234 }
235 }
236
OsTskStackInit(U32 stackSize,uintptr_t topStack)237 OS_SEC_L4_TEXT void OsTskStackInit(U32 stackSize, uintptr_t topStack)
238 {
239 U32 loop;
240 U32 stackMagicWord = OS_TSK_STACK_MAGIC;
241
242 /* 初始化任务栈,并写入栈魔术字 */
243 for (loop = 1; loop < (stackSize / sizeof(U32)); loop++) {
244 *((U32 *)topStack + loop) = stackMagicWord;
245 }
246 *((U32 *)(topStack)) = OS_TSK_STACK_TOP_MAGIC;
247 }
248
OsTaskCreateChkAndGetTcb(struct TagTskCb ** taskCb)249 OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateChkAndGetTcb(struct TagTskCb **taskCb)
250 {
251 OsTskRecycle();
252
253 if (ListEmpty(&g_tskCbFreeList)) {
254 return OS_ERRNO_TSK_TCB_UNAVAILABLE;
255 }
256
257 // 先获取到该控制块
258 *taskCb = GET_TCB_PEND(OS_LIST_FIRST(&g_tskCbFreeList));
259 // 成功,从空闲列表中移除
260 ListDelete(OS_LIST_FIRST(&g_tskCbFreeList));
261
262 return OS_OK;
263 }
264
OsTaskCreateRsrcInit(U32 taskId,struct TskInitParam * initParam,struct TagTskCb * taskCb,uintptr_t ** topStackOut,uintptr_t * curStackSize)265 OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateRsrcInit(U32 taskId, struct TskInitParam *initParam, struct TagTskCb *taskCb,
266 uintptr_t **topStackOut, uintptr_t *curStackSize)
267 {
268 U32 ret = OS_OK;
269 uintptr_t *topStack = NULL;
270
271 /* 创建任务线程 */
272 if (g_taskNameAdd != NULL) {
273 ret = g_taskNameAdd(taskId, initParam->name);
274 if (ret != OS_OK) {
275 return ret;
276 }
277 }
278
279 /* 查看用户是否配置了任务栈,如没有,则进行内存申请,并标记为系统配置,如有,则标记为用户配置。 */
280 if (initParam->stackAddr != 0) {
281 topStack = (void *)(initParam->stackAddr);
282 taskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_USER;
283 } else {
284 topStack = OsTskMemAlloc(initParam->stackSize);
285 if (topStack == NULL) {
286 ret = OS_ERRNO_TSK_NO_MEMORY;
287 } else {
288 taskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_SYS;
289 }
290 }
291 *curStackSize = initParam->stackSize;
292 if (ret != OS_OK) {
293 return ret;
294 }
295
296 *topStackOut = topStack;
297 return OS_OK;
298 }
299
OsTskCreateTcbInit(uintptr_t stackPtr,struct TskInitParam * initParam,uintptr_t topStackAddr,uintptr_t curStackSize,struct TagTskCb * taskCb)300 OS_SEC_ALW_INLINE INLINE void OsTskCreateTcbInit(uintptr_t stackPtr, struct TskInitParam *initParam,
301 uintptr_t topStackAddr, uintptr_t curStackSize, struct TagTskCb *taskCb)
302 {
303 /* Initialize the task's stack */
304 taskCb->stackPointer = (void *)stackPtr;
305 taskCb->args[OS_TSK_PARA_0] = (uintptr_t)initParam->args[OS_TSK_PARA_0];
306 taskCb->args[OS_TSK_PARA_1] = (uintptr_t)initParam->args[OS_TSK_PARA_1];
307 taskCb->args[OS_TSK_PARA_2] = (uintptr_t)initParam->args[OS_TSK_PARA_2];
308 taskCb->args[OS_TSK_PARA_3] = (uintptr_t)initParam->args[OS_TSK_PARA_3];
309 taskCb->topOfStack = topStackAddr;
310 taskCb->stackSize = curStackSize;
311 taskCb->taskSem = NULL;
312 taskCb->priority = initParam->taskPrio;
313 taskCb->taskEntry = initParam->taskEntry;
314 #if defined(OS_OPTION_EVENT)
315 taskCb->event = 0;
316 taskCb->eventMask = 0;
317 #endif
318 taskCb->lastErr = 0;
319
320 INIT_LIST_OBJECT(&taskCb->pendList);
321 INIT_LIST_OBJECT(&taskCb->timerList);
322
323 return;
324 }
325
326 /*
327 * 描述:创建一个任务但不进行激活
328 */
OsTaskCreateOnly(TskHandle * taskPid,struct TskInitParam * initParam)329 OS_SEC_L4_TEXT U32 OsTaskCreateOnly(TskHandle *taskPid, struct TskInitParam *initParam)
330 {
331 U32 ret;
332 U32 taskId;
333 uintptr_t intSave;
334 uintptr_t *topStack = NULL;
335 void *stackPtr = NULL;
336 struct TagTskCb *taskCb = NULL;
337 uintptr_t curStackSize = 0;
338
339 ret = OsTaskCreateParaCheck(taskPid, initParam);
340 if (ret != OS_OK) {
341 return ret;
342 }
343 intSave = OsIntLock();
344 ret = OsTaskCreateChkAndGetTcb(&taskCb);
345 if (ret != OS_OK) {
346 OsIntRestore(intSave);
347 return ret;
348 }
349
350 taskId = taskCb->taskPid;
351
352 ret = OsTaskCreateRsrcInit(taskId, initParam, taskCb, &topStack, &curStackSize);
353 if (ret != OS_OK) {
354 ListAdd(&taskCb->pendList, &g_tskCbFreeList);
355 OsIntRestore(intSave);
356 return ret;
357 }
358 OsTskStackInit(curStackSize, (uintptr_t)topStack);
359
360 stackPtr = OsTskContextInit(taskId, curStackSize, topStack, (uintptr_t)OsTskEntry);
361
362 OsTskCreateTcbInit((uintptr_t)stackPtr, initParam, (uintptr_t)topStack, curStackSize, taskCb);
363
364 taskCb->taskStatus = OS_TSK_SUSPEND | OS_TSK_INUSE;
365 // 出参ID传出
366 *taskPid = taskId;
367 OsIntRestore(intSave);
368 return OS_OK;
369 }
370
371 /*
372 * 描述:创建一个任务但不进行激活
373 */
PRT_TaskCreate(TskHandle * taskPid,struct TskInitParam * initParam)374 OS_SEC_L4_TEXT U32 PRT_TaskCreate(TskHandle *taskPid, struct TskInitParam *initParam)
375 {
376 return OsTaskCreateOnly(taskPid, initParam);
377 }
378