los_task.c 67.3 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
        }
    }
    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;
    }

228 229 230 231
    if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) {
        return LOS_OK;
    }

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

    return LOS_EINVAL;
}
239
///任务设置分离模式  Deatch和JOIN是一对有你没我的状态
240
LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB)
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标签
            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
///获取IdletaskId,每个CPU核都对Task进行了内部管理,做到真正的并行处理
297 298 299 300 301
UINT32 OsGetIdleTaskId(VOID)
{
    Percpu *perCpu = OsPercpuGet();//获取当前Cpu信息
    return perCpu->idleTaskID;//返回当前CPU 空闲任务ID
}
302
///创建一个空闲任务
303 304 305 306
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
{
    LosTaskCB *runTask = OsCurrTaskGet();

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

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 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
STATIC INLINE UINT32 OsTaskSyncCreate(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 peroid.
     */
    if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) {
        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 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);
        }
    }

#ifdef LOSCFG_KERNEL_VM
    if (processCB->processMode == OS_USER_MODE) {
        OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
    }
#endif

    OsTaskJoinPostUnsafe(taskCB);

    OsTaskSyncWake(taskCB);
}
423
///一个任务的退出过程
424 425 426 427
LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status)
{
    UINT32 intSave;

428 429
    LosProcessCB *runProcess = OS_PCB_FROM_PID(taskCB->processID);
    LosTaskCB *mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID);
430 431 432 433 434 435 436 437 438 439 440
    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;
    }

441
    if ((taskCB->taskStatus & OS_TASK_FLAG_EXIT_KILL) || !(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
442 443
        UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave);
        LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret);
444
        return;
445 446
    }

447 448
    OsTaskReleaseHoldLock(runProcess, taskCB);

449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
    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.
     */
469 470
    LOS_SpinUnlock(&g_taskSpin);//释放任务自旋锁
    (VOID)LOS_IntUnLock();//恢复中断
471 472 473 474

    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 */
475
    if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
476 477 478 479 480
        taskCB->joinRetval = 0;//结合数为0
    }
	
    OsTaskToExit(taskCB, 0);//到这里任务跑完了要退出了
}
481
///任务创建参数检查
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
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;
        }
    }

508
    if (initParam->pfnTaskEntry == NULL) {//入口函数不能为空
509 510 511
        return LOS_ERRNO_TSK_ENTRY_NULL;
    }

512
    if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) {//优先级必须大于31
513 514 515
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }

516
    if (initParam->uwStackSize > poolSize) {//希望申请的栈大小不能大于总池子
517 518 519
        return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
    }

520
    if (initParam->uwStackSize == 0) {//任何任务都必须由内核态栈,所以uwStackSize不能为0
521 522 523 524
        initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    }
    initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);

525
    if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) {//运行栈空间不能低于最低值
526 527 528 529 530
        return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
    }

    return LOS_OK;
}
531
///任务栈(内核态)内存分配,由内核态进程空间提供,即 KProcess 的进程空间
532 533 534 535 536 537 538 539 540 541 542 543 544 545
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 VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack)
{
    VOID *poolTmp = (VOID *)m_aucSysMem1;

    OsTaskSyncDestroy(syncSignal);

    (VOID)LOS_MemFree(poolTmp, (VOID *)topOfStack);
}
546
///从回收链表中回收任务到空闲链表
547
LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree()
548 549 550 551 552
{
    LosTaskCB *taskCB = NULL;
    UINT32 intSave;

    SCHEDULER_LOCK(intSave);
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
553 554
    while (!LOS_ListEmpty(&g_taskRecycleList)) {//不空就一个一个回收任务
        taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList));//取出第一个待回收任务
555 556 557 558 559 560 561 562 563 564 565 566 567
        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;
568 569
    UINT32 intSave;
    UINTPTR topOfStack;
570

571 572 573
#ifdef LOSCFG_KERNEL_VM
    LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
    if (OsProcessIsUserMode(processCB) && (taskCB->userMapBase != 0)) {
574
        SCHEDULER_LOCK(intSave);
575 576
        UINT32 mapBase = (UINTPTR)taskCB->userMapBase;
        UINT32 mapSize = taskCB->userMapSize;
577 578 579 580 581
        taskCB->userMapBase = 0;
        taskCB->userArea = 0;
        SCHEDULER_UNLOCK(intSave);

        LOS_ASSERT(!(processCB->vmSpace == NULL));
582
        UINT32 ret = OsUnMMap(processCB->vmSpace, (UINTPTR)mapBase, mapSize);
583 584 585 586 587
        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);
        }

588
#ifdef LOSCFG_KERNEL_LITEIPC
589 590 591
        LiteIpcRemoveServiceHandle(taskCB);
#endif
    }
592
#endif
593 594 595 596

    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        topOfStack = taskCB->topOfStack;
        taskCB->topOfStack = 0;
597
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
598 599 600 601 602 603
        syncSignal = taskCB->syncSignal;
        taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT;
#endif
        OsTaskKernelResourcesToFree(syncSignal, topOfStack);

        SCHEDULER_LOCK(intSave);
604
        OsClearSigInfoTmpList(&(taskCB->sig));
605 606 607 608 609
        OsInsertTCBToFreeList(taskCB);
        SCHEDULER_UNLOCK(intSave);
    }
    return;
}
610
///任务基本信息的初始化
611 612 613 614 615
LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
                                                   const VOID *stackPtr,
                                                   const VOID *topStack,
                                                   const TSK_INIT_PARAM_S *initParam)
{
616
    taskCB->stackPointer = (VOID *)stackPtr;//内核态SP位置
617 618 619 620
    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];
621
    taskCB->topOfStack   = (UINTPTR)topStack;	//内核态栈顶
622 623 624 625 626
    taskCB->stackSize    = initParam->uwStackSize;//
    taskCB->priority     = initParam->usTaskPrio;
    taskCB->taskEntry    = initParam->pfnTaskEntry;
    taskCB->signal       = SIGNAL_NONE;

627
#ifdef LOSCFG_KERNEL_SMP
628 629 630 631
    taskCB->currCpu      = OS_TASK_INVALID_CPUID;
    taskCB->cpuAffiMask  = (initParam->usCpuAffiMask) ?
                            initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK;
#endif
632
#ifdef LOSCFG_KERNEL_LITEIPC
633 634
    LOS_ListInit(&(taskCB->msgListHead));//初始化 liteipc的消息链表 
#endif
635
    taskCB->policy = (initParam->policy == LOS_SCHED_FIFO) ? LOS_SCHED_FIFO : LOS_SCHED_RR;//调度模式
636 637 638
    taskCB->taskStatus = OS_TASK_STATUS_INIT;
    if (initParam->uwResved & LOS_TASK_ATTR_JOINABLE) {
        taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
639
        LOS_ListInit(&taskCB->joinList);
640 641 642
    }

    taskCB->futex.index = OS_INVALID_VALUE;
643
    LOS_ListInit(&taskCB->lockList);//初始化互斥锁链表
644
    SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
645
}
646
///任务初始化
647 648
STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam,
                           const VOID *stackPtr, const VOID *topStack)
649 650 651 652 653 654 655
{
    UINT32 intSave;
    UINT32 ret;
    UINT32 numCount;
    UINT16 mode;
    LosProcessCB *processCB = NULL;

656
    OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam);//初始化任务的基本信息,
657
    					//taskCB->stackPointer指向内核态栈 sp位置,该位置存着 任务初始上下文
658 659 660 661

    SCHEDULER_LOCK(intSave);
    processCB = OS_PCB_FROM_PID(initParam->processID);//通过ID获取PCB ,单核进程数最多64个
    taskCB->processID = processCB->processID;//进程-线程的父子关系绑定
662
    mode = processCB->processMode;//模式方式同步process
663
    LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList));//挂入进程的线程链表
664
    if (mode == OS_USER_MODE) {//任务支持用户态时,将改写 taskCB->stackPointer = initParam->userParam.userSP
665 666 667
        taskCB->userArea = initParam->userParam.userArea;
        taskCB->userMapBase = initParam->userParam.userMapBase;
        taskCB->userMapSize = initParam->userParam.userMapSize;
668
        OsUserTaskStackInit(taskCB->stackPointer, (UINTPTR)taskCB->taskEntry, initParam->userParam.userSP);//初始化用户态任务栈
669
        //这里要注意,任务的上下文是始终保存在内核栈空间,而用户态时运行在用户态栈空间.(context->SP = userSP 指向了用户态栈空间)
670 671 672 673 674 675 676 677 678 679 680
    }

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

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

681 682 683 684
    if (initParam->pcName != NULL) {
        ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE);
        if (ret == LOS_OK) {
            return LOS_OK;
685 686 687
        }
    }

688 689 690
    if (snprintf_s(taskCB->taskName, OS_TCB_NAME_LEN, OS_TCB_NAME_LEN - 1, "thread%u", numCount) < 0) {
        return LOS_NOK;
    }
691 692
    return LOS_OK;
}
693
///获取一个空闲TCB
694 695 696 697 698 699 700 701 702
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");
703 704 705
#ifdef LOSCFG_DEBUG_VERSION
	(VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL);
#endif
706 707 708 709 710 711 712 713 714
        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;
}
715
///创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
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中被调用,此处是分配任务在内核态栈空间 
740
    OsTaskStackAlloc(&topStack, initParam->uwStackSize, pool);//为任务分配内核栈空间,注意此内存来自系统内核空间
741 742 743 744 745
    if (topStack == NULL) {
        errRet = LOS_ERRNO_TSK_NO_MEMORY;
        goto LOS_ERREND_REWIND_SYNC;
    }

746
    stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);//初始化内核态任务栈,返回栈SP位置
747 748 749 750
    errRet = OsTaskCBInit(taskCB, initParam, stackPtr, topStack);//初始化TCB,包括绑定进程等操作
    if (errRet != LOS_OK) {
        goto LOS_ERREND_TCB_INIT;
    }
751
    if (OsConsoleIDSetHook != NULL) {//每个任务都可以有属于自己的控制台
752 753 754 755
        OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID);//设置控制台ID
    }

    *taskID = taskCB->taskID;
756
    OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB);
757 758 759 760 761
    return LOS_OK;

LOS_ERREND_TCB_INIT:
    (VOID)LOS_MemFree(pool, topStack);
LOS_ERREND_REWIND_SYNC:
762
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
763 764 765 766 767 768 769 770 771
    OsTaskSyncDestroy(taskCB->syncSignal);
#endif
LOS_ERREND_REWIND_TCB:
    SCHEDULER_LOCK(intSave);
    OsInsertTCBToFreeList(taskCB);//归还freetask
    SCHEDULER_UNLOCK(intSave);
LOS_ERREND:
    return errRet;
}
772
///创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务
773 774 775 776 777 778 779 780 781 782 783 784 785 786
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;
    }

787 788
    if (OsProcessIsUserMode(OsCurrProcessGet())) {
        initParam->processID = OsGetKernelInitProcessID();
789
    } else {
790
        initParam->processID = OsCurrProcessGet()->processID;
791 792
    }

793
    ret = LOS_TaskCreateOnly(taskID, initParam);
794 795 796
    if (ret != LOS_OK) {
        return ret;
    }
797
    taskCB = OS_TCB_FROM_TID(*taskID);
798 799

    SCHEDULER_LOCK(intSave);
800
    OsSchedTaskEnQueue(taskCB);
801 802 803 804
    SCHEDULER_UNLOCK(intSave);

    /* in case created task not running on this core,
       schedule or not depends on other schedulers status. */
805 806 807
    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (OS_SCHEDULER_ACTIVE) {
        LOS_Schedule();
808 809 810 811
    }

    return LOS_OK;
}
812
///恢复挂起的任务,使该任务进入ready状态
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
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;//清楚挂起信号

830
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
831 832
        errRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
833
    } else if (!(taskCB->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
834 835 836 837
        errRet = LOS_ERRNO_TSK_NOT_SUSPENDED;
        OS_GOTO_ERREND();
    }

838
    taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPENDED;
839
    if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
840 841
        OsSchedTaskEnQueue(taskCB);
        if (OS_SCHEDULER_ACTIVE) {
842 843 844 845 846
            needSched = TRUE;
        }
    }
    SCHEDULER_UNLOCK(intSave);

847 848
    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (needSched) {
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
        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;

873
#ifdef LOSCFG_KERNEL_SMP
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
    /* 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;
}
896
///任务暂停,参数可以不是当前任务,也就是说 A任务可以让B任务处于阻塞状态,挂起指定的任务,然后切换任务
897 898 899 900 901 902 903 904 905 906
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;
    }

907
    if (tempStatus & OS_TASK_STATUS_SUSPENDED) {
908 909 910 911 912 913 914 915
        return LOS_ERRNO_TSK_ALREADY_SUSPENDED;
    }

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

916 917
    if (tempStatus & OS_TASK_STATUS_READY) {
        OsSchedTaskDeQueue(taskCB);
918 919
    }

920
    taskCB->taskStatus |= OS_TASK_STATUS_SUSPENDED;
921
    OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
922 923
    if (taskCB == OsCurrTaskGet()) {
        OsSchedResched();
924 925 926 927
    }

    return LOS_OK;
}
928
///外部接口,对OsTaskSuspend的封装
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
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;
}
949
///设置任务为不使用状态
950 951 952 953 954 955 956 957
STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB *taskCB)
{
    taskCB->taskStatus |= OS_TASK_STATUS_UNUSED;
    taskCB->eventMask = 0;

    OS_MEM_CLEAR(taskCB->taskID);
}

958
//删除一个正在运行的任务
959
LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask)
960
{
961 962 963
    LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID);//拿到task所属进程
    OsTaskReleaseHoldLock(processCB, runTask);//task还锁
    OsTaskStatusUnusedSet(runTask);//task重置为未使用状态,等待回收
964

965
    LOS_ListDelete(&runTask->threadList);//从进程的线程链表中将自己摘除
966
    processCB->threadNumber--;//进程的活动task --,注意进程还有一个记录总task的变量 processCB->threadCount
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
967
    LOS_ListTailInsert(&g_taskRecycleList, &runTask->pendList);//将task插入回收链表,等待回收资源再利用
968
    OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);//发送释放资源的事件,事件由 OsResourceRecoveryTask 消费
969 970 971 972

    OsSchedResched();//申请调度
    return;
}
973 974 975 976 977 978 979 980 981 982
/**
 * @brief 获取参数位图中最高位为1的索引位 例如: 00110110 返回 5
 * @verbatim
    CLZ 用于计算操作数最高端0的个数,这条指令主要用于以下两个场合
      1.计算操作数规范化(使其最高位为1)时需要左移的位数
      2.确定一个优先级掩码中最高优先级
 * @endverbatim
 * @param bitmap 
 * @return UINT16 
 */
983 984 985 986 987 988 989 990 991
/*
 * 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.
 */
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006

/**
 * @brief 
 * @verbatim
    检查是否需要对正在运行的任务执行删除操作,如果需要删除,则返回TRUE。
    如果满足以下情况,则返回FALSE:
    1.如果启用了SMP,则跨CPU执行删除
    2.禁用抢占时执行删除
    3.在硬irq中删除
    然后LOS_TaskDelete将直接返回ret值
 * @endverbatim
 * @param taskCB 
 * @param ret 
 * @return STATIC 
 */
1007 1008 1009 1010 1011
STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret)
{
    /* init default out return value */
    *ret = LOS_OK;

1012
#ifdef LOSCFG_KERNEL_SMP
1013 1014
    /* ASYNCHRONIZED. No need to do task lock checking *///异步操作,不需要进行任务锁检查
    if (taskCB->currCpu != ArchCurrCpuid()) {//任务运行在其他CPU,跨核心执行删除
1015 1016 1017 1018 1019
        /*
         * 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.
         */
1020 1021 1022
        taskCB->signal = SIGNAL_KILL;	//贴上干掉标记
        LOS_MpSchedule(taskCB->currCpu);//通知任务所属CPU发生调度
        *ret = OsTaskSyncWait(taskCB);	//同步等待可怜的任务被干掉
1023 1024 1025 1026
        return FALSE;
    }
#endif

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

1033
    if (OS_INT_ACTIVE) {//硬中断进行中...会屏蔽掉所有信号,当然包括kill了
1034 1035 1036 1037
        /*
         * delete running task in interrupt.
         * mask "kill" signal and later deletion will be handled.
         */
1038
        taskCB->signal = SIGNAL_KILL;//硬中断后将处理删除。
1039 1040 1041 1042 1043
        return FALSE;
    }

    return TRUE;
}
1044
///删除不活动的任务 !OS_TASK_STATUS_RUNNING 
1045 1046
STATIC VOID OsTaskDeleteInactive(LosProcessCB *processCB, LosTaskCB *taskCB)
{
1047
    LosMux *mux = (LosMux *)taskCB->taskMux; //任务
1048
    UINT16 taskStatus = taskCB->taskStatus;
1049

1050
    LOS_ASSERT(!(taskStatus & OS_TASK_STATUS_RUNNING));
1051

1052
    OsTaskReleaseHoldLock(processCB, taskCB);
1053

1054 1055 1056 1057
    OsSchedTaskExit(taskCB);
    if (taskStatus & OS_TASK_STATUS_PENDING) {
        if (LOS_MuxIsValid(mux) == TRUE) {
            OsMuxBitmapRestore(mux, taskCB, (LosTaskCB *)mux->owner);
1058 1059 1060
        }
    }

1061
    OsTaskStatusUnusedSet(taskCB);
1062

1063 1064
    LOS_ListDelete(&taskCB->threadList);
    processCB->threadNumber--;
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1065
    LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList);
1066 1067
    return;
}
1068
///以不安全的方式删除参数任务
1069 1070 1071 1072 1073 1074
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;

1075
    if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {//系统任务是不能被删除的, 请您说出3个系统任务.
1076 1077 1078 1079
        errRet = LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
        goto EXIT;
    }

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

1084 1085 1086 1087 1088
    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 的处理
1089
    }
1090
    OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB);
1091 1092 1093
    if (mode == OS_USER_MODE) { //用户态模式
        SCHEDULER_UNLOCK(intSave);//先释放锁
        OsTaskResourcesToFree(taskCB);//释放任务资源
1094 1095 1096
        SCHEDULER_LOCK(intSave);
    }

1097
#ifdef LOSCFG_KERNEL_SMP
1098 1099 1100 1101
    LOS_ASSERT(OsPercpuGet()->taskLockCnt == 1);
#else
    LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0);
#endif
1102
    OsRunTaskToDelete(taskCB);//删除一个正在运行的任务
1103 1104 1105 1106 1107

EXIT:
    SCHEDULER_UNLOCK(intSave);
    return errRet;
}
1108
///删除指定的任务,回归任务池
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
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();
    }

1131 1132 1133 1134 1135
    if (taskCB->taskStatus & (OS_TASK_FLAG_SYSTEM_TASK | OS_TASK_FLAG_NO_DELETE)) {
        SCHEDULER_UNLOCK(intSave);
        OsBackTrace();
        return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK;
    }
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
    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;
}
1154
///任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
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;
    }
1174
    OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick);
1175 1176
    if (tick == 0) {
        return LOS_TaskYield();
1177 1178
    }

1179 1180
    SCHEDULER_LOCK(intSave);
    OsSchedDelay(runTask, tick);
1181
    OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask);
1182 1183
    SCHEDULER_UNLOCK(intSave);

1184 1185
    return LOS_OK;
}
1186
///获取任务的优先级
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
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;
}
1208
///设置指定任务的优先级
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
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);
1228
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
1229 1230 1231 1232
        SCHEDULER_UNLOCK(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

1233
    BOOL isReady = OsSchedModifyTaskSchedParam(taskCB, taskCB->policy, taskPrio);
1234
    SCHEDULER_UNLOCK(intSave);
1235 1236 1237

    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (isReady && OS_SCHEDULER_ACTIVE) {
1238 1239 1240 1241
        LOS_Schedule();
    }
    return LOS_OK;
}
1242
///设置当前任务的优先级
1243 1244 1245 1246 1247
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio)
{
    return LOS_TaskPriSet(OsCurrTaskGet()->taskID, taskPrio);
}

1248
//当前任务释放CPU,并将其移到具有相同优先级的就绪任务队列的末尾. 读懂这个函数 你就彻底搞懂了 yield
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
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;
    }

1261
    LosTaskCB *runTask = OsCurrTaskGet();
1262 1263 1264 1265 1266 1267
    if (OS_TID_CHECK_INVALID(runTask->taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    SCHEDULER_LOCK(intSave);
    /* reset timeslice of yeilded task */
1268
    OsSchedYield();
1269 1270 1271
    SCHEDULER_UNLOCK(intSave);
    return LOS_OK;
}
1272

1273 1274 1275 1276
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
{
    UINT32 intSave;

1277 1278 1279
    intSave = LOS_IntLock();
    OsCpuSchedLock(OsPercpuGet());
    LOS_IntRestore(intSave);
1280
}
1281

1282 1283
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
{
1284
    OsCpuSchedUnlock(OsPercpuGet(), LOS_IntLock());
1285
}
1286

1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
//获取任务信息,给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;
1316
    taskInfo->uwStackSize = taskCB->stackSize;	//内核态栈大小
1317
    taskInfo->uwTopOfStack = taskCB->topOfStack;//内核态栈顶位置
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
    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;
}
1337
///CPU亲和性(affinity)将任务绑在指定CPU上,用于多核CPU情况,(该函数仅在SMP模式下支持)
1338
LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask)
1339
{
1340
#ifdef LOSCFG_KERNEL_SMP
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
    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)
{
1359 1360
    LosTaskCB *taskCB = NULL;
    BOOL needSched = FALSE;
1361
    UINT32 intSave;
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
    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;
    }
1378
    needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuAffiMask, &currCpuMask);
1379 1380 1381 1382

    SCHEDULER_UNLOCK(intSave);

    if (needSched && OS_SCHEDULER_ACTIVE) {
1383
        LOS_MpSchedule(currCpuMask);//发送信号调度信号给目标CPU
1384 1385
        LOS_Schedule();//申请调度
    }
1386

1387 1388
    return LOS_OK;
}
1389
///查询任务被绑在哪个CPU上
1390 1391
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
{
1392
#ifdef LOSCFG_KERNEL_SMP
1393 1394 1395 1396 1397 1398 1399 1400 1401
#define INVALID_CPU_AFFI_MASK   0
    LosTaskCB *taskCB = NULL;
    UINT16 cpuAffiMask;
    UINT32 intSave;

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

1402
    taskCB = OS_TCB_FROM_TID(taskID);//获取任务实体
1403
    SCHEDULER_LOCK(intSave);
1404
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { //任务必须在使用
1405 1406 1407 1408
        SCHEDULER_UNLOCK(intSave);
        return INVALID_CPU_AFFI_MASK;
    }

1409
    cpuAffiMask = taskCB->cpuAffiMask; //获取亲和力掩码
1410 1411 1412 1413 1414
    SCHEDULER_UNLOCK(intSave);

    return cpuAffiMask;
#else
    (VOID)taskID;
1415
    return 1;//单核情况直接返回1 ,0号cpu对应0x01
1416 1417 1418 1419 1420
#endif
}

/*
 * Description : Process pending signals tagged by others cores
1421 1422 1423 1424 1425
 */
 /******************************************************
 	由其他CPU核触发阻塞进程的信号
	函数由汇编代码调用 ..\arch\arm\arm\src\los_dispatch.S
 ******************************************************/
1426
LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID)
1427 1428
{
    UINT32 intSave, ret;
1429
	//私有且不可中断,无需保护。这个任务在其他CPU核看到它时总是在运行,所以它在执行代码的同时也可以继续接收信号
1430 1431 1432 1433 1434
    /*
     * 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.
     */
1435 1436 1437
    LosTaskCB *runTask = OsCurrTaskGet();
    if (runTask->signal == SIGNAL_NONE) {
        return;
1438 1439
    }

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

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

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

LITE_OS_SEC_TEXT INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName)
1467 1468 1469
{
    UINT32 intSave;
    errno_t err;
1470
    LosProcessCB *processCB = NULL;
1471 1472 1473
    const CHAR *namePtr = NULL;
    CHAR nameBuff[OS_TCB_NAME_LEN] = { 0 };

1474 1475 1476 1477 1478 1479 1480 1481 1482
    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;
        }
1483 1484 1485 1486 1487 1488 1489
        namePtr = nameBuff;
    } else {
        namePtr = name;
    }

    SCHEDULER_LOCK(intSave);

1490
    err = strncpy_s(taskCB->taskName, OS_TCB_NAME_LEN, (VOID *)namePtr, OS_TCB_NAME_LEN - 1);
1491 1492 1493 1494 1495
    if (err != EOK) {
        err = EINVAL;
        goto EXIT;
    }

1496 1497
    err = LOS_OK;
    processCB = OS_PCB_FROM_PID(taskCB->processID);
1498
    /* if thread is main thread, then set processName as taskName */
1499 1500 1501 1502 1503
    if ((taskCB->taskID == processCB->threadGroupID) && (setPName == TRUE)) {
        err = (INT32)OsSetProcessName(processCB, (const CHAR *)taskCB->taskName);
        if (err != LOS_OK) {
            err = EINVAL;
        }
1504 1505 1506 1507 1508 1509
    }

EXIT:
    SCHEDULER_UNLOCK(intSave);
    return err;
}
1510 1511 1512 1513 1514 1515

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

    taskCB->taskStatus |= OS_TASK_FLAG_EXIT_KILL;
1516
#ifdef LOSCFG_KERNEL_SMP
1517 1518 1519 1520 1521 1522
    /* 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
1523
#ifdef LOSCFG_KERNEL_VM
1524 1525 1526 1527 1528 1529 1530
    {
        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);
        }
    }
1531
#endif
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543

    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);
    }
}
1544
///1.当前进程中的任务集体退群, 2.当前进程贴上退出标签
1545 1546 1547 1548
LITE_OS_SEC_TEXT VOID OsTaskExitGroup(UINT32 status)
{
    UINT32 intSave;

1549 1550
    LosProcessCB *processCB = OsCurrProcessGet();
    LosTaskCB *currTask = OsCurrTaskGet();
1551
    SCHEDULER_LOCK(intSave);//调度自旋锁,这块锁的代码有点多,这块容易出问题!出问题也不好复现,希望鸿蒙有充分测试这块的功能. @note_thinking
1552
    if ((processCB->processStatus & OS_PROCESS_FLAG_EXIT) || !OsProcessIsUserMode(processCB)) {
1553 1554 1555 1556 1557
        SCHEDULER_UNLOCK(intSave);
        return;
    }

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

1560 1561
    LOS_DL_LIST *list = &processCB->threadSiblingList;
    LOS_DL_LIST *head = list;
1562
    do {
1563
        LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
1564 1565
        if ((taskCB->taskStatus & (OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT) ||
            ((taskCB->taskStatus & OS_TASK_STATUS_READY) && !taskCB->sig.sigIntLock)) &&
1566 1567
            !(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
            OsTaskDeleteInactive(processCB, taskCB);
1568
        } else {
1569 1570 1571 1572 1573
            if (taskCB != currTask) {
                OsExitGroupActiveTaskKilled(processCB, taskCB);
            } else {
                /* Skip the current task */
                list = list->pstNext;
1574 1575
            }
        }
1576
    } while (head != list->pstNext);
1577 1578 1579

    SCHEDULER_UNLOCK(intSave);

1580
    LOS_ASSERT(processCB->threadNumber == 1);//这一趟下来,进程只有一个正在活动的任务
1581 1582
    return;
}
1583
///任务退群并销毁,进入任务的回收链表之后再进入空闲链表,等着再次被分配使用.
1584 1585
LITE_OS_SEC_TEXT VOID OsExecDestroyTaskGroup(VOID)
{
1586
    OsTaskExitGroup(OS_PRO_EXIT_OK);//任务退出
1587
    OsTaskCBRecycleToFree();
1588 1589
}

1590 1591 1592
UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB)
{
    return OsUserProcessOperatePermissionsCheck(taskCB, OsCurrProcessGet()->processID);
1593 1594
}

1595
UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID)
1596 1597 1598 1599 1600
{
    if (taskCB == NULL) {
        return LOS_EINVAL;
    }

1601 1602 1603 1604
    if (processID == OS_INVALID_VALUE) {
        return OS_INVALID_VALUE;
    }

1605 1606 1607 1608
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        return LOS_EINVAL;
    }

1609
    if (processID != taskCB->processID) {
1610 1611 1612 1613 1614
        return LOS_EPERM;
    }

    return LOS_OK;
}
1615
///创建任务之前,检查用户态任务栈的参数,是否地址在用户空间
1616 1617 1618 1619 1620 1621 1622 1623 1624
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;
1625
    if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {//堆地址必须在用户空间
1626 1627 1628
        return OS_INVALID_VALUE;
    }

1629
    if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {//入口函数必须在用户空间
1630 1631
        return OS_INVALID_VALUE;
    }
1632
	//堆栈必须在用户空间
1633
    if (userParam->userMapBase && !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) {
1634 1635
        return OS_INVALID_VALUE;
    }
1636
	//检查堆,栈范围
1637
    if (!LOS_IsUserAddress(userParam->userSP)) {
1638 1639 1640 1641 1642
        return OS_INVALID_VALUE;
    }

    return LOS_OK;
}
1643
///创建一个用户态任务
1644
LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam)
1645 1646 1647 1648 1649 1650
{
    LosProcessCB *processCB = NULL;
    UINT32 taskID;
    UINT32 ret;
    UINT32 intSave;

1651
    ret = OsCreateUserTaskParamCheck(processID, initParam);//检查参数,堆栈,入口地址必须在用户空间
1652 1653 1654
    if (ret != LOS_OK) {
        return ret;
    }
1655
	//这里可看出一个任务有两个栈,内核态栈(内核指定栈大小)和用户态栈(用户指定栈大小)
1656
    initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE;
1657
    initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;//设置最低优先级 31级
1658 1659 1660 1661 1662 1663 1664 1665 1666
    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
1667
        if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//进程未初始化和未正在运行时
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
            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;
}
1681
///获取任务的调度方式
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
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;
1710
    BOOL needSched = FALSE;
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723

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

1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
    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;
1734
}
1735

1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
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;
    }

    if (taskID == OsCurrTaskGet()->taskID) {
        return LOS_EDEADLK;
    }
    return LOS_OK;
}

UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval)
{
    UINT32 intSave;
    LosTaskCB *runTask = OsCurrTaskGet();
    LosTaskCB *taskCB = NULL;
    UINT32 errRet;

    errRet = OsTaskJoinCheck(taskID);
    if (errRet != LOS_OK) {
        return errRet;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    SCHEDULER_LOCK(intSave);
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        SCHEDULER_UNLOCK(intSave);
        return LOS_EINVAL;
    }

    if (runTask->processID != taskCB->processID) {
        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();
    LosTaskCB *taskCB = NULL;
    UINT32 errRet;

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

    if (OS_INT_ACTIVE) {
        return LOS_EINTR;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    SCHEDULER_LOCK(intSave);
    if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        SCHEDULER_UNLOCK(intSave);
        return LOS_EINVAL;
    }

    if (runTask->processID != taskCB->processID) {
        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;
}

1834 1835 1836 1837 1838
LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID)
{
    return g_taskMaxNum;
}

1839 1840 1841 1842
LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events)
{
    (VOID)LOS_EventWrite(&g_resourceEvent, events);
}
1843 1844 1845 1846 1847

LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events)
{
    (VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL);
}
1848
///资源回收任务
1849 1850 1851 1852 1853 1854 1855
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);//读取资源事件
1856
        if (ret & (OS_RESOURCE_EVENT_FREE | OS_RESOURCE_EVENT_OOM)) {//收到资源释放或内存异常情况
1857
            OsTaskCBRecycleToFree();
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
1858
            OsProcessCBRecycleToFree();//回收进程到空闲进程池
1859 1860 1861 1862 1863 1864 1865 1866 1867
        }

#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK //内存溢出监测任务开关
        if (ret & OS_RESOURCE_EVENT_OOM) {//触发了这个事件
            (VOID)OomCheckProcess();//检查进程的内存溢出情况
        }
#endif
    }
}
1868
///创建一个回收资源的任务
1869
LITE_OS_SEC_TEXT UINT32 OsResourceFreeTaskCreate(VOID)
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
{
    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;//入口函数
1882
    taskInitParam.uwStackSize = OS_TASK_RESOURCE_STATIC_SIZE;
1883 1884
    taskInitParam.pcName = "ResourcesTask";
    taskInitParam.usTaskPrio = OS_TASK_RESOURCE_FREE_PRIORITY;// 5 ,优先级很高
1885 1886 1887 1888 1889
    ret = LOS_TaskCreate(&taskID, &taskInitParam);
    if (ret == LOS_OK) {
        OS_TCB_FROM_TID(taskID)->taskStatus |= OS_TASK_FLAG_NO_DELETE;
    }
    return ret;
1890 1891
}

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