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 = ¶m->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