• 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 
OsTaskCreateRsrcInit(U32 taskId,struct TskInitParam * initParam,struct TagTskCb * taskCb,uintptr_t ** topStackOut,uintptr_t * curStackSize)249 OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateRsrcInit(U32 taskId, struct TskInitParam *initParam, struct TagTskCb *taskCb,
250                                                   uintptr_t **topStackOut, uintptr_t *curStackSize)
251 {
252     U32 ret = OS_OK;
253     uintptr_t *topStack = NULL;
254 
255     /* 创建任务线程 */
256     if (g_taskNameAdd != NULL) {
257         ret = g_taskNameAdd(taskId, initParam->name);
258         if (ret != OS_OK) {
259             return ret;
260         }
261     }
262 
263     /* 查看用户是否配置了任务栈,如没有,则进行内存申请,并标记为系统配置,如有,则标记为用户配置。 */
264     if (initParam->stackAddr != 0) {
265         topStack = (void *)(initParam->stackAddr);
266         taskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_USER;
267     } else {
268         topStack = OsTskMemAlloc(initParam->stackSize);
269         if (topStack == NULL) {
270             ret = OS_ERRNO_TSK_NO_MEMORY;
271         } else {
272             taskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_SYS;
273         }
274     }
275     *curStackSize = initParam->stackSize;
276     if (ret != OS_OK) {
277         return ret;
278     }
279 
280     *topStackOut = topStack;
281     return OS_OK;
282 }
283 
OsTskCreateTcbInit(uintptr_t stackPtr,struct TskInitParam * initParam,uintptr_t topStackAddr,uintptr_t curStackSize,struct TagTskCb * taskCb)284 OS_SEC_ALW_INLINE INLINE void OsTskCreateTcbInit(uintptr_t stackPtr, struct TskInitParam *initParam,
285     uintptr_t topStackAddr, uintptr_t curStackSize, struct TagTskCb *taskCb)
286 {
287     /* Initialize the task's stack */
288     taskCb->stackPointer = (void *)stackPtr;
289     taskCb->args[OS_TSK_PARA_0] = (uintptr_t)initParam->args[OS_TSK_PARA_0];
290     taskCb->args[OS_TSK_PARA_1] = (uintptr_t)initParam->args[OS_TSK_PARA_1];
291     taskCb->args[OS_TSK_PARA_2] = (uintptr_t)initParam->args[OS_TSK_PARA_2];
292     taskCb->args[OS_TSK_PARA_3] = (uintptr_t)initParam->args[OS_TSK_PARA_3];
293     taskCb->topOfStack = topStackAddr;
294     taskCb->stackSize = curStackSize;
295     taskCb->taskSem = NULL;
296     taskCb->priority = initParam->taskPrio;
297     taskCb->taskEntry = initParam->taskEntry;
298 #if defined(OS_OPTION_EVENT)
299     taskCb->event = 0;
300     taskCb->eventMask = 0;
301 #endif
302     taskCb->lastErr = 0;
303 
304     INIT_LIST_OBJECT(&taskCb->semBList);
305     INIT_LIST_OBJECT(&taskCb->pendList);
306     INIT_LIST_OBJECT(&taskCb->timerList);
307 
308     return;
309 }
310 
311 /*
312  * 描述:创建一个任务但不进行激活
313  */
OsTaskCreateOnly(TskHandle * taskPid,struct TskInitParam * initParam)314 OS_SEC_L4_TEXT U32 OsTaskCreateOnly(TskHandle *taskPid, struct TskInitParam *initParam)
315 {
316     U32 ret;
317     U32 taskId;
318     uintptr_t intSave;
319     uintptr_t *topStack = NULL;
320     void *stackPtr = NULL;
321     struct TagTskCb *taskCb = NULL;
322     uintptr_t curStackSize = 0;
323 
324     ret = OsTaskCreateParaCheck(taskPid, initParam);
325     if (ret != OS_OK) {
326         return ret;
327     }
328     intSave = OsIntLock();
329     ret = OsTaskCreateChkAndGetTcb(&taskCb);
330     if (ret != OS_OK) {
331         OsIntRestore(intSave);
332         return ret;
333     }
334 
335     taskId = taskCb->taskPid;
336 
337     ret = OsTaskCreateRsrcInit(taskId, initParam, taskCb, &topStack, &curStackSize);
338     if (ret != OS_OK) {
339         ListAdd(&taskCb->pendList, &g_tskCbFreeList);
340         OsIntRestore(intSave);
341         return ret;
342     }
343     OsTskStackInit(curStackSize, (uintptr_t)topStack);
344 
345     stackPtr = OsTskContextInit(taskId, curStackSize, topStack, (uintptr_t)OsTskEntry);
346 
347     OsTskCreateTcbInit((uintptr_t)stackPtr, initParam, (uintptr_t)topStack, curStackSize, taskCb);
348 
349     taskCb->taskStatus = OS_TSK_SUSPEND | OS_TSK_INUSE;
350     // 出参ID传出
351     *taskPid = taskId;
352     OsIntRestore(intSave);
353     return OS_OK;
354 }
355 
356 /*
357  * 描述:创建一个任务但不进行激活
358  */
PRT_TaskCreate(TskHandle * taskPid,struct TskInitParam * initParam)359 OS_SEC_L4_TEXT U32 PRT_TaskCreate(TskHandle *taskPid, struct TskInitParam *initParam)
360 {
361     return OsTaskCreateOnly(taskPid, initParam);
362 }
363