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