los_task.c 66.1 KB
Newer Older
1
/*
2 3
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * 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"
36 37
#include "los_hw_pri.h"
#include "los_init.h"
38 39
#include "los_memstat_pri.h"
#include "los_mp.h"
40 41 42
#include "los_mux_pri.h"
#include "los_sched_pri.h"
#include "los_sem_pri.h"
43
#include "los_spinlock.h"
44
#include "los_strncpy_from_user.h"
45 46
#include "los_percpu_pri.h"
#include "los_process_pri.h"
47 48
#include "los_vm_map.h"
#include "los_vm_syscall.h"
49
#include "los_signal.h"
50
#include "los_hook.h"
51 52 53 54

#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
55
#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
56 57
#include "los_swtmr_pri.h"
#endif
58
#ifdef LOSCFG_KERNEL_LITEIPC
59 60 61 62 63 64 65
#include "hm_liteipc.h"
#endif
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
#include "los_oom.h"
#endif


66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/******************************************************************************
基本概念
	从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、
		使用内存空间等系统资源,并独立于其它任务运行。
	任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。具有如下特性:
	支持多任务。
		一个任务表示一个线程。
		抢占式调度机制,高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。
		相同优先级任务支持时间片轮转调度方式。
		共有32个优先级[0-31],最高优先级为0,最低优先级为31。 
		
任务状态通常分为以下四种:
	就绪(Ready):该任务在就绪队列中,只等待CPU。
	运行(Running):该任务正在执行。
	阻塞(Blocked):该任务不在就绪队列中。包含任务被挂起(suspend状态)、任务被延时(delay状态)、
		任务正在等待信号量、读写队列或者等待事件等。
	退出态(Dead):该任务运行结束,等待系统回收资源。

任务状态迁移说明
	就绪态→运行态
		任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,
		从而进入运行态,但此刻该任务依旧在就绪队列中。
	运行态→阻塞态
		正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,
		任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。
	阻塞态→就绪态(阻塞态→运行态)
		阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被
		恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于
		正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。
	就绪态→阻塞态
		任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务
		从就绪队列中删除,不会参与任务调度,直到该任务被恢复。
	运行态→就绪态
		有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务
		变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。
	运行态→退出态
		运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态
		以及Invalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是Invalid状态,即退出态。
	阻塞态→退出态
		阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。
		
主要术语
	任务ID
		任务ID,在任务创建时通过参数返回给用户,是任务的重要标识。系统中的ID号是唯一的。用户可以
		通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。

	任务优先级
		优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,
		就绪队列中最高优先级的任务将得到执行。

	任务入口函数
		新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。

	任务栈
		每个任务都拥有一个独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。

	任务上下文
		任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文。当这个任务挂起时,其他任务继续执行,
		可能会修改寄存器等资源中的值。如果任务切换时没有保存任务上下文,可能会导致任务恢复后出现未知错误。
		因此,Huawei LiteOS在任务切换时会将切出任务的任务上下文信息,保存在自身的任务栈中,以便任务恢复后,
		从栈空间中恢复挂起时的上下文信息,从而继续执行挂起时被打断的代码。
	任务控制块TCB
		每个任务都含有一个任务控制块(TCB)。TCB包含了任务上下文栈指针(stack pointer)、任务状态、
		任务优先级、任务ID、任务名、任务栈大小等信息。TCB可以反映出每个任务运行情况。
	任务切换
		任务切换包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作。

运作机制
	用户创建任务时,系统会初始化任务栈,预置上下文。此外,系统还会将“任务入口函数”
	地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。
******************************************************************************/

138 139 140 141 142 143
#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;//任务池 128个
LITE_OS_SEC_BSS LOS_DL_LIST  g_losFreeTask;//空闲任务链表
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
144
LITE_OS_SEC_BSS LOS_DL_LIST  g_taskRecycleList;//回收任务链表
145
LITE_OS_SEC_BSS UINT32       g_taskMaxNum;//任务最大个数
146
LITE_OS_SEC_BSS UINT32       g_taskScheduled; /* one bit for each cores *///任务调度器,每个CPU都有对应位 
147
LITE_OS_SEC_BSS EVENT_CB_S   g_resourceEvent;//资源的事件
148 149 150 151 152 153 154
/* 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")));

#define OS_CHECK_TASK_BLOCK (OS_TASK_STATUS_DELAY |    \
155 156
                             OS_TASK_STATUS_PENDING |  \
                             OS_TASK_STATUS_SUSPENDED)
157 158 159 160

/* temp task blocks for booting procedure */
LITE_OS_SEC_BSS STATIC LosTaskCB                g_mainTask[LOSCFG_KERNEL_CORE_NUM];//启动引导过程中使用的临时任务

161
LosTaskCB *OsGetMainTask()
162
{
163
    return (LosTaskCB *)(g_mainTask + ArchCurrCpuid());
164 165 166 167 168
}

VOID OsSetMainTask()
{
    UINT32 i;
169
    CHAR *name = "osMain";//任务名称
170

171
	//为每个CPU core 设置mainTask
172 173 174 175
    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;//128
        g_mainTask[i].priority = OS_TASK_PRIORITY_LOWEST;//31
176
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
177 178 179
        g_mainTask[i].lockDep.lockDepth = 0;
        g_mainTask[i].lockDep.waitLock = NULL;
#endif
180
        (VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1);
181
        LOS_ListInit(&g_mainTask[i].lockList);//初始化任务锁链表,上面挂的是任务已申请到的互斥锁
182 183
    }
}
184
//空闲任务,每个CPU都有自己的空闲任务
185 186 187
LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
{
    while (1) {//只有一个死循环
188
        WFI;
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
    }
}

//插入一个TCB到空闲链表
STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB *taskCB)
{
    UINT32 taskID = taskCB->taskID;
    (VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB));
    taskCB->taskID = taskID;
    taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
    taskCB->processID = OS_INVALID_VALUE;
    LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);//内核挂在g_losFreeTask上的任务都是由pendList完成
}//查找task 就通过 OS_TCB_FROM_PENDLIST 来完成,相当于由LOS_DL_LIST找到LosTaskCB
//把那些和参数任务绑在一起的task唤醒.
LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB)
{
    LosTaskCB *resumedTask = NULL;

207
    if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {//join任务处理
208 209
        if (!LOS_ListEmpty(&taskCB->joinList)) {//注意到了这里 joinList中的节点身上都有阻塞标签
            resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList)));//通过贴有JOIN标签链表的第一个节点找到Task
210 211
            OsTaskWakeClearPendMask(resumedTask);
            OsSchedTaskWake(resumedTask);
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
        }
        taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN;//去掉JOIN标签
    }
    taskCB->taskStatus |= OS_TASK_STATUS_EXIT;//贴上任务退出标签
}

LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB)
{
    LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
    if (!(processCB->processStatus & OS_PROCESS_STATUS_RUNNING)) {
        return LOS_EPERM;
    }

    if (taskCB->taskStatus & OS_TASK_STATUS_INIT) {
        return LOS_EINVAL;
    }

    if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) {
230 231
        OsTaskWaitSetPendMask(OS_TASK_WAIT_JOIN, taskCB->taskID, LOS_WAIT_FOREVER);
        return OsSchedTaskWait(&taskCB->joinList, LOS_WAIT_FOREVER, TRUE);
232 233 234 235 236 237 238
    } else if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
        return LOS_OK;
    }

    return LOS_EINVAL;
}
//任务设置分离模式  Deatch和JOIN是一对有你没我的状态
239
LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB)
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
{
    LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);//获取进程实体
    if (!(processCB->processStatus & OS_PROCESS_STATUS_RUNNING)) {//进程必须是运行状态
        return LOS_EPERM;
    }

    if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {//join状态时
        if (LOS_ListEmpty(&(taskCB->joinList))) {//joinlist中没有数据了
            LOS_ListDelete(&(taskCB->joinList));//所谓删除就是自己指向自己
            taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN;//去掉JOIN标签
            taskCB->taskStatus |= OS_TASK_FLAG_DETACHED;//贴上分离标签,自己独立存在,不和其他任务媾和,不能被别的任务回收和干掉,只能由系统回收
            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;
}

260
//初始化任务模块
261 262 263 264
LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
{
    UINT32 index;
    UINT32 size;
265
    UINT32 ret;
266 267 268 269 270 271 272

    g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;//任务池中最多默认128个,可谓铁打的任务池流水的线程
    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.
     */
273
    g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);//任务池常驻内存,不被释放
274
    if (g_taskCBArray == NULL) {
275 276
        ret = LOS_ERRNO_TSK_NO_MEMORY;
        goto EXIT;
277 278 279
    }
    (VOID)memset_s(g_taskCBArray, size, 0, size);

280
    LOS_ListInit(&g_losFreeTask);//初始化空闲任务链表
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
281
    LOS_ListInit(&g_taskRecycleList);//初始化回收任务链表
282 283 284 285 286
    for (index = 0; index < g_taskMaxNum; index++) {//任务挨个初始化
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;//默认未使用,干净.
        g_taskCBArray[index].taskID = index;//任务ID [0 ~ g_taskMaxNum - 1]
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);//通过pendList节点插入空闲任务列表 
    }//注意:这里挂的是pendList节点,所以取TCB也要通过 OS_TCB_FROM_PENDLIST 取.
287

鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
288
    ret = OsSchedInit();//调度器初始化
289

290 291 292 293 294 295
EXIT:
    if (ret != LOS_OK) {
        PRINT_ERR("OsTaskInit error\n");
    }
    return ret;
}
296 297 298 299 300 301 302 303 304 305 306
//获取IdletaskId,每个CPU核都对Task进行了内部管理,做到真正的并行处理
UINT32 OsGetIdleTaskId(VOID)
{
    Percpu *perCpu = OsPercpuGet();//获取当前Cpu信息
    return perCpu->idleTaskID;//返回当前CPU 空闲任务ID
}
//创建一个空闲任务
LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
{
    UINT32 ret;
    TSK_INIT_PARAM_S taskInitParam;
307
    Percpu *perCpu = OsPercpuGet();//获取当前运行CPU信息
308
    UINT32 *idleTaskID = &perCpu->idleTaskID;//每个CPU都有一个空闲任务
309 310

    (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));//任务初始参数清0
311 312
    taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;//入口函数
    taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;//任务栈大小 2K
313 314
    taskInitParam.pcName = "Idle";//任务名称 叫pcName有点怪怪的,不能换个撒
    taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;//默认最低优先级 31
315
    taskInitParam.processID = OsGetIdleProcessID();
316
#ifdef LOSCFG_KERNEL_SMP
317
    taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());//每个idle任务只在单独的cpu上运行
318
#endif
319 320 321
    ret = LOS_TaskCreateOnly(idleTaskID, &taskInitParam);
    LosTaskCB *idleTask = OS_TCB_FROM_TID(*idleTaskID);
    idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
322
    OsSchedSetIdleTaskSchedParam(idleTask);
323

324 325 326 327 328 329 330
    return ret;
}

/*
 * Description : get id of current running task.
 * Return      : task id
 */
331
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)//获取当前任务的ID
332 333 334 335 336 337 338 339 340 341 342 343 344 345
{
    LosTaskCB *runTask = OsCurrTaskGet();

    if (runTask == NULL) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }
    return runTask->taskID;
}

//一个任务的退出过程
LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status)
{
    UINT32 intSave;

346 347
    LosProcessCB *runProcess = OS_PCB_FROM_PID(taskCB->processID);
    LosTaskCB *mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID);
348 349 350 351 352 353 354 355 356 357 358
    if (mainTask == taskCB) {//如果参数任务就是主任务
        OsTaskExitGroup(status);//task退出线程组
    }

    SCHEDULER_LOCK(intSave);
    if (runProcess->threadNumber == 1) { /* 1: The last task of the process exits *///进程的最后一个任务退出
        SCHEDULER_UNLOCK(intSave);
        (VOID)OsProcessExit(taskCB, status);//调用进程退出流程
        return;
    }

359 360 361 362
    /* The thread being killed must be able to exit automatically and will have the detached property */
    OsTaskJoinPostUnsafe(taskCB);

    if (taskCB->taskStatus & (OS_TASK_FLAG_DETACHED | OS_TASK_FLAG_EXIT_KILL)) {
363 364
        UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave);
        LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret);
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    }

    OsSchedResched();//申请调度
    SCHEDULER_UNLOCK(intSave);
    return;
}

/*
 * Description : All task entry
 * Input       : taskID     --- The ID of the task to be run
 *///所有任务的入口函数,OsTaskEntry是在new task OsTaskStackInit 时指定的
LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID)
{
    LosTaskCB *taskCB = NULL;

    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.
     */
387 388
    LOS_SpinUnlock(&g_taskSpin);//释放任务自旋锁
    (VOID)LOS_IntUnLock();//恢复中断
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425

    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_DETACHED) {//task有分离标签时
        taskCB->joinRetval = 0;//结合数为0
    }
	
    OsTaskToExit(taskCB, 0);//到这里任务跑完了要退出了
}
//任务创建参数检查
LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32 *taskID,
    TSK_INIT_PARAM_S *initParam, VOID **pool)
{
    LosProcessCB *process = NULL;
    UINT32 poolSize = OS_SYS_MEM_SIZE;
    *pool = (VOID *)m_aucSysMem1;//默认使用

    if (taskID == NULL) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    if (initParam == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    process = OS_PCB_FROM_PID(initParam->processID);
    if (process->processMode > OS_USER_MODE) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    if (!OsProcessIsUserMode(process)) {
        if (initParam->pcName == NULL) {
            return LOS_ERRNO_TSK_NAME_EMPTY;
        }
    }

426
    if (initParam->pfnTaskEntry == NULL) {//入口函数不能为空
427 428 429
        return LOS_ERRNO_TSK_ENTRY_NULL;
    }

430
    if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) {//优先级必须大于31
431 432 433
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }

434
    if (initParam->uwStackSize > poolSize) {//希望申请的栈大小不能大于总池子
435 436 437
        return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
    }

438
    if (initParam->uwStackSize == 0) {//任何任务都必须由内核态栈,所以uwStackSize不能为0
439 440 441 442
        initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    }
    initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);

443
    if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) {//运行栈空间不能低于最低值
444 445 446 447 448
        return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
    }

    return LOS_OK;
}
449
//任务栈(内核态)内存分配,由内核态进程空间提供,即 KProcess 的进程空间
450 451 452 453 454 455 456
LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID **topStack, UINT32 stackSize, VOID *pool)
{
    *topStack = (VOID *)LOS_MemAllocAlign(pool, stackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
}
//创建任务同步信号
STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB)
{
457
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
458 459 460 461 462 463 464 465 466 467 468 469
    UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal);//创建一个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)
{
470
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
471 472 473 474 475
    (VOID)LOS_SemDelete(syncSignal);
#else
    (VOID)syncSignal;
#endif
}
476
/******************************************
477
等待任务的同步信号量,
478 479 480 481
A --发送syncSignal-- > B
B --回一个syncSignal-- > A
如此A就知道B此时还在
*******************************************/
482 483
LITE_OS_SEC_TEXT UINT32 OsTaskSyncWait(const LosTaskCB *taskCB)
{
484
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
485 486 487 488 489 490 491 492 493
    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 peroid.
     */
494
    if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) {//发送同步信号量
495 496 497 498 499 500 501 502 503 504 505 506 507 508
        ret = LOS_ERRNO_TSK_MP_SYNC_FAILED;
    }

    LOS_SpinLock(&g_taskSpin);

    return ret;
#else
    (VOID)taskCB;
    return LOS_OK;
#endif
}
//任务同步唤醒
STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB)
{
509
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
    (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL);//唤醒一个挂在信号量链表上的阻塞任务
#else
    (VOID)taskCB;
#endif
}
//释放任务内核资源
STATIC VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack)
{
    VOID *poolTmp = (VOID *)m_aucSysMem1;

    OsTaskSyncDestroy(syncSignal);

    (VOID)LOS_MemFree(poolTmp, (VOID *)topOfStack);
}
//从回收链表中回收任务到空闲链表
525
LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree()
526 527 528 529 530
{
    LosTaskCB *taskCB = NULL;
    UINT32 intSave;

    SCHEDULER_LOCK(intSave);
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
531 532
    while (!LOS_ListEmpty(&g_taskRecycleList)) {//不空就一个一个回收任务
        taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList));//取出第一个待回收任务
533 534 535 536 537 538 539 540 541 542 543 544 545
        LOS_ListDelete(&taskCB->pendList);//从回收链表上将自己摘除
        SCHEDULER_UNLOCK(intSave);

        OsTaskResourcesToFree(taskCB);//释放任务资源

        SCHEDULER_LOCK(intSave);
    }
    SCHEDULER_UNLOCK(intSave);
}

LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB)
{
    UINT32 syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
546 547
    UINT32 intSave;
    UINTPTR topOfStack;
548

549 550 551
#ifdef LOSCFG_KERNEL_VM
    LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
    if (OsProcessIsUserMode(processCB) && (taskCB->userMapBase != 0)) {
552
        SCHEDULER_LOCK(intSave);
553 554
        UINT32 mapBase = (UINTPTR)taskCB->userMapBase;
        UINT32 mapSize = taskCB->userMapSize;
555 556 557 558 559
        taskCB->userMapBase = 0;
        taskCB->userArea = 0;
        SCHEDULER_UNLOCK(intSave);

        LOS_ASSERT(!(processCB->vmSpace == NULL));
560
        UINT32 ret = OsUnMMap(processCB->vmSpace, (UINTPTR)mapBase, mapSize);
561 562 563 564 565
        if ((ret != LOS_OK) && (mapBase != 0) && !(processCB->processStatus & OS_PROCESS_STATUS_INIT)) {
            PRINT_ERR("process(%u) ummap user task(%u) stack failed! mapbase: 0x%x size :0x%x, error: %d\n",
                      processCB->processID, taskCB->taskID, mapBase, mapSize, ret);
        }

566
#ifdef LOSCFG_KERNEL_LITEIPC
567 568 569
        LiteIpcRemoveServiceHandle(taskCB);
#endif
    }
570
#endif
571 572 573 574

    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        topOfStack = taskCB->topOfStack;
        taskCB->topOfStack = 0;
575
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
576 577 578 579 580 581
        syncSignal = taskCB->syncSignal;
        taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
#endif
        OsTaskKernelResourcesToFree(syncSignal, topOfStack);

        SCHEDULER_LOCK(intSave);
582
        OsClearSigInfoTmpList(&(taskCB->sig));
583 584 585 586 587 588 589 590 591 592 593
        OsInsertTCBToFreeList(taskCB);
        SCHEDULER_UNLOCK(intSave);
    }
    return;
}
//任务基本信息的初始化
LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
                                                   const VOID *stackPtr,
                                                   const VOID *topStack,
                                                   const TSK_INIT_PARAM_S *initParam)
{
594
    taskCB->stackPointer = (VOID *)stackPtr;//内核态SP位置
595 596 597 598
    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];
599
    taskCB->topOfStack   = (UINTPTR)topStack;	//内核态栈顶
600 601 602 603 604
    taskCB->stackSize    = initParam->uwStackSize;//
    taskCB->priority     = initParam->usTaskPrio;
    taskCB->taskEntry    = initParam->pfnTaskEntry;
    taskCB->signal       = SIGNAL_NONE;

605
#ifdef LOSCFG_KERNEL_SMP
606 607 608 609
    taskCB->currCpu      = OS_TASK_INVALID_CPUID;
    taskCB->cpuAffiMask  = (initParam->usCpuAffiMask) ?
                            initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK;
#endif
610
#ifdef LOSCFG_KERNEL_LITEIPC
611 612
    LOS_ListInit(&(taskCB->msgListHead));//初始化 liteipc的消息链表 
#endif
613 614
    taskCB->policy = (initParam->policy == LOS_SCHED_FIFO) ? LOS_SCHED_FIFO : LOS_SCHED_RR;//调度模式
    taskCB->taskStatus = OS_TASK_STATUS_INIT;//任务初始状态
615
    if (initParam->uwResved & OS_TASK_FLAG_DETACHED) {//分离模式 代表任务与其他任务的关系
616
        taskCB->taskStatus |= OS_TASK_FLAG_DETACHED;//任务状态贴上分离标签
617
    } else {//参与模式
618
        taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;//任务状态贴上联合标签
619
        LOS_ListInit(&taskCB->joinList);
620 621 622
    }

    taskCB->futex.index = OS_INVALID_VALUE;
623
    LOS_ListInit(&taskCB->lockList);//初始化互斥锁链表
624
    SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
625 626
}
//任务初始化
627 628
STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam,
                           const VOID *stackPtr, const VOID *topStack)
629 630 631 632 633 634 635
{
    UINT32 intSave;
    UINT32 ret;
    UINT32 numCount;
    UINT16 mode;
    LosProcessCB *processCB = NULL;

636
    OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam);//初始化任务的基本信息,
637
    					//taskCB->stackPointer指向内核态栈 sp位置,该位置存着 任务初始上下文
638 639 640 641

    SCHEDULER_LOCK(intSave);
    processCB = OS_PCB_FROM_PID(initParam->processID);//通过ID获取PCB ,单核进程数最多64个
    taskCB->processID = processCB->processID;//进程-线程的父子关系绑定
642
    mode = processCB->processMode;//模式方式同步process
643
    LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList));//挂入进程的线程链表
644
    if (mode == OS_USER_MODE) {//任务支持用户态时,将改写 taskCB->stackPointer = initParam->userParam.userSP
645 646 647
        taskCB->userArea = initParam->userParam.userArea;
        taskCB->userMapBase = initParam->userParam.userMapBase;
        taskCB->userMapSize = initParam->userParam.userMapSize;
648
        OsUserTaskStackInit(taskCB->stackPointer, (UINTPTR)taskCB->taskEntry, initParam->userParam.userSP);//初始化用户态任务栈
649
        //这里要注意,任务的上下文是始终保存在内核栈空间,而用户态时运行在用户态栈空间.(context->SP = userSP 指向了用户态栈空间)
650 651 652 653 654 655 656 657 658 659 660
    }

    if (!processCB->threadNumber) {//进程线程数量为0时,
        processCB->threadGroupID = taskCB->taskID;//任务为线程组 组长
    }
    processCB->threadNumber++;//这里说明 线程和TASK是一个意思 threadNumber代表活动线程数,thread消亡的时候会 threadNumber--

    numCount = processCB->threadCount;//代表总线程数,包括销毁的,只要存在过的都算,这个值也就是在这里用下,
    processCB->threadCount++;//线程总数++,注意这个数会一直累加的,哪怕thread最后退出了,这个统计这个进程曾经存在过的线程数量
    SCHEDULER_UNLOCK(intSave);

661 662 663 664
    if (initParam->pcName != NULL) {
        ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE);
        if (ret == LOS_OK) {
            return LOS_OK;
665 666 667
        }
    }

668 669 670
    if (snprintf_s(taskCB->taskName, OS_TCB_NAME_LEN, OS_TCB_NAME_LEN - 1, "thread%u", numCount) < 0) {
        return LOS_NOK;
    }
671 672 673 674 675 676 677 678 679 680 681 682
    return LOS_OK;
}
//获取一个空闲TCB
LITE_OS_SEC_TEXT LosTaskCB *OsGetFreeTaskCB(VOID)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;

    SCHEDULER_LOCK(intSave);
    if (LOS_ListEmpty(&g_losFreeTask)) {//全局空闲task为空
        SCHEDULER_UNLOCK(intSave);
        PRINT_ERR("No idle TCB in the system!\n");
683 684 685
#ifdef LOSCFG_DEBUG_VERSION
	(VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL);
#endif
686 687 688 689 690 691 692 693 694
        return NULL;
    }

    taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask));//拿到第一节点并通过pendlist拿到完整的TCB
    LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask));//从g_losFreeTask链表中摘除自己
    SCHEDULER_UNLOCK(intSave);

    return taskCB;
}
695
//创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
    UINT32 intSave, errRet;
    VOID *topStack = NULL;
    VOID *stackPtr = NULL;
    LosTaskCB *taskCB = NULL;
    VOID *pool = NULL;

    errRet = OsTaskCreateParamCheck(taskID, initParam, &pool);//参数检查
    if (errRet != LOS_OK) {
        return errRet;
    }

    taskCB = OsGetFreeTaskCB();//从g_losFreeTask中获取,还记得吗任务池中最多默认128个
    if (taskCB == NULL) {
        errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
        goto LOS_ERREND;
    }

    errRet = OsTaskSyncCreate(taskCB);//SMP cpu多核间负载均衡相关
    if (errRet != LOS_OK) {
        goto LOS_ERREND_REWIND_TCB;
    }
	//OsTaskStackAlloc 只在LOS_TaskCreateOnly中被调用,此处是分配任务在内核态栈空间 
720
    OsTaskStackAlloc(&topStack, initParam->uwStackSize, pool);//为任务分配内核栈空间,注意此内存来自系统内核空间
721 722 723 724 725
    if (topStack == NULL) {
        errRet = LOS_ERRNO_TSK_NO_MEMORY;
        goto LOS_ERREND_REWIND_SYNC;
    }

726
    stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);//初始化内核态任务栈,返回栈SP位置
727 728 729 730
    errRet = OsTaskCBInit(taskCB, initParam, stackPtr, topStack);//初始化TCB,包括绑定进程等操作
    if (errRet != LOS_OK) {
        goto LOS_ERREND_TCB_INIT;
    }
731
    if (OsConsoleIDSetHook != NULL) {//每个任务都可以有属于自己的控制台
732 733 734 735
        OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID);//设置控制台ID
    }

    *taskID = taskCB->taskID;
736
    OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB);
737 738 739 740 741
    return LOS_OK;

LOS_ERREND_TCB_INIT:
    (VOID)LOS_MemFree(pool, topStack);
LOS_ERREND_REWIND_SYNC:
742
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
743 744 745 746 747 748 749 750 751
    OsTaskSyncDestroy(taskCB->syncSignal);
#endif
LOS_ERREND_REWIND_TCB:
    SCHEDULER_LOCK(intSave);
    OsInsertTCBToFreeList(taskCB);//归还freetask
    SCHEDULER_UNLOCK(intSave);
LOS_ERREND:
    return errRet;
}
752
//创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务
753 754 755 756 757 758 759 760 761 762 763 764 765 766
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
    UINT32 ret;
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;

    if (initParam == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    if (OS_INT_ACTIVE) {
        return LOS_ERRNO_TSK_YIELD_IN_INT;
    }

767 768
    if (OsProcessIsUserMode(OsCurrProcessGet())) {
        initParam->processID = OsGetKernelInitProcessID();
769
    } else {
770
        initParam->processID = OsCurrProcessGet()->processID;
771
    }
772 773 774
    initParam->uwResved &= ~OS_TASK_FLAG_PTHREAD_JOIN;
    if (initParam->uwResved & LOS_TASK_STATUS_DETACHED) {
        initParam->uwResved = OS_TASK_FLAG_DETACHED;
775 776
    }

777
    ret = LOS_TaskCreateOnly(taskID, initParam);
778 779 780
    if (ret != LOS_OK) {
        return ret;
    }
781
    taskCB = OS_TCB_FROM_TID(*taskID);
782 783

    SCHEDULER_LOCK(intSave);
784
    OsSchedTaskEnQueue(taskCB);
785 786 787 788
    SCHEDULER_UNLOCK(intSave);

    /* in case created task not running on this core,
       schedule or not depends on other schedulers status. */
789 790 791
    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (OS_SCHEDULER_ACTIVE) {
        LOS_Schedule();
792 793 794 795
    }

    return LOS_OK;
}
796
//恢复挂起的任务,使该任务进入ready状态
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
{
    UINT32 intSave;
    UINT32 errRet;
    LosTaskCB *taskCB = NULL;
    BOOL needSched = FALSE;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);//拿到任务实体
    SCHEDULER_LOCK(intSave);

    /* clear pending signal */
    taskCB->signal &= ~SIGNAL_SUSPEND;//清楚挂起信号

814
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
815 816
        errRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
817
    } else if (!(taskCB->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
818 819 820 821
        errRet = LOS_ERRNO_TSK_NOT_SUSPENDED;
        OS_GOTO_ERREND();
    }

822
    taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPENDED;
823
    if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
824 825
        OsSchedTaskEnQueue(taskCB);
        if (OS_SCHEDULER_ACTIVE) {
826 827 828 829 830
            needSched = TRUE;
        }
    }
    SCHEDULER_UNLOCK(intSave);

831 832
    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (needSched) {
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
        LOS_Schedule();
    }

    return LOS_OK;

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.						//如果需要暂停,返回TRUE。
 * Rerturn FALSE, if meets following circumstances:					//如果满足以下情况,则返回FALSE:
 * 1. Do the suspension across cores, if SMP is enabled				//1.如果启用了SMP,则跨CPU核执行挂起操作
 * 2. Do the suspension when preemption is disabled					//2.当禁用抢占时则挂起
 * 3. Do the suspension in hard-irq									//3.在硬中断时则挂起
 * then LOS_TaskSuspend will directly return with 'ret' value.		//那么LOS_taskssuspend将直接返回ret值。
 */
LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UINT32 *ret)
{
    /* init default out return value */
    *ret = LOS_OK;

857
#ifdef LOSCFG_KERNEL_SMP
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
    /* ASYNCHRONIZED. No need to do task lock checking */
    if (taskCB->currCpu != ArchCurrCpuid()) {//跨CPU核的情况
        taskCB->signal = SIGNAL_SUSPEND;
        LOS_MpSchedule(taskCB->currCpu);//task所属CPU执行调度
        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;
}
880
//任务暂停,参数可以不是当前任务,也就是说 A任务可以让B任务处于阻塞状态,挂起指定的任务,然后切换任务
881 882 883 884 885 886 887 888 889 890
LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB)
{
    UINT32 errRet;
    UINT16 tempStatus;

    tempStatus = taskCB->taskStatus;
    if (tempStatus & OS_TASK_STATUS_UNUSED) {
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

891
    if (tempStatus & OS_TASK_STATUS_SUSPENDED) {
892 893 894 895 896 897 898 899
        return LOS_ERRNO_TSK_ALREADY_SUSPENDED;
    }

    if ((tempStatus & OS_TASK_STATUS_RUNNING) && //如果参数任务正在运行,注意多Cpu core情况下,贴着正在运行标签的任务并不一定是当前CPU的执行任务,
        !OsTaskSuspendCheckOnRun(taskCB, &errRet)) {//很有可能是别的CPU core在跑的任务
        return errRet;
    }

900 901
    if (tempStatus & OS_TASK_STATUS_READY) {
        OsSchedTaskDeQueue(taskCB);
902 903
    }

904
    taskCB->taskStatus |= OS_TASK_STATUS_SUSPENDED;
905
    OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
906 907
    if (taskCB == OsCurrTaskGet()) {
        OsSchedResched();
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
    }

    return LOS_OK;
}
//外部接口,对OsTaskSuspend的封装
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;
    UINT32 errRet;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    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);
}
//task释放持有的所有锁,一个任务可以持有很多把锁
STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, 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);
        }
    }

    if (processCB->processMode == OS_USER_MODE) {//如果是用户模式,会怎样?
        OsTaskJoinPostUnsafe(taskCB);//把taskCB绑在一起的其他task唤醒.
958
#ifdef LOSCFG_KERNEL_VM
959
        OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
960
#endif
961 962 963 964
    }

    OsTaskSyncWake(taskCB);//同步唤醒任务
}
965
//删除一个正在运行的任务
966
LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask)
967
{
968 969 970
    LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID);//拿到task所属进程
    OsTaskReleaseHoldLock(processCB, runTask);//task还锁
    OsTaskStatusUnusedSet(runTask);//task重置为未使用状态,等待回收
971

972
    LOS_ListDelete(&runTask->threadList);//从进程的线程链表中将自己摘除
973
    processCB->threadNumber--;//进程的活动task --,注意进程还有一个记录总task的变量 processCB->threadCount
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
974
    LOS_ListTailInsert(&g_taskRecycleList, &runTask->pendList);//将task插入回收链表,等待回收资源再利用
975
    OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);//发送释放资源的事件,事件由 OsResourceRecoveryTask 消费
976 977 978 979 980 981 982 983 984 985 986 987 988 989

    OsSchedResched();//申请调度
    return;
}

/*
 * Check if needs to do the delete operation on the running task.
 * Return TRUE, if needs to do the deletion.
 * Rerturn FALSE, if meets following circumstances:
 * 1. Do the deletion across cores, if SMP is enabled
 * 2. Do the deletion when preemption is disabled
 * 3. Do the deletion in hard-irq
 * then LOS_TaskDelete will directly return with 'ret' value.
 */
990 991 992 993 994 995 996 997
 /****************************************************************
 检查是否需要对正在运行的任务执行删除操作,如果需要删除,则返回TRUE。
 如果满足以下情况,则返回FALSE:
 1.如果启用了SMP,则跨CPU执行删除
 2.禁用抢占时执行删除
 3.在硬irq中删除
 然后LOS_TaskDelete将直接返回ret值
 ****************************************************************/
998 999 1000 1001 1002
STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret)
{
    /* init default out return value */
    *ret = LOS_OK;

1003
#ifdef LOSCFG_KERNEL_SMP
1004 1005
    /* ASYNCHRONIZED. No need to do task lock checking *///异步操作,不需要进行任务锁检查
    if (taskCB->currCpu != ArchCurrCpuid()) {//任务运行在其他CPU,跨核心执行删除
1006 1007 1008 1009 1010
        /*
         * the task is running on another cpu.
         * mask the target task with "kill" signal, and trigger mp schedule
         * which might not be essential but the deletion could more in time.
         */
1011 1012 1013
        taskCB->signal = SIGNAL_KILL;	//贴上干掉标记
        LOS_MpSchedule(taskCB->currCpu);//通知任务所属CPU发生调度
        *ret = OsTaskSyncWait(taskCB);	//同步等待可怜的任务被干掉
1014 1015 1016 1017
        return FALSE;
    }
#endif

1018
    if (!OsPreemptableInSched()) {//如果任务正在运行且调度程序已锁定,则无法删除它
1019 1020 1021 1022 1023
        /* If the task is running and scheduler is locked then you can not delete it */
        *ret = LOS_ERRNO_TSK_DELETE_LOCKED;
        return FALSE;
    }

1024
    if (OS_INT_ACTIVE) {//硬中断进行中...会屏蔽掉所有信号,当然包括kill了
1025 1026 1027 1028
        /*
         * delete running task in interrupt.
         * mask "kill" signal and later deletion will be handled.
         */
1029
        taskCB->signal = SIGNAL_KILL;//硬中断后将处理删除。
1030 1031 1032 1033 1034
        return FALSE;
    }

    return TRUE;
}
1035
//删除不活动的任务 !OS_TASK_STATUS_RUNNING 
1036 1037
STATIC VOID OsTaskDeleteInactive(LosProcessCB *processCB, LosTaskCB *taskCB)
{
1038
    LosMux *mux = (LosMux *)taskCB->taskMux; //任务
1039
    UINT16 taskStatus = taskCB->taskStatus;
1040

1041
    LOS_ASSERT(!(taskStatus & OS_TASK_STATUS_RUNNING));
1042

1043
    OsTaskReleaseHoldLock(processCB, taskCB);
1044

1045 1046 1047 1048
    OsSchedTaskExit(taskCB);
    if (taskStatus & OS_TASK_STATUS_PENDING) {
        if (LOS_MuxIsValid(mux) == TRUE) {
            OsMuxBitmapRestore(mux, taskCB, (LosTaskCB *)mux->owner);
1049 1050 1051
        }
    }

1052
    OsTaskStatusUnusedSet(taskCB);
1053

1054 1055
    LOS_ListDelete(&taskCB->threadList);
    processCB->threadNumber--;
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1056
    LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList);
1057 1058
    return;
}
1059
//以不安全的方式删除参数任务
1060 1061 1062 1063 1064 1065
LITE_OS_SEC_TEXT UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave)
{
    LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);//获取进程实体
    UINT32 mode = processCB->processMode;
    UINT32 errRet = LOS_OK;

1066
    if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {//系统任务是不能被删除的, 请您说出3个系统任务.
1067 1068 1069 1070
        errRet = LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
        goto EXIT;
    }

1071
    if ((taskCB->taskStatus & OS_TASK_STATUS_RUNNING) && !OsRunTaskToDeleteCheckOnRun(taskCB, &errRet)) {//正在运行且检测正在运行不能删除的情况
1072 1073 1074
        goto EXIT;
    }

1075 1076 1077 1078 1079
    if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {//任务不在活动
        OsTaskDeleteInactive(processCB, taskCB);//删除未活动的任务
        SCHEDULER_UNLOCK(intSave);//释放自旋锁,这就是不安全的标记,函数内部并没有拿自旋锁
        OsWriteResourceEvent(OS_RESOURCE_EVENT_FREE);//写一个资源释放事件,资源回收任务会收到事件,并回收任务的资源.
        return errRet;//消费OS_RESOURCE_EVENT_FREE事件可见于 OsResourceRecoveryTask 的处理
1080
    }
1081
    OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB);
1082 1083 1084
    if (mode == OS_USER_MODE) { //用户态模式
        SCHEDULER_UNLOCK(intSave);//先释放锁
        OsTaskResourcesToFree(taskCB);//释放任务资源
1085 1086 1087
        SCHEDULER_LOCK(intSave);
    }

1088
#ifdef LOSCFG_KERNEL_SMP
1089 1090 1091 1092
    LOS_ASSERT(OsPercpuGet()->taskLockCnt == 1);
#else
    LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0);
#endif
1093
    OsRunTaskToDelete(taskCB);//删除一个正在运行的任务
1094 1095 1096 1097 1098

EXIT:
    SCHEDULER_UNLOCK(intSave);
    return errRet;
}
1099
//删除指定的任务,回归任务池
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
{
    UINT32 intSave;
    UINT32 ret;
    LosTaskCB *taskCB = NULL;
    LosProcessCB *processCB = NULL;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    if (OS_INT_ACTIVE) {
        return LOS_ERRNO_TSK_YIELD_IN_INT;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    SCHEDULER_LOCK(intSave);
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        ret = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    }

1122 1123 1124 1125 1126
    if (taskCB->taskStatus & (OS_TASK_FLAG_SYSTEM_TASK | OS_TASK_FLAG_NO_DELETE)) {
        SCHEDULER_UNLOCK(intSave);
        OsBackTrace();
        return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
    }
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
    processCB = OS_PCB_FROM_PID(taskCB->processID);
    if (processCB->threadNumber == 1) {//此任务为进程的最后一个任务的处理
        if (processCB == OsCurrProcessGet()) {//是否为当前任务
            SCHEDULER_UNLOCK(intSave);
            OsProcessExit(taskCB, OS_PRO_EXIT_OK);//进程退出
            return LOS_OK;
        }

        ret = LOS_ERRNO_TSK_ID_INVALID;
        OS_GOTO_ERREND();
    }

    return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave);//任务以非安全模式删除

LOS_ERREND:
    SCHEDULER_UNLOCK(intSave);
    return ret;
}
1145
//任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
{
    UINT32 intSave;
    LosTaskCB *runTask = NULL;

    if (OS_INT_ACTIVE) {
        PRINT_ERR("In interrupt not allow delay task!\n");
        return LOS_ERRNO_TSK_DELAY_IN_INT;
    }

    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;
    }
1165
    OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick);
1166 1167
    if (tick == 0) {
        return LOS_TaskYield();
1168 1169
    }

1170 1171
    SCHEDULER_LOCK(intSave);
    OsSchedDelay(runTask, tick);
1172
    OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask);
1173 1174
    SCHEDULER_UNLOCK(intSave);

1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
    return LOS_OK;
}
//获取任务的优先级
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 priority;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return (UINT16)OS_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    SCHEDULER_LOCK(intSave);
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//就这么一句话也要来个自旋锁,内核代码自旋锁真是无处不在啊
        SCHEDULER_UNLOCK(intSave);
        return (UINT16)OS_INVALID;
    }

    priority = taskCB->priority;
    SCHEDULER_UNLOCK(intSave);
    return priority;
}
1199
//设置指定任务的优先级
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;

    if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }

    if (OS_TID_CHECK_INVALID(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
        return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
    }

    SCHEDULER_LOCK(intSave);
1219
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1220 1221 1222 1223
        SCHEDULER_UNLOCK(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

1224
    BOOL isReady = OsSchedModifyTaskSchedParam(taskCB, taskCB->policy, taskPrio);
1225
    SCHEDULER_UNLOCK(intSave);
1226 1227 1228

    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (isReady && OS_SCHEDULER_ACTIVE) {
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
        LOS_Schedule();
    }
    return LOS_OK;
}
//设置当前任务的优先级
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio)
{
    return LOS_TaskPriSet(OsCurrTaskGet()->taskID, taskPrio);
}

1239
//当前任务释放CPU,并将其移到具有相同优先级的就绪任务队列的末尾. 读懂这个函数 你就彻底搞懂了 yield
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
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;
    }

1252
    LosTaskCB *runTask = OsCurrTaskGet();
1253 1254 1255 1256 1257 1258
    if (OS_TID_CHECK_INVALID(runTask->taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    SCHEDULER_LOCK(intSave);
    /* reset timeslice of yeilded task */
1259
    OsSchedYield();
1260 1261 1262
    SCHEDULER_UNLOCK(intSave);
    return LOS_OK;
}
1263

1264 1265 1266 1267
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
{
    UINT32 intSave;

1268 1269 1270
    intSave = LOS_IntLock();
    OsCpuSchedLock(OsPercpuGet());
    LOS_IntRestore(intSave);
1271
}
1272

1273 1274
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
{
1275
    OsCpuSchedUnlock(OsPercpuGet(), LOS_IntLock());
1276
}
1277

1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
//获取任务信息,给shell使用的
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;

    if (taskInfo == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    if (OS_TID_CHECK_INVALID(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    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();
    }

    taskInfo->usTaskStatus = taskCB->taskStatus;
    taskInfo->usTaskPrio = taskCB->priority;
1307
    taskInfo->uwStackSize = taskCB->stackSize;	//内核态栈大小
1308
    taskInfo->uwTopOfStack = taskCB->topOfStack;//内核态栈顶位置
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    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;
}
1328
//CPU亲和性(affinity)将任务绑在指定CPU上,用于多核CPU情况,(该函数仅在SMP模式下支持)
1329
LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask)
1330
{
1331
#ifdef LOSCFG_KERNEL_SMP
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
    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)
{
1350 1351
    LosTaskCB *taskCB = NULL;
    BOOL needSched = FALSE;
1352
    UINT32 intSave;
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
    UINT16 currCpuMask;

    if (OS_TID_CHECK_INVALID(taskID)) {//检测taskid是否有效,task由task池分配,鸿蒙默认128个任务 ID范围[0:127]
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    if (!(cpuAffiMask & LOSCFG_KERNEL_CPU_MASK)) {//检测cpu亲和力
        return LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR;
    }

    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;
    }
1369
    needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuAffiMask, &currCpuMask);
1370 1371 1372 1373

    SCHEDULER_UNLOCK(intSave);

    if (needSched && OS_SCHEDULER_ACTIVE) {
1374
        LOS_MpSchedule(currCpuMask);//发送信号调度信号给目标CPU
1375 1376
        LOS_Schedule();//申请调度
    }
1377

1378 1379
    return LOS_OK;
}
1380
//查询任务被绑在哪个CPU上
1381 1382
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
{
1383
#ifdef LOSCFG_KERNEL_SMP
1384 1385 1386 1387 1388 1389 1390 1391 1392
#define INVALID_CPU_AFFI_MASK   0
    LosTaskCB *taskCB = NULL;
    UINT16 cpuAffiMask;
    UINT32 intSave;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return INVALID_CPU_AFFI_MASK;
    }

1393
    taskCB = OS_TCB_FROM_TID(taskID);//获取任务实体
1394
    SCHEDULER_LOCK(intSave);
1395
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { //任务必须在使用
1396 1397 1398 1399
        SCHEDULER_UNLOCK(intSave);
        return INVALID_CPU_AFFI_MASK;
    }

1400
    cpuAffiMask = taskCB->cpuAffiMask; //获取亲和力掩码
1401 1402 1403 1404 1405
    SCHEDULER_UNLOCK(intSave);

    return cpuAffiMask;
#else
    (VOID)taskID;
1406
    return 1;//单核情况直接返回1 ,0号cpu对应0x01
1407 1408 1409 1410 1411
#endif
}

/*
 * Description : Process pending signals tagged by others cores
1412 1413 1414 1415 1416
 */
 /******************************************************
 	由其他CPU核触发阻塞进程的信号
	函数由汇编代码调用 ..\arch\arm\arm\src\los_dispatch.S
 ******************************************************/
1417
LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID)
1418 1419
{
    UINT32 intSave, ret;
1420
	//私有且不可中断,无需保护。这个任务在其他CPU核看到它时总是在运行,所以它在执行代码的同时也可以继续接收信号
1421 1422 1423 1424 1425
    /*
     * private and uninterruptable, no protection needed.
     * while this task is always running when others cores see it,
     * so it keeps recieving signals while follow code excuting.
     */
1426 1427 1428
    LosTaskCB *runTask = OsCurrTaskGet();
    if (runTask->signal == SIGNAL_NONE) {
        return;
1429 1430
    }

1431
    if (runTask->signal & SIGNAL_KILL) {//意思是其他cpu发起了要干掉你的信号
1432 1433 1434
        /*
         * clear the signal, and do the task deletion. if the signaled task has been
         * scheduled out, then this deletion will wait until next run.
1435
         *///如果发出信号的任务已出调度就绪队列,则此删除将等待下次运行
1436
        SCHEDULER_LOCK(intSave);
1437 1438
        runTask->signal = SIGNAL_NONE;//清除信号,
        ret = OsTaskDeleteUnsafe(runTask, OS_PRO_EXIT_OK, intSave);//任务的自杀行动,这可是正在运行的任务.
1439 1440 1441
        if (ret) {
            PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret);
        }
1442
    } else if (runTask->signal & SIGNAL_SUSPEND) {//意思是其他cpu发起了要挂起你的信号
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1443
        runTask->signal &= ~SIGNAL_SUSPEND;//任务贴上被其他CPU挂起的标签
1444 1445 1446

        /* suspend killed task may fail, ignore the result */
        (VOID)LOS_TaskSuspend(runTask->taskID);
1447
#ifdef LOSCFG_KERNEL_SMP
1448
    } else if (runTask->signal & SIGNAL_AFFI) {//意思是下次调度其他cpu要媾和你
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1449
        runTask->signal &= ~SIGNAL_AFFI;//任务贴上被其他CPU媾和的标签
1450 1451

        /* pri-queue has updated, notify the target cpu */
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1452
        LOS_MpSchedule((UINT32)runTask->cpuAffiMask);//发生调度,此任务将移交给媾和CPU运行.
1453 1454 1455
#endif
    }
}
1456 1457

LITE_OS_SEC_TEXT INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName)
1458 1459 1460
{
    UINT32 intSave;
    errno_t err;
1461
    LosProcessCB *processCB = NULL;
1462 1463 1464
    const CHAR *namePtr = NULL;
    CHAR nameBuff[OS_TCB_NAME_LEN] = { 0 };

1465 1466 1467 1468 1469 1470 1471 1472 1473
    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;
        }
1474 1475 1476 1477 1478 1479 1480
        namePtr = nameBuff;
    } else {
        namePtr = name;
    }

    SCHEDULER_LOCK(intSave);

1481
    err = strncpy_s(taskCB->taskName, OS_TCB_NAME_LEN, (VOID *)namePtr, OS_TCB_NAME_LEN - 1);
1482 1483 1484 1485 1486
    if (err != EOK) {
        err = EINVAL;
        goto EXIT;
    }

1487 1488
    err = LOS_OK;
    processCB = OS_PCB_FROM_PID(taskCB->processID);
1489
    /* if thread is main thread, then set processName as taskName */
1490 1491 1492 1493 1494
    if ((taskCB->taskID == processCB->threadGroupID) && (setPName == TRUE)) {
        err = (INT32)OsSetProcessName(processCB, (const CHAR *)taskCB->taskName);
        if (err != LOS_OK) {
            err = EINVAL;
        }
1495 1496 1497 1498 1499 1500
    }

EXIT:
    SCHEDULER_UNLOCK(intSave);
    return err;
}
1501 1502 1503 1504 1505 1506

STATIC VOID OsExitGroupActiveTaskKilled(LosProcessCB *processCB, LosTaskCB *taskCB)
{
    INT32 ret;

    taskCB->taskStatus |= OS_TASK_FLAG_EXIT_KILL;
1507
#ifdef LOSCFG_KERNEL_SMP
1508 1509 1510 1511 1512 1513
    /* The other core that the thread is running on and is currently running in a non-system call */
    if (!taskCB->sig.sigIntLock && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
        taskCB->signal = SIGNAL_KILL;
        LOS_MpSchedule(taskCB->currCpu);
    } else
#endif
1514
#ifdef LOSCFG_KERNEL_VM
1515 1516 1517 1518 1519 1520 1521
    {
        ret = OsTaskKillUnsafe(taskCB->taskID, SIGKILL);
        if (ret != LOS_OK) {
            PRINT_ERR("pid %u exit, Exit task group %u kill %u failed! ERROR: %d\n",
                      taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, ret);
        }
    }
1522
#endif
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534

    if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
        taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
        LOS_ListInit(&taskCB->joinList);
    }

    ret = OsTaskJoinPendUnsafe(taskCB);
    if (ret != LOS_OK) {
        PRINT_ERR("pid %u exit, Exit task group %u to wait others task %u(0x%x) exit failed! ERROR: %d\n",
                  taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, taskCB->taskStatus, ret);
    }
}
1535
//1.当前进程中的任务集体退群, 2.当前进程贴上退出标签
1536 1537 1538 1539
LITE_OS_SEC_TEXT VOID OsTaskExitGroup(UINT32 status)
{
    UINT32 intSave;

1540 1541
    LosProcessCB *processCB = OsCurrProcessGet();
    LosTaskCB *currTask = OsCurrTaskGet();
1542
    SCHEDULER_LOCK(intSave);//调度自旋锁,这块锁的代码有点多,这块容易出问题!出问题也不好复现,希望鸿蒙有充分测试这块的功能. @note_thinking
1543
    if ((processCB->processStatus & OS_PROCESS_FLAG_EXIT) || !OsProcessIsUserMode(processCB)) {
1544 1545 1546 1547 1548
        SCHEDULER_UNLOCK(intSave);
        return;
    }

    processCB->processStatus |= OS_PROCESS_FLAG_EXIT;//贴上进程要退出的标签
1549
    processCB->threadGroupID = currTask->taskID;
1550

1551 1552
    LOS_DL_LIST *list = &processCB->threadSiblingList;
    LOS_DL_LIST *head = list;
1553
    do {
1554
        LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
1555 1556
        if ((taskCB->taskStatus & (OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT) ||
            ((taskCB->taskStatus & OS_TASK_STATUS_READY) && !taskCB->sig.sigIntLock)) &&
1557 1558
            !(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
            OsTaskDeleteInactive(processCB, taskCB);
1559
        } else {
1560 1561 1562 1563 1564
            if (taskCB != currTask) {
                OsExitGroupActiveTaskKilled(processCB, taskCB);
            } else {
                /* Skip the current task */
                list = list->pstNext;
1565 1566
            }
        }
1567
    } while (head != list->pstNext);
1568 1569 1570

    SCHEDULER_UNLOCK(intSave);

1571
    LOS_ASSERT(processCB->threadNumber == 1);//这一趟下来,进程只有一个正在活动的任务
1572 1573 1574 1575 1576
    return;
}
//任务退群并销毁,进入任务的回收链表之后再进入空闲链表,等着再次被分配使用.
LITE_OS_SEC_TEXT VOID OsExecDestroyTaskGroup(VOID)
{
1577
    OsTaskExitGroup(OS_PRO_EXIT_OK);//任务退出
1578
    OsTaskCBRecycleToFree();
1579 1580
}

1581 1582 1583
UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB)
{
    return OsUserProcessOperatePermissionsCheck(taskCB, OsCurrProcessGet()->processID);
1584 1585
}

1586
UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID)
1587 1588 1589 1590 1591
{
    if (taskCB == NULL) {
        return LOS_EINVAL;
    }

1592 1593 1594 1595
    if (processID == OS_INVALID_VALUE) {
        return OS_INVALID_VALUE;
    }

1596 1597 1598 1599
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        return LOS_EINVAL;
    }

1600
    if (processID != taskCB->processID) {
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
        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;
1616
    if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {//堆地址必须在用户空间
1617 1618 1619
        return OS_INVALID_VALUE;
    }

1620
    if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {//入口函数必须在用户空间
1621 1622
        return OS_INVALID_VALUE;
    }
1623
	//堆栈必须在用户空间
1624
    if (userParam->userMapBase && !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) {
1625 1626
        return OS_INVALID_VALUE;
    }
1627
	//检查堆,栈范围
1628
    if (!LOS_IsUserAddress(userParam->userSP)) {
1629 1630 1631 1632 1633
        return OS_INVALID_VALUE;
    }

    return LOS_OK;
}
1634
//创建一个用户态任务
1635
LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam)
1636 1637 1638 1639 1640 1641
{
    LosProcessCB *processCB = NULL;
    UINT32 taskID;
    UINT32 ret;
    UINT32 intSave;

1642
    ret = OsCreateUserTaskParamCheck(processID, initParam);//检查参数,堆栈,入口地址必须在用户空间
1643 1644 1645
    if (ret != LOS_OK) {
        return ret;
    }
1646
	//这里可看出一个任务有两个栈,内核态栈(内核指定栈大小)和用户态栈(用户指定栈大小)
1647
    initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE;
1648
    initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;//设置最低优先级 31级
1649 1650 1651 1652 1653 1654 1655 1656 1657
    initParam->policy = LOS_SCHED_RR;//调度方式为抢占式,注意鸿蒙不仅仅只支持抢占式调度方式
    if (processID == OS_INVALID_VALUE) {//外面没指定进程ID的处理
        SCHEDULER_LOCK(intSave);
        processCB = OsCurrProcessGet();//拿当前运行的进程
        initParam->processID = processCB->processID;//进程ID赋值
        initParam->consoleID = processCB->consoleID;//任务控制台ID归属
        SCHEDULER_UNLOCK(intSave);
    } else {//进程已经创建
        processCB = OS_PCB_FROM_PID(processID);//通过ID拿到进程PCB
1658
        if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//进程未初始化和未正在运行时
1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
            return OS_INVALID_VALUE;//@note_why 为什么这两种情况下会创建任务失败
        }
        initParam->processID = processID;//进程ID赋值
        initParam->consoleID = 0;//默认0号控制台
    }

    ret = LOS_TaskCreateOnly(&taskID, initParam);//只创建task实体,不申请调度
    if (ret != LOS_OK) {
        return OS_INVALID_VALUE;
    }

    return taskID;
}
//获取任务的调度方式
LITE_OS_SEC_TEXT INT32 LOS_GetTaskScheduler(INT32 taskID)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;
    INT32 policy;

    if (OS_TID_CHECK_INVALID(taskID)) {
        return -LOS_EINVAL;
    }

    taskCB = OS_TCB_FROM_TID(taskID);//通过任务ID获得任务TCB
    SCHEDULER_LOCK(intSave);
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//状态不能是没有在使用
        policy = -LOS_EINVAL;
        OS_GOTO_ERREND();
    }

    policy = taskCB->policy;//任务的调度方式

LOS_ERREND:
    SCHEDULER_UNLOCK(intSave);
    return policy;
}

//设置任务的调度信息
LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority)
{
    UINT32 intSave;
1701
    BOOL needSched = FALSE;
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714

    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;
    }

1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
    SCHEDULER_LOCK(intSave);
    needSched = OsSchedModifyTaskSchedParam(OS_TCB_FROM_TID(taskID), policy, priority);
    SCHEDULER_UNLOCK(intSave);

    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (needSched && OS_SCHEDULER_ACTIVE) {
        LOS_Schedule();
    }

    return LOS_OK;
1725
}
1726 1727 1728 1729 1730 1731

LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID)
{
    return g_taskMaxNum;
}

1732 1733 1734 1735
LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events)
{
    (VOID)LOS_EventWrite(&g_resourceEvent, events);
}
1736 1737 1738 1739 1740

LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events)
{
    (VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL);
}
1741 1742 1743 1744 1745 1746 1747 1748
//资源回收任务
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);//读取资源事件
1749
        if (ret & (OS_RESOURCE_EVENT_FREE | OS_RESOURCE_EVENT_OOM)) {//收到资源释放或内存异常情况
1750
            OsTaskCBRecycleToFree();
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1751
            OsProcessCBRecycleToFree();//回收进程到空闲进程池
1752 1753 1754 1755 1756 1757 1758 1759 1760 1761
        }

#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出监测任务开关
        if (ret & OS_RESOURCE_EVENT_OOM) {//触发了这个事件
            (VOID)OomCheckProcess();//检查进程的内存溢出情况
        }
#endif
    }
}
//创建一个回收资源的任务
1762
LITE_OS_SEC_TEXT UINT32 OsResourceFreeTaskCreate(VOID)
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
{
    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;//入口函数
1775
    taskInitParam.uwStackSize = OS_TASK_RESOURCE_STATIC_SIZE;
1776 1777
    taskInitParam.pcName = "ResourcesTask";
    taskInitParam.usTaskPrio = OS_TASK_RESOURCE_FREE_PRIORITY;// 5 ,优先级很高
1778 1779 1780 1781 1782
    ret = LOS_TaskCreate(&taskID, &taskInitParam);
    if (ret == LOS_OK) {
        OS_TCB_FROM_TID(taskID)->taskStatus |= OS_TASK_FLAG_NO_DELETE;
    }
    return ret;
1783 1784
}

鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1785
LOS_MODULE_INIT(OsResourceFreeTaskCreate, LOS_INIT_LEVEL_KMOD_TASK);//资源回收任务初始化