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