更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_mp.c 文件参考

浏览源代码.

函数

LITE_OS_SEC_BSS SPIN_LOCK_INIT (g_mpCallSpin)
 
VOID LOS_MpSchedule (UINT32 target)
 
VOID OsMpWakeHandler (VOID)
 硬中断唤醒处理函数 更多...
 
VOID OsMpScheduleHandler (VOID)
 硬中断调度处理函数 更多...
 
VOID OsMpHaltHandler (VOID)
 硬中断暂停处理函数 更多...
 
VOID OsMpCollectTasks (VOID)
 MP定时器处理函数, 递归检查所有可用任务 更多...
 
VOID OsMpFuncCall (UINT32 target, SMP_FUNC_CALL func, VOID *args)
 OsMpFuncCall 向指定CPU的funcLink上注册回调函数, 该怎么理解这个函数呢 ? 具体有什么用呢 ?
可由CPU a核向b核发起一个请求,让b核去执行某个函数, 这是否是分布式调度的底层实现基础 ? 更多...
 
VOID OsMpFuncCallHandler (VOID)
 OsMpFuncCallHandler
回调向当前CPU注册过的函数 更多...
 
VOID OsMpFuncCallInit (VOID)
 CPU层级的回调模块初始化 更多...
 
UINT32 OsMpInit (VOID)
 
 LOS_MODULE_INIT (OsMpInit, LOS_INIT_LEVEL_KMOD_TASK)
 

详细描述

    多CPU核的操作系统3种处理模式(SMP+AMP+BMP) 鸿蒙实现的是 SMP 的方式
    非对称多处理(Asymmetric multiprocessing,AMP)每个CPU内核
    运行一个独立的操作系统或同一操作系统的独立实例(instantiation)。
    
    对称多处理(Symmetric multiprocessing,SMP)一个操作系统的实例
    可以同时管理所有CPU内核,且应用并不绑定某一个内核。
    
    混合多处理(Bound multiprocessing,BMP)一个操作系统的实例可以
    同时管理所有CPU内核,但每个应用被锁定于某个指定的核心。

   多核多线程处理器的中断
    由 PIC(Programmable Interrupt Controller)统一控制。PIC 允许一个
    硬件线程中断其他的硬件线程,这种方式被称为核间中断(Inter-Processor Interrupts,IPI)
    
   SGI:软件触发中断(Software Generated Interrupt)。在arm处理器中,
    SGI共有16个,硬件中断号分别为ID0~ID15。它通常用于多核间通讯。
* 
版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2021-11-18

@history

在文件 los_mp.c 中定义.

函数说明

◆ LOS_MODULE_INIT()

LOS_MODULE_INIT ( OsMpInit  ,
LOS_INIT_LEVEL_KMOD_TASK   
)

◆ LOS_MpSchedule()

STATIC INLINE VOID LOS_MpSchedule ( UINT32  target)

在文件 los_mp.c76 行定义.

77{
78 UINT32 cpuid = ArchCurrCpuid();
79 target &= ~(1U << cpuid);//获取除了自身之外的其他CPU
80 HalIrqSendIpi(target, LOS_MP_IPI_SCHEDULE);//向目标CPU发送调度信号,核间中断(Inter-Processor Interrupts),IPI
81}
VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
Definition: gic_v2.c:58
STATIC INLINE UINT32 ArchCurrCpuid(VOID)
Definition: los_hw_cpu.h:168
@ LOS_MP_IPI_SCHEDULE
!< 唤醒CPU
Definition: los_mp.h:51
unsigned int UINT32
Definition: los_typedef.h:57
函数调用图:
这是这个函数的调用关系图:

◆ OsMpCollectTasks()

VOID OsMpCollectTasks ( VOID  )

MP定时器处理函数, 递归检查所有可用任务

在文件 los_mp.c105 行定义.

106{
107 LosTaskCB *taskCB = NULL;
108 UINT32 taskID = 0;
109 UINT32 ret;
110
111 /* recursive checking all the available task */
112 for (; taskID <= g_taskMaxNum; taskID++) { //递归检查所有可用任务
113 taskCB = &g_taskCBArray[taskID];
114
115 if (OsTaskIsUnused(taskCB) || OsTaskIsRunning(taskCB)) {
116 continue;
117 }
118
119 /* 虽然任务状态不是原子的,但此检查可能成功,但无法完成删除,此删除将在下次运行之前处理
120 * though task status is not atomic, this check may success but not accomplish
121 * the deletion; this deletion will be handled until the next run.
122 */
123 if (taskCB->signal & SIGNAL_KILL) {//任务收到被干掉信号
124 ret = LOS_TaskDelete(taskID);//干掉任务,回归任务池
125 if (ret != LOS_OK) {
126 PRINT_WARN("GC collect task failed err:0x%x\n", ret);
127 }
128 }
129 }
130}
LITE_OS_SEC_BSS UINT32 g_taskMaxNum
任务最大数量 默认128个
Definition: los_task.c:150
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
Delete a task.
Definition: los_task.c:968
LITE_OS_SEC_BSS LosTaskCB * g_taskCBArray
外部变量 任务池 默认128个
Definition: los_task.c:147
STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
任务是否在使用
Definition: los_task_pri.h:255
UINT32 signal
函数调用图:
这是这个函数的调用关系图:

◆ OsMpFuncCall()

INLINE VOID OsMpFuncCall ( UINT32  target,
SMP_FUNC_CALL  func,
VOID *  args 
)

OsMpFuncCall 向指定CPU的funcLink上注册回调函数, 该怎么理解这个函数呢 ? 具体有什么用呢 ?
可由CPU a核向b核发起一个请求,让b核去执行某个函数, 这是否是分布式调度的底层实现基础 ?

参数
args
func
target
返回
参见

在文件 los_mp.c144 行定义.

145{
146 UINT32 index;
147 UINT32 intSave;
148
149 if (func == NULL) {
150 return;
151 }
152
153 if (!(target & OS_MP_CPU_ALL)) {//检查目标CPU是否正确
154 return;
155 }
156
157 for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {//遍历所有核
158 if (CPUID_TO_AFFI_MASK(index) & target) {
159 MpCallFunc *mpCallFunc = (MpCallFunc *)LOS_MemAlloc(m_aucSysMem0, sizeof(MpCallFunc));//从内核空间 分配回调结构体
160 if (mpCallFunc == NULL) {
161 PRINT_ERR("smp func call malloc failed\n");
162 return;
163 }
164 mpCallFunc->func = func;
165 mpCallFunc->args = args;
166
167 MP_CALL_LOCK(intSave);
168 LOS_ListAdd(&g_percpu[index].funcLink, &(mpCallFunc->node));//将回调结构体挂入链表尾部
169 MP_CALL_UNLOCK(intSave);
170 }
171 }
172 HalIrqSendIpi(target, LOS_MP_IPI_FUNC_CALL);//向目标CPU发起核间中断
173}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
Definition: los_list.h:217
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
@ LOS_MP_IPI_FUNC_CALL
!< 停止CPU
Definition: los_mp.h:54
Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM]
CPU池,池大小由CPU核数决定
Definition: los_percpu.c:36
SMP_FUNC_CALL func
回调函数地址
Definition: los_mp.h:76
VOID * args
回调函数的参数
Definition: los_mp.h:77
LOS_DL_LIST node
链表节点,将挂到 g_percpu[cpuid]上
Definition: los_mp.h:75
函数调用图:

◆ OsMpFuncCallHandler()

VOID OsMpFuncCallHandler ( VOID  )

OsMpFuncCallHandler
回调向当前CPU注册过的函数

返回
参见

在文件 los_mp.c182 行定义.

183{
184 UINT32 intSave;
185 UINT32 cpuid = ArchCurrCpuid();//获取当前CPU
186 LOS_DL_LIST *list = NULL;
187 MpCallFunc *mpCallFunc = NULL;
188
189 MP_CALL_LOCK(intSave);
190 while (!LOS_ListEmpty(&g_percpu[cpuid].funcLink)) {//遍历回调函数链表,知道为空
191 list = LOS_DL_LIST_FIRST(&g_percpu[cpuid].funcLink);//获取链表第一个数据
192 LOS_ListDelete(list);//将自己从链表上摘除
193 MP_CALL_UNLOCK(intSave);
194
195 mpCallFunc = LOS_DL_LIST_ENTRY(list, MpCallFunc, node);//获取回调函数
196 mpCallFunc->func(mpCallFunc->args);//获取参数并回调该函数
197 (VOID)LOS_MemFree(m_aucSysMem0, mpCallFunc);//释放回调函数内存
198
199 MP_CALL_LOCK(intSave);
200 }
201 MP_CALL_UNLOCK(intSave);
202}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
函数调用图:
这是这个函数的调用关系图:

◆ OsMpFuncCallInit()

VOID OsMpFuncCallInit ( VOID  )

CPU层级的回调模块初始化

在文件 los_mp.c204 行定义.

205{
206 UINT32 index;
207 /* init funclink for each core | 为每个CPU核整一个回调函数链表*/
208 for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
209 LOS_ListInit(&g_percpu[index].funcLink);//链表初始化
210 }
211}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
函数调用图:
这是这个函数的调用关系图:

◆ OsMpHaltHandler()

VOID OsMpHaltHandler ( VOID  )

硬中断暂停处理函数

在文件 los_mp.c97 行定义.

98{
99 (VOID)LOS_IntLock();
100 OsPercpuGet()->excFlag = CPU_HALT;//让当前Cpu停止工作
101
102 while (1) {}//陷入空循环,也就是空闲状态
103}
STATIC INLINE UINT32 LOS_IntLock(VOID)
Disable all interrupts. | 关闭当前处理器所有中断响应
Definition: los_hwi.h:286
@ CPU_HALT
cpu in the halt | CPU处于暂停状态
STATIC INLINE Percpu * OsPercpuGet(VOID)
UINT32 excFlag
函数调用图:
这是这个函数的调用关系图:

◆ OsMpInit()

UINT32 OsMpInit ( VOID  )

在文件 los_mp.c214 行定义.

215{
216 UINT16 swtmrId;
217
218 (VOID)LOS_SwtmrCreate(OS_MP_GC_PERIOD, LOS_SWTMR_MODE_PERIOD, //创建一个周期性,持续时间为 100个tick的定时器
219 (SWTMR_PROC_FUNC)OsMpCollectTasks, &swtmrId, 0);//OsMpCollectTasks为超时回调函数
220 (VOID)LOS_SwtmrStart(swtmrId);//开始定时任务
221#ifdef LOSCFG_KERNEL_SMP_CALL
223#endif
224 return LOS_OK;
225}
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrID)
接口函数 启动定时器 参数定时任务ID
Definition: los_swtmr.c:764
VOID(* SWTMR_PROC_FUNC)(UINTPTR arg)
Define the type of a callback function that handles software timer timeout.
Definition: los_swtmr.h:260
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval, UINT8 mode, SWTMR_PROC_FUNC handler, UINT16 *swtmrID, UINTPTR arg)
创建定时器,设置定时器的定时时长、定时器模式、回调函数,并返回定时器ID
Definition: los_swtmr.c:712
@ LOS_SWTMR_MODE_PERIOD
Definition: los_swtmr.h:233
VOID OsMpCollectTasks(VOID)
MP定时器处理函数, 递归检查所有可用任务
Definition: los_mp.c:105
VOID OsMpFuncCallInit(VOID)
CPU层级的回调模块初始化
Definition: los_mp.c:204
unsigned short UINT16
Definition: los_typedef.h:56
函数调用图:

◆ OsMpScheduleHandler()

VOID OsMpScheduleHandler ( VOID  )

硬中断调度处理函数

在文件 los_mp.c88 行定义.

89{//将调度标志设置为与唤醒功能不同,这样就可以在硬中断结束时触发调度程序。
90 /*
91 * set schedule flag to differ from wake function,
92 * so that the scheduler can be triggered at the end of irq.
93 */
95}
STATIC INLINE VOID OsSchedRunqueuePendingSet(VOID)
函数调用图:
这是这个函数的调用关系图:

◆ OsMpWakeHandler()

VOID OsMpWakeHandler ( VOID  )

硬中断唤醒处理函数

在文件 los_mp.c83 行定义.

84{
85 /* generic wakeup ipi, do nothing */
86}
这是这个函数的调用关系图:

◆ SPIN_LOCK_INIT()

LITE_OS_SEC_BSS SPIN_LOCK_INIT ( g_mpCallSpin  )