You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LiteOS-Reading/src/kernel/base/los_mp.c

211 lines
7.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
* Description: Muti-core processing
* Author: Huawei LiteOS Team
* Create: 2018-07-10
* 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.
* --------------------------------------------------------------------------- */
/*针对多处理器SMP系统的操作系统内核部分的实现
主要包括了多处理器调度、任务管理和中断处理等功能*/
#include "los_mp_pri.h"
#include "los_task_pri.h"
#include "los_percpu_pri.h"
#include "los_sched_pri.h"
#include "los_swtmr.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_KERNEL_SMP
#ifdef LOSCFG_KERNEL_SMP_CALL
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_mpCallSpin);
#define MP_CALL_LOCK(state) LOS_SpinLockSave(&g_mpCallSpin, &(state))
#define MP_CALL_UNLOCK(state) LOS_SpinUnlockRestore(&g_mpCallSpin, (state))
#endif
//LOS_MpSchedule多处理器调度函数用于向指定的处理器发送调度中断
VOID LOS_MpSchedule(UINT32 target)
{
UINT32 ret;
UINT32 cpuid = ArchCurrCpuid();
target &= ~(1U << cpuid);
ret = HalIrqSendIpi(target, LOS_MP_IPI_SCHEDULE);
if (ret != LOS_OK) {
return;
}
return;
}
//OsMpWakeHandler多处理器唤醒处理函数目前为空实现无特定操作
VOID OsMpWakeHandler(VOID)
{
/* generic wakeup ipi, do nothing */
}
//OsMpScheduleHandler多处理器调度处理函数设置调度标志以触发调度器在中断结束时执行调度
VOID OsMpScheduleHandler(VOID)
{
/*
* set schedule flag to differ from wake function,
* so that the scheduler can be triggered at the end of irq.
*/
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
}
//OsMpHaltHandler多处理器停机处理函数将当前处理器标记为已停机状态并进入死循环
VOID OsMpHaltHandler(VOID)
{
(VOID)LOS_IntLock();
OsPercpuGet()->excFlag = CPU_HALT;
while (1) {}
}
//OsMpCollectTasks多处理器任务回收函数用于递归检查所有可用任务并删除标记为需要销毁的任务
VOID OsMpCollectTasks(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 taskId = 0;
UINT32 ret;
/* recursive checking all the available task */
for (; taskId <= g_taskMaxNum; taskId++) {
taskCB = &g_taskCBArray[taskId];
if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED) ||
(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
continue;
}
/*
* though task status is not atomic, this check may success but not accomplish
* the deletion; this deletion will be handled until the next run.
*/
if (taskCB->signal & SIGNAL_KILL) {
ret = LOS_TaskDelete(taskId);
if (ret != LOS_OK) {
PRINT_WARN("GC collect task failed err:0x%x\n", ret);
}
}
}
}
#ifdef LOSCFG_KERNEL_SMP_CALL
//OsMpFuncCall多处理器函数调用函数用于向指定的处理器发送函数调用请求
VOID OsMpFuncCall(UINT32 target, SMP_FUNC_CALL func, VOID *args)
{
UINT32 index;
UINT32 intSave;
UINT32 ret;
if (func == NULL) {
return;
}
if (!(target & OS_MP_CPU_ALL)) {
return;
}
for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
if (CPUID_TO_AFFI_MASK(index) & target) {
MpCallFunc *mpCallFunc = (MpCallFunc *)LOS_MemAlloc(m_aucSysMem0, sizeof(MpCallFunc));
if (mpCallFunc == NULL) {
PRINT_ERR("smp func call malloc failed\n");
return;
}
mpCallFunc->func = func;
mpCallFunc->args = args;
MP_CALL_LOCK(intSave);
LOS_ListAdd(&g_percpu[index].funcLink, &(mpCallFunc->node));
MP_CALL_UNLOCK(intSave);
}
}
ret = HalIrqSendIpi(target, LOS_MP_IPI_FUNC_CALL);
if (ret != LOS_OK) {
return;
}
return;
}
//OsMpFuncCallHandler多处理器函数调用处理函数从本处理器的函数调用队列中取出并执行函数调用请求
VOID OsMpFuncCallHandler(VOID)
{
UINT32 intSave;
UINT32 cpuid = ArchCurrCpuid();
LOS_DL_LIST *list = NULL;
MpCallFunc* mpCallFunc = NULL;
MP_CALL_LOCK(intSave);
while (!LOS_ListEmpty(&g_percpu[cpuid].funcLink)) {
list = LOS_DL_LIST_FIRST(&g_percpu[cpuid].funcLink);
LOS_ListDelete(list);
MP_CALL_UNLOCK(intSave);
mpCallFunc = LOS_DL_LIST_ENTRY(list, MpCallFunc, node);
mpCallFunc->func(mpCallFunc->args);
(VOID)LOS_MemFree(m_aucSysMem0, mpCallFunc);
MP_CALL_LOCK(intSave);
}
MP_CALL_UNLOCK(intSave);
}
//OsMpFuncCallInit多处理器函数调用初始化函数用于初始化每个核心的函数调用队列
VOID OsMpFuncCallInit(VOID)
{
UINT32 index;
/* init funclink for each core */
for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
LOS_ListInit(&g_percpu[index].funcLink);
}
}
#endif /* LOSCFG_KERNEL_SMP_CALL */
//OsMpInit多处理器初始化函数包括创建周期性软件定时器和初始化函数调用队列等
UINT32 OsMpInit(VOID)
{
UINT16 swtmrId;
UINT32 ret;
ret = LOS_SwtmrCreate(OS_MP_GC_PERIOD, LOS_SWTMR_MODE_PERIOD,
(SWTMR_PROC_FUNC)OsMpCollectTasks, &swtmrId, 0);
if (ret != LOS_OK) {
PRINT_ERR("Swtmr Create failed err:0x%x\n", ret);
return ret;
}
ret = LOS_SwtmrStart(swtmrId);
if (ret != LOS_OK) {
PRINT_ERR("Swtmr Start failed err:0x%x\n", ret);
return ret;
}
#ifdef LOSCFG_KERNEL_SMP_CALL
OsMpFuncCallInit();
#endif
return LOS_OK;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */