• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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