330 Star 2.3K Fork 1.1K

OpenHarmony/kernel_liteos_a

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
los_task.c 44.44 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_task_pri.h"
#include "los_base_pri.h"
#include "los_event_pri.h"
#include "los_exc.h"
#include "los_hw_pri.h"
#include "los_init.h"
#include "los_memstat_pri.h"
#include "los_mp.h"
#include "los_mux_pri.h"
#include "los_sched_pri.h"
#include "los_sem_pri.h"
#include "los_spinlock.h"
#include "los_strncpy_from_user.h"
#include "los_percpu_pri.h"
#include "los_process_pri.h"
#include "los_vm_map.h"
#include "los_vm_syscall.h"
#include "los_signal.h"
#include "los_hook.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
#include "los_swtmr_pri.h"
#endif
#ifdef LOSCFG_KERNEL_LITEIPC
#include "hm_liteipc.h"
#endif
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
#include "los_oom.h"
#endif
#ifdef LOSCFG_KERNEL_CONTAINER
#include "los_container_pri.h"
#endif
#if (LOSCFG_BASE_CORE_TSK_LIMIT <= 0)
#error "task maxnum cannot be zero"
#endif /* LOSCFG_BASE_CORE_TSK_LIMIT <= 0 */
LITE_OS_SEC_BSS LosTaskCB *g_taskCBArray;
LITE_OS_SEC_BSS LOS_DL_LIST g_losFreeTask;
LITE_OS_SEC_BSS LOS_DL_LIST g_taskRecycleList;
LITE_OS_SEC_BSS UINT32 g_taskMaxNum;
LITE_OS_SEC_BSS UINT32 g_taskScheduled; /* one bit for each cores */
LITE_OS_SEC_BSS EVENT_CB_S g_resourceEvent;
/* spinlock for task module, only available on SMP mode */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_taskSpin);
STATIC VOID OsConsoleIDSetHook(UINT32 param1,
UINT32 param2) __attribute__((weakref("OsSetConsoleID")));
/* temp task blocks for booting procedure */
LITE_OS_SEC_BSS STATIC LosTaskCB g_mainTask[LOSCFG_KERNEL_CORE_NUM];
LosTaskCB *OsGetMainTask(VOID)
{
return (LosTaskCB *)(g_mainTask + ArchCurrCpuid());
}
VOID OsSetMainTask(VOID)
{
UINT32 i;
CHAR *name = "osMain";
SchedParam schedParam = { 0 };
schedParam.policy = LOS_SCHED_RR;
schedParam.basePrio = OS_PROCESS_PRIORITY_HIGHEST;
schedParam.priority = OS_TASK_PRIORITY_LOWEST;
for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED;
g_mainTask[i].taskID = LOSCFG_BASE_CORE_TSK_LIMIT;
g_mainTask[i].processCB = OS_KERNEL_PROCESS_GROUP;
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
g_mainTask[i].lockDep.lockDepth = 0;
g_mainTask[i].lockDep.waitLock = NULL;
#endif
(VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1);
LOS_ListInit(&g_mainTask[i].lockList);
(VOID)OsSchedParamInit(&g_mainTask[i], schedParam.policy, &schedParam, NULL);
}
}
VOID OsSetMainTaskProcess(UINTPTR processCB)
{
for (UINT32 i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
g_mainTask[i].processCB = processCB;
#ifdef LOSCFG_PID_CONTAINER
g_mainTask[i].pidContainer = OS_PID_CONTAINER_FROM_PCB((LosProcessCB *)processCB);
#endif
}
}
LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
{
while (1) {
WFI;
}
}
VOID OsTaskInsertToRecycleList(LosTaskCB *taskCB)
{
LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList);
}
LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
if (!LOS_ListEmpty(&taskCB->joinList)) {
LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList)));
OsTaskWakeClearPendMask(resumedTask);
resumedTask->ops->wake(resumedTask);
}
}
taskCB->taskStatus |= OS_TASK_STATUS_EXIT;
}
LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_INIT) {
return LOS_EINVAL;
}
if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
return LOS_OK;
}
if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) {
OsTaskWaitSetPendMask(OS_TASK_WAIT_JOIN, taskCB->taskID, LOS_WAIT_FOREVER);
LosTaskCB *runTask = OsCurrTaskGet();
return runTask->ops->wait(runTask, &taskCB->joinList, LOS_WAIT_FOREVER);
}
return LOS_EINVAL;
}
LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
if (LOS_ListEmpty(&(taskCB->joinList))) {
LOS_ListDelete(&(taskCB->joinList));
taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN;
return LOS_OK;
}
/* This error code has a special purpose and is not allowed to appear again on the interface */
return LOS_ESRCH;
}
return LOS_EINVAL;
}
LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(UINTPTR processCB)
{
UINT32 index;
UINT32 size;
UINT32 ret;
g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;
size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
/*
* This memory is resident memory and is used to save the system resources
* of task control block and will not be freed.
*/
g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_taskCBArray == NULL) {
ret = LOS_ERRNO_TSK_NO_MEMORY;
goto EXIT;
}
(VOID)memset_s(g_taskCBArray, size, 0, size);
LOS_ListInit(&g_losFreeTask);
LOS_ListInit(&g_taskRecycleList);
for (index = 0; index < g_taskMaxNum; index++) {
g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
g_taskCBArray[index].taskID = index;
g_taskCBArray[index].processCB = processCB;
LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);
}
g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
g_taskCBArray[index].taskID = index;
g_taskCBArray[index].processCB = processCB;
ret = OsSchedInit();
EXIT:
if (ret != LOS_OK) {
PRINT_ERR("OsTaskInit error\n");
}
return ret;
}
UINT32 OsGetIdleTaskId(VOID)
{
return OsSchedRunqueueIdleGet()->taskID;
}
LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(UINTPTR processID)
{
UINT32 ret;
TSK_INIT_PARAM_S taskInitParam;
UINT32 idleTaskID;
(VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;
taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;
taskInitParam.pcName = "Idle";
taskInitParam.policy = LOS_SCHED_IDLE;
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
taskInitParam.processID = processID;
#ifdef LOSCFG_KERNEL_SMP
taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
#endif
ret = LOS_TaskCreateOnly(&idleTaskID, &taskInitParam);
if (ret != LOS_OK) {
return ret;
}
LosTaskCB *idleTask = OS_TCB_FROM_TID(idleTaskID);
idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
OsSchedRunqueueIdleInit(idleTask);
return LOS_TaskResume(idleTaskID);
}
/*
* Description : get id of current running task.
* Return : task id
*/
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
if (runTask == NULL) {
return LOS_ERRNO_TSK_ID_INVALID;
}
return runTask->taskID;
}
STATIC INLINE UINT32 TaskSyncCreate(LosTaskCB *taskCB)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal);
if (ret != LOS_OK) {
return LOS_ERRNO_TSK_MP_SYNC_RESOURCE;
}
#else
(VOID)taskCB;
#endif
return LOS_OK;
}
STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
(VOID)LOS_SemDelete(syncSignal);
#else
(VOID)syncSignal;
#endif
}
#ifdef LOSCFG_KERNEL_SMP
STATIC INLINE UINT32 OsTaskSyncWait(const LosTaskCB *taskCB)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
UINT32 ret = LOS_OK;
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
LOS_SpinUnlock(&g_taskSpin);
/*
* gc soft timer works every OS_MP_GC_PERIOD period, to prevent this timer
* triggered right at the timeout has reached, we set the timeout as double
* of the gc period.
*/
if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) { /* 2: Wait 200 ms */
ret = LOS_ERRNO_TSK_MP_SYNC_FAILED;
}
LOS_SpinLock(&g_taskSpin);
return ret;
#else
(VOID)taskCB;
return LOS_OK;
#endif
}
#endif
STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
(VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL);
#else
(VOID)taskCB;
#endif
}
STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB *taskCB)
{
#ifdef LOSCFG_PID_CONTAINER
OsFreeVtid(taskCB);
#endif
UINT32 taskID = taskCB->taskID;
(VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB));
taskCB->taskID = taskID;
taskCB->processCB = (UINTPTR)OsGetDefaultProcessCB();
taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
}
STATIC VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack)
{
OsTaskSyncDestroy(syncSignal);
(VOID)LOS_MemFree((VOID *)m_aucSysMem1, (VOID *)topOfStack);
}
STATIC VOID OsTaskResourcesToFree(LosTaskCB *taskCB)
{
UINT32 syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
UINT32 intSave;
UINTPTR topOfStack;
#ifdef LOSCFG_KERNEL_VM
if ((taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) && (taskCB->userMapBase != 0)) {
SCHEDULER_LOCK(intSave);
UINT32 mapBase = (UINTPTR)taskCB->userMapBase;
UINT32 mapSize = taskCB->userMapSize;
taskCB->userMapBase = 0;
taskCB->userArea = 0;
SCHEDULER_UNLOCK(intSave);
LosProcessCB *processCB = OS_PCB_FROM_TCB(taskCB);
LOS_ASSERT(!(OsProcessVmSpaceGet(processCB) == NULL));
UINT32 ret = OsUnMMap(OsProcessVmSpaceGet(processCB), (UINTPTR)mapBase, mapSize);
if ((ret != LOS_OK) && (mapBase != 0) && !OsProcessIsInit(processCB)) {
PRINT_ERR("process(%u) unmmap user task(%u) stack failed! mapbase: 0x%x size :0x%x, error: %d\n",
processCB->processID, taskCB->taskID, mapBase, mapSize, ret);
}
#ifdef LOSCFG_KERNEL_LITEIPC
LiteIpcRemoveServiceHandle(taskCB->taskID);
#endif
}
#endif
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
topOfStack = taskCB->topOfStack;
taskCB->topOfStack = 0;
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
syncSignal = taskCB->syncSignal;
taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
#endif
OsTaskKernelResourcesToFree(syncSignal, topOfStack);
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_KERNEL_VM
OsClearSigInfoTmpList(&(taskCB->sig));
#endif
OsInsertTCBToFreeList(taskCB);
SCHEDULER_UNLOCK(intSave);
}
return;
}
LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree(void)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
while (!LOS_ListEmpty(&g_taskRecycleList)) {
LosTaskCB *taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList));
LOS_ListDelete(&taskCB->pendList);
SCHEDULER_UNLOCK(intSave);
OsTaskResourcesToFree(taskCB);
SCHEDULER_LOCK(intSave);
}
SCHEDULER_UNLOCK(intSave);
}
/*
* Description : All task entry
* Input : taskID --- The ID of the task to be run
*/
LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID)
{
LOS_ASSERT(!OS_TID_CHECK_INVALID(taskID));
/*
* task scheduler needs to be protected throughout the whole process
* from interrupt and other cores. release task spinlock and enable
* interrupt in sequence at the task entry.
*/
LOS_SpinUnlock(&g_taskSpin);
(VOID)LOS_IntUnLock();
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
taskCB->joinRetval = taskCB->taskEntry(taskCB->args[0], taskCB->args[1],
taskCB->args[2], taskCB->args[3]); /* 2 & 3: just for args array index */
if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
taskCB->joinRetval = 0;
}
OsRunningTaskToExit(taskCB, 0);
}
STATIC UINT32 TaskCreateParamCheck(const UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
UINT32 poolSize = OS_SYS_MEM_SIZE;
if (taskID == NULL) {
return LOS_ERRNO_TSK_ID_INVALID;
}
if (initParam == NULL) {
return LOS_ERRNO_TSK_PTR_NULL;
}
if (!OsProcessIsUserMode((LosProcessCB *)initParam->processID)) {
if (initParam->pcName == NULL) {
return LOS_ERRNO_TSK_NAME_EMPTY;
}
}
if (initParam->pfnTaskEntry == NULL) {
return LOS_ERRNO_TSK_ENTRY_NULL;
}
if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) {
return LOS_ERRNO_TSK_PRIOR_ERROR;
}
if (initParam->uwStackSize > poolSize) {
return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
}
if (initParam->uwStackSize == 0) {
initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
}
initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) {
return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
}
return LOS_OK;
}
STATIC VOID TaskCBDeInit(LosTaskCB *taskCB)
{
UINT32 intSave;
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
if (taskCB->syncSignal != OS_INVALID_VALUE) {
OsTaskSyncDestroy(taskCB->syncSignal);
taskCB->syncSignal = OS_INVALID_VALUE;
}
#endif
if (taskCB->topOfStack != (UINTPTR)NULL) {
(VOID)LOS_MemFree(m_aucSysMem1, (VOID *)taskCB->topOfStack);
taskCB->topOfStack = (UINTPTR)NULL;
}
SCHEDULER_LOCK(intSave);
LosProcessCB *processCB = OS_PCB_FROM_TCB(taskCB);
if (processCB != OsGetDefaultProcessCB()) {
LOS_ListDelete(&taskCB->threadList);
processCB->threadNumber--;
processCB->threadCount--;
}
OsInsertTCBToFreeList(taskCB);
SCHEDULER_UNLOCK(intSave);
}
STATIC VOID TaskCBBaseInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam)
{
taskCB->stackPointer = NULL;
taskCB->args[0] = initParam->auwArgs[0]; /* 0~3: just for args array index */
taskCB->args[1] = initParam->auwArgs[1];
taskCB->args[2] = initParam->auwArgs[2];
taskCB->args[3] = initParam->auwArgs[3];
taskCB->topOfStack = (UINTPTR)NULL;
taskCB->stackSize = initParam->uwStackSize;
taskCB->taskEntry = initParam->pfnTaskEntry;
taskCB->signal = SIGNAL_NONE;
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
taskCB->syncSignal = OS_INVALID_VALUE;
#endif
#ifdef LOSCFG_KERNEL_SMP
taskCB->currCpu = OS_TASK_INVALID_CPUID;
taskCB->cpuAffiMask = (initParam->usCpuAffiMask) ?
initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK;
#endif
taskCB->taskStatus = OS_TASK_STATUS_INIT;
if (initParam->uwResved & LOS_TASK_ATTR_JOINABLE) {
taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
LOS_ListInit(&taskCB->joinList);
}
LOS_ListInit(&taskCB->lockList);
SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
#ifdef LOSCFG_KERNEL_VM
taskCB->futex.index = OS_INVALID_VALUE;
#endif
}
STATIC UINT32 TaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam)
{
UINT32 ret;
UINT32 numCount;
SchedParam schedParam = { 0 };
LosSchedParam initSchedParam = {0};
UINT16 policy = (initParam->policy == LOS_SCHED_NORMAL) ? LOS_SCHED_RR : initParam->policy;
TaskCBBaseInit(taskCB, initParam);
schedParam.policy = policy;
ret = OsProcessAddNewTask(initParam->processID, taskCB, &schedParam, &numCount);
if (ret != LOS_OK) {
return ret;
}
if (policy == LOS_SCHED_DEADLINE) {
initSchedParam.runTimeUs = initParam->runTimeUs;
initSchedParam.deadlineUs = initParam->deadlineUs;
initSchedParam.periodUs = initParam->periodUs;
} else {
initSchedParam.priority = initParam->usTaskPrio;
}
ret = OsSchedParamInit(taskCB, policy, &schedParam, &initSchedParam);
if (ret != LOS_OK) {
return ret;
}
if (initParam->pcName != NULL) {
ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE);
if (ret == LOS_OK) {
return LOS_OK;
}
}
if (snprintf_s(taskCB->taskName, OS_TCB_NAME_LEN, OS_TCB_NAME_LEN - 1, "thread%u", numCount) < 0) {
return LOS_NOK;
}
return LOS_OK;
}
STATIC UINT32 TaskStackInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam)
{
VOID *topStack = (VOID *)LOS_MemAllocAlign(m_aucSysMem1, initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
if (topStack == NULL) {
return LOS_ERRNO_TSK_NO_MEMORY;
}
taskCB->topOfStack = (UINTPTR)topStack;
taskCB->stackPointer = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);
#ifdef LOSCFG_KERNEL_VM
if (taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) {
taskCB->userArea = initParam->userParam.userArea;
taskCB->userMapBase = initParam->userParam.userMapBase;
taskCB->userMapSize = initParam->userParam.userMapSize;
OsUserTaskStackInit(taskCB->stackPointer, (UINTPTR)taskCB->taskEntry, initParam->userParam.userSP);
}
#endif
return LOS_OK;
}
STATIC LosTaskCB *GetFreeTaskCB(VOID)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&g_losFreeTask)) {
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("No idle TCB in the system!\n");
return NULL;
}
LosTaskCB *taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask));
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask));
SCHEDULER_UNLOCK(intSave);
return taskCB;
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
UINT32 errRet = TaskCreateParamCheck(taskID, initParam);
if (errRet != LOS_OK) {
return errRet;
}
LosTaskCB *taskCB = GetFreeTaskCB();
if (taskCB == NULL) {
return LOS_ERRNO_TSK_TCB_UNAVAILABLE;
}
errRet = TaskCBInit(taskCB, initParam);
if (errRet != LOS_OK) {
goto DEINIT_TCB;
}
errRet = TaskSyncCreate(taskCB);
if (errRet != LOS_OK) {
goto DEINIT_TCB;
}
errRet = TaskStackInit(taskCB, initParam);
if (errRet != LOS_OK) {
goto DEINIT_TCB;
}
if (OsConsoleIDSetHook != NULL) {
OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID);
}
*taskID = taskCB->taskID;
OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB);
return LOS_OK;
DEINIT_TCB:
TaskCBDeInit(taskCB);
return errRet;
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
UINT32 ret;
UINT32 intSave;
if (initParam == NULL) {
return LOS_ERRNO_TSK_PTR_NULL;
}
if (OS_INT_ACTIVE) {
return LOS_ERRNO_TSK_YIELD_IN_INT;
}
if (OsProcessIsUserMode(OsCurrProcessGet())) {
initParam->processID = (UINTPTR)OsGetKernelInitProcess();
} else {
initParam->processID = (UINTPTR)OsCurrProcessGet();
}
ret = LOS_TaskCreateOnly(taskID, initParam);
if (ret != LOS_OK) {
return ret;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(*taskID);
SCHEDULER_LOCK(intSave);
taskCB->ops->enqueue(OsSchedRunqueue(), taskCB);
SCHEDULER_UNLOCK(intSave);
/* in case created task not running on this core,
schedule or not depends on other schedulers status. */
LOS_MpSchedule(OS_MP_CPU_ALL);
if (OS_SCHEDULER_ACTIVE) {
LOS_Schedule();
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
{
UINT32 intSave;
UINT32 errRet;
BOOL needSched = FALSE;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
/* clear pending signal */
taskCB->signal &= ~SIGNAL_SUSPEND;
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
errRet = LOS_ERRNO_TSK_NOT_CREATED;
OS_GOTO_ERREND();
} else if (!(taskCB->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
errRet = LOS_ERRNO_TSK_NOT_SUSPENDED;
OS_GOTO_ERREND();
}
errRet = taskCB->ops->resume(taskCB, &needSched);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
if (OS_SCHEDULER_ACTIVE && needSched) {
LOS_Schedule();
}
return errRet;
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
return errRet;
}
/*
* Check if needs to do the suspend operation on the running task.
* Return TRUE, if needs to do the suspension.
* Return FALSE, if meets following circumstances:
* 1. Do the suspension across cores, if SMP is enabled
* 2. Do the suspension when preemption is disabled
* 3. Do the suspension in hard-irq
* then LOS_TaskSuspend will directly return with 'ret' value.
*/
LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UINT32 *ret)
{
/* init default out return value */
*ret = LOS_OK;
#ifdef LOSCFG_KERNEL_SMP
/* ASYNCHRONIZED. No need to do task lock checking */
if (taskCB->currCpu != ArchCurrCpuid()) {
taskCB->signal = SIGNAL_SUSPEND;
LOS_MpSchedule(taskCB->currCpu);
return FALSE;
}
#endif
if (!OsPreemptableInSched()) {
/* Suspending the current core's running task */
*ret = LOS_ERRNO_TSK_SUSPEND_LOCKED;
return FALSE;
}
if (OS_INT_ACTIVE) {
/* suspend running task in interrupt */
taskCB->signal = SIGNAL_SUSPEND;
return FALSE;
}
return TRUE;
}
LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB)
{
UINT32 errRet;
UINT16 tempStatus = taskCB->taskStatus;
if (tempStatus & OS_TASK_STATUS_UNUSED) {
return LOS_ERRNO_TSK_NOT_CREATED;
}
if (tempStatus & OS_TASK_STATUS_SUSPENDED) {
return LOS_ERRNO_TSK_ALREADY_SUSPENDED;
}
if ((tempStatus & OS_TASK_STATUS_RUNNING) &&
!OsTaskSuspendCheckOnRun(taskCB, &errRet)) {
return errRet;
}
return taskCB->ops->suspend(taskCB);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
{
UINT32 intSave;
UINT32 errRet;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
}
SCHEDULER_LOCK(intSave);
errRet = OsTaskSuspend(taskCB);
SCHEDULER_UNLOCK(intSave);
return errRet;
}
STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB *taskCB)
{
taskCB->taskStatus |= OS_TASK_STATUS_UNUSED;
taskCB->eventMask = 0;
OS_MEM_CLEAR(taskCB->taskID);
}
STATIC VOID OsTaskReleaseHoldLock(LosTaskCB *taskCB)
{
LosMux *mux = NULL;
UINT32 ret;
while (!LOS_ListEmpty(&taskCB->lockList)) {
mux = LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(&taskCB->lockList), LosMux, holdList);
ret = OsMuxUnlockUnsafe(taskCB, mux, NULL);
if (ret != LOS_OK) {
LOS_ListDelete(&mux->holdList);
PRINT_ERR("mux ulock failed! : %u\n", ret);
}
}
#ifdef LOSCFG_KERNEL_VM
if (taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) {
OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
}
#endif
OsTaskJoinPostUnsafe(taskCB);
OsTaskSyncWake(taskCB);
}
LITE_OS_SEC_TEXT VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status)
{
UINT32 intSave;
if (OsIsProcessThreadGroup(runTask)) {
OsProcessThreadGroupDestroy();
}
OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, runTask);
SCHEDULER_LOCK(intSave);
if (OsProcessThreadNumberGet(runTask) == 1) { /* 1: The last task of the process exits */
SCHEDULER_UNLOCK(intSave);
OsTaskResourcesToFree(runTask);
OsProcessResourcesToFree(OS_PCB_FROM_TCB(runTask));
SCHEDULER_LOCK(intSave);
OsProcessNaturalExit(OS_PCB_FROM_TCB(runTask), status);
OsTaskReleaseHoldLock(runTask);
OsTaskStatusUnusedSet(runTask);
} else if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
OsTaskReleaseHoldLock(runTask);
} else {
SCHEDULER_UNLOCK(intSave);
OsTaskResourcesToFree(runTask);
SCHEDULER_LOCK(intSave);
OsInactiveTaskDelete(runTask);
OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);
}
OsSchedResched();
SCHEDULER_UNLOCK(intSave);
return;
}
LITE_OS_SEC_TEXT VOID OsInactiveTaskDelete(LosTaskCB *taskCB)
{
UINT16 taskStatus = taskCB->taskStatus;
OsTaskReleaseHoldLock(taskCB);
taskCB->ops->exit(taskCB);
if (taskStatus & OS_TASK_STATUS_PENDING) {
LosMux *mux = (LosMux *)taskCB->taskMux;
if (LOS_MuxIsValid(mux) == TRUE) {
OsMuxBitmapRestore(mux, NULL, taskCB);
}
}
OsTaskStatusUnusedSet(taskCB);
OsDeleteTaskFromProcess(taskCB);
OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
{
UINT32 intSave;
UINT32 ret = LOS_OK;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
if (OS_INT_ACTIVE) {
return LOS_ERRNO_TSK_YIELD_IN_INT;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
if (taskCB == OsCurrTaskGet()) {
if (!OsPreemptable()) {
return LOS_ERRNO_TSK_DELETE_LOCKED;
}
OsRunningTaskToExit(taskCB, OS_PRO_EXIT_OK);
return LOS_NOK;
}
SCHEDULER_LOCK(intSave);
if (OsTaskIsNotDelete(taskCB)) {
if (OsTaskIsUnused(taskCB)) {
ret = LOS_ERRNO_TSK_NOT_CREATED;
} else {
ret = LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
}
OS_GOTO_ERREND();
}
#ifdef LOSCFG_KERNEL_SMP
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
taskCB->signal = SIGNAL_KILL;
LOS_MpSchedule(taskCB->currCpu);
ret = OsTaskSyncWait(taskCB);
OS_GOTO_ERREND();
}
#endif
OsInactiveTaskDelete(taskCB);
OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
if (ret == LOS_OK) {
LOS_Schedule();
}
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
{
UINT32 intSave;
if (OS_INT_ACTIVE) {
PRINT_ERR("In interrupt not allow delay task!\n");
return LOS_ERRNO_TSK_DELAY_IN_INT;
}
LosTaskCB *runTask = OsCurrTaskGet();
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
OsBackTrace();
return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
}
if (!OsPreemptable()) {
return LOS_ERRNO_TSK_DELAY_IN_LOCK;
}
OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick);
if (tick == 0) {
return LOS_TaskYield();
}
SCHEDULER_LOCK(intSave);
UINT32 ret = runTask->ops->delay(runTask, OS_SCHED_TICK_TO_CYCLE(tick));
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask);
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
{
UINT32 intSave;
SchedParam param = { 0 };
if (OS_TID_CHECK_INVALID(taskID)) {
return (UINT16)OS_INVALID;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return (UINT16)OS_INVALID;
}
taskCB->ops->schedParamGet(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
return param.priority;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
{
UINT32 intSave;
SchedParam param = { 0 };
if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
return LOS_ERRNO_TSK_PRIOR_ERROR;
}
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
}
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_ERRNO_TSK_NOT_CREATED;
}
taskCB->ops->schedParamGet(taskCB, &param);
param.priority = taskPrio;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
if (needSched && OS_SCHEDULER_ACTIVE) {
LOS_Schedule();
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio)
{
return LOS_TaskPriSet(OsCurrTaskGet()->taskID, taskPrio);
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID)
{
UINT32 intSave;
if (OS_INT_ACTIVE) {
return LOS_ERRNO_TSK_YIELD_IN_INT;
}
if (!OsPreemptable()) {
return LOS_ERRNO_TSK_YIELD_IN_LOCK;
}
LosTaskCB *runTask = OsCurrTaskGet();
if (OS_TID_CHECK_INVALID(runTask->taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
SCHEDULER_LOCK(intSave);
/* reset timeslice of yielded task */
runTask->ops->yield(runTask);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
{
UINT32 intSave;
intSave = LOS_IntLock();
OsSchedLock();
LOS_IntRestore(intSave);
}
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
{
UINT32 intSave;
intSave = LOS_IntLock();
BOOL needSched = OsSchedUnlockResch();
LOS_IntRestore(intSave);
if (needSched) {
LOS_Schedule();
}
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo)
{
UINT32 intSave;
SchedParam param = { 0 };
if (taskInfo == NULL) {
return LOS_ERRNO_TSK_PTR_NULL;
}
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_ERRNO_TSK_NOT_CREATED;
}
if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING) || OS_INT_ACTIVE) {
taskInfo->uwSP = (UINTPTR)taskCB->stackPointer;
} else {
taskInfo->uwSP = ArchSPGet();
}
taskCB->ops->schedParamGet(taskCB, &param);
taskInfo->usTaskStatus = taskCB->taskStatus;
taskInfo->usTaskPrio = param.priority;
taskInfo->uwStackSize = taskCB->stackSize;
taskInfo->uwTopOfStack = taskCB->topOfStack;
taskInfo->uwEventMask = taskCB->eventMask;
taskInfo->taskEvent = taskCB->taskEvent;
taskInfo->pTaskMux = taskCB->taskMux;
taskInfo->uwTaskID = taskID;
if (strncpy_s(taskInfo->acName, LOS_TASK_NAMELEN, taskCB->taskName, LOS_TASK_NAMELEN - 1) != EOK) {
PRINT_ERR("Task name copy failed!\n");
}
taskInfo->acName[LOS_TASK_NAMELEN - 1] = '\0';
taskInfo->uwBottomOfStack = TRUNCATE(((UINTPTR)taskCB->topOfStack + taskCB->stackSize),
OS_TASK_STACK_ADDR_ALIGN);
taskInfo->uwCurrUsed = (UINT32)(taskInfo->uwBottomOfStack - taskInfo->uwSP);
taskInfo->bOvf = OsStackWaterLineGet((const UINTPTR *)taskInfo->uwBottomOfStack,
(const UINTPTR *)taskInfo->uwTopOfStack, &taskInfo->uwPeakUsed);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask)
{
#ifdef LOSCFG_KERNEL_SMP
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
taskCB->cpuAffiMask = newCpuAffiMask;
*oldCpuAffiMask = CPUID_TO_AFFI_MASK(taskCB->currCpu);
if (!((*oldCpuAffiMask) & newCpuAffiMask)) {
taskCB->signal = SIGNAL_AFFI;
return TRUE;
}
#else
(VOID)taskID;
(VOID)newCpuAffiMask;
(VOID)oldCpuAffiMask;
#endif /* LOSCFG_KERNEL_SMP */
return FALSE;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMask)
{
BOOL needSched = FALSE;
UINT32 intSave;
UINT16 currCpuMask;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
if (!(cpuAffiMask & LOSCFG_KERNEL_CPU_MASK)) {
return LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_ERRNO_TSK_NOT_CREATED;
}
needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuAffiMask, &currCpuMask);
SCHEDULER_UNLOCK(intSave);
if (needSched && OS_SCHEDULER_ACTIVE) {
LOS_MpSchedule(currCpuMask);
LOS_Schedule();
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
{
#ifdef LOSCFG_KERNEL_SMP
#define INVALID_CPU_AFFI_MASK 0
UINT16 cpuAffiMask;
UINT32 intSave;
if (OS_TID_CHECK_INVALID(taskID)) {
return INVALID_CPU_AFFI_MASK;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return INVALID_CPU_AFFI_MASK;
}
cpuAffiMask = taskCB->cpuAffiMask;
SCHEDULER_UNLOCK(intSave);
return cpuAffiMask;
#else
(VOID)taskID;
return 1;
#endif
}
/*
* Description : Process pending signals tagged by others cores
*/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID)
{
UINT32 ret;
/*
* private and uninterruptable, no protection needed.
* while this task is always running when others cores see it,
* so it keeps receiving signals while follow code executing.
*/
LosTaskCB *runTask = OsCurrTaskGet();
if (runTask->signal == SIGNAL_NONE) {
return;
}
if (runTask->signal & SIGNAL_KILL) {
/*
* clear the signal, and do the task deletion. if the signaled task has been
* scheduled out, then this deletion will wait until next run.
*/
runTask->signal = SIGNAL_NONE;
ret = LOS_TaskDelete(runTask->taskID);
if (ret != LOS_OK) {
PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret);
}
} else if (runTask->signal & SIGNAL_SUSPEND) {
runTask->signal &= ~SIGNAL_SUSPEND;
/* suspend killed task may fail, ignore the result */
(VOID)LOS_TaskSuspend(runTask->taskID);
#ifdef LOSCFG_KERNEL_SMP
} else if (runTask->signal & SIGNAL_AFFI) {
runTask->signal &= ~SIGNAL_AFFI;
/* priority queue has updated, notify the target cpu */
LOS_MpSchedule((UINT32)runTask->cpuAffiMask);
#endif
}
}
LITE_OS_SEC_TEXT INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName)
{
UINT32 intSave;
errno_t err;
const CHAR *namePtr = NULL;
CHAR nameBuff[OS_TCB_NAME_LEN] = { 0 };
if ((taskCB == NULL) || (name == NULL)) {
return EINVAL;
}
if (LOS_IsUserAddress((VADDR_T)(UINTPTR)name)) {
err = LOS_StrncpyFromUser(nameBuff, (const CHAR *)name, OS_TCB_NAME_LEN);
if (err < 0) {
return -err;
}
namePtr = nameBuff;
} else {
namePtr = name;
}
SCHEDULER_LOCK(intSave);
err = strncpy_s(taskCB->taskName, OS_TCB_NAME_LEN, (VOID *)namePtr, OS_TCB_NAME_LEN - 1);
if (err != EOK) {
err = EINVAL;
goto EXIT;
}
err = LOS_OK;
/* if thread is main thread, then set processName as taskName */
if (OsIsProcessThreadGroup(taskCB) && (setPName == TRUE)) {
err = (INT32)OsSetProcessName(OS_PCB_FROM_TCB(taskCB), (const CHAR *)taskCB->taskName);
if (err != LOS_OK) {
err = EINVAL;
}
}
EXIT:
SCHEDULER_UNLOCK(intSave);
return err;
}
INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB)
{
return OsUserProcessOperatePermissionsCheck(taskCB, (UINTPTR)OsCurrProcessGet());
}
INT32 OsUserProcessOperatePermissionsCheck(const LosTaskCB *taskCB, UINTPTR processCB)
{
if (taskCB == NULL) {
return LOS_EINVAL;
}
if (processCB == (UINTPTR)OsGetDefaultProcessCB()) {
return LOS_EINVAL;
}
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
return LOS_EINVAL;
}
if (processCB != taskCB->processCB) {
return LOS_EPERM;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsCreateUserTaskParamCheck(UINT32 processID, TSK_INIT_PARAM_S *param)
{
UserTaskParam *userParam = NULL;
if (param == NULL) {
return OS_INVALID_VALUE;
}
userParam = &param->userParam;
if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {
return OS_INVALID_VALUE;
}
if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {
return OS_INVALID_VALUE;
}
if (userParam->userMapBase && !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) {
return OS_INVALID_VALUE;
}
if (!LOS_IsUserAddress(userParam->userSP)) {
return OS_INVALID_VALUE;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINTPTR processID, TSK_INIT_PARAM_S *initParam)
{
UINT32 taskID;
UINT32 ret;
UINT32 intSave;
INT32 policy;
SchedParam param;
ret = OsCreateUserTaskParamCheck(processID, initParam);
if (ret != LOS_OK) {
return ret;
}
initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE;
initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;
if (processID == OS_INVALID_VALUE) {
SCHEDULER_LOCK(intSave);
LosProcessCB *processCB = OsCurrProcessGet();
initParam->processID = (UINTPTR)processCB;
initParam->consoleID = processCB->consoleID;
SCHEDULER_UNLOCK(intSave);
ret = LOS_GetProcessScheduler(processCB->processID, &policy, NULL);
if (ret != LOS_OK) {
return OS_INVALID_VALUE;
}
initParam->policy = policy;
if (policy == LOS_SCHED_DEADLINE) {
OsSchedProcessDefaultSchedParamGet((UINT16)policy, &param);
initParam->runTimeUs = param.runTimeUs;
initParam->deadlineUs = param.deadlineUs;
initParam->periodUs = param.periodUs;
}
} else {
initParam->policy = LOS_SCHED_RR;
initParam->processID = processID;
initParam->consoleID = 0;
}
ret = LOS_TaskCreateOnly(&taskID, initParam);
if (ret != LOS_OK) {
return OS_INVALID_VALUE;
}
return taskID;
}
LITE_OS_SEC_TEXT INT32 LOS_GetTaskScheduler(INT32 taskID)
{
UINT32 intSave;
INT32 policy;
SchedParam param = { 0 };
if (OS_TID_CHECK_INVALID(taskID)) {
return -LOS_EINVAL;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
policy = -LOS_EINVAL;
OS_GOTO_ERREND();
}
taskCB->ops->schedParamGet(taskCB, &param);
policy = (INT32)param.policy;
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
return policy;
}
LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority)
{
SchedParam param = { 0 };
UINT32 intSave;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ESRCH;
}
if (priority > OS_TASK_PRIORITY_LOWEST) {
return LOS_EINVAL;
}
if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)) {
return LOS_EINVAL;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
return LOS_EPERM;
}
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_EINVAL;
}
taskCB->ops->schedParamGet(taskCB, &param);
param.policy = policy;
param.priority = priority;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
if (needSched && OS_SCHEDULER_ACTIVE) {
LOS_Schedule();
}
return LOS_OK;
}
STATIC UINT32 OsTaskJoinCheck(UINT32 taskID)
{
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_EINVAL;
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
if (!OsPreemptable()) {
return LOS_EINVAL;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
return LOS_EPERM;
}
if (taskCB == OsCurrTaskGet()) {
return LOS_EDEADLK;
}
return LOS_OK;
}
UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval)
{
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
UINT32 errRet;
errRet = OsTaskJoinCheck(taskID);
if (errRet != LOS_OK) {
return errRet;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_EINVAL;
}
if (runTask->processCB != taskCB->processCB) {
SCHEDULER_UNLOCK(intSave);
return LOS_EPERM;
}
errRet = OsTaskJoinPendUnsafe(taskCB);
SCHEDULER_UNLOCK(intSave);
if (errRet == LOS_OK) {
LOS_Schedule();
if (retval != NULL) {
*retval = (UINTPTR)taskCB->joinRetval;
}
(VOID)LOS_TaskDelete(taskID);
return LOS_OK;
}
return errRet;
}
UINT32 LOS_TaskDetach(UINT32 taskID)
{
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
UINT32 errRet;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_EINVAL;
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_EINVAL;
}
if (runTask->processCB != taskCB->processCB) {
SCHEDULER_UNLOCK(intSave);
return LOS_EPERM;
}
if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
SCHEDULER_UNLOCK(intSave);
return LOS_TaskJoin(taskID, NULL);
}
errRet = OsTaskSetDetachUnsafe(taskCB);
SCHEDULER_UNLOCK(intSave);
return errRet;
}
LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID)
{
return g_taskMaxNum;
}
LosTaskCB *OsGetDefaultTaskCB(VOID)
{
return &g_taskCBArray[g_taskMaxNum];
}
LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events)
{
(VOID)LOS_EventWrite(&g_resourceEvent, events);
}
LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events)
{
(VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL);
}
STATIC VOID OsResourceRecoveryTask(VOID)
{
UINT32 ret;
while (1) {
ret = LOS_EventRead(&g_resourceEvent, OS_RESOURCE_EVENT_MASK,
LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
if (ret & (OS_RESOURCE_EVENT_FREE | OS_RESOURCE_EVENT_OOM)) {
OsTaskCBRecycleToFree();
OsProcessCBRecycleToFree();
}
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
if (ret & OS_RESOURCE_EVENT_OOM) {
(VOID)OomCheckProcess();
}
#endif
}
}
LITE_OS_SEC_TEXT UINT32 OsResourceFreeTaskCreate(VOID)
{
UINT32 ret;
UINT32 taskID;
TSK_INIT_PARAM_S taskInitParam;
ret = LOS_EventInit((PEVENT_CB_S)&g_resourceEvent);
if (ret != LOS_OK) {
return LOS_NOK;
}
(VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsResourceRecoveryTask;
taskInitParam.uwStackSize = OS_TASK_RESOURCE_STATIC_SIZE;
taskInitParam.pcName = "ResourcesTask";
taskInitParam.usTaskPrio = OS_TASK_RESOURCE_FREE_PRIORITY;
ret = LOS_TaskCreate(&taskID, &taskInitParam);
if (ret == LOS_OK) {
OS_TCB_FROM_TID(taskID)->taskStatus |= OS_TASK_FLAG_NO_DELETE;
}
return ret;
}
LOS_MODULE_INIT(OsResourceFreeTaskCreate, LOS_INIT_LEVEL_KMOD_TASK);
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/openharmony/kernel_liteos_a.git
git@gitee.com:openharmony/kernel_liteos_a.git
openharmony
kernel_liteos_a
kernel_liteos_a
master

搜索帮助