• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_task_pri.h"
33 #include "los_base_pri.h"
34 #include "los_event_pri.h"
35 #include "los_exc.h"
36 #include "los_hw_pri.h"
37 #include "los_init.h"
38 #include "los_memstat_pri.h"
39 #include "los_mp.h"
40 #include "los_mux_pri.h"
41 #include "los_sched_pri.h"
42 #include "los_sem_pri.h"
43 #include "los_spinlock.h"
44 #include "los_strncpy_from_user.h"
45 #include "los_percpu_pri.h"
46 #include "los_process_pri.h"
47 #include "los_vm_map.h"
48 #include "los_vm_syscall.h"
49 #include "los_signal.h"
50 #include "los_hook.h"
51 
52 #ifdef LOSCFG_KERNEL_CPUP
53 #include "los_cpup_pri.h"
54 #endif
55 #ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
56 #include "los_swtmr_pri.h"
57 #endif
58 #ifdef LOSCFG_KERNEL_LITEIPC
59 #include "hm_liteipc.h"
60 #endif
61 #ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
62 #include "los_oom.h"
63 #endif
64 
65 #if (LOSCFG_BASE_CORE_TSK_LIMIT <= 0)
66 #error "task maxnum cannot be zero"
67 #endif  /* LOSCFG_BASE_CORE_TSK_LIMIT <= 0 */
68 
69 LITE_OS_SEC_BSS LosTaskCB    *g_taskCBArray;
70 LITE_OS_SEC_BSS LOS_DL_LIST  g_losFreeTask;
71 LITE_OS_SEC_BSS LOS_DL_LIST  g_taskRecycleList;
72 LITE_OS_SEC_BSS UINT32       g_taskMaxNum;
73 LITE_OS_SEC_BSS UINT32       g_taskScheduled; /* one bit for each cores */
74 LITE_OS_SEC_BSS EVENT_CB_S   g_resourceEvent;
75 /* spinlock for task module, only available on SMP mode */
76 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_taskSpin);
77 
78 STATIC VOID OsConsoleIDSetHook(UINT32 param1,
79                                UINT32 param2) __attribute__((weakref("OsSetConsoleID")));
80 
81 /* temp task blocks for booting procedure */
82 LITE_OS_SEC_BSS STATIC LosTaskCB                g_mainTask[LOSCFG_KERNEL_CORE_NUM];
83 
OsGetMainTask()84 LosTaskCB *OsGetMainTask()
85 {
86     return (LosTaskCB *)(g_mainTask + ArchCurrCpuid());
87 }
88 
OsSetMainTask()89 VOID OsSetMainTask()
90 {
91     UINT32 i;
92     CHAR *name = "osMain";
93     SchedParam schedParam = { 0 };
94 
95     schedParam.policy = LOS_SCHED_RR;
96     schedParam.basePrio = OS_PROCESS_PRIORITY_HIGHEST;
97     schedParam.priority = OS_TASK_PRIORITY_LOWEST;
98 
99     for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
100         g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED;
101         g_mainTask[i].taskID = LOSCFG_BASE_CORE_TSK_LIMIT;
102         g_mainTask[i].processID = OS_KERNEL_PROCESS_GROUP;
103 #ifdef LOSCFG_KERNEL_SMP_LOCKDEP
104         g_mainTask[i].lockDep.lockDepth = 0;
105         g_mainTask[i].lockDep.waitLock = NULL;
106 #endif
107         (VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1);
108         LOS_ListInit(&g_mainTask[i].lockList);
109         (VOID)OsSchedParamInit(&g_mainTask[i], schedParam.policy, &schedParam, NULL);
110     }
111 }
112 
OsIdleTask(VOID)113 LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
114 {
115     while (1) {
116         WFI;
117     }
118 }
119 
OsTaskInsertToRecycleList(LosTaskCB * taskCB)120 VOID OsTaskInsertToRecycleList(LosTaskCB *taskCB)
121 {
122     LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList);
123 }
124 
OsTaskJoinPostUnsafe(LosTaskCB * taskCB)125 LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB)
126 {
127     if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
128         if (!LOS_ListEmpty(&taskCB->joinList)) {
129             LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList)));
130             OsTaskWakeClearPendMask(resumedTask);
131             resumedTask->ops->wake(resumedTask);
132         }
133     }
134     taskCB->taskStatus |= OS_TASK_STATUS_EXIT;
135 }
136 
OsTaskJoinPendUnsafe(LosTaskCB * taskCB)137 LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB)
138 {
139     if (taskCB->taskStatus & OS_TASK_STATUS_INIT) {
140         return LOS_EINVAL;
141     }
142 
143     if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
144         return LOS_OK;
145     }
146 
147     if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) {
148         OsTaskWaitSetPendMask(OS_TASK_WAIT_JOIN, taskCB->taskID, LOS_WAIT_FOREVER);
149         LosTaskCB *runTask = OsCurrTaskGet();
150         return runTask->ops->wait(runTask, &taskCB->joinList, LOS_WAIT_FOREVER);
151     }
152 
153     return LOS_EINVAL;
154 }
155 
OsTaskSetDetachUnsafe(LosTaskCB * taskCB)156 LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB)
157 {
158     if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
159         if (LOS_ListEmpty(&(taskCB->joinList))) {
160             LOS_ListDelete(&(taskCB->joinList));
161             taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN;
162             return LOS_OK;
163         }
164         /* This error code has a special purpose and is not allowed to appear again on the interface */
165         return LOS_ESRCH;
166     }
167 
168     return LOS_EINVAL;
169 }
170 
OsTaskInit(VOID)171 LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
172 {
173     UINT32 index;
174     UINT32 size;
175     UINT32 ret;
176 
177     g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;
178     size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
179     /*
180      * This memory is resident memory and is used to save the system resources
181      * of task control block and will not be freed.
182      */
183     g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
184     if (g_taskCBArray == NULL) {
185         ret = LOS_ERRNO_TSK_NO_MEMORY;
186         goto EXIT;
187     }
188     (VOID)memset_s(g_taskCBArray, size, 0, size);
189 
190     LOS_ListInit(&g_losFreeTask);
191     LOS_ListInit(&g_taskRecycleList);
192     for (index = 0; index < g_taskMaxNum; index++) {
193         g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
194         g_taskCBArray[index].taskID = index;
195         LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);
196     }
197 
198     ret = OsSchedInit();
199 
200 EXIT:
201     if (ret != LOS_OK) {
202         PRINT_ERR("OsTaskInit error\n");
203     }
204     return ret;
205 }
206 
OsGetIdleTaskId(VOID)207 UINT32 OsGetIdleTaskId(VOID)
208 {
209     return OsSchedRunqueueIdleGet();
210 }
211 
OsIdleTaskCreate(VOID)212 LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
213 {
214     UINT32 ret;
215     TSK_INIT_PARAM_S taskInitParam;
216     UINT32 idleTaskID;
217 
218     (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
219     taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;
220     taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;
221     taskInitParam.pcName = "Idle";
222     taskInitParam.policy = LOS_SCHED_IDLE;
223     taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
224     taskInitParam.processID = OsGetIdleProcessID();
225 #ifdef LOSCFG_KERNEL_SMP
226     taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
227 #endif
228     ret = LOS_TaskCreateOnly(&idleTaskID, &taskInitParam);
229     if (ret != LOS_OK) {
230         return ret;
231     }
232     LosTaskCB *idleTask = OS_TCB_FROM_TID(idleTaskID);
233     idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
234     OsSchedRunqueueIdleInit(idleTaskID);
235 
236     return LOS_TaskResume(idleTaskID);
237 }
238 
239 /*
240  * Description : get id of current running task.
241  * Return      : task id
242  */
LOS_CurTaskIDGet(VOID)243 LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
244 {
245     LosTaskCB *runTask = OsCurrTaskGet();
246 
247     if (runTask == NULL) {
248         return LOS_ERRNO_TSK_ID_INVALID;
249     }
250     return runTask->taskID;
251 }
252 
OsTaskSyncCreate(LosTaskCB * taskCB)253 STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB)
254 {
255 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
256     UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal);
257     if (ret != LOS_OK) {
258         return LOS_ERRNO_TSK_MP_SYNC_RESOURCE;
259     }
260 #else
261     (VOID)taskCB;
262 #endif
263     return LOS_OK;
264 }
265 
OsTaskSyncDestroy(UINT32 syncSignal)266 STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal)
267 {
268 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
269     (VOID)LOS_SemDelete(syncSignal);
270 #else
271     (VOID)syncSignal;
272 #endif
273 }
274 
275 #ifdef LOSCFG_KERNEL_SMP
OsTaskSyncWait(const LosTaskCB * taskCB)276 STATIC INLINE UINT32 OsTaskSyncWait(const LosTaskCB *taskCB)
277 {
278 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
279     UINT32 ret = LOS_OK;
280 
281     LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
282     LOS_SpinUnlock(&g_taskSpin);
283     /*
284      * gc soft timer works every OS_MP_GC_PERIOD period, to prevent this timer
285      * triggered right at the timeout has reached, we set the timeout as double
286      * of the gc period.
287      */
288     if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) { /* 2: Wait 200 ms */
289         ret = LOS_ERRNO_TSK_MP_SYNC_FAILED;
290     }
291 
292     LOS_SpinLock(&g_taskSpin);
293 
294     return ret;
295 #else
296     (VOID)taskCB;
297     return LOS_OK;
298 #endif
299 }
300 #endif
301 
OsTaskSyncWake(const LosTaskCB * taskCB)302 STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB)
303 {
304 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
305     (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL);
306 #else
307     (VOID)taskCB;
308 #endif
309 }
310 
OsInsertTCBToFreeList(LosTaskCB * taskCB)311 STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB *taskCB)
312 {
313     UINT32 taskID = taskCB->taskID;
314     (VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB));
315     taskCB->taskID = taskID;
316     taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
317     taskCB->processID = OS_INVALID_VALUE;
318     LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
319 }
320 
OsTaskKernelResourcesToFree(UINT32 syncSignal,UINTPTR topOfStack)321 STATIC VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack)
322 {
323     OsTaskSyncDestroy(syncSignal);
324 
325     (VOID)LOS_MemFree((VOID *)m_aucSysMem1, (VOID *)topOfStack);
326 }
327 
OsTaskResourcesToFree(LosTaskCB * taskCB)328 STATIC VOID OsTaskResourcesToFree(LosTaskCB *taskCB)
329 {
330     UINT32 syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
331     UINT32 intSave;
332     UINTPTR topOfStack;
333 
334 #ifdef LOSCFG_KERNEL_VM
335     if ((taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) && (taskCB->userMapBase != 0)) {
336         SCHEDULER_LOCK(intSave);
337         UINT32 mapBase = (UINTPTR)taskCB->userMapBase;
338         UINT32 mapSize = taskCB->userMapSize;
339         taskCB->userMapBase = 0;
340         taskCB->userArea = 0;
341         SCHEDULER_UNLOCK(intSave);
342 
343         LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
344         LOS_ASSERT(!(OsProcessVmSpaceGet(processCB) == NULL));
345         UINT32 ret = OsUnMMap(OsProcessVmSpaceGet(processCB), (UINTPTR)mapBase, mapSize);
346         if ((ret != LOS_OK) && (mapBase != 0) && !OsProcessIsInit(processCB)) {
347             PRINT_ERR("process(%u) unmmap user task(%u) stack failed! mapbase: 0x%x size :0x%x, error: %d\n",
348                       taskCB->processID, taskCB->taskID, mapBase, mapSize, ret);
349         }
350 
351 #ifdef LOSCFG_KERNEL_LITEIPC
352         LiteIpcRemoveServiceHandle(taskCB->taskID);
353 #endif
354     }
355 #endif
356 
357     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
358         topOfStack = taskCB->topOfStack;
359         taskCB->topOfStack = 0;
360 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
361         syncSignal = taskCB->syncSignal;
362         taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
363 #endif
364         OsTaskKernelResourcesToFree(syncSignal, topOfStack);
365 
366         SCHEDULER_LOCK(intSave);
367 #ifdef LOSCFG_KERNEL_VM
368         OsClearSigInfoTmpList(&(taskCB->sig));
369 #endif
370         OsInsertTCBToFreeList(taskCB);
371         SCHEDULER_UNLOCK(intSave);
372     }
373     return;
374 }
375 
OsTaskCBRecycleToFree()376 LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree()
377 {
378     UINT32 intSave;
379 
380     SCHEDULER_LOCK(intSave);
381     while (!LOS_ListEmpty(&g_taskRecycleList)) {
382         LosTaskCB *taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList));
383         LOS_ListDelete(&taskCB->pendList);
384         SCHEDULER_UNLOCK(intSave);
385 
386         OsTaskResourcesToFree(taskCB);
387 
388         SCHEDULER_LOCK(intSave);
389     }
390     SCHEDULER_UNLOCK(intSave);
391 }
392 
393 /*
394  * Description : All task entry
395  * Input       : taskID     --- The ID of the task to be run
396  */
OsTaskEntry(UINT32 taskID)397 LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID)
398 {
399     LOS_ASSERT(!OS_TID_CHECK_INVALID(taskID));
400 
401     /*
402      * task scheduler needs to be protected throughout the whole process
403      * from interrupt and other cores. release task spinlock and enable
404      * interrupt in sequence at the task entry.
405      */
406     LOS_SpinUnlock(&g_taskSpin);
407     (VOID)LOS_IntUnLock();
408 
409     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
410     taskCB->joinRetval = taskCB->taskEntry(taskCB->args[0], taskCB->args[1],
411                                            taskCB->args[2], taskCB->args[3]); /* 2 & 3: just for args array index */
412     if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
413         taskCB->joinRetval = 0;
414     }
415 
416     OsRunningTaskToExit(taskCB, 0);
417 }
418 
OsTaskCreateParamCheck(const UINT32 * taskID,TSK_INIT_PARAM_S * initParam,VOID ** pool)419 LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32 *taskID,
420     TSK_INIT_PARAM_S *initParam, VOID **pool)
421 {
422     UINT32 poolSize = OS_SYS_MEM_SIZE;
423     *pool = (VOID *)m_aucSysMem1;
424 
425     if (taskID == NULL) {
426         return LOS_ERRNO_TSK_ID_INVALID;
427     }
428 
429     if (initParam == NULL) {
430         return LOS_ERRNO_TSK_PTR_NULL;
431     }
432 
433     LosProcessCB *process = OS_PCB_FROM_PID(initParam->processID);
434     if (!OsProcessIsUserMode(process)) {
435         if (initParam->pcName == NULL) {
436             return LOS_ERRNO_TSK_NAME_EMPTY;
437         }
438     }
439 
440     if (initParam->pfnTaskEntry == NULL) {
441         return LOS_ERRNO_TSK_ENTRY_NULL;
442     }
443 
444     if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) {
445         return LOS_ERRNO_TSK_PRIOR_ERROR;
446     }
447 
448     if (initParam->uwStackSize > poolSize) {
449         return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
450     }
451 
452     if (initParam->uwStackSize == 0) {
453         initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
454     }
455     initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
456 
457     if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) {
458         return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
459     }
460 
461     return LOS_OK;
462 }
463 
OsTaskStackAlloc(VOID ** topStack,UINT32 stackSize,VOID * pool)464 LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID **topStack, UINT32 stackSize, VOID *pool)
465 {
466     *topStack = (VOID *)LOS_MemAllocAlign(pool, stackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
467 }
468 
TaskCBBaseInit(LosTaskCB * taskCB,const VOID * stackPtr,const VOID * topStack,const TSK_INIT_PARAM_S * initParam)469 STATIC VOID TaskCBBaseInit(LosTaskCB *taskCB, const VOID *stackPtr, const VOID *topStack,
470                            const TSK_INIT_PARAM_S *initParam)
471 {
472     taskCB->stackPointer = (VOID *)stackPtr;
473     taskCB->args[0]      = initParam->auwArgs[0]; /* 0~3: just for args array index */
474     taskCB->args[1]      = initParam->auwArgs[1];
475     taskCB->args[2]      = initParam->auwArgs[2];
476     taskCB->args[3]      = initParam->auwArgs[3];
477     taskCB->topOfStack   = (UINTPTR)topStack;
478     taskCB->stackSize    = initParam->uwStackSize;
479     taskCB->taskEntry    = initParam->pfnTaskEntry;
480     taskCB->signal       = SIGNAL_NONE;
481 
482 #ifdef LOSCFG_KERNEL_SMP
483     taskCB->currCpu      = OS_TASK_INVALID_CPUID;
484     taskCB->cpuAffiMask  = (initParam->usCpuAffiMask) ?
485                             initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK;
486 #endif
487     taskCB->taskStatus = OS_TASK_STATUS_INIT;
488     if (initParam->uwResved & LOS_TASK_ATTR_JOINABLE) {
489         taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
490         LOS_ListInit(&taskCB->joinList);
491     }
492 
493     LOS_ListInit(&taskCB->lockList);
494     SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
495 }
496 
OsTaskCBInit(LosTaskCB * taskCB,const TSK_INIT_PARAM_S * initParam,const VOID * stackPtr,const VOID * topStack)497 STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam,
498                            const VOID *stackPtr, const VOID *topStack)
499 {
500     UINT32 ret;
501     UINT32 numCount;
502     SchedParam schedParam = { 0 };
503     UINT16 policy = (initParam->policy == LOS_SCHED_NORMAL) ? LOS_SCHED_RR : initParam->policy;
504 
505     TaskCBBaseInit(taskCB, stackPtr, topStack, initParam);
506 
507     schedParam.policy = policy;
508     numCount = OsProcessAddNewTask(initParam->processID, taskCB, &schedParam);
509 #ifdef LOSCFG_KERNEL_VM
510     taskCB->futex.index = OS_INVALID_VALUE;
511     if (taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) {
512         taskCB->userArea = initParam->userParam.userArea;
513         taskCB->userMapBase = initParam->userParam.userMapBase;
514         taskCB->userMapSize = initParam->userParam.userMapSize;
515         OsUserTaskStackInit(taskCB->stackPointer, (UINTPTR)taskCB->taskEntry, initParam->userParam.userSP);
516     }
517 #endif
518 
519     ret = OsSchedParamInit(taskCB, policy, &schedParam, initParam);
520     if (ret != LOS_OK) {
521         return ret;
522     }
523 
524     if (initParam->pcName != NULL) {
525         ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE);
526         if (ret == LOS_OK) {
527             return LOS_OK;
528         }
529     }
530 
531     if (snprintf_s(taskCB->taskName, OS_TCB_NAME_LEN, OS_TCB_NAME_LEN - 1, "thread%u", numCount) < 0) {
532         return LOS_NOK;
533     }
534     return LOS_OK;
535 }
536 
OsGetFreeTaskCB(VOID)537 LITE_OS_SEC_TEXT LosTaskCB *OsGetFreeTaskCB(VOID)
538 {
539     UINT32 intSave;
540 
541     SCHEDULER_LOCK(intSave);
542     if (LOS_ListEmpty(&g_losFreeTask)) {
543         SCHEDULER_UNLOCK(intSave);
544         PRINT_ERR("No idle TCB in the system!\n");
545         return NULL;
546     }
547 
548     LosTaskCB *taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask));
549     LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask));
550     SCHEDULER_UNLOCK(intSave);
551 
552     return taskCB;
553 }
554 
LOS_TaskCreateOnly(UINT32 * taskID,TSK_INIT_PARAM_S * initParam)555 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
556 {
557     UINT32 intSave, errRet;
558     VOID *topStack = NULL;
559     VOID *pool = NULL;
560 
561     errRet = OsTaskCreateParamCheck(taskID, initParam, &pool);
562     if (errRet != LOS_OK) {
563         return errRet;
564     }
565 
566     LosTaskCB *taskCB = OsGetFreeTaskCB();
567     if (taskCB == NULL) {
568         errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
569         goto LOS_ERREND;
570     }
571 
572     errRet = OsTaskSyncCreate(taskCB);
573     if (errRet != LOS_OK) {
574         goto LOS_ERREND_REWIND_TCB;
575     }
576 
577     OsTaskStackAlloc(&topStack, initParam->uwStackSize, pool);
578     if (topStack == NULL) {
579         errRet = LOS_ERRNO_TSK_NO_MEMORY;
580         goto LOS_ERREND_REWIND_SYNC;
581     }
582 
583     VOID *stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);
584     errRet = OsTaskCBInit(taskCB, initParam, stackPtr, topStack);
585     if (errRet != LOS_OK) {
586         goto LOS_ERREND_TCB_INIT;
587     }
588     if (OsConsoleIDSetHook != NULL) {
589         OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID);
590     }
591 
592     *taskID = taskCB->taskID;
593     OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB);
594     return LOS_OK;
595 
596 LOS_ERREND_TCB_INIT:
597     (VOID)LOS_MemFree(pool, topStack);
598 LOS_ERREND_REWIND_SYNC:
599 #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
600     OsTaskSyncDestroy(taskCB->syncSignal);
601 #endif
602 LOS_ERREND_REWIND_TCB:
603     SCHEDULER_LOCK(intSave);
604     OsInsertTCBToFreeList(taskCB);
605     SCHEDULER_UNLOCK(intSave);
606 LOS_ERREND:
607     return errRet;
608 }
609 
LOS_TaskCreate(UINT32 * taskID,TSK_INIT_PARAM_S * initParam)610 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
611 {
612     UINT32 ret;
613     UINT32 intSave;
614 
615     if (initParam == NULL) {
616         return LOS_ERRNO_TSK_PTR_NULL;
617     }
618 
619     if (OS_INT_ACTIVE) {
620         return LOS_ERRNO_TSK_YIELD_IN_INT;
621     }
622 
623     if (OsProcessIsUserMode(OsCurrProcessGet())) {
624         initParam->processID = OsGetKernelInitProcessID();
625     } else {
626         initParam->processID = OsCurrProcessGet()->processID;
627     }
628 
629     ret = LOS_TaskCreateOnly(taskID, initParam);
630     if (ret != LOS_OK) {
631         return ret;
632     }
633 
634     LosTaskCB *taskCB = OS_TCB_FROM_TID(*taskID);
635 
636     SCHEDULER_LOCK(intSave);
637     taskCB->ops->enqueue(OsSchedRunqueue(), taskCB);
638     SCHEDULER_UNLOCK(intSave);
639 
640     /* in case created task not running on this core,
641        schedule or not depends on other schedulers status. */
642     LOS_MpSchedule(OS_MP_CPU_ALL);
643     if (OS_SCHEDULER_ACTIVE) {
644         LOS_Schedule();
645     }
646 
647     return LOS_OK;
648 }
649 
LOS_TaskResume(UINT32 taskID)650 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
651 {
652     UINT32 intSave;
653     UINT32 errRet;
654     BOOL needSched = FALSE;
655 
656     if (OS_TID_CHECK_INVALID(taskID)) {
657         return LOS_ERRNO_TSK_ID_INVALID;
658     }
659 
660     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
661     SCHEDULER_LOCK(intSave);
662 
663     /* clear pending signal */
664     taskCB->signal &= ~SIGNAL_SUSPEND;
665 
666     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
667         errRet = LOS_ERRNO_TSK_NOT_CREATED;
668         OS_GOTO_ERREND();
669     } else if (!(taskCB->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
670         errRet = LOS_ERRNO_TSK_NOT_SUSPENDED;
671         OS_GOTO_ERREND();
672     }
673 
674     errRet = taskCB->ops->resume(taskCB, &needSched);
675     SCHEDULER_UNLOCK(intSave);
676 
677     LOS_MpSchedule(OS_MP_CPU_ALL);
678     if (OS_SCHEDULER_ACTIVE && needSched) {
679         LOS_Schedule();
680     }
681 
682     return errRet;
683 
684 LOS_ERREND:
685     SCHEDULER_UNLOCK(intSave);
686     return errRet;
687 }
688 
689 /*
690  * Check if needs to do the suspend operation on the running task.
691  * Return TRUE, if needs to do the suspension.
692  * Return FALSE, if meets following circumstances:
693  * 1. Do the suspension across cores, if SMP is enabled
694  * 2. Do the suspension when preemption is disabled
695  * 3. Do the suspension in hard-irq
696  * then LOS_TaskSuspend will directly return with 'ret' value.
697  */
OsTaskSuspendCheckOnRun(LosTaskCB * taskCB,UINT32 * ret)698 LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UINT32 *ret)
699 {
700     /* init default out return value */
701     *ret = LOS_OK;
702 
703 #ifdef LOSCFG_KERNEL_SMP
704     /* ASYNCHRONIZED. No need to do task lock checking */
705     if (taskCB->currCpu != ArchCurrCpuid()) {
706         taskCB->signal = SIGNAL_SUSPEND;
707         LOS_MpSchedule(taskCB->currCpu);
708         return FALSE;
709     }
710 #endif
711 
712     if (!OsPreemptableInSched()) {
713         /* Suspending the current core's running task */
714         *ret = LOS_ERRNO_TSK_SUSPEND_LOCKED;
715         return FALSE;
716     }
717 
718     if (OS_INT_ACTIVE) {
719         /* suspend running task in interrupt */
720         taskCB->signal = SIGNAL_SUSPEND;
721         return FALSE;
722     }
723 
724     return TRUE;
725 }
726 
OsTaskSuspend(LosTaskCB * taskCB)727 LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB)
728 {
729     UINT32 errRet;
730     UINT16 tempStatus = taskCB->taskStatus;
731     if (tempStatus & OS_TASK_STATUS_UNUSED) {
732         return LOS_ERRNO_TSK_NOT_CREATED;
733     }
734 
735     if (tempStatus & OS_TASK_STATUS_SUSPENDED) {
736         return LOS_ERRNO_TSK_ALREADY_SUSPENDED;
737     }
738 
739     if ((tempStatus & OS_TASK_STATUS_RUNNING) &&
740         !OsTaskSuspendCheckOnRun(taskCB, &errRet)) {
741         return errRet;
742     }
743 
744     return taskCB->ops->suspend(taskCB);
745 }
746 
LOS_TaskSuspend(UINT32 taskID)747 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
748 {
749     UINT32 intSave;
750     UINT32 errRet;
751 
752     if (OS_TID_CHECK_INVALID(taskID)) {
753         return LOS_ERRNO_TSK_ID_INVALID;
754     }
755 
756     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
757     if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
758         return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
759     }
760 
761     SCHEDULER_LOCK(intSave);
762     errRet = OsTaskSuspend(taskCB);
763     SCHEDULER_UNLOCK(intSave);
764     return errRet;
765 }
766 
OsTaskStatusUnusedSet(LosTaskCB * taskCB)767 STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB *taskCB)
768 {
769     taskCB->taskStatus |= OS_TASK_STATUS_UNUSED;
770     taskCB->eventMask = 0;
771 
772     OS_MEM_CLEAR(taskCB->taskID);
773 }
774 
OsTaskReleaseHoldLock(LosTaskCB * taskCB)775 STATIC VOID OsTaskReleaseHoldLock(LosTaskCB *taskCB)
776 {
777     LosMux *mux = NULL;
778     UINT32 ret;
779 
780     while (!LOS_ListEmpty(&taskCB->lockList)) {
781         mux = LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(&taskCB->lockList), LosMux, holdList);
782         ret = OsMuxUnlockUnsafe(taskCB, mux, NULL);
783         if (ret != LOS_OK) {
784             LOS_ListDelete(&mux->holdList);
785             PRINT_ERR("mux ulock failed! : %u\n", ret);
786         }
787     }
788 
789 #ifdef LOSCFG_KERNEL_VM
790     if (taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) {
791         OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
792     }
793 #endif
794 
795     OsTaskJoinPostUnsafe(taskCB);
796 
797     OsTaskSyncWake(taskCB);
798 }
799 
OsRunningTaskToExit(LosTaskCB * runTask,UINT32 status)800 LITE_OS_SEC_TEXT VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status)
801 {
802     UINT32 intSave;
803 
804     if (OsProcessThreadGroupIDGet(runTask) == runTask->taskID) {
805         OsProcessThreadGroupDestroy();
806     }
807 
808     OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, runTask);
809 
810     SCHEDULER_LOCK(intSave);
811     if (OsProcessThreadNumberGet(runTask) == 1) { /* 1: The last task of the process exits */
812         SCHEDULER_UNLOCK(intSave);
813 
814         OsTaskResourcesToFree(runTask);
815         OsProcessResourcesToFree(OS_PCB_FROM_PID(runTask->processID));
816 
817         SCHEDULER_LOCK(intSave);
818 
819         OsProcessNaturalExit(OS_PCB_FROM_PID(runTask->processID), status);
820         OsTaskReleaseHoldLock(runTask);
821         OsTaskStatusUnusedSet(runTask);
822     } else if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
823         OsTaskReleaseHoldLock(runTask);
824     } else {
825         SCHEDULER_UNLOCK(intSave);
826 
827         OsTaskResourcesToFree(runTask);
828 
829         SCHEDULER_LOCK(intSave);
830         OsInactiveTaskDelete(runTask);
831         OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);
832     }
833 
834     OsSchedResched();
835     SCHEDULER_UNLOCK(intSave);
836     return;
837 }
838 
OsInactiveTaskDelete(LosTaskCB * taskCB)839 LITE_OS_SEC_TEXT VOID OsInactiveTaskDelete(LosTaskCB *taskCB)
840 {
841     UINT16 taskStatus = taskCB->taskStatus;
842 
843     OsTaskReleaseHoldLock(taskCB);
844 
845     taskCB->ops->exit(taskCB);
846     if (taskStatus & OS_TASK_STATUS_PENDING) {
847         LosMux *mux = (LosMux *)taskCB->taskMux;
848         if (LOS_MuxIsValid(mux) == TRUE) {
849             OsMuxBitmapRestore(mux, NULL, taskCB);
850         }
851     }
852 
853     OsTaskStatusUnusedSet(taskCB);
854 
855     OsDeleteTaskFromProcess(taskCB);
856 
857     OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB);
858 }
859 
LOS_TaskDelete(UINT32 taskID)860 LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
861 {
862     UINT32 intSave;
863     UINT32 ret = LOS_OK;
864 
865     if (OS_TID_CHECK_INVALID(taskID)) {
866         return LOS_ERRNO_TSK_ID_INVALID;
867     }
868 
869     if (OS_INT_ACTIVE) {
870         return LOS_ERRNO_TSK_YIELD_IN_INT;
871     }
872 
873     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
874     if (taskCB == OsCurrTaskGet()) {
875         if (!OsPreemptable()) {
876             return LOS_ERRNO_TSK_DELETE_LOCKED;
877         }
878 
879         OsRunningTaskToExit(taskCB, OS_PRO_EXIT_OK);
880         return LOS_NOK;
881     }
882 
883     SCHEDULER_LOCK(intSave);
884     if (taskCB->taskStatus & (OS_TASK_STATUS_UNUSED | OS_TASK_FLAG_SYSTEM_TASK | OS_TASK_FLAG_NO_DELETE)) {
885         if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
886             ret = LOS_ERRNO_TSK_NOT_CREATED;
887         } else {
888             ret = LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
889         }
890         OS_GOTO_ERREND();
891     }
892 
893 #ifdef LOSCFG_KERNEL_SMP
894     if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
895         taskCB->signal = SIGNAL_KILL;
896         LOS_MpSchedule(taskCB->currCpu);
897         ret = OsTaskSyncWait(taskCB);
898         OS_GOTO_ERREND();
899     }
900 #endif
901 
902     OsInactiveTaskDelete(taskCB);
903     OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);
904 
905 LOS_ERREND:
906     SCHEDULER_UNLOCK(intSave);
907     if (ret == LOS_OK) {
908         LOS_Schedule();
909     }
910     return ret;
911 }
912 
LOS_TaskDelay(UINT32 tick)913 LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
914 {
915     UINT32 intSave;
916 
917     if (OS_INT_ACTIVE) {
918         PRINT_ERR("In interrupt not allow delay task!\n");
919         return LOS_ERRNO_TSK_DELAY_IN_INT;
920     }
921 
922     LosTaskCB *runTask = OsCurrTaskGet();
923     if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
924         OsBackTrace();
925         return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
926     }
927 
928     if (!OsPreemptable()) {
929         return LOS_ERRNO_TSK_DELAY_IN_LOCK;
930     }
931     OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick);
932     if (tick == 0) {
933         return LOS_TaskYield();
934     }
935 
936     SCHEDULER_LOCK(intSave);
937     UINT32 ret = runTask->ops->delay(runTask, OS_SCHED_TICK_TO_CYCLE(tick));
938     OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask);
939     SCHEDULER_UNLOCK(intSave);
940     return ret;
941 }
942 
LOS_TaskPriGet(UINT32 taskID)943 LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
944 {
945     UINT32 intSave;
946     SchedParam param = { 0 };
947 
948     if (OS_TID_CHECK_INVALID(taskID)) {
949         return (UINT16)OS_INVALID;
950     }
951 
952     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
953     SCHEDULER_LOCK(intSave);
954     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
955         SCHEDULER_UNLOCK(intSave);
956         return (UINT16)OS_INVALID;
957     }
958 
959     taskCB->ops->schedParamGet(taskCB, &param);
960     SCHEDULER_UNLOCK(intSave);
961     return param.priority;
962 }
963 
LOS_TaskPriSet(UINT32 taskID,UINT16 taskPrio)964 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
965 {
966     UINT32 intSave;
967     SchedParam param = { 0 };
968 
969     if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
970         return LOS_ERRNO_TSK_PRIOR_ERROR;
971     }
972 
973     if (OS_TID_CHECK_INVALID(taskID)) {
974         return LOS_ERRNO_TSK_ID_INVALID;
975     }
976 
977     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
978     if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
979         return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
980     }
981 
982     SCHEDULER_LOCK(intSave);
983     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
984         SCHEDULER_UNLOCK(intSave);
985         return LOS_ERRNO_TSK_NOT_CREATED;
986     }
987 
988     taskCB->ops->schedParamGet(taskCB, &param);
989 
990     param.priority = taskPrio;
991 
992     BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
993     SCHEDULER_UNLOCK(intSave);
994 
995     LOS_MpSchedule(OS_MP_CPU_ALL);
996     if (needSched && OS_SCHEDULER_ACTIVE) {
997         LOS_Schedule();
998     }
999     return LOS_OK;
1000 }
1001 
LOS_CurTaskPriSet(UINT16 taskPrio)1002 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio)
1003 {
1004     return LOS_TaskPriSet(OsCurrTaskGet()->taskID, taskPrio);
1005 }
1006 
LOS_TaskYield(VOID)1007 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID)
1008 {
1009     UINT32 intSave;
1010 
1011     if (OS_INT_ACTIVE) {
1012         return LOS_ERRNO_TSK_YIELD_IN_INT;
1013     }
1014 
1015     if (!OsPreemptable()) {
1016         return LOS_ERRNO_TSK_YIELD_IN_LOCK;
1017     }
1018 
1019     LosTaskCB *runTask = OsCurrTaskGet();
1020     if (OS_TID_CHECK_INVALID(runTask->taskID)) {
1021         return LOS_ERRNO_TSK_ID_INVALID;
1022     }
1023 
1024     SCHEDULER_LOCK(intSave);
1025     /* reset timeslice of yielded task */
1026     runTask->ops->yield(runTask);
1027     SCHEDULER_UNLOCK(intSave);
1028     return LOS_OK;
1029 }
1030 
LOS_TaskLock(VOID)1031 LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
1032 {
1033     UINT32 intSave;
1034 
1035     intSave = LOS_IntLock();
1036     OsSchedLock();
1037     LOS_IntRestore(intSave);
1038 }
1039 
LOS_TaskUnlock(VOID)1040 LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
1041 {
1042     UINT32 intSave;
1043 
1044     intSave = LOS_IntLock();
1045     BOOL needSched = OsSchedUnlockResch();
1046     LOS_IntRestore(intSave);
1047 
1048     if (needSched) {
1049         LOS_Schedule();
1050     }
1051 }
1052 
LOS_TaskInfoGet(UINT32 taskID,TSK_INFO_S * taskInfo)1053 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo)
1054 {
1055     UINT32 intSave;
1056     SchedParam param = { 0 };
1057 
1058     if (taskInfo == NULL) {
1059         return LOS_ERRNO_TSK_PTR_NULL;
1060     }
1061 
1062     if (OS_TID_CHECK_INVALID(taskID)) {
1063         return LOS_ERRNO_TSK_ID_INVALID;
1064     }
1065 
1066     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1067     SCHEDULER_LOCK(intSave);
1068     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1069         SCHEDULER_UNLOCK(intSave);
1070         return LOS_ERRNO_TSK_NOT_CREATED;
1071     }
1072 
1073     if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING) || OS_INT_ACTIVE) {
1074         taskInfo->uwSP = (UINTPTR)taskCB->stackPointer;
1075     } else {
1076         taskInfo->uwSP = ArchSPGet();
1077     }
1078 
1079     taskCB->ops->schedParamGet(taskCB, &param);
1080     taskInfo->usTaskStatus = taskCB->taskStatus;
1081     taskInfo->usTaskPrio = param.priority;
1082     taskInfo->uwStackSize = taskCB->stackSize;
1083     taskInfo->uwTopOfStack = taskCB->topOfStack;
1084     taskInfo->uwEventMask = taskCB->eventMask;
1085     taskInfo->taskEvent = taskCB->taskEvent;
1086     taskInfo->pTaskMux = taskCB->taskMux;
1087     taskInfo->uwTaskID = taskID;
1088 
1089     if (strncpy_s(taskInfo->acName, LOS_TASK_NAMELEN, taskCB->taskName, LOS_TASK_NAMELEN - 1) != EOK) {
1090         PRINT_ERR("Task name copy failed!\n");
1091     }
1092     taskInfo->acName[LOS_TASK_NAMELEN - 1] = '\0';
1093 
1094     taskInfo->uwBottomOfStack = TRUNCATE(((UINTPTR)taskCB->topOfStack + taskCB->stackSize),
1095                                          OS_TASK_STACK_ADDR_ALIGN);
1096     taskInfo->uwCurrUsed = (UINT32)(taskInfo->uwBottomOfStack - taskInfo->uwSP);
1097 
1098     taskInfo->bOvf = OsStackWaterLineGet((const UINTPTR *)taskInfo->uwBottomOfStack,
1099                                          (const UINTPTR *)taskInfo->uwTopOfStack, &taskInfo->uwPeakUsed);
1100     SCHEDULER_UNLOCK(intSave);
1101     return LOS_OK;
1102 }
1103 
OsTaskCpuAffiSetUnsafe(UINT32 taskID,UINT16 newCpuAffiMask,UINT16 * oldCpuAffiMask)1104 LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask)
1105 {
1106 #ifdef LOSCFG_KERNEL_SMP
1107     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1108 
1109     taskCB->cpuAffiMask = newCpuAffiMask;
1110     *oldCpuAffiMask = CPUID_TO_AFFI_MASK(taskCB->currCpu);
1111     if (!((*oldCpuAffiMask) & newCpuAffiMask)) {
1112         taskCB->signal = SIGNAL_AFFI;
1113         return TRUE;
1114     }
1115 #else
1116     (VOID)taskID;
1117     (VOID)newCpuAffiMask;
1118     (VOID)oldCpuAffiMask;
1119 #endif /* LOSCFG_KERNEL_SMP */
1120     return FALSE;
1121 }
1122 
LOS_TaskCpuAffiSet(UINT32 taskID,UINT16 cpuAffiMask)1123 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMask)
1124 {
1125     BOOL needSched = FALSE;
1126     UINT32 intSave;
1127     UINT16 currCpuMask;
1128 
1129     if (OS_TID_CHECK_INVALID(taskID)) {
1130         return LOS_ERRNO_TSK_ID_INVALID;
1131     }
1132 
1133     if (!(cpuAffiMask & LOSCFG_KERNEL_CPU_MASK)) {
1134         return LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR;
1135     }
1136 
1137     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1138     SCHEDULER_LOCK(intSave);
1139     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1140         SCHEDULER_UNLOCK(intSave);
1141         return LOS_ERRNO_TSK_NOT_CREATED;
1142     }
1143     needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuAffiMask, &currCpuMask);
1144 
1145     SCHEDULER_UNLOCK(intSave);
1146     if (needSched && OS_SCHEDULER_ACTIVE) {
1147         LOS_MpSchedule(currCpuMask);
1148         LOS_Schedule();
1149     }
1150 
1151     return LOS_OK;
1152 }
1153 
LOS_TaskCpuAffiGet(UINT32 taskID)1154 LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
1155 {
1156 #ifdef LOSCFG_KERNEL_SMP
1157 #define INVALID_CPU_AFFI_MASK   0
1158     UINT16 cpuAffiMask;
1159     UINT32 intSave;
1160 
1161     if (OS_TID_CHECK_INVALID(taskID)) {
1162         return INVALID_CPU_AFFI_MASK;
1163     }
1164 
1165     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1166     SCHEDULER_LOCK(intSave);
1167     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1168         SCHEDULER_UNLOCK(intSave);
1169         return INVALID_CPU_AFFI_MASK;
1170     }
1171 
1172     cpuAffiMask = taskCB->cpuAffiMask;
1173     SCHEDULER_UNLOCK(intSave);
1174 
1175     return cpuAffiMask;
1176 #else
1177     (VOID)taskID;
1178     return 1;
1179 #endif
1180 }
1181 
1182 /*
1183  * Description : Process pending signals tagged by others cores
1184  */
OsTaskProcSignal(VOID)1185 LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID)
1186 {
1187     UINT32 ret;
1188 
1189     /*
1190      * private and uninterruptable, no protection needed.
1191      * while this task is always running when others cores see it,
1192      * so it keeps receiving signals while follow code executing.
1193      */
1194     LosTaskCB *runTask = OsCurrTaskGet();
1195     if (runTask->signal == SIGNAL_NONE) {
1196         return;
1197     }
1198 
1199     if (runTask->signal & SIGNAL_KILL) {
1200         /*
1201          * clear the signal, and do the task deletion. if the signaled task has been
1202          * scheduled out, then this deletion will wait until next run.
1203          */
1204         runTask->signal = SIGNAL_NONE;
1205         ret = LOS_TaskDelete(runTask->taskID);
1206         if (ret != LOS_OK) {
1207             PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret);
1208         }
1209     } else if (runTask->signal & SIGNAL_SUSPEND) {
1210         runTask->signal &= ~SIGNAL_SUSPEND;
1211 
1212         /* suspend killed task may fail, ignore the result */
1213         (VOID)LOS_TaskSuspend(runTask->taskID);
1214 #ifdef LOSCFG_KERNEL_SMP
1215     } else if (runTask->signal & SIGNAL_AFFI) {
1216         runTask->signal &= ~SIGNAL_AFFI;
1217 
1218         /* priority queue has updated, notify the target cpu */
1219         LOS_MpSchedule((UINT32)runTask->cpuAffiMask);
1220 #endif
1221     }
1222 }
1223 
OsSetTaskName(LosTaskCB * taskCB,const CHAR * name,BOOL setPName)1224 LITE_OS_SEC_TEXT INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName)
1225 {
1226     UINT32 intSave;
1227     errno_t err;
1228     const CHAR *namePtr = NULL;
1229     CHAR nameBuff[OS_TCB_NAME_LEN] = { 0 };
1230 
1231     if ((taskCB == NULL) || (name == NULL)) {
1232         return EINVAL;
1233     }
1234 
1235     if (LOS_IsUserAddress((VADDR_T)(UINTPTR)name)) {
1236         err = LOS_StrncpyFromUser(nameBuff, (const CHAR *)name, OS_TCB_NAME_LEN);
1237         if (err < 0) {
1238             return -err;
1239         }
1240         namePtr = nameBuff;
1241     } else {
1242         namePtr = name;
1243     }
1244 
1245     SCHEDULER_LOCK(intSave);
1246 
1247     err = strncpy_s(taskCB->taskName, OS_TCB_NAME_LEN, (VOID *)namePtr, OS_TCB_NAME_LEN - 1);
1248     if (err != EOK) {
1249         err = EINVAL;
1250         goto EXIT;
1251     }
1252 
1253     err = LOS_OK;
1254     /* if thread is main thread, then set processName as taskName */
1255     if ((taskCB->taskID == OsProcessThreadGroupIDGet(taskCB)) && (setPName == TRUE)) {
1256         err = (INT32)OsSetProcessName(OS_PCB_FROM_PID(taskCB->processID), (const CHAR *)taskCB->taskName);
1257         if (err != LOS_OK) {
1258             err = EINVAL;
1259         }
1260     }
1261 
1262 EXIT:
1263     SCHEDULER_UNLOCK(intSave);
1264     return err;
1265 }
1266 
OsUserTaskOperatePermissionsCheck(const LosTaskCB * taskCB)1267 INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB)
1268 {
1269     return OsUserProcessOperatePermissionsCheck(taskCB, OsCurrProcessGet()->processID);
1270 }
1271 
OsUserProcessOperatePermissionsCheck(const LosTaskCB * taskCB,UINT32 processID)1272 INT32 OsUserProcessOperatePermissionsCheck(const LosTaskCB *taskCB, UINT32 processID)
1273 {
1274     if (taskCB == NULL) {
1275         return LOS_EINVAL;
1276     }
1277 
1278     if (processID == OS_INVALID_VALUE) {
1279         return LOS_EINVAL;
1280     }
1281 
1282     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1283         return LOS_EINVAL;
1284     }
1285 
1286     if (processID != taskCB->processID) {
1287         return LOS_EPERM;
1288     }
1289 
1290     return LOS_OK;
1291 }
1292 
OsCreateUserTaskParamCheck(UINT32 processID,TSK_INIT_PARAM_S * param)1293 LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsCreateUserTaskParamCheck(UINT32 processID, TSK_INIT_PARAM_S *param)
1294 {
1295     UserTaskParam *userParam = NULL;
1296 
1297     if (param == NULL) {
1298         return OS_INVALID_VALUE;
1299     }
1300 
1301     userParam = &param->userParam;
1302     if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {
1303         return OS_INVALID_VALUE;
1304     }
1305 
1306     if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {
1307         return OS_INVALID_VALUE;
1308     }
1309 
1310     if (userParam->userMapBase && !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) {
1311         return OS_INVALID_VALUE;
1312     }
1313 
1314     if (!LOS_IsUserAddress(userParam->userSP)) {
1315         return OS_INVALID_VALUE;
1316     }
1317 
1318     return LOS_OK;
1319 }
1320 
OsCreateUserTask(UINT32 processID,TSK_INIT_PARAM_S * initParam)1321 LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam)
1322 {
1323     UINT32 taskID;
1324     UINT32 ret;
1325     UINT32 intSave;
1326 
1327     ret = OsCreateUserTaskParamCheck(processID, initParam);
1328     if (ret != LOS_OK) {
1329         return ret;
1330     }
1331 
1332     initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE;
1333     initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;
1334     initParam->policy = LOS_SCHED_RR;
1335     if (processID == OS_INVALID_VALUE) {
1336         SCHEDULER_LOCK(intSave);
1337         LosProcessCB *processCB = OsCurrProcessGet();
1338         initParam->processID = processCB->processID;
1339         initParam->consoleID = processCB->consoleID;
1340         SCHEDULER_UNLOCK(intSave);
1341     } else {
1342         initParam->processID = processID;
1343         initParam->consoleID = 0;
1344     }
1345 
1346     ret = LOS_TaskCreateOnly(&taskID, initParam);
1347     if (ret != LOS_OK) {
1348         return OS_INVALID_VALUE;
1349     }
1350 
1351     return taskID;
1352 }
1353 
LOS_GetTaskScheduler(INT32 taskID)1354 LITE_OS_SEC_TEXT INT32 LOS_GetTaskScheduler(INT32 taskID)
1355 {
1356     UINT32 intSave;
1357     INT32 policy;
1358     SchedParam param = { 0 };
1359 
1360     if (OS_TID_CHECK_INVALID(taskID)) {
1361         return -LOS_EINVAL;
1362     }
1363 
1364     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1365     SCHEDULER_LOCK(intSave);
1366     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1367         policy = -LOS_EINVAL;
1368         OS_GOTO_ERREND();
1369     }
1370 
1371     taskCB->ops->schedParamGet(taskCB, &param);
1372     policy = (INT32)param.policy;
1373 
1374 LOS_ERREND:
1375     SCHEDULER_UNLOCK(intSave);
1376     return policy;
1377 }
1378 
LOS_SetTaskScheduler(INT32 taskID,UINT16 policy,UINT16 priority)1379 LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority)
1380 {
1381     SchedParam param = { 0 };
1382     UINT32 intSave;
1383 
1384     if (OS_TID_CHECK_INVALID(taskID)) {
1385         return LOS_ESRCH;
1386     }
1387 
1388     if (priority > OS_TASK_PRIORITY_LOWEST) {
1389         return LOS_EINVAL;
1390     }
1391 
1392     if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)) {
1393         return LOS_EINVAL;
1394     }
1395 
1396     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1397     if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
1398         return LOS_EPERM;
1399     }
1400 
1401     SCHEDULER_LOCK(intSave);
1402     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1403         SCHEDULER_UNLOCK(intSave);
1404         return LOS_EINVAL;
1405     }
1406 
1407     taskCB->ops->schedParamGet(taskCB, &param);
1408     param.policy = policy;
1409     param.priority = priority;
1410     BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
1411     SCHEDULER_UNLOCK(intSave);
1412 
1413     LOS_MpSchedule(OS_MP_CPU_ALL);
1414     if (needSched && OS_SCHEDULER_ACTIVE) {
1415         LOS_Schedule();
1416     }
1417 
1418     return LOS_OK;
1419 }
1420 
OsTaskJoinCheck(UINT32 taskID)1421 STATIC UINT32 OsTaskJoinCheck(UINT32 taskID)
1422 {
1423     if (OS_TID_CHECK_INVALID(taskID)) {
1424         return LOS_EINVAL;
1425     }
1426 
1427     if (OS_INT_ACTIVE) {
1428         return LOS_EINTR;
1429     }
1430 
1431     if (!OsPreemptable()) {
1432         return LOS_EINVAL;
1433     }
1434 
1435     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1436     if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
1437         return LOS_EPERM;
1438     }
1439 
1440     if (taskCB == OsCurrTaskGet()) {
1441         return LOS_EDEADLK;
1442     }
1443 
1444     return LOS_OK;
1445 }
1446 
LOS_TaskJoin(UINT32 taskID,UINTPTR * retval)1447 UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval)
1448 {
1449     UINT32 intSave;
1450     LosTaskCB *runTask = OsCurrTaskGet();
1451     UINT32 errRet;
1452 
1453     errRet = OsTaskJoinCheck(taskID);
1454     if (errRet != LOS_OK) {
1455         return errRet;
1456     }
1457 
1458     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1459     SCHEDULER_LOCK(intSave);
1460     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1461         SCHEDULER_UNLOCK(intSave);
1462         return LOS_EINVAL;
1463     }
1464 
1465     if (runTask->processID != taskCB->processID) {
1466         SCHEDULER_UNLOCK(intSave);
1467         return LOS_EPERM;
1468     }
1469 
1470     errRet = OsTaskJoinPendUnsafe(taskCB);
1471     SCHEDULER_UNLOCK(intSave);
1472 
1473     if (errRet == LOS_OK) {
1474         LOS_Schedule();
1475 
1476         if (retval != NULL) {
1477             *retval = (UINTPTR)taskCB->joinRetval;
1478         }
1479 
1480         (VOID)LOS_TaskDelete(taskID);
1481         return LOS_OK;
1482     }
1483 
1484     return errRet;
1485 }
1486 
LOS_TaskDetach(UINT32 taskID)1487 UINT32 LOS_TaskDetach(UINT32 taskID)
1488 {
1489     UINT32 intSave;
1490     LosTaskCB *runTask = OsCurrTaskGet();
1491     UINT32 errRet;
1492 
1493     if (OS_TID_CHECK_INVALID(taskID)) {
1494         return LOS_EINVAL;
1495     }
1496 
1497     if (OS_INT_ACTIVE) {
1498         return LOS_EINTR;
1499     }
1500 
1501     LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
1502     SCHEDULER_LOCK(intSave);
1503     if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1504         SCHEDULER_UNLOCK(intSave);
1505         return LOS_EINVAL;
1506     }
1507 
1508     if (runTask->processID != taskCB->processID) {
1509         SCHEDULER_UNLOCK(intSave);
1510         return LOS_EPERM;
1511     }
1512 
1513     if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
1514         SCHEDULER_UNLOCK(intSave);
1515         return LOS_TaskJoin(taskID, NULL);
1516     }
1517 
1518     errRet = OsTaskSetDetachUnsafe(taskCB);
1519     SCHEDULER_UNLOCK(intSave);
1520     return errRet;
1521 }
1522 
LOS_GetSystemTaskMaximum(VOID)1523 LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID)
1524 {
1525     return g_taskMaxNum;
1526 }
1527 
OsWriteResourceEvent(UINT32 events)1528 LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events)
1529 {
1530     (VOID)LOS_EventWrite(&g_resourceEvent, events);
1531 }
1532 
OsWriteResourceEventUnsafe(UINT32 events)1533 LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events)
1534 {
1535     (VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL);
1536 }
1537 
OsResourceRecoveryTask(VOID)1538 STATIC VOID OsResourceRecoveryTask(VOID)
1539 {
1540     UINT32 ret;
1541 
1542     while (1) {
1543         ret = LOS_EventRead(&g_resourceEvent, OS_RESOURCE_EVENT_MASK,
1544                             LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
1545         if (ret & (OS_RESOURCE_EVENT_FREE | OS_RESOURCE_EVENT_OOM)) {
1546             OsTaskCBRecycleToFree();
1547 
1548             OsProcessCBRecycleToFree();
1549         }
1550 
1551 #ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
1552         if (ret & OS_RESOURCE_EVENT_OOM) {
1553             (VOID)OomCheckProcess();
1554         }
1555 #endif
1556     }
1557 }
1558 
OsResourceFreeTaskCreate(VOID)1559 LITE_OS_SEC_TEXT UINT32 OsResourceFreeTaskCreate(VOID)
1560 {
1561     UINT32 ret;
1562     UINT32 taskID;
1563     TSK_INIT_PARAM_S taskInitParam;
1564 
1565     ret = LOS_EventInit((PEVENT_CB_S)&g_resourceEvent);
1566     if (ret != LOS_OK) {
1567         return LOS_NOK;
1568     }
1569 
1570     (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
1571     taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsResourceRecoveryTask;
1572     taskInitParam.uwStackSize = OS_TASK_RESOURCE_STATIC_SIZE;
1573     taskInitParam.pcName = "ResourcesTask";
1574     taskInitParam.usTaskPrio = OS_TASK_RESOURCE_FREE_PRIORITY;
1575     ret = LOS_TaskCreate(&taskID, &taskInitParam);
1576     if (ret == LOS_OK) {
1577         OS_TCB_FROM_TID(taskID)->taskStatus |= OS_TASK_FLAG_NO_DELETE;
1578     }
1579     return ret;
1580 }
1581 
1582 LOS_MODULE_INIT(OsResourceFreeTaskCreate, LOS_INIT_LEVEL_KMOD_TASK);
1583 
1584