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